问:
Python: Anything wrong with dynamically assigning instance methods as instance attributes
I came up with the following code to decorate instance methods using a decorator that requires the instance itself as an argument:

```<code>from functools import wraps

def logging_decorator(tricky_instance):
    def wrapper(fn):
        @wraps(fn)
        def wrapped(*a, **kw):
            if tricky_instance.log:
                print("Calling %s.." % fn.__name__)
            return fn(*a, **kw)
        return wrapped
    return wrapper

class Tricky(object):
    def __init__(self, log):
        self.log = log
        self.say_hi = logging_decorator(self)(self.say_hi)

    def say_hi(self):
       print("Hello, world!")

i1 = Tricky(log=True)
i2 = Tricky(log=False)

i1.say_hi()
i2.say_hi()
</code>```

This seems to work great, but I fear that I may have overlooked some unintended side effects of this trick. Am I about to shoot myself in the foot, or is this  safe?

Note that I don't actually want to use this for logging, it's just the shortest meaningful example I could come up with.

答:
I think I was trying to be needlessly smart. There seems to be an embarrassingly simpler solution:</p>

```<code>from functools import wraps

def logging_decorator(fn):
    @wraps(fn)
    def wrapped(self, *a, **kw):
        if self.log:
            print("Calling %s.." % fn.__name__)
        return fn(self, *a, **kw)
    return wrapped

class Tricky(object):
    def __init__(self, log):
        self.log = log

    @logging_decorator
    def say_hi(self):
       print("Hello, world!")

i1 = Tricky(log=True)
i2 = Tricky(log=False)

i1.say_hi()
i2.say_hi()
</code>```

Body:
I came up with the following code to decorate instance methods using a decorator that requires the instance itself as an argument:

from functools import wraps

def logging_decorator(tricky_instance):
    def wrapper(fn):
        @wraps(fn)
        def wrapped(*a, **kw):
            if tricky_instance.log:
                print("Calling %s.." % fn.__name__)
            return fn(*a, **kw)
        return wrapped
    return wrapper

class Tricky(object):
    def __init__(self, log):
        self.log = log
        self.say_hi = logging_decorator(self)(self.say_hi)

    def say_hi(self):
       print("Hello, world!")

i1 = Tricky(log=True)
i2 = Tricky(log=False)

i1.say_hi()
i2.say_hi()

This seems to work great, but I fear that I may have overlooked some unintended side effects of this trick. Am I about to shoot myself in the foot, or is this  safe?

Note that I don't actually want to use this for logging, it's just the shortest meaningful example I could come up with.

Body:
I think I was trying to be needlessly smart. There seems to be an embarrassingly simpler solution:

from functools import wraps

def logging_decorator(fn):
    @wraps(fn)
    def wrapped(self, *a, **kw):
        if self.log:
            print("Calling %s.." % fn.__name__)
        return fn(self, *a, **kw)
    return wrapped

class Tricky(object):
    def __init__(self, log):
        self.log = log

    @logging_decorator
    def say_hi(self):
       print("Hello, world!")

i1 = Tricky(log=True)
i2 = Tricky(log=False)

i1.say_hi()
i2.say_hi()


来源: stackexchange

问:
Python chunk list from one element to another
I've got the following code:

```<code>for paragraph in document.paragraphs:
while paragraph.style.name == 'Heading 2':
    print(paragraph.style.name)
    print(paragraph.text)
</code>```

This basically doesn't work because I don't know how to accommodate the right logic.
I'm using python docx library https://python-docx.readthedocs.io/en/latest/user/styles-using.html to iterate through the document's paragraphs.

Now, I want to split the list of paragraphs into sublists starting from every Heading 2, then adding all the next paragraphs with different paragraph.style.name until the next Heading 2 element, so that each chunk will contain one Heading 2 paragraph with its corresponding text.

In other words, I'm looking for a way to split the list into chunks from one element to another. Please help :)

答:
You could use an itertools.groupby to accomplish this:

from itertools import groupby

groups, next_group = [], []

for k, group in groupby(document.paragraphs, lambda x: x.style.name == 'Heading 2'):
    # If the predicate is True and next_group is populated,
    # we create a new chunk
    if k and next_group:
        groups.append(next_group)
        next_group = []

    # Fill up the current chunk
    for paragraph in group:
        # feel free to swap this out with a print statement
        # or whatever data structure suits you
        next_group.append({'style_name': paragraph.style.name, 'text': paragraph.text})
```

I'm using a list of dictionaries here for clarity, but you can substitute any data structure

ContentLicense: CC BY-SA 4.0

Body:
I've got the following code:

for paragraph in document.paragraphs:
while paragraph.style.name == 'Heading 2':
    print(paragraph.style.name)
    print(paragraph.text)

This basically doesn't work because I don't know how to accommodate the right logic.
I'm using python docx library https://python-docx.readthedocs.io/en/latest/user/styles-using.html to iterate through the document's paragraphs.

Now, I want to split the list of paragraphs into sublists starting from every Heading 2, then adding all the next paragraphs with different paragraph.style.name until the next Heading 2 element, so that each chunk will contain one Heading 2 paragraph with its corresponding text.

In other words, I'm looking for a way to split the list into chunks from one element to another. Please help :)

Body:
You could use an itertools.groupby to accomplish this:

from itertools import groupby

groups, next_group = [], []

for k, group in groupby(document.paragraphs, lambda x: x.style.name == 'Heading 2'):
    # If the predicate is True and next_group is populated,
    # we create a new chunk
    if k and next_group:
        groups.append(next_group)
        next_group = []

    # Fill up the current chunk
    for paragraph in group:
        # feel free to swap this out with a print statement
        # or whatever data structure suits you
        next_group.append({'style_name': paragraph.style.name, 'text': paragraph.text})

I'm using a list of dictionaries here for clarity, but you can substitute any data structure


问:
Connecting User Model To two Databases In Rails
In my rails 6 application, I have to connect User model to two database conditionally. So on some condition I have to fetch record from users table in Database 1 and on some conditions I have to fetch records from users table in Database 2.

Is it possible to configure two different database in model level?

答:
Rails supports connections to multiple databases, but you'll have to configure them above the model level.

Have a look at https://guides.rubyonrails.org/active_record_multiple_databases.html and more specifically at https://guides.rubyonrails.org/active_record_multiple_databases.html#granular-database-connection-switching


问:
Order a Query by Name of Parent and its child
I have this table where you have an ParentID within the same table.

ID
Name
ParentID

1
Alpha
NULL

2
Delta
4

3
Sigma
7

4
Beta
NULL

5
Charlie
1

6
Echo
1

7
Foxtrot
NULL

8
Omega
7

How can I query ALL sorted by Name (Parent First) and child under it. So the result will be like this:

ID
Name
ParentID

1
Alpha
NULL

5
Charlie
1

6
Echo
1

4
Beta
NULL

2
Delta
4

7
Foxtrot
NULL

8
Omega
7

3
Sigma
7

答:
Obviously the null parent ID means it is a parent and we just need a way to replace the NULL parent ID with the actual ID.

Coalesce allows us to take the first non-null value in a series

So

```<code>order by coalesce(parentID, ID), Name
</code>```

This then will put the parentID first and it not, then ID.

note this slows performance on indexes, so if mySQL supports the concept of function based indexes performance could improve by creating one.

Alternatively; instead of using NULL to denote the parent, use the ID of the parent and when they match it is a parent. (but this can cause looping problems when traversing a hierarchy if not handled)

THis also assumes 1 level of depth.  If you have sub levles such as...

```<code> 1
 1.2
 1.2.3 <--
</code>```

Then a recursive CTE would be required or similar and we'd have to build out the path for each node and sort by it.

NOTE: All Code content and data from here on is directly from the URL mentioned below.
Possible Example: https://www.geeksforgeeks.org/mysql-recursive-cte-common-table-expressions/

In it they give against a 2 column table: (node, Parent)

```<code>WITH RECURSIVE
cte ( node, path )
AS
( SELECT node, cast ( 1 as char(30) )
          FROM bst WHERE parent IS NULL
  UNION ALL
  SELECT bst.node,  CONCAT ( cte.path, '-->', bst.node )
         FROM cte JOIN bst ON cte.node = bst.parent
)
SELECT * FROM cte ORDER BY node;
</code>```

Giving us:

```<code>+------+-----------+
| node |   path    |
+------+-----------+
|  1   | 1         |
|  2   | 1-->2     |
|  3   | 1-->3     |
|  4   | 1-->2-->4 |
|  5   | 1-->2-->5 |
|  6   | 1-->3-->6 |
|  7   | 1-->3-->7 |
+------+-----------+
</code>```

Which would allow you to sort then by the path and name

Body:
Obviously the null parent ID means it is a parent and we just need a way to replace the NULL parent ID with the actual ID.

Coalesce allows us to take the first non-null value in a series

So

order by coalesce(parentID, ID), Name

This then will put the parentID first and it not, then ID.

note this slows performance on indexes, so if mySQL supports the concept of function based indexes performance could improve by creating one.

Alternatively; instead of using NULL to denote the parent, use the ID of the parent and when they match it is a parent. (but this can cause looping problems when traversing a hierarchy if not handled)

THis also assumes 1 level of depth.  If you have sub levles such as...

 1
 1.2
 1.2.3 <--

Then a recursive CTE would be required or similar and we'd have to build out the path for each node and sort by it.

NOTE: All Code content and data from here on is directly from the URL mentioned below.
Possible Example: https://www.geeksforgeeks.org/mysql-recursive-cte-common-table-expressions/

In it they give against a 2 column table: (node, Parent)

WITH RECURSIVE
cte ( node, path )
AS
( SELECT node, cast ( 1 as char(30) )
          FROM bst WHERE parent IS NULL
  UNION ALL
  SELECT bst.node,  CONCAT ( cte.path, '-->', bst.node )
         FROM cte JOIN bst ON cte.node = bst.parent
)
SELECT * FROM cte ORDER BY node;

Giving us:

+------+-----------+
| node |   path    |
+------+-----------+
|  1   | 1         |
|  2   | 1-->2     |
|  3   | 1-->3     |
|  4   | 1-->2-->4 |
|  5   | 1-->2-->5 |
|  6   | 1-->3-->6 |
|  7   | 1-->3-->7 |
+------+-----------+

Which would allow you to sort then by the path and name


问:
Docker container has no access to host's interfaces
I'm trying to access the host's network interfaces from inside a Docker container with the host-network option.
For debugging purposes I tried to run a clean Alpine container using docker run --network host --rm -it alpine:3.9. Running ip link returns

```<code>1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: tap0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 65520 qdisc pfifo_fast state UP qlen 1000
    link/ether 62:db:1e:6b:52:fe brd ff:ff:ff:ff:ff:ff
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN
    link/ether 02:42:9a:e6:96:40 brd ff:ff:ff:ff:ff:ff
</code>```

I would expect the same result as on my host machine with all the interfaces (lo, two wired and one wireless interface, docker). Why is that not the case?

UPDATE to include various outputs:

dpkg -l | grep docker:

```<code>ii  docker-ce                            5:20.10.12~3-0~raspbian-bullseye armhf        Docker: the open-source application container engine
ii  docker-ce-cli                        5:20.10.12~3-0~raspbian-bullseye armhf        Docker CLI: the open-source application container engine
ii  docker-ce-rootless-extras            5:20.10.12~3-0~raspbian-bullseye armhf        Rootless support for Docker.
</code>```

tail -4 /proc/cpuinfo:

```<code>Hardware    : BCM2711
Revision    : d03114
Serial      : 1000000025d45b15
Model       : Raspberry Pi 4 Model B Rev 1.4
</code>```

cat /etc/debian_version:

```<code>11.2
</code>```

答:
Executing the command with sudo fixes the issue as a workaround.

Executing the run-command without sudo after a dockerd-rootless-setuptool.sh installation causes the stated issue where the network interfaces are not available, instead a virtual interface is created.

Body:
I'm trying to access the host's network interfaces from inside a Docker container with the host-network option.
For debugging purposes I tried to run a clean Alpine container using docker run --network host --rm -it alpine:3.9. Running ip link returns

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: tap0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 65520 qdisc pfifo_fast state UP qlen 1000
    link/ether 62:db:1e:6b:52:fe brd ff:ff:ff:ff:ff:ff
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN
    link/ether 02:42:9a:e6:96:40 brd ff:ff:ff:ff:ff:ff

I would expect the same result as on my host machine with all the interfaces (lo, two wired and one wireless interface, docker). Why is that not the case?

UPDATE to include various outputs:

dpkg -l | grep docker:

ii  docker-ce                            5:20.10.12~3-0~raspbian-bullseye armhf        Docker: the open-source application container engine
ii  docker-ce-cli                        5:20.10.12~3-0~raspbian-bullseye armhf        Docker CLI: the open-source application container engine
ii  docker-ce-rootless-extras            5:20.10.12~3-0~raspbian-bullseye armhf        Rootless support for Docker.

tail -4 /proc/cpuinfo:

Hardware    : BCM2711
Revision    : d03114
Serial      : 1000000025d45b15
Model       : Raspberry Pi 4 Model B Rev 1.4

cat /etc/debian_version:

11.2


问:
SortBy nested non-comparable object with comparator
Suppose I have

```<code>data class NonComparable(val a : Any) //i.e. does not implement Comparable
data class WrappingElement(val nc : NonComparable)
val unordered = listOf<NonComparable>(....)
val comparator = Comparator<NonComparable>(){...}
</code>```

What is the cleanest (least lines of code) way of sorting unordered with comparator?

In other words: How to reuse the logic in comparator (for NonComparable) to order a list of WrappingElements?

答:
Given you have a custom Comparator you want to reuse, like below:

object NonComparableComparator: Comparator<NonComparable> {
    override fun compare(p0: NonComparable, p1: NonComparable): Int {
        // your custom comparision logic here ...
    }
}

val comparator = NonComparableComparator
```
<p>There is nothing stopping you to re-use this comparator in a Comparator for the wrapping element.</p>
<pre class="lang-kotlin prettyprint-override"><code>val wrappingElementComparator = Comparator<WrappingElement> {
        p0, p1 -> comparator.compare(p0.nonComparable, p1.nonComparable)
}

val sortedList = unsortedList.sortedWith(wrappingElementComparator)
</code>```

All code above is based on the following:

data class NonComparable(val value: Any?)
data class WrappingElement(val nonComparable: NonComparable)

val unsortedList = listOf(
    WrappingElement(NonComparable(3)),
    WrappingElement(NonComparable(2)),
    WrappingElement(NonComparable(4)),
    WrappingElement(NonComparable(5)),
    WrappingElement(NonComparable(0)),
    WrappingElement(NonComparable(1)),
)
```

Body:
Suppose I have

data class NonComparable(val a : Any) //i.e. does not implement Comparable
data class WrappingElement(val nc : NonComparable)
val unordered = listOf<NonComparable>(....)
val comparator = Comparator<NonComparable>(){...}

What is the cleanest (least lines of code) way of sorting unordered with comparator?

In other words: How to reuse the logic in comparator (for NonComparable) to order a list of WrappingElements?

Body:
Given you have a custom Comparator you want to reuse, like below:

object NonComparableComparator: Comparator<NonComparable> {
    override fun compare(p0: NonComparable, p1: NonComparable): Int {
        // your custom comparision logic here ...
    }
}

val comparator = NonComparableComparator

There is nothing stopping you to re-use this comparator in a Comparator for the wrapping element.

val wrappingElementComparator = Comparator<WrappingElement> {
        p0, p1 -> comparator.compare(p0.nonComparable, p1.nonComparable)
}

val sortedList = unsortedList.sortedWith(wrappingElementComparator)

All code above is based on the following:

data class NonComparable(val value: Any?)
data class WrappingElement(val nonComparable: NonComparable)

val unsortedList = listOf(
    WrappingElement(NonComparable(3)),
    WrappingElement(NonComparable(2)),
    WrappingElement(NonComparable(4)),
    WrappingElement(NonComparable(5)),
    WrappingElement(NonComparable(0)),
    WrappingElement(NonComparable(1)),
)


问:
Job DSL script fails on generating job with allure plugin for reports
I have some groovy script for generating jenkins jobs, which worked great.
But after reinstallation of jenkins this script throws exception.

problem part of script is:

```<code>publishers {
            allure(['path-to/reports'])
        }
</code>```

And error is:

```<code>Processing DSL script seed.groovy
ERROR: (JobBuilder.groovy, line 55) No signature of method:
javaposse.jobdsl.dsl.helpers.publisher.PublisherContext.allure() is
applicable for argument types: (java.util.ArrayList) values:
[[PyUIAutotest/reports]]
Possible solutions: mailer(java.lang.String),
use([Ljava.lang.Object;), asType(java.lang.Class)
Finished: FAILURE
</code>```

It fails on wrong signature of method, but it is correct, and i don't know what is wrong.

example of script available on wiki dock. and javadoc for allure() method

Jenkins ver. 2.46.2; Job DSL ver. 1.63, Allure-Jenkins-Plugin ver. 2.15

weird thing in that, i have another server with same plugin versions, and it works fine

答:
You might find my answer here useful: https://stackoverflow.com/a/71082002/1169433

In short, you may need to add the allure-jenkins-plugin in your build dependencies.

ContentLicense: CC BY-SA 3.0

Body:
I have some groovy script for generating jenkins jobs, which worked great.
But after reinstallation of jenkins this script throws exception.

problem part of script is:

publishers {
            allure(['path-to/reports'])
        }

And error is:

Processing DSL script seed.groovy
ERROR: (JobBuilder.groovy, line 55) No signature of method:
javaposse.jobdsl.dsl.helpers.publisher.PublisherContext.allure() is
applicable for argument types: (java.util.ArrayList) values:
[[PyUIAutotest/reports]]
Possible solutions: mailer(java.lang.String),
use([Ljava.lang.Object;), asType(java.lang.Class)
Finished: FAILURE

It fails on wrong signature of method, but it is correct, and i don't know what is wrong.

example of script available on wiki dock. and javadoc for allure() method

Jenkins ver. 2.46.2; Job DSL ver. 1.63, Allure-Jenkins-Plugin ver. 2.15

weird thing in that, i have another server with same plugin versions, and it works fine


问:
Using logic in Regex
I would like to extract data from the following configuration using Regex:

```<code>Eth 1/1/1       abc-p01.be01    up       10G      full     -
Eth 1/1/2                       down     0        full     A    1    -
Eth 1/1/3                       down     0        full     A    1    -
Eth 1/1/4       abc-02.be01     up       10G      full     -
Eth 1/1/14      dcba-08.fa01    up       10G      full     -
</code>```

I've come this far:

```<code>(?P<port>Eth [\/\w\d\-]+)\s+[\w\d\-.]+\s+(?P<status>[up]+)\s+(?<speed>[\d\w]+)
</code>```

Which gave me this result (https://regex101.com):

This is exactly what I want but it only works if the status is up. Is it possible to also match the down status (and with that the 0 speed) in the same regular expression? I've read about using logical operators in Regex (|) but I can't seem to figure it out.

答:
You can update the pattern with an optional part as there is no value before "down", and then match either up or down in the named group status.

Note that \w also matches \d and if you put the hyphen at the end of the character class you don't have to escape it.

```<code>(?P<port>Eth [\/\w-]+)\s+(?:[\w.-]+\s+)?(?P<status>down|up)\s+(?<speed>\w+)
</code>```

Regex demo

Title: Using logic in Regex

Body:
I would like to extract data from the following configuration using Regex:

Eth 1/1/1       abc-p01.be01    up       10G      full     -
Eth 1/1/2                       down     0        full     A    1    -
Eth 1/1/3                       down     0        full     A    1    -
Eth 1/1/4       abc-02.be01     up       10G      full     -
Eth 1/1/14      dcba-08.fa01    up       10G      full     -

I've come this far:

(?P<port>Eth [\/\w\d\-]+)\s+[\w\d\-.]+\s+(?P<status>[up]+)\s+(?<speed>[\d\w]+)

Which gave me this result (https://regex101.com):

This is exactly what I want but it only works if the status is up. Is it possible to also match the down status (and with that the 0 speed) in the same regular expression? I've read about using logical operators in Regex (|) but I can't seem to figure it out.

Body:
You can update the pattern with an optional part as there is no value before "down", and then match either up or down in the named group status.

Note that \w also matches \d and if you put the hyphen at the end of the character class you don't have to escape it.

(?P<port>Eth [\/\w-]+)\s+(?:[\w.-]+\s+)?(?P<status>down|up)\s+(?<speed>\w+)

Regex demo


问:
Add a calculated column to a pivot table in pandas
Hi I am trying to create  new columns to a multi-indexed pandas pivot table to do a countif statement (similar to excel) depending if a level of the index contains a specific string. This is the sample data:

```<code>df = pd.DataFrame({'City': ['Houston', 'Austin', 'Hoover','Adak','Denver','Houston','Adak','Denver'],
                   'State': ['Texas', 'Texas', 'Alabama','Alaska','Colorado','Texas','Alaska','Colorado'],
                   'Name':['Aria', 'Penelope', 'Niko','Susan','Aria','Niko','Aria','Niko'],
                   'Unit':['Sales', 'Marketing', 'Operations','Sales','Operations','Operations','Sales','Operations'],
                   'Assigned':['Yes','No','Maybe','No','Yes','Yes','Yes','Yes']},
                 columns=['City', 'State', 'Name', 'Unit','Assigned'])

pivot=df.pivot_table(index=['City','State'],columns=['Name','Unit'],values=['Assigned'],aggfunc=lambda x:', '.join(set(x)),fill_value='')
</code>```

and this is the desired output (in screenshot). Thanks in advance!

答:
try:

```<code>temp = pivot[('Mango',     'Aria',      'Sales')].str.len()>0
pivot['new col'] = temp.astype(int)
</code>```

the result:

Based on your edit:

```<code>import numpy as np
temp = pivot.xs('Sales', level=2, drop_level=False, axis = 1).apply(lambda x: np.sum([1 if y!='' else 0 for y in x]), axis = 1)
pivot[('',     'total sales',      'count how many...')]=temp
</code>```

Body:
Hi I am trying to create  new columns to a multi-indexed pandas pivot table to do a countif statement (similar to excel) depending if a level of the index contains a specific string. This is the sample data:

df = pd.DataFrame({'City': ['Houston', 'Austin', 'Hoover','Adak','Denver','Houston','Adak','Denver'],
                   'State': ['Texas', 'Texas', 'Alabama','Alaska','Colorado','Texas','Alaska','Colorado'],
                   'Name':['Aria', 'Penelope', 'Niko','Susan','Aria','Niko','Aria','Niko'],
                   'Unit':['Sales', 'Marketing', 'Operations','Sales','Operations','Operations','Sales','Operations'],
                   'Assigned':['Yes','No','Maybe','No','Yes','Yes','Yes','Yes']},
                 columns=['City', 'State', 'Name', 'Unit','Assigned'])

pivot=df.pivot_table(index=['City','State'],columns=['Name','Unit'],values=['Assigned'],aggfunc=lambda x:', '.join(set(x)),fill_value='')

and this is the desired output (in screenshot). Thanks in advance!

Body:
try:

temp = pivot[('Mango',     'Aria',      'Sales')].str.len()>0
pivot['new col'] = temp.astype(int)

the result:

Based on your edit:

import numpy as np
temp = pivot.xs('Sales', level=2, drop_level=False, axis = 1).apply(lambda x: np.sum([1 if y!='' else 0 for y in x]), axis = 1)
pivot[('',     'total sales',      'count how many...')]=temp


问:
Merging two bezier-based shapes into one to create a new outline
Lets say I have the data to render two overlaying bezier-based shapes, that are overlapping, displayed in a svg or on the canvas (doesn't really matter where). I would like to calculate the outline of the shape resulting from the merge of the two shapes, so that I have a clean (new) outline and as few nodes and handles as possible.
I would like to achieve the effect that vector programs like adobe illustrator offers with Pathfinder > Add or the font program glyphs with Remove Overlap.
Example: https://helpx.adobe.com/illustrator/using/combining-objects.html

Is there possible a library or a concept for that task?
I am working with javascript in the browser, but any other source for how to make such a calculation would help as well.

It is also important, that this calculation happens before the rendering an agnostic to the rendered result (be it svg/canvas).

In the illustration bellow, on the left side is the input shape. and on the right side the expected result. I have the data, meaning all the nodes and handles (from the bezier curve) and I would like to calculate the coordinates of the red (nodes) and green dots (handles) on the right side.

答:
Paper.js might be the perfect library for this task:

In particular it's Boolean operations – like unite() to merge path elements. The syntax looks something like this:

```<code>let unitedPath = path1.unite(path2);
</code>```

The following example also employs Jarek Foksa's pathData polyfill.

Example: unite paths:

/**
 * merge paths
 */
function unite(svg, decimals = 3) {
  let paths = svg.querySelectorAll("path");
  let path0 = paths[0];
  let d0 = path0.getAttribute("d");
  // create new paper.js path object
  let paperPath0 = new Path(d0);

  for (let i = 1; i < paths.length; i++) {
    let pathI = paths[i];
    let dI = pathI.getAttribute("d");
    // create new paper.js path object for all children
    let paperPathI = new Path(dI);
    paperPath0 = paperPath0.unite(paperPathI);
    pathI.remove();
  }

  let dUnited = paperPath0
    .exportSVG({
      precision: 3
    })
    .getAttribute("d");
  path0.setAttribute("d", dUnited);
}

// init paper.js
window.addEventListener("DOMContentLoaded", (e) => {
  initPaper();
});

// init paper.js and add mandatory canvas
function initPaper() {
  canvas = document.createElement("canvas");
  canvas.id = "canvasPaper";
  canvas.setAttribute("style", "display:none");
  document.body.appendChild(canvas);
  paper.install(window);
  paper.setup("canvasPaper");
}```
<pre class="snippet-code-css lang-css prettyprint-override"><code>svg {
  display: inline-block;
  width: 10em
}

svg * {
  fill: none;
  stroke: red;
  stroke-width: 0.25%;
}</code>```

  <button type="button" onclick="unite(svg, 3)">Unite Path </button>

<svg class="svgunite" id="svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" stroke-width="1" stroke="#000">
<path fill="none" d="M50.05 23.21l-19.83 61.51h-9.27l23.6-69.44h10.82l23.7 69.44h-9.58l-20.44-61.51h1z"/>
<rect fill="none" x="35.49" y="52.75" width="28.5" height="6.17">
</rect>
</svg>

```

Optional: Path normalization (using getPathData() polyfill)

You might also need to convert svg primitives (<rect>, <circle>, <polygon>) like the horizontal stroke in the capital A  .

The pathData polyfill provides a method of normalizing svg elements.

This normalization will output a d attribute (for every selected svg child element) containing only a reduced set of cubic path commands (M, C, L, Z) – all based on absolute coordinates.

Little downer:

I won't say paper.js can boast of a plethora of tutorials or detailed examples. But you might check the reference for pathItem to see all options.

See also: Subtracting SVG paths programmatically

Body:
Paper.js might be the perfect library for this task:

In particular it's Boolean operations – like unite() to merge path elements. The syntax looks something like this:

let unitedPath = path1.unite(path2);

The following example also employs Jarek Foksa's pathData polyfill.

Example: unite paths:

/**
 * merge paths
 */
function unite(svg, decimals = 3) {
  let paths = svg.querySelectorAll("path");
  let path0 = paths[0];
  let d0 = path0.getAttribute("d");
  // create new paper.js path object
  let paperPath0 = new Path(d0);

  for (let i = 1; i < paths.length; i++) {
    let pathI = paths[i];
    let dI = pathI.getAttribute("d");
    // create new paper.js path object for all children
    let paperPathI = new Path(dI);
    paperPath0 = paperPath0.unite(paperPathI);
    pathI.remove();
  }

  let dUnited = paperPath0
    .exportSVG({
      precision: 3
    })
    .getAttribute("d");
  path0.setAttribute("d", dUnited);
}

// init paper.js
window.addEventListener("DOMContentLoaded", (e) => {
  initPaper();
});

// init paper.js and add mandatory canvas
function initPaper() {
  canvas = document.createElement("canvas");
  canvas.id = "canvasPaper";
  canvas.setAttribute("style", "display:none");
  document.body.appendChild(canvas);
  paper.install(window);
  paper.setup("canvasPaper");
}

svg {
  display: inline-block;
  width: 10em
}

svg * {
  fill: none;
  stroke: red;
  stroke-width: 0.25%;
}

<p>
  <button type="button" onclick="unite(svg, 3)">Unite Path </button>
</p>

<svg class="svgunite" id="svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" stroke-width="1" stroke="#000">
<path fill="none" d="M50.05 23.21l-19.83 61.51h-9.27l23.6-69.44h10.82l23.7 69.44h-9.58l-20.44-61.51h1z"/>
<rect fill="none" x="35.49" y="52.75" width="28.5" height="6.17">
</rect>
</svg>

<script src="https://cdnjs.cloudflare.com/ajax/libs/paper.js/0.12.0/paper-full.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/path-data-polyfill@1.0.4/path-data-polyfill.min.js"></script>

<script>
  /**
   * convert all primitives to paths
   * like <rect>, <circle> etc
   */
  convertPrimitives(svg);

  function convertPrimitives(svg) {
    let els = svg.querySelectorAll("path, rect, circle, polygon, ellipse ");
    let pathDataCombined = [];
    let className = els[0].getAttribute("class") ?
      els[0].getAttribute("class") :
      "";
    let id = els[0].id;
    let fill = els[0].getAttribute("fill");
    els.forEach(function(el, i) {
      let pathData = el.getPathData({
        normalize: true
      });
      // create path for conversion
      let pathTmp = document.createElementNS(
        "http://www.w3.org/2000/svg",
        "path"
      );
      pathTmp.id = id;
      pathTmp.setAttribute("class", className);
      pathTmp.setAttribute("fill", fill);
      pathTmp.setPathData(pathData);
      el.replaceWith(pathTmp);
    });
  }
</script>

Optional: Path normalization (using getPathData() polyfill)

You might also need to convert svg primitives (<rect>, <circle>, <polygon>) like the horizontal stroke in the capital A  .

The pathData polyfill provides a method of normalizing svg elements.

This normalization will output a d attribute (for every selected svg child element) containing only a reduced set of cubic path commands (M, C, L, Z) – all based on absolute coordinates.

Little downer:

I won't say paper.js can boast of a plethora of tutorials or detailed examples. But you might check the reference for pathItem to see all options.

See also: Subtracting SVG paths programmatically


问:
How to show custom time In dom using new Date() object in JavaScript?
I am a beginner in javascript, what I am trying to do is using new Date() object and show a custom hour, minutes and seconds but in countDown() function I have to pass full date and it starts counting from that date.

My goal is for example I give number 1 as (hour) and then it should start counting down.

I would appreciate it if someone can help me

class Timer {
  constructor(holder) {

    var controller = {
      holder: holder,
      end: null,
      intervalID: 0,
      display: function () {
        var _second = 1000;
        var _minute = _second * 60;
        var _hour = _minute * 60;
        var _day = _hour * 24;

        var msg = "";

        var now = new Date();

        var distance = controller.end - now;
        if (distance < 0) {

          clearInterval(controller.intervalID);
          controller.holder.innerHTML = 'EXPIRED!';

          return;
        }

        var days = Math.floor(distance / _day);
        var hours = Math.floor((distance % _day) / _hour);
        var minutes = Math.floor((distance % _hour) / _minute);
        var seconds = Math.floor((distance % _minute) / _second);
        controller.holder.innerHTML = hours + ' Hours | ' + minutes + ' Minutes | ' + seconds + ' Seconds ';

      }
    };

    this.countDown = function (end) {
      controller.end = end;
      controller.intervalID = setInterval(controller.display, 1000);
    };
  }
}

var timers = {};

timers.one = new Timer(document.getElementById("one"));
timers.two = new Timer(document.getElementById("two"));
timers.three = new Timer(document.getElementById("three"));

//Hier I should be able to give a number
timers.one.countDown(new Date("Feb 30, 2022 15:37:25"));
timers.two.countDown(new Date(2022, 10, 29, 12, 40, 40));
timers.three.countDown(new Date(2022, 11, 9, 13, 45, 30));```
<pre class="snippet-code-html lang-html prettyprint-override"><code> <div id="one"></div>
 <div id="two"></div>
 <div id="three"></div></code>```

答:
finally, I could manage and find an answer to this question, here we need to convert the time to second and use the getTime() method, for this reason we need to write to function to do this job. In the following you can see the code.

function CreateEndTime(hours, minutes, seconds)
 {
   const result = new Date(new Date().getTime() + ConvertInMilliSeconds(hours, minutes, seconds));
   return result;
 }

 function ConvertInMilliSeconds(hours, minutes, seconds)
 {
   const result = (((hours * 60) + minutes) * 60) + seconds;
   return 1000 * result;
 }```


问:
Android ,Interface ,new Instance
i have a problem with a newInstance call using Reflection in Android.

My Interface:

```<code>public interface IGiver {
    public int getNr();
}
</code>```

My Class to call Reflection:

```<code>public class NrGiver implements IGiver {
    int i = 10;
    @Override
    public int getNr() {
        return i;
    }
}
</code>```

The way i try to call getNr:

```<code>String packageName = "de.package";
String className = "de.package.NrGiver";

String apkName = getPackageManager().getApplicationInfo(packageName, 0).sourceDir;
            PathClassLoader myClassLoader =
                new dalvik.system.PathClassLoader(
                            apkName,
                        ClassLoader.getSystemClassLoader());
Class c =  Class.forName(className);
IGiver giver = (IGiver) c.newInstance();
</code>```

The last line wont work it cause an Error and my App stops.
I know it fault of newInstance, but i want to work on the IGiver object.

Pls Help me.

My Solution:

Hey guys finally i got the chicken.

I found an other way. this time i also used newInstance, but this time its worked.
My solution:

```<code>Class c =  Class.forName(className);
Method methode = c.getDeclaredMethod("getNr");
Object i = methode.invoke(c.newInstance(), new Object[]{});
</code>```

And this what i wanted to do.
I have an NrGiver.class somewhere on my Phone. And it implements the Interface IGiver. So it can be loaded into my App dynamically. I need the Integer from the class NrGiver. So i can make my code generic. I tried to Cast the Object to my Interface, but it failed.

So i found an other way to invoke the method of a class.

Thx for help

答:
not sure why is classloader used. if both IGiver and NrGiver are loaded:</p>

```<code>Class k = NrGiver.class;
IGiver g = (IGiver)k.newInstance();
</code>```

Title: Android ,Interface ,new Instance

Body:
i have a problem with a newInstance call using Reflection in Android.

My Interface:

public interface IGiver {
    public int getNr();
}

My Class to call Reflection:

public class NrGiver implements IGiver {
    int i = 10;
    @Override
    public int getNr() {
        return i;
    }
}

The way i try to call getNr:

String packageName = "de.package";
String className = "de.package.NrGiver";

String apkName = getPackageManager().getApplicationInfo(packageName, 0).sourceDir;
            PathClassLoader myClassLoader =
                new dalvik.system.PathClassLoader(
                            apkName,
                        ClassLoader.getSystemClassLoader());
Class c =  Class.forName(className);
IGiver giver = (IGiver) c.newInstance();

The last line wont work it cause an Error and my App stops.
I know it fault of newInstance, but i want to work on the IGiver object.

Pls Help me.

My Solution:

Hey guys finally i got the chicken.

I found an other way. this time i also used newInstance, but this time its worked.
My solution:

Class c =  Class.forName(className);
Method methode = c.getDeclaredMethod("getNr");
Object i = methode.invoke(c.newInstance(), new Object[]{});

And this what i wanted to do.
I have an NrGiver.class somewhere on my Phone. And it implements the Interface IGiver. So it can be loaded into my App dynamically. I need the Integer from the class NrGiver. So i can make my code generic. I tried to Cast the Object to my Interface, but it failed.

So i found an other way to invoke the method of a class.

Thx for help

Body:
not sure why is classloader used. if both IGiver and NrGiver are loaded:

Class k = NrGiver.class;
IGiver g = (IGiver)k.newInstance();


问:
Filtering Outlook items using C#
I am using the Office object model to retrieve my calendar items from Outlook. I want to use the Restrict() method to only get today's appointments. I also want to include the single instance of all recurring appointments (i.e. not all recurrences - just those today).

With the below code, I get many (but not all) recurring items like birthdays regardless of the date. I also get various other appointments - but not those for today.

I've tried different formats for the date, including 2013-07-25 00:00:00, without luck. I've researched the net, and tried to copy examples from VBA scripts - no luck.

Appreciate any ideas from others' who have done this.

```<code>var outlook = new Application();
var calendar = outlook.GetNamespace("MAPI").GetDefaultFolder(OlDefaultFolders.olFolderCalendar);
DateTime today = DateTime.Today, tomorrow = today.AddDays(1);
const string DateFormat = "dd/MM/yyyy HH:mm";
string filter = string.Format("[Start] >= '{0}' AND [Start] < '{1}'", today.ToString(DateFormat), tomorrow.ToString(DateFormat));
var todaysAppointments = calendar.Items.Restrict(filter);
// todaysAppointments.IncludeRecurrences = true;
todaysAppointments.Sort("[Start]");
</code>```

答:
https://learn.microsoft.com/en-us/dotnet/api/microsoft.office.interop.outlook._items.restrict?view=outlook-pia

That document uses other date Format.
I use next filter to check daily for new or edited appointments.

```<code>        DateTime filterDate = DateTime.Now.Date.AddDays(-days);
        string filterDateString = filterDate.Day + "/" + filterDate.Month + "/" + filterDate.Year + " 1:00pm";
        string filter = "[LastModificationTime] > '" + string.Format(filterDateString, "ddddd h:nn AMPM") + "'";

        Microsoft.Office.Interop.Outlook.Application oApp = new
        Microsoft.Office.Interop.Outlook.Application();
        NameSpace nameSpace = oApp.GetNamespace("MAPI");
        MAPIFolder calendarFolder = nameSpace.GetDefaultFolder(OlDefaultFolders.olFolderCalendar);
        Items outlookCalendarItems = calendarFolder.Items.Restrict(filter);
        List<AppointmentItem> appsList = new List<AppointmentItem>();
</code>```

Title: Filtering Outlook items using C#

Body:
I am using the Office object model to retrieve my calendar items from Outlook. I want to use the Restrict() method to only get today's appointments. I also want to include the single instance of all recurring appointments (i.e. not all recurrences - just those today).

With the below code, I get many (but not all) recurring items like birthdays regardless of the date. I also get various other appointments - but not those for today.

I've tried different formats for the date, including 2013-07-25 00:00:00, without luck. I've researched the net, and tried to copy examples from VBA scripts - no luck.

Appreciate any ideas from others' who have done this.

var outlook = new Application();
var calendar = outlook.GetNamespace("MAPI").GetDefaultFolder(OlDefaultFolders.olFolderCalendar);
DateTime today = DateTime.Today, tomorrow = today.AddDays(1);
const string DateFormat = "dd/MM/yyyy HH:mm";
string filter = string.Format("[Start] >= '{0}' AND [Start] < '{1}'", today.ToString(DateFormat), tomorrow.ToString(DateFormat));
var todaysAppointments = calendar.Items.Restrict(filter);
// todaysAppointments.IncludeRecurrences = true;
todaysAppointments.Sort("[Start]");

Body:
https://learn.microsoft.com/en-us/dotnet/api/microsoft.office.interop.outlook._items.restrict?view=outlook-pia

That document uses other date Format.
I use next filter to check daily for new or edited appointments.

        DateTime filterDate = DateTime.Now.Date.AddDays(-days);
        string filterDateString = filterDate.Day + "/" + filterDate.Month + "/" + filterDate.Year + " 1:00pm";
        string filter = "[LastModificationTime] > '" + string.Format(filterDateString, "ddddd h:nn AMPM") + "'";

        Microsoft.Office.Interop.Outlook.Application oApp = new
        Microsoft.Office.Interop.Outlook.Application();
        NameSpace nameSpace = oApp.GetNamespace("MAPI");
        MAPIFolder calendarFolder = nameSpace.GetDefaultFolder(OlDefaultFolders.olFolderCalendar);
        Items outlookCalendarItems = calendarFolder.Items.Restrict(filter);
        List<AppointmentItem> appsList = new List<AppointmentItem>();


问:
Apache Tika - Getting Metadata Without Downloading File
I have been trying to implement an application to determine content type of any file. I use Apache Tika for determination.

Here is a basic code implementation for that:

```<code>InputStream fileStream = ContentTypeController.class.getClassLoader().getResourceAsStream(fileName);

Tika tika = new Tika();
String contentType = null;
try {
    contentType = tika.detect(fileStream);
} catch (IOException e) {
    e.printStackTrace();
}
</code>```

Instead of code above I have to download files from Openstack to determine file content type. Some files are more than 100GB and downloading all file is heavy.

I can not figure out how to overcome this necessity of downloading all file, I hope you have any idea/solution without downloading all file

答:
Tika has ability to determine content type of file without downloading all if you pass a URL parameter to detect() function.</p>
```<code>Tika tika = new Tika();
String contentType = null;
try {
    contentType = tika.detect(new URL("a url"));
} catch (IOException e) {
    e.printStackTrace();
}
</code>```

Body:
I have been trying to implement an application to determine content type of any file. I use Apache Tika for determination.

Here is a basic code implementation for that:

InputStream fileStream = ContentTypeController.class.getClassLoader().getResourceAsStream(fileName);

Tika tika = new Tika();
String contentType = null;
try {
    contentType = tika.detect(fileStream);
} catch (IOException e) {
    e.printStackTrace();
}

Instead of code above I have to download files from Openstack to determine file content type. Some files are more than 100GB and downloading all file is heavy.

I can not figure out how to overcome this necessity of downloading all file, I hope you have any idea/solution without downloading all file

Body:
Tika has ability to determine content type of file without downloading all if you pass a URL parameter to detect() function.

Tika tika = new Tika();
String contentType = null;
try {
    contentType = tika.detect(new URL("a url"));
} catch (IOException e) {
    e.printStackTrace();
}


问:
Add Javascript counters to colour counter
I am making a colour counter application, That has has 6 different colours.

I am currently trying to implement a pure JavaScript counter that has a individual counter for each colour.

(Correction: It is not to count the different colours displayed on the page, but when the user sees a colour in their surrounding environment that matches one of the 6 colours, they increase the counter by 1, for example the user sees the sky is blue and the grass is green, The user hovers over the blue colour, the increase and decrease buttons appear, the user increases the blue colour by 1 increment, Then for the grass the user hovers over the green colour, again the button appears and the user increases the green counter by 1.)

When a user hovers over the colour buttons must appear to increase or decrease the counter by 1, to a minimum of 0.

The count of each colour must always be displayed above the colour.

My current method seems rather long I'm sure there is a way to set up some sort of a method to handle all colours but again to have separate counters for each colour.

Please see the below image for what I am trying to achieve:
See this image

Any help would be appreciated,
I have included my current code below for reference

var green = 0;
var countEl1 = document.getElementById("green");
function plus1(){
    green++;
    countEl1.value = green;
}
function minus1(){
    if (green > 0) {
        green--;
        countEl1.value = green;
    }
}
var brown = 0;
var countEl2 = document.getElementById("brown");
function plus2(){
    brown++;
    countEl2.value = brown;
}
function minus2(){
    if (brown > 0) {
        brown--;
        countEl2.value = brown;
    }
}
var blue = 0;
var countEl3 = document.getElementById("blue");
function plus3(){
    blue++;
    countEl3.value = blue;
}
function minus3(){
    if (blue > 0) {
        blue--;
        countEl3.value = blue;
    }
}
var yellow = 0;
var countEl4 = document.getElementById("yellow");
function plus4(){
    yellow++;
    countEl4.value = yellow;
}
function minus4(){
    if (yellow > 0) {
        yellow--;
        countEl4.value = yellow;
    }
}
var gold = 0;
var countEl5 = document.getElementById("gold");
function plus5(){
    gold++;
    countEl5.value = gold;
}
function minus5(){
    if (gold > 0) {
        gold--;
        countEl5.value = gold;
    }
}
var red = 0;
var countEl6 = document.getElementById("red");
function plus6(){
    red++;
    countEl6.value = red;
}
function minus6(){
    if (red > 0) {
        red--;
        countEl6.value = red;
    }
}```
<pre class="snippet-code-css lang-css prettyprint-override"><code>.pyramid {
    clip-path: polygon(50% 0, 100% 100%, 0 100%);
    width: 100vmin;
    aspect-ratio: 9 / 15; /* 2/1 */
    background-color: white;
    display: grid;
    grid-template-columns: 1fr;

}
.pyramid > * {
    background: white;
}
.one {
    background-color: rgba(234, 27, 7, 0.97);
}
.two {
    background-color: rgba(244, 182, 0, 0.98);
    margin-top: 10px;
}
.three {
    background-color: rgba(249, 224, 41, 0.98);
    margin-top: 10px;
}
.four {
    background-color: rgba(4, 157, 252, 0.98);
}
.five {
    background-color: rgba(167, 118, 67, 0.99);
    gap: 0% !important;
}
.six {
    background-color: rgba(92, 213, 51, 0.98);
}
.counter input[type=button], input[type=text] {
    display: inline-block;
    width: 20px;
    background-color: transparent;
    outline: none;
    border: none;
    text-align: center;
    cursor: pointer;
    padding: 0px;
    color: black;
    height: 33px;
    font-family: 'Open Sans';
}
#container {
    width: 100px;
    height: 100px;
    position: relative;
}
#navi,
#infoi {
    width: 100%;
    height: 100%;
    position: absolute;
    top: 0;
    left: 0;
}
#infoi {
    z-index: 10;
}
button {
    border-radius: 50%;
}</code>```

<!DOCTYPE html>

    <meta charset="UTF-8">
    <title>Colour counter</title>
    <link rel="stylesheet" href="css/style.css">

Colour counter

Counter Test

    <input type="button" value="-" id="minus1" onclick="minus1()">
    <input type="text" size="25" value="0" id="green">
    <input type="button" value="+" id="plus1" onclick="plus1()">

    <input type="button" value="-" id="minus2" onclick="minus2()">
    <input type="text" size="25" value="0" id="brown">
    <input type="button" value="+" id="plus2" onclick="plus2()">

```

答:
I have made a variaton adding dinamically colors using an input so you can call any color name you want.

Put the buttons above each color is kinda dificult because you are using a polygon, so in this example the button are in the left side

    <!DOCTYPE html>

      <meta charset="UTF-8">
      <title>Colour counter</title>
      <link rel="stylesheet" href="css/style.css">

Colour counter

        <form>
          Enter the colour name:

          <input id="fcolour" type="text" name="fcolour">

          <input type="button" value="Submit">
        </form>

    ```

Body:
I am making a colour counter application, That has has 6 different colours.

I am currently trying to implement a pure JavaScript counter that has a individual counter for each colour.

(Correction: It is not to count the different colours displayed on the page, but when the user sees a colour in their surrounding environment that matches one of the 6 colours, they increase the counter by 1, for example the user sees the sky is blue and the grass is green, The user hovers over the blue colour, the increase and decrease buttons appear, the user increases the blue colour by 1 increment, Then for the grass the user hovers over the green colour, again the button appears and the user increases the green counter by 1.)

When a user hovers over the colour buttons must appear to increase or decrease the counter by 1, to a minimum of 0.

The count of each colour must always be displayed above the colour.

My current method seems rather long I'm sure there is a way to set up some sort of a method to handle all colours but again to have separate counters for each colour.

Please see the below image for what I am trying to achieve:
See this image

Any help would be appreciated,
I have included my current code below for reference

var green = 0;
var countEl1 = document.getElementById("green");
function plus1(){
    green++;
    countEl1.value = green;
}
function minus1(){
    if (green > 0) {
        green--;
        countEl1.value = green;
    }
}
var brown = 0;
var countEl2 = document.getElementById("brown");
function plus2(){
    brown++;
    countEl2.value = brown;
}
function minus2(){
    if (brown > 0) {
        brown--;
        countEl2.value = brown;
    }
}
var blue = 0;
var countEl3 = document.getElementById("blue");
function plus3(){
    blue++;
    countEl3.value = blue;
}
function minus3(){
    if (blue > 0) {
        blue--;
        countEl3.value = blue;
    }
}
var yellow = 0;
var countEl4 = document.getElementById("yellow");
function plus4(){
    yellow++;
    countEl4.value = yellow;
}
function minus4(){
    if (yellow > 0) {
        yellow--;
        countEl4.value = yellow;
    }
}
var gold = 0;
var countEl5 = document.getElementById("gold");
function plus5(){
    gold++;
    countEl5.value = gold;
}
function minus5(){
    if (gold > 0) {
        gold--;
        countEl5.value = gold;
    }
}
var red = 0;
var countEl6 = document.getElementById("red");
function plus6(){
    red++;
    countEl6.value = red;
}
function minus6(){
    if (red > 0) {
        red--;
        countEl6.value = red;
    }
}

.pyramid {
    clip-path: polygon(50% 0, 100% 100%, 0 100%);
    width: 100vmin;
    aspect-ratio: 9 / 15; /* 2/1 */
    background-color: white;
    display: grid;
    grid-template-columns: 1fr;

}
.pyramid > * {
    background: white;
}
.one {
    background-color: rgba(234, 27, 7, 0.97);
}
.two {
    background-color: rgba(244, 182, 0, 0.98);
    margin-top: 10px;
}
.three {
    background-color: rgba(249, 224, 41, 0.98);
    margin-top: 10px;
}
.four {
    background-color: rgba(4, 157, 252, 0.98);
}
.five {
    background-color: rgba(167, 118, 67, 0.99);
    gap: 0% !important;
}
.six {
    background-color: rgba(92, 213, 51, 0.98);
}
.counter input[type=button], input[type=text] {
    display: inline-block;
    width: 20px;
    background-color: transparent;
    outline: none;
    border: none;
    text-align: center;
    cursor: pointer;
    padding: 0px;
    color: black;
    height: 33px;
    font-family: 'Open Sans';
}
#container {
    width: 100px;
    height: 100px;
    position: relative;
}
#navi,
#infoi {
    width: 100%;
    height: 100%;
    position: absolute;
    top: 0;
    left: 0;
}
#infoi {
    z-index: 10;
}
button {
    border-radius: 50%;
}

<!DOCTYPE html>

    <meta charset="UTF-8">
    <title>Colour counter</title>
    <link rel="stylesheet" href="css/style.css">

Colour counter

Counter Test

    <input type="button" value="-" id="minus1" onclick="minus1()">
    <input type="text" size="25" value="0" id="green">
    <input type="button" value="+" id="plus1" onclick="plus1()">

    <input type="button" value="-" id="minus2" onclick="minus2()">
    <input type="text" size="25" value="0" id="brown">
    <input type="button" value="+" id="plus2" onclick="plus2()">

Body:
I have made a variaton adding dinamically colors using an input so you can call any color name you want.

Put the buttons above each color is kinda dificult because you are using a polygon, so in this example the button are in the left side

    <!DOCTYPE html>
    <html lang="en">

    <head>
      <meta charset="UTF-8">
      <title>Colour counter</title>
      <link rel="stylesheet" href="css/style.css">
      <script src="js/Main.js"></script>

      <style>
        .grid {
          display: flex;
          text-align: center;
          max-width: 480px;
        }

        .grid .counter {
          margin-right: 15px;
        }

        .counter .column {
          text-align: center;
          vertical-align: middle;
        }

        .column {
          height: 100px;
          width: 100px;
          display: flex;
          align-content: center;
          justify-content: center;
          align-items: center;
        }

        .form {
          margin: 10px 0;
        }

        .form input[type='text'] {
          margin: 3px 0;
          border: 1px solid black;
          width: 200px;
        }

        input[type='button'] {
          border: 1px solid black;
          margin: 0 4px;
        }

        .pyramid {
          clip-path: polygon(50% 0, 100% 100%, 0 100%);
          width: 300px;
          aspect-ratio: 9 / 15;
          /* 2/1 */
          background-color: white;
          display: grid;
          grid-template-columns: 1fr;

        }

        .pyramid>* {
          background: white;
        }

        .counter input[type=button],
        input[type=text] {
          display: inline-block;
          width: 20px;
          background-color: transparent;
          outline: none;
          border: none;
          text-align: center;
          cursor: pointer;
          padding: 0px;
          color: black;
          height: 33px;
          font-family: 'Open Sans';
        }

        #container {
          width: 100px;
          height: 100px;
          position: relative;
        }

        button {
          border-radius: 50%;
        }
      </style>

    </head>

    <body>
      <div class="color-counter">
        <h1>Colour counter</h1>
      </div>

      <div class="form">
        <form>
          <label for="fcolour">Enter the colour name: </label>
          <br>
          <input id="fcolour" type="text" name="fcolour">
          <br>
          <input type="button" value="Submit">
        </form>
      </div>

      <div id="container">

        <div class="grid">
          <div class="counter">
          </div>
          <div class="pyramid">
          </div>
        </div>

      </div>

      <script>

        document.querySelector('form input[type="button"]').addEventListener('click', function (e) {
          var colCounter = document.querySelector('.grid .counter')
          var colPyramid = document.querySelector('.grid .pyramid')
          var colorName = document.getElementById('fcolour').value

          var newCounterChild = document.createElement('div')
          newCounterChild.classList.add('column')
          newCounterChild.innerHTML = `
            <input type="button" value="-" id="minus_${colorName}">
            <input type="text" size="25" value="0" id=counter_${colorName}>
            <input type="button" value="+" id="plus_${colorName}">
          `

          colCounter.appendChild(newCounterChild)

          var newPyramidChild = document.createElement('div')
          newPyramidChild.classList.add('column')
          newPyramidChild.style.backgroundColor = colorName
          newPyramidChild.style.marginTop = '10px'

          colPyramid.appendChild(newPyramidChild)

          document.getElementById(`plus_${colorName}`).addEventListener('click', function (v) {
            document.getElementById(`counter_${colorName}`).value++
          })

          document.getElementById(`minus_${colorName}`).addEventListener('click', function (v) {
            var val = document.getElementById(`counter_${colorName}`)
            val.value > 0 ? val.value-- : null
          })

        })

      </script>

    </body>


问:
Query with OData URL
I want write a query as URL to order by a column in OData URL descending format.

My data has a '_id' column in JSON format.

I tried the URL in below but it does not work. It showed me just first row in JSON format but I want to see the biggest id in JSON format.

```<code>https://HOSTNAME/en/datastore/odata3.0/7aec630d-2757-4da0-97f1-71b140abd818?$orderby=MAX(_id)&$format=json&$top=1
</code>```

答:
Your implementation looks like an OData v3 compliant API.

10.2.3.3 The $orderby System Query Option

The $orderby System Query option specifies the order in which entities are returned from the service.

The value of the $orderby System Query option contains a comma separated list of property navigation paths to sort by, where each property navigation path terminates on a primitive property.

A type cast using the qualified entity type name is required to order by a property defined on a derived type.

The property name MAY include the suffix “asc” for ascending or “desc” for descending, separated from the property name by one or more spaces. If “asc” or “desc” is not specified, the service MUST order by the specified property in ascending order.

Therefore, to order by _id in descending order, you should use this segment:

$orderby=_id desc

In which case the URL would be similar to:

```<code>https://HOSTNAME/en/datastore/odata3.0/7aec630d-2757-4da0-97f1-71b140abd818?$orderby=_id desc&$format=json&$top=1
</code>```

Using the Max() function is not a known OData convention for ordering. If Max() was going to do anything it would evalutate to the same value for all records, the max value in the table, and would therefore not afect the ordering at all.

Title: Query with OData URL

Body:
I want write a query as URL to order by a column in OData URL descending format.

My data has a '_id' column in JSON format.

I tried the URL in below but it does not work. It showed me just first row in JSON format but I want to see the biggest id in JSON format.

https://HOSTNAME/en/datastore/odata3.0/7aec630d-2757-4da0-97f1-71b140abd818?$orderby=MAX(_id)&$format=json&$top=1

Body:
Your implementation looks like an OData v3 compliant API.

10.2.3.3 The $orderby System Query Option

The $orderby System Query option specifies the order in which entities are returned from the service.

The value of the $orderby System Query option contains a comma separated list of property navigation paths to sort by, where each property navigation path terminates on a primitive property.

A type cast using the qualified entity type name is required to order by a property defined on a derived type.

The property name MAY include the suffix “asc” for ascending or “desc” for descending, separated from the property name by one or more spaces. If “asc” or “desc” is not specified, the service MUST order by the specified property in ascending order.

Therefore, to order by _id in descending order, you should use this segment:

$orderby=_id desc

In which case the URL would be similar to:

https://HOSTNAME/en/datastore/odata3.0/7aec630d-2757-4da0-97f1-71b140abd818?$orderby=_id desc&$format=json&$top=1

Using the Max() function is not a known OData convention for ordering. If Max() was going to do anything it would evalutate to the same value for all records, the max value in the table, and would therefore not afect the ordering at all.


问:
Remove chromedriver prompt NightwatchJS
When I run my NightwatchJS tests npx nightwatch I seem to have the chromedriver prompt open alongside the browser. The test suite proceeds to press the buttons and assert elements correctly but I have to minimise the prompt in order to see what's going myself. Is there any way I can prevent it from appearing in the first place and only have the browser open?

My nightwatch.conf.js file:

```<code>// Autogenerated by Nightwatch
// Refer to the online docs for more details: https://nightwatchjs.org/gettingstarted/configuration/
const Services = {}; loadServices();

//  _   _  _         _      _                     _          _
// | \ | |(_)       | |    | |                   | |        | |
// |  \| | _   __ _ | |__  | |_ __      __  __ _ | |_   ___ | |__
// | . ` || | / _` || '_ \ | __|\ \ /\ / / / _` || __| / __|| '_ \
// | |\  || || (_| || | | || |_  \ V  V / | (_| || |_ | (__ | | | |
// \_| \_/|_| \__, ||_| |_| \__|  \_/\_/   \__,_| \__| \___||_| |_|
//             __/ |
//            |___/

module.exports = {
  // An array of folders (excluding subfolders) where your tests are located;
  // if this is not specified, the test source must be passed as the second argument to the test runner.
  src_folders: ['./tests'],

  // See https://nightwatchjs.org/guide/working-with-page-objects/
  page_objects_path: ['node_modules/nightwatch/examples/pages/'],

  // See https://nightwatchjs.org/guide/extending-nightwatch/#writing-custom-commands
  custom_commands_path: ['node_modules/nightwatch/examples/custom-commands/'],

  // See https://nightwatchjs.org/guide/extending-nightwatch/#writing-custom-assertions
  custom_assertions_path: '',

  // See https://nightwatchjs.org/guide/#external-globals
  globals_path : '',

  webdriver: {},

  test_settings: {
    default: {
      disable_error_log: false,
      launch_url: 'https://nightwatchjs.org',

      screenshots: {
        enabled: false,
        path: 'screens',
        on_failure: true
      },

      desiredCapabilities: {
        browserName : 'chrome'
      },

      webdriver: {
        start_process: true,
        server_path: ''
      }
    },

    firefox: {
      desiredCapabilities : {
        browserName : 'firefox',
        alwaysMatch: {
          acceptInsecureCerts: true,
          'moz:firefoxOptions': {
            args: [
              // '-headless',
              // '-verbose'
            ]
          }
        }
      },
      webdriver: {
        start_process: true,
        server_path: '',
        cli_args: [
          // very verbose geckodriver logs
          // '-vv'
        ]
      }
    },

    chrome: {
      desiredCapabilities : {
        browserName : 'chrome',
        'goog:chromeOptions' : {
          // More info on Chromedriver: https://sites.google.com/a/chromium.org/chromedriver/
          //
          // w3c:false tells Chromedriver to run using the legacy JSONWire protocol (not required in Chrome 78)
          w3c: true,
          args: [
            //'--no-sandbox',
            //'--ignore-certificate-errors',
            //'--allow-insecure-localhost',
            //'--headless'
          ]
        }
      },

      webdriver: {
        start_process: true,
        server_path: '',
        cli_args: [
          // --verbose
        ]
      }
    },

    edge: {
      desiredCapabilities : {
        browserName : 'MicrosoftEdge',
        'ms:edgeOptions' : {
          w3c: true,
          // More info on EdgeDriver: https://learn.microsoft.com/en-us/microsoft-edge/webdriver-chromium/capabilities-edge-options
          args: [
            //'--headless'
          ]
        }
      },

      webdriver: {
        start_process: true,
        // Download msedgedriver from https://learn.microsoft.com/en-us/microsoft-edge/webdriver-chromium/
        //  and set the location below:
        server_path: '',
        cli_args: [
          // --verbose
        ]
      }
    },

    //////////////////////////////////////////////////////////////////////////////////
    // Configuration for when using cucumber-js (https://cucumber.io)                |
    //                                                                               |
    // It uses the bundled examples inside the nightwatch examples folder; feel free |
    // to adapt this to your own project needs                                       |
    //////////////////////////////////////////////////////////////////////////////////
    'cucumber-js': {
      src_folders: ['examples/cucumber-js/features/step_definitions'],

      test_runner: {
        // set cucumber as the runner
        type: 'cucumber',

        // define cucumber specific options
        options: {
          //set the feature path
          feature_path: 'node_modules/nightwatch/examples/cucumber-js/*/*.feature',

          // start the webdriver session automatically (enabled by default)
          // auto_start_session: true

          // use parallel execution in Cucumber
          // parallel: 2 // set number of workers to use (can also be defined in the cli as --parallel 2
        }
      }
    },

    //////////////////////////////////////////////////////////////////////////////////
    // Configuration for when using the browserstack.com cloud service               |
    //                                                                               |
    // Please set the username and access key by setting the environment variables:  |
    // - BROWSERSTACK_USER                                                           |
    // - BROWSERSTACK_KEY                                                            |
    // .env files are supported                                                      |
    //////////////////////////////////////////////////////////////////////////////////
    browserstack: {
      selenium: {
        host: 'hub-cloud.browserstack.com',
        port: 443
      },
      // More info on configuring capabilities can be found on:
      // https://www.browserstack.com/automate/capabilities?tag=selenium-4
      desiredCapabilities: {
        'bstack:options' : {
          userName: '${BROWSERSTACK_USER}',
          accessKey: '${BROWSERSTACK_KEY}',
        }
      },

      disable_error_log: true,
      webdriver: {
        timeout_options: {
          timeout: 15000,
          retry_attempts: 3
        },
        keep_alive: true,
        start_process: false
      }
    },

    'browserstack.local': {
      extends: 'browserstack',
      desiredCapabilities: {
        'browserstack.local': true
      }
    },

    'browserstack.chrome': {
      extends: 'browserstack',
      desiredCapabilities: {
        browserName: 'chrome',
        chromeOptions : {
          w3c: true
        }
      }
    },

    'browserstack.firefox': {
      extends: 'browserstack',
      desiredCapabilities: {
        browserName: 'firefox'
      }
    },

    'browserstack.ie': {
      extends: 'browserstack',
      desiredCapabilities: {
        browserName: 'internet explorer',
        browserVersion: '11.0'
      }
    },

    'browserstack.safari': {
      extends: 'browserstack',
      desiredCapabilities: {
        browserName: 'safari'
      }
    },

    'browserstack.local_chrome': {
      extends: 'browserstack.local',
      desiredCapabilities: {
        browserName: 'chrome'
      }
    },

    'browserstack.local_firefox': {
      extends: 'browserstack.local',
      desiredCapabilities: {
        browserName: 'firefox'
      }
    },
    //////////////////////////////////////////////////////////////////////////////////
    // Configuration for when using the Selenium service, either locally or remote,  |
    //  like Selenium Grid                                                           |
    //////////////////////////////////////////////////////////////////////////////////
    selenium_server: {
      // Selenium Server is running locally and is managed by Nightwatch
      selenium: {
        start_process: true,
        port: 4444,
        server_path: (Services.seleniumServer ? Services.seleniumServer.path : ''),
        cli_args: {
          'webdriver.gecko.driver': (Services.geckodriver ? Services.geckodriver.path : ''),
          'webdriver.chrome.driver': (Services.chromedriver ? Services.chromedriver.path : '')
        }
      }
    },

    'selenium.chrome': {
      extends: 'selenium_server',
      desiredCapabilities: {
        browserName: 'chrome',
        chromeOptions : {
          w3c: true
        }
      }
    },

    'selenium.firefox': {
      extends: 'selenium_server',
      desiredCapabilities: {
        browserName: 'firefox',
        'moz:firefoxOptions': {
          args: [
            // '-headless',
            // '-verbose'
          ]
        }
      }
    }
  }
};

function loadServices() {
  try {
    Services.seleniumServer = require('selenium-server');
  } catch (err) {}

  try {
    Services.chromedriver = require('chromedriver');
  } catch (err) {}

  try {
    Services.geckodriver = require('geckodriver');
  } catch (err) {}
}
</code>```

答: I had this issue and I fixed it by updating versions and downgrading Nightwatch versions. Also please update the chrome driver. Try to use 2.0 alpha. It won't persist I believe.</p>

Title: Remove chromedriver prompt NightwatchJS

Body:
When I run my NightwatchJS tests npx nightwatch I seem to have the chromedriver prompt open alongside the browser. The test suite proceeds to press the buttons and assert elements correctly but I have to minimise the prompt in order to see what's going myself. Is there any way I can prevent it from appearing in the first place and only have the browser open?

My nightwatch.conf.js file:

// Autogenerated by Nightwatch
// Refer to the online docs for more details: https://nightwatchjs.org/gettingstarted/configuration/
const Services = {}; loadServices();

//  _   _  _         _      _                     _          _
// | \ | |(_)       | |    | |                   | |        | |
// |  \| | _   __ _ | |__  | |_ __      __  __ _ | |_   ___ | |__
// | . ` || | / _` || '_ \ | __|\ \ /\ / / / _` || __| / __|| '_ \
// | |\  || || (_| || | | || |_  \ V  V / | (_| || |_ | (__ | | | |
// \_| \_/|_| \__, ||_| |_| \__|  \_/\_/   \__,_| \__| \___||_| |_|
//             __/ |
//            |___/

module.exports = {
  // An array of folders (excluding subfolders) where your tests are located;
  // if this is not specified, the test source must be passed as the second argument to the test runner.
  src_folders: ['./tests'],

  // See https://nightwatchjs.org/guide/working-with-page-objects/
  page_objects_path: ['node_modules/nightwatch/examples/pages/'],

  // See https://nightwatchjs.org/guide/extending-nightwatch/#writing-custom-commands
  custom_commands_path: ['node_modules/nightwatch/examples/custom-commands/'],

  // See https://nightwatchjs.org/guide/extending-nightwatch/#writing-custom-assertions
  custom_assertions_path: '',

  // See https://nightwatchjs.org/guide/#external-globals
  globals_path : '',

  webdriver: {},

  test_settings: {
    default: {
      disable_error_log: false,
      launch_url: 'https://nightwatchjs.org',

      screenshots: {
        enabled: false,
        path: 'screens',
        on_failure: true
      },

      desiredCapabilities: {
        browserName : 'chrome'
      },

      webdriver: {
        start_process: true,
        server_path: ''
      }
    },

    firefox: {
      desiredCapabilities : {
        browserName : 'firefox',
        alwaysMatch: {
          acceptInsecureCerts: true,
          'moz:firefoxOptions': {
            args: [
              // '-headless',
              // '-verbose'
            ]
          }
        }
      },
      webdriver: {
        start_process: true,
        server_path: '',
        cli_args: [
          // very verbose geckodriver logs
          // '-vv'
        ]
      }
    },

    chrome: {
      desiredCapabilities : {
        browserName : 'chrome',
        'goog:chromeOptions' : {
          // More info on Chromedriver: https://sites.google.com/a/chromium.org/chromedriver/
          //
          // w3c:false tells Chromedriver to run using the legacy JSONWire protocol (not required in Chrome 78)
          w3c: true,
          args: [
            //'--no-sandbox',
            //'--ignore-certificate-errors',
            //'--allow-insecure-localhost',
            //'--headless'
          ]
        }
      },

      webdriver: {
        start_process: true,
        server_path: '',
        cli_args: [
          // --verbose
        ]
      }
    },

    edge: {
      desiredCapabilities : {
        browserName : 'MicrosoftEdge',
        'ms:edgeOptions' : {
          w3c: true,
          // More info on EdgeDriver: https://learn.microsoft.com/en-us/microsoft-edge/webdriver-chromium/capabilities-edge-options
          args: [
            //'--headless'
          ]
        }
      },

      webdriver: {
        start_process: true,
        // Download msedgedriver from https://learn.microsoft.com/en-us/microsoft-edge/webdriver-chromium/
        //  and set the location below:
        server_path: '',
        cli_args: [
          // --verbose
        ]
      }
    },

    //////////////////////////////////////////////////////////////////////////////////
    // Configuration for when using cucumber-js (https://cucumber.io)                |
    //                                                                               |
    // It uses the bundled examples inside the nightwatch examples folder; feel free |
    // to adapt this to your own project needs                                       |
    //////////////////////////////////////////////////////////////////////////////////
    'cucumber-js': {
      src_folders: ['examples/cucumber-js/features/step_definitions'],

      test_runner: {
        // set cucumber as the runner
        type: 'cucumber',

        // define cucumber specific options
        options: {
          //set the feature path
          feature_path: 'node_modules/nightwatch/examples/cucumber-js/*/*.feature',

          // start the webdriver session automatically (enabled by default)
          // auto_start_session: true

          // use parallel execution in Cucumber
          // parallel: 2 // set number of workers to use (can also be defined in the cli as --parallel 2
        }
      }
    },

    //////////////////////////////////////////////////////////////////////////////////
    // Configuration for when using the browserstack.com cloud service               |
    //                                                                               |
    // Please set the username and access key by setting the environment variables:  |
    // - BROWSERSTACK_USER                                                           |
    // - BROWSERSTACK_KEY                                                            |
    // .env files are supported                                                      |
    //////////////////////////////////////////////////////////////////////////////////
    browserstack: {
      selenium: {
        host: 'hub-cloud.browserstack.com',
        port: 443
      },
      // More info on configuring capabilities can be found on:
      // https://www.browserstack.com/automate/capabilities?tag=selenium-4
      desiredCapabilities: {
        'bstack:options' : {
          userName: '${BROWSERSTACK_USER}',
          accessKey: '${BROWSERSTACK_KEY}',
        }
      },

      disable_error_log: true,
      webdriver: {
        timeout_options: {
          timeout: 15000,
          retry_attempts: 3
        },
        keep_alive: true,
        start_process: false
      }
    },

    'browserstack.local': {
      extends: 'browserstack',
      desiredCapabilities: {
        'browserstack.local': true
      }
    },

    'browserstack.chrome': {
      extends: 'browserstack',
      desiredCapabilities: {
        browserName: 'chrome',
        chromeOptions : {
          w3c: true
        }
      }
    },

    'browserstack.firefox': {
      extends: 'browserstack',
      desiredCapabilities: {
        browserName: 'firefox'
      }
    },

    'browserstack.ie': {
      extends: 'browserstack',
      desiredCapabilities: {
        browserName: 'internet explorer',
        browserVersion: '11.0'
      }
    },

    'browserstack.safari': {
      extends: 'browserstack',
      desiredCapabilities: {
        browserName: 'safari'
      }
    },

    'browserstack.local_chrome': {
      extends: 'browserstack.local',
      desiredCapabilities: {
        browserName: 'chrome'
      }
    },

    'browserstack.local_firefox': {
      extends: 'browserstack.local',
      desiredCapabilities: {
        browserName: 'firefox'
      }
    },
    //////////////////////////////////////////////////////////////////////////////////
    // Configuration for when using the Selenium service, either locally or remote,  |
    //  like Selenium Grid                                                           |
    //////////////////////////////////////////////////////////////////////////////////
    selenium_server: {
      // Selenium Server is running locally and is managed by Nightwatch
      selenium: {
        start_process: true,
        port: 4444,
        server_path: (Services.seleniumServer ? Services.seleniumServer.path : ''),
        cli_args: {
          'webdriver.gecko.driver': (Services.geckodriver ? Services.geckodriver.path : ''),
          'webdriver.chrome.driver': (Services.chromedriver ? Services.chromedriver.path : '')
        }
      }
    },

    'selenium.chrome': {
      extends: 'selenium_server',
      desiredCapabilities: {
        browserName: 'chrome',
        chromeOptions : {
          w3c: true
        }
      }
    },

    'selenium.firefox': {
      extends: 'selenium_server',
      desiredCapabilities: {
        browserName: 'firefox',
        'moz:firefoxOptions': {
          args: [
            // '-headless',
            // '-verbose'
          ]
        }
      }
    }
  }
};

function loadServices() {
  try {
    Services.seleniumServer = require('selenium-server');
  } catch (err) {}

  try {
    Services.chromedriver = require('chromedriver');
  } catch (err) {}

  try {
    Services.geckodriver = require('geckodriver');
  } catch (err) {}
}


问:
Python - os.getcwd() doesn't return the full path
At the start of the file, I specified the path using:

```<code>path = r"C:\Documents\Data"
os.chdir(path)
</code>```

Later on, I want to iterate through subfolders in the Data folder. This folder contains 2018, which contains Level2A. I do this with:

```<code>for root, subdirectories, files in os.walk(path):
        for filename in subdirectories:
            if filename.endswith('.SAFE'):
                print(filename)
                print(os.getcwd())
</code>```

When printing the subfolder's name, it works; it prints folder_name.SAFE. When I, however want to print the path which it's currently looking at, I get the following:

```<code>print(os.getcwd())
>>> C:\Documents\Data
</code>```

Why do I not get C:\Documents\Data\2018\Level2A whose file I printed is? What do I have to change to do get this?

答:
os.getcwd() returns the current working directory and that is the directory you changed into using os.chdir()

To get the folder of the file, we can look at the docs of os.walk():

it yields a 3-tuple (dirpath, dirnames, filenames)

and

To get a full path (which begins with top) to a file or directory in dirpath, do os.path.join(dirpath, name).

So in your case, try:

print(os.path.join(root, filename))
```

Also, check out the newer Pathlib module

Body:
At the start of the file, I specified the path using:

path = r"C:\Documents\Data"
os.chdir(path)

Later on, I want to iterate through subfolders in the Data folder. This folder contains 2018, which contains Level2A. I do this with:

for root, subdirectories, files in os.walk(path):
        for filename in subdirectories:
            if filename.endswith('.SAFE'):
                print(filename)
                print(os.getcwd())

When printing the subfolder's name, it works; it prints folder_name.SAFE. When I, however want to print the path which it's currently looking at, I get the following:

print(os.getcwd())
>>> C:\Documents\Data

Why do I not get C:\Documents\Data\2018\Level2A whose file I printed is? What do I have to change to do get this?

Body:
os.getcwd() returns the current working directory and that is the directory you changed into using os.chdir()

To get the folder of the file, we can look at the docs of os.walk():

it yields a 3-tuple (dirpath, dirnames, filenames)

and

To get a full path (which begins with top) to a file or directory in dirpath, do os.path.join(dirpath, name).

So in your case, try:

print(os.path.join(root, filename))

Also, check out the newer Pathlib module


问:
Creating link table to connect one to one relationship of same model
I want to make sure table join with joining table has strong one-to-one relationship. Following is example
Run generator

```<code>bundle exec rails g model Page name:string content:text
bundle exec rails g model PageAssociation left_page_id:integer right_page_id:integer
</code>```

After running these generator, I have to change my page model following

```<code>class Page < ApplicationRecord
  has_one :left_page_association, :foreign_key => :left_page_id,
           :class_name => 'PageAssociation'
  has_one :right_page_association, :foreign_key => :right_page_id,
           :class_name => 'PageAssociation'
  has_one :left_page, :through => :left_page_association,
           :source => :right_page
  has_one :right_page, :through => :right_page_association,
           :source => :left_page
end
</code>```

In my association table model page_association

```<code>class PageAssociation < ApplicationRecord
  belongs_to :left_page, class_name: 'Page'
  belongs_to :right_page, class_name: 'Page'
end
</code>```

Now using rails c I can do following

```<code>page_one = Page.create(name: 'first page', content: 'first page content')
page_two = Page.create(name: 'second page', content: 'second page content')
PageAssociation.create(left_page: page_one, right_page: page_two)
page_one.left_page
page_two.right_page
</code>```

All working fine and it is returning pages. but I can do also this

```<code>page_three = Page.create(name: 'third page', content: 'third page content')
PageAssociation.create(left_page: page_one, right_page: page_three)
</code>```

Of course it still shows on relationship due to has_one but it is creating another relationship. So I want following

Only one association can be created and it should not allow another one

What is best way to do this as we have million of records

Is it one to use page.left_page? or is there any other optimised way to do same thing.

Should I add indexing using following migration lines. Does it effect performance.

```<code>add_foreign_key :page_associations, :pages, column: :left_page_id
add_foreign_key :page_associations, :pages, column: :right_page_id
</code>```

I changed migration to make column value unique, so it now give error when I create another PageAssociate with same page.id but is it right way?

```<code>      t.integer :left_page_id, null: false, index: { unique: true }
      t.integer :right_page_id, null: false, index: { unique: true }
</code>```

what problem I am solving

So I have books table where I have multiple books, but some books borrow pages from one another. So suppose I have book-A and book-B so I want to show relationship of book-a to book-b. If they are related then I will create another relationship of book-a page-10 linked to book-b page 20, so when I click on book-a to synchronise, it will bring all changes of book-b page 20 in my book-a.
So above is my first step to connected two books. I understand solving it using self join and keys is best but I can't do as we have huge number of records so that is not possible. So I have used above method to do it. But I did add unique constraints on db and validations in model to solve it. but I feel it is still not good way of doing it.
later one I will make following

```<code>main-book , main-book-page, secondary-book-page

</code>```

This will allow me to bound later pages each other. The name book and pages are fictions, actually entities are different.

答:
What you want here is really just a normal many to many table setup:

```<code>class Book < ApplicationRecord
  has_many :book_pages
  has_many :pages, through: :book_pages
end

class Page < ApplicationRecord
  has_many :book_pages
  has_many :books, through: :book_pages
end

class BookPage < ApplicationRecord
  belongs_to :book
  belongs_to :page
  validates_uniqueness_of :book_id, scope: :page_id
end
</code>```

Uniqueness in this case can be guarenteed by adding a unique index:

```<code>add_index :book_pages, [:book_id, :page_id]
</code>```

Why?

M2M join table setups where you have two foreign keys that are assigned arbitrarily  are not a very good design and don't work well with ActiveRecord since you can't define assocations with an OR clause.

Each association can only have a single foreign key. This means that you can't treat it as a homogenius collection and cannot eager load it.

That means you need to write crappy joins like this instead of being able to work with a proper assocation:

Book.joins(
  "LEFT JOIN pages_assocations pa ON pa.left_page_id = books.id OR pa.left_page_id = books.id"
)
```
<p>And you also have to write steaming piles when creating indirect assocations.</p>
<p>While the table setup with a single row per book/page combo may seem to require more rows on the onset its also much more flexible as you can map out the assocations between books by subqueries, lateral joins or grouping and counting the number of matches.</p>
<pre class="lang-ruby prettyprint-override"><code>class Book < ApplicationRecord
  has_many :book_pages
  has_many :pages, through: :book_pages

  def books_with_pages_in_common
     Book.where(
        id: BookPage.select(:book_id)
                    .where(page_id: pages)
     )
  end
end
</code>```

Body:
I want to make sure table join with joining table has strong one-to-one relationship. Following is example
Run generator

bundle exec rails g model Page name:string content:text
bundle exec rails g model PageAssociation left_page_id:integer right_page_id:integer

After running these generator, I have to change my page model following

class Page < ApplicationRecord
  has_one :left_page_association, :foreign_key => :left_page_id,
           :class_name => 'PageAssociation'
  has_one :right_page_association, :foreign_key => :right_page_id,
           :class_name => 'PageAssociation'
  has_one :left_page, :through => :left_page_association,
           :source => :right_page
  has_one :right_page, :through => :right_page_association,
           :source => :left_page
end

In my association table model page_association

class PageAssociation < ApplicationRecord
  belongs_to :left_page, class_name: 'Page'
  belongs_to :right_page, class_name: 'Page'
end

Now using rails c I can do following

page_one = Page.create(name: 'first page', content: 'first page content')
page_two = Page.create(name: 'second page', content: 'second page content')
PageAssociation.create(left_page: page_one, right_page: page_two)
page_one.left_page
page_two.right_page

All working fine and it is returning pages. but I can do also this

page_three = Page.create(name: 'third page', content: 'third page content')
PageAssociation.create(left_page: page_one, right_page: page_three)

Of course it still shows on relationship due to has_one but it is creating another relationship. So I want following

Only one association can be created and it should not allow another one

What is best way to do this as we have million of records

Is it one to use page.left_page? or is there any other optimised way to do same thing.

Should I add indexing using following migration lines. Does it effect performance.

add_foreign_key :page_associations, :pages, column: :left_page_id
add_foreign_key :page_associations, :pages, column: :right_page_id

I changed migration to make column value unique, so it now give error when I create another PageAssociate with same page.id but is it right way?

      t.integer :left_page_id, null: false, index: { unique: true }
      t.integer :right_page_id, null: false, index: { unique: true }

what problem I am solving

So I have books table where I have multiple books, but some books borrow pages from one another. So suppose I have book-A and book-B so I want to show relationship of book-a to book-b. If they are related then I will create another relationship of book-a page-10 linked to book-b page 20, so when I click on book-a to synchronise, it will bring all changes of book-b page 20 in my book-a.
So above is my first step to connected two books. I understand solving it using self join and keys is best but I can't do as we have huge number of records so that is not possible. So I have used above method to do it. But I did add unique constraints on db and validations in model to solve it. but I feel it is still not good way of doing it.
later one I will make following

main-book , main-book-page, secondary-book-page

This will allow me to bound later pages each other. The name book and pages are fictions, actually entities are different.

Body:
What you want here is really just a normal many to many table setup:

class Book < ApplicationRecord
  has_many :book_pages
  has_many :pages, through: :book_pages
end

class Page < ApplicationRecord
  has_many :book_pages
  has_many :books, through: :book_pages
end

class BookPage < ApplicationRecord
  belongs_to :book
  belongs_to :page
  validates_uniqueness_of :book_id, scope: :page_id
end

Uniqueness in this case can be guarenteed by adding a unique index:

add_index :book_pages, [:book_id, :page_id]

Why?

M2M join table setups where you have two foreign keys that are assigned arbitrarily  are not a very good design and don't work well with ActiveRecord since you can't define assocations with an OR clause.

Each association can only have a single foreign key. This means that you can't treat it as a homogenius collection and cannot eager load it.

That means you need to write crappy joins like this instead of being able to work with a proper assocation:

Book.joins(
  "LEFT JOIN pages_assocations pa ON pa.left_page_id = books.id OR pa.left_page_id = books.id"
)

And you also have to write steaming piles when creating indirect assocations.

While the table setup with a single row per book/page combo may seem to require more rows on the onset its also much more flexible as you can map out the assocations between books by subqueries, lateral joins or grouping and counting the number of matches.

class Book < ApplicationRecord
  has_many :book_pages
  has_many :pages, through: :book_pages

  def books_with_pages_in_common
     Book.where(
        id: BookPage.select(:book_id)
                    .where(page_id: pages)
     )
  end
end