问:
Saving Core Data From Multiple TableVIews
I have an app that has multiple tableviews and I want to use Core Data to capture all the data.  I have two entities - freezers and items.  In the first tableview I add a freezer and it saves correctly. I quit the app, re-open, and it is there.  I click on the freezer (opening another tableview) and add some items and I can see them in my new sectioned tableview.  I quit my app, restart it, see the freezer, click on it and there are no items.

I have my managedObjectContext in my appDelegate and reference it from there using all views, so I am not creating multiple instances.  Here is the code I use to save the items to a freezer, both the managedObjectContext and my itemsArray:

```<code>Item *item = (Item *)[NSEntityDescription insertNewObjectForEntityForName:@"Item" inManagedObjectContext:[delegate managedObjectContext]];
    [item setFreezer:freezerName];
    [item setName:name];
    [item setQuantity:quantity];
    [item setSection:section];
    [item setAdded:added];
    [item setNotes:notes];

    NSError *error = nil;
    if (![[delegate managedObjectContext] save:&error]) {
        NSLog(@"Freezer info didn't save.  Need to handle this.");
    }

    [items insertObject:item atIndex:0];
</code>```

Here is the code I use in the ItemViewController to retrieve the items within viewDidLoad:

```<code> NSFetchRequest *request = [[NSFetchRequest alloc] init];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"freezer == '%@'", freezerName];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Item" inManagedObjectContext:[delegate managedObjectContext]];
    NSSortDescriptor *sorts = [[NSSortDescriptor alloc] initWithKey:@"section" ascending:NO];
    NSArray *sort = [[NSArray alloc] initWithObjects:sorts, nil];

    [request setSortDescriptors:sort];
    [request setEntity:entity];
    [request setPredicate:predicate];

    NSError *error = nil;

    NSMutableArray *results = [[[delegate managedObjectContext] executeFetchRequest:request error:&error] mutableCopy];
    if(results == nil) {
        NSLog(@"Error fetching results... need to handle");
    }

    [self setItems:results];

    NSLog(@"items count:%d", [items count]);
</code>```

The item count returned is zero.

I am completely stumped and have spent several hours searching online, trying different things, and I can't figure it out.  I know there are some much smarter coders out there and I hope one of you can see what the problem is.

答:
Maybe the problem is that you load data in

```<code>- viewDidLoad:
</code>```

method. It's called only once when your view is loaded, so when underlaying data get's changed, your view controller is not aware about it.

You can either move your loading code to

```<code>- viewWillAppear:
</code>```

method or introduce notifications to spread the information that data store has changed its state and reload table views upon that event.

The best way is probably to use NSFetchedResultsController as your data source, as its always aware of its data store changes. Check docs for reference to that class.

Body:
I have an app that has multiple tableviews and I want to use Core Data to capture all the data.  I have two entities - freezers and items.  In the first tableview I add a freezer and it saves correctly. I quit the app, re-open, and it is there.  I click on the freezer (opening another tableview) and add some items and I can see them in my new sectioned tableview.  I quit my app, restart it, see the freezer, click on it and there are no items.

I have my managedObjectContext in my appDelegate and reference it from there using all views, so I am not creating multiple instances.  Here is the code I use to save the items to a freezer, both the managedObjectContext and my itemsArray:

Item *item = (Item *)[NSEntityDescription insertNewObjectForEntityForName:@"Item" inManagedObjectContext:[delegate managedObjectContext]];
    [item setFreezer:freezerName];
    [item setName:name];
    [item setQuantity:quantity];
    [item setSection:section];
    [item setAdded:added];
    [item setNotes:notes];

    NSError *error = nil;
    if (![[delegate managedObjectContext] save:&error]) {
        NSLog(@"Freezer info didn't save.  Need to handle this.");
    }

    [items insertObject:item atIndex:0];

Here is the code I use in the ItemViewController to retrieve the items within viewDidLoad:

 NSFetchRequest *request = [[NSFetchRequest alloc] init];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"freezer == '%@'", freezerName];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Item" inManagedObjectContext:[delegate managedObjectContext]];
    NSSortDescriptor *sorts = [[NSSortDescriptor alloc] initWithKey:@"section" ascending:NO];
    NSArray *sort = [[NSArray alloc] initWithObjects:sorts, nil];

    [request setSortDescriptors:sort];
    [request setEntity:entity];
    [request setPredicate:predicate];

    NSError *error = nil;

    NSMutableArray *results = [[[delegate managedObjectContext] executeFetchRequest:request error:&error] mutableCopy];
    if(results == nil) {
        NSLog(@"Error fetching results... need to handle");
    }

    [self setItems:results];

    NSLog(@"items count:%d", [items count]);

The item count returned is zero.

I am completely stumped and have spent several hours searching online, trying different things, and I can't figure it out.  I know there are some much smarter coders out there and I hope one of you can see what the problem is.

Body:
Maybe the problem is that you load data in

- viewDidLoad:

method. It's called only once when your view is loaded, so when underlaying data get's changed, your view controller is not aware about it.

You can either move your loading code to

- viewWillAppear:

method or introduce notifications to spread the information that data store has changed its state and reload table views upon that event.

The best way is probably to use NSFetchedResultsController as your data source, as its always aware of its data store changes. Check docs for reference to that class.


来源: stackexchange

问:
How to read a CSV value, calculate the increases and then find the max value
I need to read a CSV file, and be able to divide the variables between each other in order to receive percentages.
The CSV file is in the format

Date & time | Usage

so for example

02/08/20 16:02:00 | 1432

03/08/20 17:02:00 | 1440

04/08/20 15:02:00 | 1445

so for example id want to divide 1440  by 1432 to give 1.0055 and 1445 by 1440 to give 1.00347 and then find the max value (1.0055) printing both.

This is about as far as ive gotten

```<code>import pandas as pd

A = pd.read_csv("Test4.csv")
</code>```

Thank you for any and all help and your time.

答:
And now </p>

```<code>A.Usage.pct_change.max() + 1
</code>```

ContentLicense: CC BY-SA 4.0

Body:
I need to read a CSV file, and be able to divide the variables between each other in order to receive percentages.
The CSV file is in the format

Date & time | Usage

so for example

02/08/20 16:02:00 | 1432

03/08/20 17:02:00 | 1440

04/08/20 15:02:00 | 1445

so for example id want to divide 1440  by 1432 to give 1.0055 and 1445 by 1440 to give 1.00347 and then find the max value (1.0055) printing both.

This is about as far as ive gotten

import pandas as pd

A = pd.read_csv("Test4.csv")

Thank you for any and all help and your time.

Body:
And now

A.Usage.pct_change.max() + 1


问:
JsonResponse return string object instead of json in symfony 3.4
I'm trying to return an json object from controller's route

```<code>return new JsonResponse($result);
</code>```

It returns

```<code>string(36) "e91a6865-b2a8-4b7d-9351-2eac29f7aa30"
{
   //data
}
</code>```

How can I get rid of the string(36) "e91a6865-b2a8-4b7d-9351-2eac29f7aa30"?

答:
a string(36) "e91a6865-b2a8-4b7d-9351-2eac29f7aa30" or something similar, that wasn't added to the JsonResponse, usually is caused by a stray var_dump/dump call somewhere in the code base (but in a part that gets evaluated).

Essentially what happens: the var_dump/dump is called and it produces the output, and afterwards the output from the Response object (be it the JsonResponse or some other Response) is appended to that.

Options to handle this:

remember where you put those calls ;o) (works most of the time)

do not commit any var_dump/dump/dd calls to version control ever (and always do version control!), you'll find the calls easily in the git diff.

run grep -nr dump src in the project root (on linux obviously, replace dump by dd if appropriate), this should find the relevant locations in code.

However, overall it's a rather benign source of irritating output.

Body:
I'm trying to return an json object from controller's route

return new JsonResponse($result);

It returns

string(36) "e91a6865-b2a8-4b7d-9351-2eac29f7aa30"
{
   //data
}

How can I get rid of the string(36) "e91a6865-b2a8-4b7d-9351-2eac29f7aa30"?


问:
remove special char from rows in pandas python
I have the following dataframe...unable to remove the "-" char and trim it to the right "int" number for the cell:

```<code>    Branch   Market Company     Brand Name  MRP 2020-05-15 2020-05-19 2020-05-22 2020-05-26
1      USA      abc     xqz           A     165    180-190    170-180        170        170
2      USA      abc     xqz           B     165    180-190    170-180        170        170
3      USA      abc     xqz           C     100        120    110-120        120        120
4      USA      abc     xqz           D      95        110        100        100        110
5      USA      abc     xqz           E      59         70         70         70         70

</code>```

want the following dataframe to plot a scatter plot with brand name in x-axis and MRP in y axis.

```<code>    Branch   Market Company     Brand Name  MRP 2020-05-15 2020-05-19 2020-05-22 2020-05-26
1      USA      abc     xqz           A     165        185        175        170        170
2      USA      abc     xqz           B     165        185        175        170        170
3      USA      abc     xqz           C     100        120        115        120        120
4      USA      abc     xqz           D      95        110        100        100        110
5      USA      abc     xqz           E      59         70         70         70         70

</code>```

can you plz help. tried many codes, but unable to get the desired result/df.

答:
Use Series.str.split and statistics.mean:

```<code>import statistics

df['2020-05-15'] = df['2020-05-15'].str.split('-').apply(lambda x: statistics.mean(list(map(int, x))))

df['2020-05-19'] = df['2020-05-19'].str.split('-').apply(lambda x: statistics.mean(list(map(int, x))))
</code>```

Output:

```<code>   Branch Market Company Brand Name  MRP  2020-05-15  2020-05-19  2020-05-22  2020-05-26
0       1    USA     abc   xqz    A  165         185         175         170         170
1       2    USA     abc   xqz    B  165         185         175         170         170
2       3    USA     abc   xqz    C  100         120         115         120         120
3       4    USA     abc   xqz    D   95         110         100         100         110
4       5    USA     abc   xqz    E   59          70          70          70          70
</code>```

Body:
I have the following dataframe...unable to remove the "-" char and trim it to the right "int" number for the cell:

    Branch   Market Company     Brand Name  MRP 2020-05-15 2020-05-19 2020-05-22 2020-05-26
1      USA      abc     xqz           A     165    180-190    170-180        170        170
2      USA      abc     xqz           B     165    180-190    170-180        170        170
3      USA      abc     xqz           C     100        120    110-120        120        120
4      USA      abc     xqz           D      95        110        100        100        110
5      USA      abc     xqz           E      59         70         70         70         70

want the following dataframe to plot a scatter plot with brand name in x-axis and MRP in y axis.

    Branch   Market Company     Brand Name  MRP 2020-05-15 2020-05-19 2020-05-22 2020-05-26
1      USA      abc     xqz           A     165        185        175        170        170
2      USA      abc     xqz           B     165        185        175        170        170
3      USA      abc     xqz           C     100        120        115        120        120
4      USA      abc     xqz           D      95        110        100        100        110
5      USA      abc     xqz           E      59         70         70         70         70

can you plz help. tried many codes, but unable to get the desired result/df.

Body:
Use Series.str.split and statistics.mean:

import statistics

df['2020-05-15'] = df['2020-05-15'].str.split('-').apply(lambda x: statistics.mean(list(map(int, x))))

df['2020-05-19'] = df['2020-05-19'].str.split('-').apply(lambda x: statistics.mean(list(map(int, x))))

Output:

   Branch Market Company Brand Name  MRP  2020-05-15  2020-05-19  2020-05-22  2020-05-26
0       1    USA     abc   xqz    A  165         185         175         170         170
1       2    USA     abc   xqz    B  165         185         175         170         170
2       3    USA     abc   xqz    C  100         120         115         120         120
3       4    USA     abc   xqz    D   95         110         100         100         110
4       5    USA     abc   xqz    E   59          70          70          70          70


问:
How to generate IDs based on column values
I will provide examples and code where I can. Assume everything except [CycleStart] and [CycleEnd] datatypes are Varchar, I'm not too fussed about this at this stage.

Table A consists of the following RAW sample data:

```<code>+-------+---------+----------------+------------+------------+
| JobID | JobName | CycleDesc      | CycleStart | CycleEnd   |
+-------+---------+----------------+------------+------------+
| 10003 | Run1    | January 2019   | 31/12/2018 | 31/12/2018 |
| 10005 | Run2    | December 2018  | 31/12/2017 | 31/11/2018 |
| 10006 | Run3    | March 2019     | 31/12/2018 | 31/02/2019 |
| 10007 | Run4    | September 2019 | 31/12/2018 | 31/09/2019 |
| 10008 | Run5    | November 2019  | 31/12/2018 | 31/10/2019 |
+-------+---------+----------------+------------+------------+
</code>```

Table B consists of the following sample data and the code used to generate this data is below:

```<code>+-------+---------+---------+
| JobID | PeriodID | Entity |
+-------+---------+---------+
| 10003 | 202101   | XYZ1   |
| 10003 | 202112   | XYZ2   |
| 10007 | 202008   | XYZ3   |
| 10007 | 202003   | XYZ4   |
| 10008 | 201904   | XYZ5   |
+-------+----------+--------+
</code>```

```<code>Declare  @Counter3 INT

SELECT @Counter3=1

WHILE @Counter3 <= 1000
BEGIN

INSERT INTO [dbo].[TableB]

SELECT
FLOOR(RAND()*(33979-1+1))+1 [JobID]
,CAST(ROUND(((2021 - 2019 -1) * RAND() + 2020), 0) AS VARCHAR) + RIGHT('0'+CAST(FLOOR(RAND()*(12-1+1))+1 AS VARCHAR),2) [PeriodID]
,FLOOR(RAND()*(23396-1+1))+1 [Entity]
</code>```

The issue lies within Table B column [PeriodID]. This column represents an ID generated from [CycleStart] in Table A e.g. 31/12/2018 = 201812 (YYYYMM).

What I want to show in Table B is a Period ID for each Job ID but show EACH month + 30 years ahead of the [CycleStart] date. Example table of what I am looking to achieve:

```<code>+-------+---------+---------+
| JobID | PeriodID | Entity |
+-------+---------+---------+
| 10006 | 201812   | XYZ1   |
| 10006 | 201901   | XYZ2   |
| 10006 | 201902   | XYZ3   |
| 10006 | 201903   | XYZ4   |
| 10006 | 201904   | XYZ5   |
| 10006 | 201905   | XYZ5   |
| 10006 | 201906   | XYZ5   |
| 10006 | 201907   | XYZ5   |
| ...   | +30yrs   | ...    |
| 10006 | 204812   | XYZ5   |
+-------+----------+--------+
</code>```

How can I achieve this? Currently I am just randomly generating IDs which is not related to the [CycleStart] date and therefore just skewing my data but this is the only way I can think of doing it.

答:
The best way is to create a calendar table / date dimension.  You can use this table to solve this issue, and reuse it for other problems later.  (Search online for some examples on how to build one).

If you have this table then you only need to join this table and that's it.

e.g.

```<code>INSERT INTO TableB ( JobID , PeriodID)
SELECT DISTINCT A.JobID , D.TheYear * 100 + D.TheMonth
FROM tableA A
JOIN myDateTable D
    ON D.TheDate BETWEEN CONVERT(date , A.CycleStart ,  103) AND DATEADD(YEAR,30, CONVERT(date , A.CycleStart ,  103));
</code>```

Body:
I will provide examples and code where I can. Assume everything except [CycleStart] and [CycleEnd] datatypes are Varchar, I'm not too fussed about this at this stage.

Table A consists of the following RAW sample data:

+-------+---------+----------------+------------+------------+
| JobID | JobName | CycleDesc      | CycleStart | CycleEnd   |
+-------+---------+----------------+------------+------------+
| 10003 | Run1    | January 2019   | 31/12/2018 | 31/12/2018 |
| 10005 | Run2    | December 2018  | 31/12/2017 | 31/11/2018 |
| 10006 | Run3    | March 2019     | 31/12/2018 | 31/02/2019 |
| 10007 | Run4    | September 2019 | 31/12/2018 | 31/09/2019 |
| 10008 | Run5    | November 2019  | 31/12/2018 | 31/10/2019 |
+-------+---------+----------------+------------+------------+

Table B consists of the following sample data and the code used to generate this data is below:

+-------+---------+---------+
| JobID | PeriodID | Entity |
+-------+---------+---------+
| 10003 | 202101   | XYZ1   |
| 10003 | 202112   | XYZ2   |
| 10007 | 202008   | XYZ3   |
| 10007 | 202003   | XYZ4   |
| 10008 | 201904   | XYZ5   |
+-------+----------+--------+

Declare  @Counter3 INT

SELECT @Counter3=1

WHILE @Counter3 <= 1000
BEGIN

INSERT INTO [dbo].[TableB]

SELECT
FLOOR(RAND()*(33979-1+1))+1 [JobID]
,CAST(ROUND(((2021 - 2019 -1) * RAND() + 2020), 0) AS VARCHAR) + RIGHT('0'+CAST(FLOOR(RAND()*(12-1+1))+1 AS VARCHAR),2) [PeriodID]
,FLOOR(RAND()*(23396-1+1))+1 [Entity]

The issue lies within Table B column [PeriodID]. This column represents an ID generated from [CycleStart] in Table A e.g. 31/12/2018 = 201812 (YYYYMM).

What I want to show in Table B is a Period ID for each Job ID but show EACH month + 30 years ahead of the [CycleStart] date. Example table of what I am looking to achieve:

+-------+---------+---------+
| JobID | PeriodID | Entity |
+-------+---------+---------+
| 10006 | 201812   | XYZ1   |
| 10006 | 201901   | XYZ2   |
| 10006 | 201902   | XYZ3   |
| 10006 | 201903   | XYZ4   |
| 10006 | 201904   | XYZ5   |
| 10006 | 201905   | XYZ5   |
| 10006 | 201906   | XYZ5   |
| 10006 | 201907   | XYZ5   |
| ...   | +30yrs   | ...    |
| 10006 | 204812   | XYZ5   |
+-------+----------+--------+

How can I achieve this? Currently I am just randomly generating IDs which is not related to the [CycleStart] date and therefore just skewing my data but this is the only way I can think of doing it.

Body:
The best way is to create a calendar table / date dimension.  You can use this table to solve this issue, and reuse it for other problems later.  (Search online for some examples on how to build one).

If you have this table then you only need to join this table and that's it.

e.g.

INSERT INTO TableB ( JobID , PeriodID)
SELECT DISTINCT A.JobID , D.TheYear * 100 + D.TheMonth
FROM tableA A
JOIN myDateTable D
    ON D.TheDate BETWEEN CONVERT(date , A.CycleStart ,  103) AND DATEADD(YEAR,30, CONVERT(date , A.CycleStart ,  103));


问:
HQL query with LIKE % is not wokring
I tried to reproduce this SQL query which is working for me, havent copied exact syntax for privacy issues, but I think you get the purpose from this query.

```<code>SELECT t1.Column1, t2.Column2, t2.Column3
FROM Table1 as t1
INNER JOIN Table2 as t2 ON t1.Column1 LIKE %t2.Column2%
INNER JOIN Table2 as t2 ON t1.Column1 LIKE %t2.Column3% ;
</code>```

while on the HQL query I tried this but it doesnt seem to get me any results :

returns empty list [ ]

HQL query :

```<code>session.createQuery("... where
t1.Column1 LIKE '%"+"t2.Column2"+"%'
and t1.Column1 LIKE '%"+"t2.Column3"+"%' ").list();
</code>```

I've tried to insert actual values instead of columns, it does actually work, but i think hibernate treats attributes as raw values instead of iterating over the objects.
Can anyone please suggest a solution , I've seen people approaching this issue with criterias, but the main problem is that I'm not making any associations between these classes so I don't think it'd work.

I've been stuck with this problem for over a week now, one very easy solution that comes to my mind but it's not really optimal, is doing a for each loop like this one (keeping it as last resolve):

```<code>//list1 of query result unique column2 values
//list2 of query result unique column3 values
for each (list1)
for each (list2)
HashSet<Object,Object> result = Session.createQuery("... where
t1.Column1 LIKE '%"+":list1"+"%'
and t1.Column1 LIKE '%"+":list2"+"%'").setParameter("list1",list1).setParameter("list2",list2).tolist();
HashSet<Object,Object> lastresult= new HashSet();
lastresult.add(result);
</code>```

答:
Update (Solution) :

Update : As suspected, the query was treating the object's properties as raw values instead of actual objects to iterate from, so the approach I took by adding "+" sign was the mistake, I should've gone with the function 'CONCAT' instead and it did resolve my issue.

```<code>session.createQuery("... WHERE lower(t1.Column1) LIKE
Concat(Concat('%',lower(t2.Column2)),'%') and lower(t1.Column1) LIKE Concat(Concat('%',lower(t2.Column3)),'%')").tolist();
</code>```

Title: HQL query with LIKE % is not wokring

Body:
I tried to reproduce this SQL query which is working for me, havent copied exact syntax for privacy issues, but I think you get the purpose from this query.

SELECT t1.Column1, t2.Column2, t2.Column3
FROM Table1 as t1
INNER JOIN Table2 as t2 ON t1.Column1 LIKE %t2.Column2%
INNER JOIN Table2 as t2 ON t1.Column1 LIKE %t2.Column3% ;

while on the HQL query I tried this but it doesnt seem to get me any results :

returns empty list [ ]

HQL query :

session.createQuery("... where
t1.Column1 LIKE '%"+"t2.Column2"+"%'
and t1.Column1 LIKE '%"+"t2.Column3"+"%' ").list();

I've tried to insert actual values instead of columns, it does actually work, but i think hibernate treats attributes as raw values instead of iterating over the objects.
Can anyone please suggest a solution , I've seen people approaching this issue with criterias, but the main problem is that I'm not making any associations between these classes so I don't think it'd work.

I've been stuck with this problem for over a week now, one very easy solution that comes to my mind but it's not really optimal, is doing a for each loop like this one (keeping it as last resolve):

//list1 of query result unique column2 values
//list2 of query result unique column3 values
for each (list1)
for each (list2)
HashSet<Object,Object> result = Session.createQuery("... where
t1.Column1 LIKE '%"+":list1"+"%'
and t1.Column1 LIKE '%"+":list2"+"%'").setParameter("list1",list1).setParameter("list2",list2).tolist();
HashSet<Object,Object> lastresult= new HashSet();
lastresult.add(result);

Body:
Update (Solution) :

Update : As suspected, the query was treating the object's properties as raw values instead of actual objects to iterate from, so the approach I took by adding "+" sign was the mistake, I should've gone with the function 'CONCAT' instead and it did resolve my issue.

session.createQuery("... WHERE lower(t1.Column1) LIKE
Concat(Concat('%',lower(t2.Column2)),'%') and lower(t1.Column1) LIKE Concat(Concat('%',lower(t2.Column3)),'%')").tolist();


问:
microk8s Broken K8s Dashboard and Kubeflow Dashboard
I'm using microk8s in an Ubuntu 18.04 LTS VM, 3 cores, 60 GB storage, 12 GB of memory. I followed the instructions from microk8s website here to install it.

$ snap install microk8s --classic --channel=1.18/stable
$ sudo microk8s start
$ sudo microk8s enable dns storage dashboard
$ sudo microk8s enable kubeflow
```

<p>This took some time but everything got started. I have 110 pods running.  When Kubeflow finished installing I got </p>

<pre class="lang-sh prettyprint-override"><code>Operator pods ready.
Waiting for service pods to become ready.

Congratulations, Kubeflow is now available.
The dashboard is available at http://10.64.140.43.xip.io/

    Username: admin
    Password: VIVGI9KB7GEX6JNAQJXZTXD97S42XD
</code>```

Which did not work. When I put that URL into my browser, I get a white screen.  I then tried to access the kubernetes dashboard and was able to login with my token but it says it cannot find any resources.  It doesn't show anything in namespaces, nodes, or anything.

The namespace is still at default because I cannot get it to show kubeflow.  The documentation says that kubeflow doesn't work for kubernetes 1.18 but if you install an older version of microk8s it doesn't give you the option to enable kubeflow.  That also doesn't explain why the dashboard is not working.  I don't really know what to check to fix this issue. I tried using the internal IP address for the kubeflow ambassador  (kubeflow load balancer) but that didn't seem to work either.

here is more detail on the ambassador service

sudo microk8s kubectl -n kubeflow describe service/ambassador
Name:                     ambassador
Namespace:                kubeflow
Labels:                   juju-app=ambassador
Annotations:              juju.io/controller: 7fe60455-b041-4b5e-8c85-0c8155b0f52d
                          juju.io/model: f635bf6f-c598-4d5c-841b-e798f520a898
                          metallb.universe.tf/address-pool: default
Selector:                 juju-app=ambassador
Type:                     LoadBalancer
IP:                       10.152.183.67
LoadBalancer Ingress:     10.64.140.43
Port:                     ambassador  80/TCP
TargetPort:               80/TCP
NodePort:                 ambassador  30085/TCP
Endpoints:                10.1.40.17:80
Session Affinity:         None
External Traffic Policy:  Cluster
Events:
  Type    Reason        Age                 From                Message
  ----    ------        ----                ----                -------
  Normal  IPAllocated   58m                 metallb-controller  Assigned IP "10.64.140.43"
  Normal  nodeAssigned  2m5s (x5 over 56m)  metallb-speaker     announcing from node "tatooine"
```

答:
I am running MicroK8s 1.18.2 + Kubeflow on Ubuntu 18.04.3 LTS natively (not in a VM environment) and had the same issue. Luckily I was able to solve the issue and would like to share my solution with you. It turned out that my laptop was not able to resolve the URL to the dashboard (10.64.140.43.xip.io), so I added this address into the hosts file.

My installation routine:

```<code>> # Install MicroK8s
> $ sudo snap install microk8s --classic --channel=1.18/stable

> # Set IP forwarding
> $ sudo apt-get update -qq
> $ sudo apt-get install -qq -y iptables-persistent
> $ sudo iptables -P FORWARD ACCEPT

> # Add xip.io adress to hosts
> $ sudo -- sh -c "echo '10.64.140.43\t10.64.140.43.xip.io' >>
> /etc/hosts"

> # Check if MicroK8s is Running
> $ microk8s status --wait-ready | grep microk8s
> $ microk8s kubectl get nodes
> $ microk8s kubectl get services

> # Set kubectl alias for MicroK8s
> $ sudo snap alias microk8s.kubectl kubectl

> # Activate MicroK8s Add-ons (DNS, Storage, K8s-Dashboard)
> $ microk8s.enable dns storage dashboard

> # (OPTIONAL) Activate GPU Devices for Nvidia GPUs
> $ microk8s.enable gpu

> # Activate Kubeflow
> $ microk8s.enable kubeflow

> # Check if MicroK8s Add-ons are Running
> $ microk8s status --wait-ready
</code>```

Depending on your hardware and internet connection, it might take some time until all services are ready. If all services are up, simply open http://10.64.140.43.xip.io in your browser and enter the user (admin) and your generated password.

I hope this works for you as well. :)

Body:
I'm using microk8s in an Ubuntu 18.04 LTS VM, 3 cores, 60 GB storage, 12 GB of memory. I followed the instructions from microk8s website here to install it.

$ snap install microk8s --classic --channel=1.18/stable
$ sudo microk8s start
$ sudo microk8s enable dns storage dashboard
$ sudo microk8s enable kubeflow

This took some time but everything got started. I have 110 pods running.  When Kubeflow finished installing I got

Operator pods ready.
Waiting for service pods to become ready.

Congratulations, Kubeflow is now available.
The dashboard is available at http://10.64.140.43.xip.io/

    Username: admin
    Password: VIVGI9KB7GEX6JNAQJXZTXD97S42XD

Which did not work. When I put that URL into my browser, I get a white screen.  I then tried to access the kubernetes dashboard and was able to login with my token but it says it cannot find any resources.  It doesn't show anything in namespaces, nodes, or anything.

The namespace is still at default because I cannot get it to show kubeflow.  The documentation says that kubeflow doesn't work for kubernetes 1.18 but if you install an older version of microk8s it doesn't give you the option to enable kubeflow.  That also doesn't explain why the dashboard is not working.  I don't really know what to check to fix this issue. I tried using the internal IP address for the kubeflow ambassador  (kubeflow load balancer) but that didn't seem to work either.

here is more detail on the ambassador service

sudo microk8s kubectl -n kubeflow describe service/ambassador
Name:                     ambassador
Namespace:                kubeflow
Labels:                   juju-app=ambassador
Annotations:              juju.io/controller: 7fe60455-b041-4b5e-8c85-0c8155b0f52d
                          juju.io/model: f635bf6f-c598-4d5c-841b-e798f520a898
                          metallb.universe.tf/address-pool: default
Selector:                 juju-app=ambassador
Type:                     LoadBalancer
IP:                       10.152.183.67
LoadBalancer Ingress:     10.64.140.43
Port:                     ambassador  80/TCP
TargetPort:               80/TCP
NodePort:                 ambassador  30085/TCP
Endpoints:                10.1.40.17:80
Session Affinity:         None
External Traffic Policy:  Cluster
Events:
  Type    Reason        Age                 From                Message
  ----    ------        ----                ----                -------
  Normal  IPAllocated   58m                 metallb-controller  Assigned IP "10.64.140.43"
  Normal  nodeAssigned  2m5s (x5 over 56m)  metallb-speaker     announcing from node "tatooine"

Body:
I am running MicroK8s 1.18.2 + Kubeflow on Ubuntu 18.04.3 LTS natively (not in a VM environment) and had the same issue. Luckily I was able to solve the issue and would like to share my solution with you. It turned out that my laptop was not able to resolve the URL to the dashboard (10.64.140.43.xip.io), so I added this address into the hosts file.

My installation routine:

> # Install MicroK8s
> $ sudo snap install microk8s --classic --channel=1.18/stable

> # Set IP forwarding
> $ sudo apt-get update -qq
> $ sudo apt-get install -qq -y iptables-persistent
> $ sudo iptables -P FORWARD ACCEPT

> # Add xip.io adress to hosts
> $ sudo -- sh -c "echo '10.64.140.43\t10.64.140.43.xip.io' >>
> /etc/hosts"

> # Check if MicroK8s is Running
> $ microk8s status --wait-ready | grep microk8s
> $ microk8s kubectl get nodes
> $ microk8s kubectl get services

> # Set kubectl alias for MicroK8s
> $ sudo snap alias microk8s.kubectl kubectl

> # Activate MicroK8s Add-ons (DNS, Storage, K8s-Dashboard)
> $ microk8s.enable dns storage dashboard

> # (OPTIONAL) Activate GPU Devices for Nvidia GPUs
> $ microk8s.enable gpu

> # Activate Kubeflow
> $ microk8s.enable kubeflow

> # Check if MicroK8s Add-ons are Running
> $ microk8s status --wait-ready

Depending on your hardware and internet connection, it might take some time until all services are ready. If all services are up, simply open http://10.64.140.43.xip.io in your browser and enter the user (admin) and your generated password.

I hope this works for you as well. :)


问:
How to install laravel/cashier 6.0 in Laravel 5.8
everyone.
Recently I have upgraded my laravel 5.2 project to laravel 5.8.
But I want to use laravel/cashier 6.0 in laravel 5.8.
I have installed it by "composer require laravel/cashier:6.0" but it throws error something like this.

Is there any way to do this for me?
Thank you.

答:
It seems that Laravel Cashier requires Carbon v1, which is deprecated in Laravel 5.8
If you may use Laravel 5.7 things should go different.
Anyway both Laravel 5.7 and 5.8 are old versions with no long term support, so in that sense, best choice should be Laravel 6
Regards.</p>


问:
Convert basic array to PHP array
I have an array that I pull that looks like this:

[157966745,275000353,43192565,305328212]...

How do I go about taking that "string" and converting it to a PHP array which I can then manipulate.

ContentLicense: CC BY-SA 3.0

Title: Convert basic array to PHP array

Body:
$s = "[157966745,275000353,43192565,305328212]";

$matches;
preg_match_all("/\d+/", $s, $matches);

print_r($matches);


问:
Limit replicas per node on Kubernetes
Is there a way to limit the number os replicas per node in Kubernetes? I found some info about Spreading Constraints but didn't understand if this is possible.

Example: I want to have only 1 replica per node on the cluster.

I know that K8S automatically balances the replicas spreading across the nodes, but I want to enforce a specific limit in each node.

Is this possible?

答: You can create daemon set which makes sure every node in the cluster runs exactly one replica</p>

Title: Limit replicas per node on Kubernetes


问:
InvalidArgumentError : input depth must be evenly divisible by filter depth: 4 vs 3
I'm a beginner. I tried Image Classification by Tensorflow, and got the following error. I found the similar issue on web, but I couldn't understand. What does the error mean? How should I do for it? Please give me some advice. I use 100 files(png/15pix, 15pix) like a sample image. Tensorflow ver.2.0.0 / python ver.3.8.1 / Jupyter notebook.

```<code>    num_epochs = 30
    steps_per_epoch = round(num_train)//BATCH_SIZE
    val_steps = 20
    history = model.fit(train_data.repeat(),
                epochs=num_epochs,
                steps_per_epoch = steps_per_epoch,
                validation_data=val_data.repeat(),
                validation_steps=val_steps)
</code>```

InvalidArgumentError:  input depth must be evenly divisible by filter depth: 4 vs 3
       [[node sequential_2/mobilenetv2_1.00_96/Conv1/Conv2D (defined at C:\Users\XXXXX\Anaconda3\lib\site-packages\tensorflow_core\python\framework\ops.py:1751) ]] [Op:__inference_distributed_function_42611]
  Function call stack:
  distributed_function

答: The error is because of mismatch in dimensions of the input provided. The model requires a depth of '3' for the input but is given '4'.</p>

Body:
I'm a beginner. I tried Image Classification by Tensorflow, and got the following error. I found the similar issue on web, but I couldn't understand. What does the error mean? How should I do for it? Please give me some advice. I use 100 files(png/15pix, 15pix) like a sample image. Tensorflow ver.2.0.0 / python ver.3.8.1 / Jupyter notebook.

    num_epochs = 30
    steps_per_epoch = round(num_train)//BATCH_SIZE
    val_steps = 20
    history = model.fit(train_data.repeat(),
                epochs=num_epochs,
                steps_per_epoch = steps_per_epoch,
                validation_data=val_data.repeat(),
                validation_steps=val_steps)

InvalidArgumentError:  input depth must be evenly divisible by filter depth: 4 vs 3
       [[node sequential_2/mobilenetv2_1.00_96/Conv1/Conv2D (defined at C:\Users\XXXXX\Anaconda3\lib\site-packages\tensorflow_core\python\framework\ops.py:1751) ]] [Op:__inference_distributed_function_42611]
  Function call stack:
  distributed_function


答: In your composer.json, change Carbon version to 1.26.3. Next, run composer update (not composer install.)

Title: How to install laravel/cashier 6.0 in Laravel 5.8

Body:
everyone.
Recently I have upgraded my laravel 5.2 project to laravel 5.8.
But I want to use laravel/cashier 6.0 in laravel 5.8.
I have installed it by "composer require laravel/cashier:6.0" but it throws error something like this.

Is there any way to do this for me?
Thank you.


问:
Dynamic JavaScript slideshow
I have a JavaScript slideshow that pre-loads images out of a MySQL database and then displays them one at a time in an image tag in the HTML document. Briefly, it accomplishes this by pre-loading images like many slideshow tutorials show on the web, but instead of using static images (i.e. images/image1.jpg etc.) it uses a dynamic image provided via PHP (i.e. getData.php?n=1) The getData.php script runs on the server and opens a new connection to the database for every image that is preloaded.

Is there anyway to avoid making so many connections to the database and having each connection make only a single query on the image database with LIMIT n,1?

It seems that if I am going to use getData.php as the image.src then getData.php needs to return a single image at a time! I'd really like to fetch them in blocks of 10 and then assign them to Image() objects one by one on the client side. I think this would be faster because when I wrote a client app in python to display the images (outside the browser of course) blocks of 10 or so transferred much faster (and reduces the load on the mySQL server). Can I accomplish this with JavaScript and PHP? Do I use XML in between? If I could get binary image data into JavaScript with AJAX could I do anything with it? Is there an imagecreatefromstring() function in JavaScript that I'm missing?

I can figure out exact code on my own, but I'm new to web programming and need a tip about how to tackle this problem! I think I'm missing some piece of major framework. Do I need ActionScript or something other than JavaScript for this problem? Thanks for the tip in advance!

EDIT: I like this first suggestion and I think I could get that done. It will also enable me too follow part of alex shishkin's suggestion to avoid LIMIT n,1 queries (I do want to keep the SQL BLOB fields though) But how do I stick binary data from XML into an Image() object in JavaScript ?

答:
Create a web page.

Let the page connect to the server and get XML or JSON with the IDs for the images.

Request the images from the server using the ID from step 2.

Title: Dynamic JavaScript slideshow

LastEditorDisplayName: agartland

ContentLicense: CC BY-SA 2.5


问:
How and when is the memory of a global or static array allocated?
When defining a global or static array in c++ its memory is not immediately reserved at the start of the programme but only once we write to the array. What I found surprising is, if we only write to a small part of the array it still does not reserve the entire memory. Consider the following small example which writes sparsely to the global array:

```<code>#include <cstdio>
#include <cstdlib>

#define MAX_SIZE 250000000
double global[MAX_SIZE];

int main(int argc, char** argv) {
   if(argc<2) {
      printf("usage: %s <step size>\n", argv[0]);
      exit(EXIT_FAILURE);
   }
   size_t   step_size=atoi(argv[1]);

   for(size_t i=0; i<MAX_SIZE; i+=step_size) {
      global[i]=(double) i;
   }

   printf("finished\n"); getchar();
   return EXIT_SUCCESS;
}
</code>```

Now executing this for different step sizes and looking at the output of top we get for example:

```<code>./a.out 1000000
./a.out 100000
./a.out 10000
./a.out 1000
./a.out 100

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
15718 user      20   0 1918m 1868  728 S    0  0.0   0:00.00 a.out
15748 user      20   0 1918m  10m  728 S    0  0.1   0:00.00 a.out
15749 user      20   0 1918m  98m  728 S    1  0.8   0:00.04 a.out
15750 user      20   0 1918m 977m  728 S    0  8.1   0:00.39 a.out
15751 user      20   0 1918m 1.9g  728 S   23 15.9   0:00.80 a.out
</code>```

The RES column indicates memory is only reserved in small blocks, which also means the array is unlikely to be contiguous in physical memory. Anyone got more insight on the lower level of things?

This also has the negative side effect that I can easily run many programmes where the sum of all VIRT exceeds the physical memory as long the sum of RES is below. However, as soon as they all write to the global arrays the system runs out of physical memory and programmes get sent sigkill or something.

Ideally I'd like to tell the compiler to reserve the memory of global and static variables at the start. Possible?

Edit

@Magnus: The lines are actually in the right order. :) Take the first line for example ./a.out 1000000 means I'm writing every 1 millionth entry in the array and so only 250 in total. This corresponds to a RES of only 1868k. In the last example ./a.out 100 every one hundreds entry is written and then the total memory is also physically allocated RES=VIRT=1.9g. From the numbers it appears that whenever an entry is written to the array something like a full 4k block is reserved on the physical memory.

@Nawaz: The array is contiguous in virtual address space but as I understand the OS might be lazy and only reserve physical memory when it's actually needed. Since this is done in little blocks and not the whole array at once how can it be guaranteed to be contiguous in physical memory?

@Nemo: Thanks for that, indeed when calling multiple instances of a.out which pause at the beginning and then write to the array I got oom-killer messages in /var/log/messages, and indeed your sysctrl command prevents me from starting too many a.out instances in the first place. Thanks!

```<code>Jun  1 17:49:16 localhost kernel: [32590.293421] a.out invoked oom-killer: gfp_mask=0x280da, order=0, oomkilladj=0
Jun  1 17:49:18 localhost kernel: [32592.110033] kded4 invoked oom-killer: gfp_mask=0x201da, order=0, oomkilladj=0
Jun  1 17:49:20 localhost kernel: [32594.718757] firefox invoked oom-killer: gfp_mask=0x201da, order=0, oomkilladj=0
</code>```

The last two lines slightly worrying. :)

@doron: Thanks, great explanation, sorry can't upvote/select.

答:
There are two things in play here viz. virtual memory and physical memory.

The virtual memory for for the static data, just like the instructions for your program are assigned before your program begins execution. By this I mean that the address, for your program is always defined.

The operating system might be lazy, however when it comes to loading both static data and program instructions into physical memory RAM. The way that this works is like this:

The process loader assigned process virtual memory for the static data but does not load the data into RAM.

When one tries to access these addresses, a processor exception is triggered and we then enter kernel mode.

The kernel now loads the data into RAM and links the RAM into the processes virtual address space.

The kernel switches back into user mode to the exact point where the processor exception happenned.

Since the RAM is now linked into the processes virtual address space, the program will now continue executing as if nothing had ever happenned.

This is a total slight of hand which the operating system is allowed to do simply because it is totally undetectable to the running process. Unless of course we are short of memory.

Body:
When defining a global or static array in c++ its memory is not immediately reserved at the start of the programme but only once we write to the array. What I found surprising is, if we only write to a small part of the array it still does not reserve the entire memory. Consider the following small example which writes sparsely to the global array:

#include <cstdio>
#include <cstdlib>

#define MAX_SIZE 250000000
double global[MAX_SIZE];

int main(int argc, char** argv) {
   if(argc<2) {
      printf("usage: %s <step size>\n", argv[0]);
      exit(EXIT_FAILURE);
   }
   size_t   step_size=atoi(argv[1]);

   for(size_t i=0; i<MAX_SIZE; i+=step_size) {
      global[i]=(double) i;
   }

   printf("finished\n"); getchar();
   return EXIT_SUCCESS;
}

Now executing this for different step sizes and looking at the output of top we get for example:

./a.out 1000000
./a.out 100000
./a.out 10000
./a.out 1000
./a.out 100

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
15718 user      20   0 1918m 1868  728 S    0  0.0   0:00.00 a.out
15748 user      20   0 1918m  10m  728 S    0  0.1   0:00.00 a.out
15749 user      20   0 1918m  98m  728 S    1  0.8   0:00.04 a.out
15750 user      20   0 1918m 977m  728 S    0  8.1   0:00.39 a.out
15751 user      20   0 1918m 1.9g  728 S   23 15.9   0:00.80 a.out

The RES column indicates memory is only reserved in small blocks, which also means the array is unlikely to be contiguous in physical memory. Anyone got more insight on the lower level of things?

This also has the negative side effect that I can easily run many programmes where the sum of all VIRT exceeds the physical memory as long the sum of RES is below. However, as soon as they all write to the global arrays the system runs out of physical memory and programmes get sent sigkill or something.

Ideally I'd like to tell the compiler to reserve the memory of global and static variables at the start. Possible?

Edit

@Magnus: The lines are actually in the right order. :) Take the first line for example ./a.out 1000000 means I'm writing every 1 millionth entry in the array and so only 250 in total. This corresponds to a RES of only 1868k. In the last example ./a.out 100 every one hundreds entry is written and then the total memory is also physically allocated RES=VIRT=1.9g. From the numbers it appears that whenever an entry is written to the array something like a full 4k block is reserved on the physical memory.

@Nawaz: The array is contiguous in virtual address space but as I understand the OS might be lazy and only reserve physical memory when it's actually needed. Since this is done in little blocks and not the whole array at once how can it be guaranteed to be contiguous in physical memory?

@Nemo: Thanks for that, indeed when calling multiple instances of a.out which pause at the beginning and then write to the array I got oom-killer messages in /var/log/messages, and indeed your sysctrl command prevents me from starting too many a.out instances in the first place. Thanks!

Jun  1 17:49:16 localhost kernel: [32590.293421] a.out invoked oom-killer: gfp_mask=0x280da, order=0, oomkilladj=0
Jun  1 17:49:18 localhost kernel: [32592.110033] kded4 invoked oom-killer: gfp_mask=0x201da, order=0, oomkilladj=0
Jun  1 17:49:20 localhost kernel: [32594.718757] firefox invoked oom-killer: gfp_mask=0x201da, order=0, oomkilladj=0

The last two lines slightly worrying. :)

@doron: Thanks, great explanation, sorry can't upvote/select.


问:
Flex container with table inside
I have a container grid with 3 div flex subelements. The first in the header (fixed), the second is the body and the third is the footer (fixed). In the body i have a table. I wish that when I resize the window the table inside the "body" section would remain inside the section by applying overflow-y of the tbody so that the table never "stretches" the section in which it is contended. Some ideas?

In the first image I have the table inside the yellow body with tbody.height=600px. The yellow body is 660px. If i resize the window the situation is as second image. The scollbar appear in the window because the height of the table exceed the yellow height. In this condition the footer (orange) disappear. When I resize the window I would like the window scrollbar to not appear but instead the height of the table is reduced so that only the table scrollbar appears as in the third image.

答:
Better to see an example.

But for now i can suggest this:

Header element has positon: fixed and top: 0, like you said.

Middle element has padding-top: 100px (the same as height of Header) and padding-bottom: 100px (the same as height of Footer).

Footer element has positon: fixed and bottom: 0, like you said.

And you will use body standard scrolling in this case.

Please, add some live example, so I could answer more accurate. You can use https://jsfiddle.net/

UPDATED

As I suggested - here is an example with only body scrolling

* {
  box-sizing: border-box;
}

html {
  height: 100%;
}

body {
  min-height: 100%;
  margin: 0;
  padding: 0;
}

.header {
  position: fixed;
  left: 0;
  top: 0;
  width: 100%;
  height: 50px;
  z-index: 2;
  background: #1c679a;
}

.footer {
  position: fixed;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 50px;
  z-index: 2;
  background: #1c9a25;
}

.container {
  position: relative;
  z-index: 1;
  padding-top: 50px; /* same as .header height */
  padding-bottom: 50px; /* same as .footer height */
}

.table {
  width: 100%;
  border: 0;
}

.table thead th {
  position: sticky;
  top: 50px; /* same as .header height */
  background: #ccc;
  border: 0;
}```
<pre class="snippet-code-html lang-html prettyprint-override"><code><div class="header"></div>
<div class="container">
  <table class="table">
    <thead>
      <tr>
        <th>title</th>
        <th>title</th>
        <th>title</th>
        <th>title</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>1</td>
        <td>1</td>
        <td>1</td>
        <td>1</td>
      </tr>
      <tr>
        <td>2</td>
        <td>2</td>
        <td>2</td>
        <td>2</td>
      </tr>
      <tr>
        <td>1</td>
        <td>1</td>
        <td>1</td>
        <td>1</td>
      </tr>
      <tr>
        <td>1</td>
        <td>1</td>
        <td>1</td>
        <td>1</td>
      </tr>
      <tr>
        <td>1</td>
        <td>1</td>
        <td>1</td>
        <td>1</td>
      </tr>
      <tr>
        <td>1</td>
        <td>1</td>
        <td>1</td>
        <td>1</td>
      </tr>
      <tr>
        <td>1</td>
        <td>1</td>
        <td>1</td>
        <td>1</td>
      </tr>
      <tr>
        <td>1</td>
        <td>1</td>
        <td>1</td>
        <td>1</td>
      </tr>
      <tr>
        <td>1</td>
        <td>1</td>
        <td>1</td>
        <td>1</td>
      </tr>
      <tr>
        <td>1</td>
        <td>1</td>
        <td>1</td>
        <td>1</td>
      </tr>
      <tr>
        <td>1</td>
        <td>1</td>
        <td>1</td>
        <td>1</td>
      </tr>
      <tr>
        <td>1</td>
        <td>1</td>
        <td>1</td>
        <td>1</td>
      </tr>
      <tr>
        <td>1</td>
        <td>1</td>
        <td>1</td>
        <td>1</td>
      </tr>
      <tr>
        <td>1</td>
        <td>1</td>
        <td>1</td>
        <td>1</td>
      </tr>
      <tr>
        <td>1</td>
        <td>1</td>
        <td>1</td>
        <td>1</td>
      </tr>
      <tr>
        <td>1</td>
        <td>1</td>
        <td>1</td>
        <td>1</td>
      </tr>
      <tr>
        <td>last</td>
        <td>last</td>
        <td>last</td>
        <td>last</td>
      </tr>
    </tbody>
  </table>
</div>
<div class="footer"></div></code>```

Title: Flex container with table inside

Body:
Better to see an example.

But for now i can suggest this:

Header element has positon: fixed and top: 0, like you said.

Middle element has padding-top: 100px (the same as height of Header) and padding-bottom: 100px (the same as height of Footer).

Footer element has positon: fixed and bottom: 0, like you said.

And you will use body standard scrolling in this case.

Please, add some live example, so I could answer more accurate. You can use https://jsfiddle.net/

UPDATED

As I suggested - here is an example with only body scrolling

* {
  box-sizing: border-box;
}

html {
  height: 100%;
}

body {
  min-height: 100%;
  margin: 0;
  padding: 0;
}

.header {
  position: fixed;
  left: 0;
  top: 0;
  width: 100%;
  height: 50px;
  z-index: 2;
  background: #1c679a;
}

.footer {
  position: fixed;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 50px;
  z-index: 2;
  background: #1c9a25;
}

.container {
  position: relative;
  z-index: 1;
  padding-top: 50px; /* same as .header height */
  padding-bottom: 50px; /* same as .footer height */
}

.table {
  width: 100%;
  border: 0;
}

.table thead th {
  position: sticky;
  top: 50px; /* same as .header height */
  background: #ccc;
  border: 0;
}

<div class="header"></div>
<div class="container">
  <table class="table">
    <thead>
      <tr>
        <th>title</th>
        <th>title</th>
        <th>title</th>
        <th>title</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>1</td>
        <td>1</td>
        <td>1</td>
        <td>1</td>
      </tr>
      <tr>
        <td>2</td>
        <td>2</td>
        <td>2</td>
        <td>2</td>
      </tr>
      <tr>
        <td>1</td>
        <td>1</td>
        <td>1</td>
        <td>1</td>
      </tr>
      <tr>
        <td>1</td>
        <td>1</td>
        <td>1</td>
        <td>1</td>
      </tr>
      <tr>
        <td>1</td>
        <td>1</td>
        <td>1</td>
        <td>1</td>
      </tr>
      <tr>
        <td>1</td>
        <td>1</td>
        <td>1</td>
        <td>1</td>
      </tr>
      <tr>
        <td>1</td>
        <td>1</td>
        <td>1</td>
        <td>1</td>
      </tr>
      <tr>
        <td>1</td>
        <td>1</td>
        <td>1</td>
        <td>1</td>
      </tr>
      <tr>
        <td>1</td>
        <td>1</td>
        <td>1</td>
        <td>1</td>
      </tr>
      <tr>
        <td>1</td>
        <td>1</td>
        <td>1</td>
        <td>1</td>
      </tr>
      <tr>
        <td>1</td>
        <td>1</td>
        <td>1</td>
        <td>1</td>
      </tr>
      <tr>
        <td>1</td>
        <td>1</td>
        <td>1</td>
        <td>1</td>
      </tr>
      <tr>
        <td>1</td>
        <td>1</td>
        <td>1</td>
        <td>1</td>
      </tr>
      <tr>
        <td>1</td>
        <td>1</td>
        <td>1</td>
        <td>1</td>
      </tr>
      <tr>
        <td>1</td>
        <td>1</td>
        <td>1</td>
        <td>1</td>
      </tr>
      <tr>
        <td>1</td>
        <td>1</td>
        <td>1</td>
        <td>1</td>
      </tr>
      <tr>
        <td>last</td>
        <td>last</td>
        <td>last</td>
        <td>last</td>
      </tr>
    </tbody>
  </table>
</div>
<div class="footer"></div>


问:
Make the button inactive if the input length is 0
I want to make the button not active if text.length <= 0, how do I set its properties and write it in the tag? In Vue js<button> Add task </button>

答:
If not active means disabled then something like this:

```<code><button :disabled="!text.length"> Add task </button>
</code>```

Body:
If not active means disabled then something like this:

<button :disabled="!text.length"> Add task </button>


问:
Custom tooltip with Rxjs
I'm trying to implement my custom tooltip on a diagram using vis-network library and RXJS.

The main principle is:

One observable diagramElementHover$ to show the tooltip

One observable hideTooltipObs$ to hide the tooltip (the emitted value is null)

I want the tooltip to wait 1000ms to check if the mouse pointer is still under the element to be displayed (clear the tooltip if the pointer has gone before that delay)

The tooltip display uses the *ngIf directive with tooltip value

For now, the problem is that I can't prevent the tooltip to be shown if the user hovers one element and stays less that 1 second (then the tooltip is not hidden, unless you enter another node)

Globally, my implementation looks like this:

this.sub = merge(
    diagramElementHover$.pipe(
        mergeMap(event => of(event).pipe(delay(1000))),
        repeat()
    ),
        hideTooltipObs$
    ).pipe(
        tap(tooltip => this.tooltip = tooltip)
    )
```

I tried to use the takeUntil() operator but without success...
Can you guide me through this?

Here is the stackblitz example.

答:
Here could be an approach in which you don't have to manually subscribe:

app.component.html

{{ tooltip.text }}

```

<h3>app.component.ts</h3>

<pre class="lang-js prettyprint-override"><code>const diagramElementHover$ = merge(
    fromEventPattern(handler => this.network.on('hoverNode', handler))
      .pipe(
        map<any, any>(params => ({ event: params.event, element: this.nodes.find(n => n.id === params.node) }))
      ),

    fromEventPattern(handler => this.network.on('hoverEdge', handler))
      .pipe(
        map<any, any>(params => ({ event: params.event, element: this.edges.find(e => e.id === params.edge) }))
      ),
    ).pipe(
        map(obj => ({
          text: obj.element.label,
          x: obj.event.offsetX + 10,
          y: obj.event.offsetY + 10
        })
      )
    );

  const hideTooltipObs$ = merge(
      fromEventPattern(handler => this.network.on('selectNode', handler)),
      fromEventPattern(handler => this.network.on('blurEdge', handler)),
      fromEventPattern(handler => this.network.on('blurNode', handler)),
  ).pipe(
    mapTo(null),
    tap(() => console.log('hide tooltip')),
    publish(),
    refCount(),
  );

  const showTooltip$ = diagramElementHover$.pipe(
    switchMap(
      obj =>
        timer(1000).pipe(
          takeUntil(hideTooltipObs$),
          isEmpty(),
          map(isEmpty => isEmpty ? null : obj)
        ),
    )
  );

  const hideToolTip$ = hideTooltipObs$;

  this.tooltip$ = merge(showTooltip$, hideToolTip$);
</code>```

Let's go through each relevant part.

fromEventPattern simply provides a way to convert an API to an Observable.

In the cases above, it creates an Observable that will emit whenever the handler function is called.

You can read more about it here.

const hideTooltipObs$ = merge(
    /* ... */
).pipe(
  mapTo(null),
  tap(() => console.log('hide tooltip')),
  publish(),
  refCount(),
);
```

<p><code>publish()</code> + <code>refCount()</code> will multicast the results by placing a <code>Subject</code> instance between the data producer(<code>hideTooltipObs$</code>) and the data consumers(e.g <code>hideTooltipObs$.pipe().subscribe()</code>). This is needed as <code>hideTooltipObs$</code> is subscribed in multiple places.</p>

<pre class="lang-js prettyprint-override"><code>const showTooltip$ = diagramElementHover$.pipe(
  switchMap(
    obj =>
      timer(1000).pipe(
        takeUntil(hideTooltipObs$),
        isEmpty(),
        map(isEmpty => isEmpty ? null : obj)
      ),
  )
);
</code>```

Whenever diagramElementHover$ emits, start a timer (timer(1000)) that will complete when either 1s has passed or hideTooltipObs$ emits(due to takeUntil). isEmpty() will emit true if the source completed without emitting any values and false otherwise.

If isEmpty === true, it means that hideTooltipObs$ emitted before 1s had passed.

Title: Custom tooltip with Rxjs

Body:
I'm trying to implement my custom tooltip on a diagram using vis-network library and RXJS.

The main principle is:

One observable diagramElementHover$ to show the tooltip

One observable hideTooltipObs$ to hide the tooltip (the emitted value is null)

I want the tooltip to wait 1000ms to check if the mouse pointer is still under the element to be displayed (clear the tooltip if the pointer has gone before that delay)

The tooltip display uses the *ngIf directive with tooltip value

For now, the problem is that I can't prevent the tooltip to be shown if the user hovers one element and stays less that 1 second (then the tooltip is not hidden, unless you enter another node)

Globally, my implementation looks like this:

this.sub = merge(
    diagramElementHover$.pipe(
        mergeMap(event => of(event).pipe(delay(1000))),
        repeat()
    ),
        hideTooltipObs$
    ).pipe(
        tap(tooltip => this.tooltip = tooltip)
    )

I tried to use the takeUntil() operator but without success...
Can you guide me through this?

Here is the stackblitz example.

Body:
Here could be an approach in which you don't have to manually subscribe:

app.component.html

<div *ngIf="tooltip$ | async as tooltip"
     class="diagram-tooltip"
     [style.top.px]="tooltip.y"
     [style.left.px]="tooltip.x">
     <p>{{ tooltip.text }}</p>
</div>

app.component.ts

const diagramElementHover$ = merge(
    fromEventPattern(handler => this.network.on('hoverNode', handler))
      .pipe(
        map<any, any>(params => ({ event: params.event, element: this.nodes.find(n => n.id === params.node) }))
      ),

    fromEventPattern(handler => this.network.on('hoverEdge', handler))
      .pipe(
        map<any, any>(params => ({ event: params.event, element: this.edges.find(e => e.id === params.edge) }))
      ),
    ).pipe(
        map(obj => ({
          text: obj.element.label,
          x: obj.event.offsetX + 10,
          y: obj.event.offsetY + 10
        })
      )
    );

  const hideTooltipObs$ = merge(
      fromEventPattern(handler => this.network.on('selectNode', handler)),
      fromEventPattern(handler => this.network.on('blurEdge', handler)),
      fromEventPattern(handler => this.network.on('blurNode', handler)),
  ).pipe(
    mapTo(null),
    tap(() => console.log('hide tooltip')),
    publish(),
    refCount(),
  );

  const showTooltip$ = diagramElementHover$.pipe(
    switchMap(
      obj =>
        timer(1000).pipe(
          takeUntil(hideTooltipObs$),
          isEmpty(),
          map(isEmpty => isEmpty ? null : obj)
        ),
    )
  );

  const hideToolTip$ = hideTooltipObs$;

  this.tooltip$ = merge(showTooltip$, hideToolTip$);

Let's go through each relevant part.

fromEventPattern simply provides a way to convert an API to an Observable.

In the cases above, it creates an Observable that will emit whenever the handler function is called.

You can read more about it here.

const hideTooltipObs$ = merge(
    /* ... */
).pipe(
  mapTo(null),
  tap(() => console.log('hide tooltip')),
  publish(),
  refCount(),
);

publish() + refCount() will multicast the results by placing a Subject instance between the data producer(hideTooltipObs$) and the data consumers(e.g hideTooltipObs$.pipe().subscribe()). This is needed as hideTooltipObs$ is subscribed in multiple places.

const showTooltip$ = diagramElementHover$.pipe(
  switchMap(
    obj =>
      timer(1000).pipe(
        takeUntil(hideTooltipObs$),
        isEmpty(),
        map(isEmpty => isEmpty ? null : obj)
      ),
  )
);

Whenever diagramElementHover$ emits, start a timer (timer(1000)) that will complete when either 1s has passed or hideTooltipObs$ emits(due to takeUntil). isEmpty() will emit true if the source completed without emitting any values and false otherwise.

If isEmpty === true, it means that hideTooltipObs$ emitted before 1s had passed.


问:
How to call a function after other function in angular 8
I have 2 functions one func1 and func2, I need to execute the func2 only after func1 will execute. Here the code below

home.component.ts

```<code>import { Component, OnInit } from '@angular/core';
@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css']
})

export class HomeComponent implements OnInit {

 constructor() { }

 ngOnInit() {
    this.func1();
    this.func2();
 }

 func1(){
    console.log('function1')
 }

 func2(){
    console.log('function2')
 }
}
</code>```

答:
There are a few things you need to know here.
If your func1 is not an asynchronous function then you don't need to do anything as the func2() will only execute after completion of func1(). But if the func2() is an asynchronous function where you do some HTTP operation then you need to use call back function.

Let me show you.

Type - 1 (using async and await)

```<code>async ngOnInit() {
  await this.func1();
  this.func2();
}

func1(){
  this.func1().then(() => {
    this.func2();
  })
}

func2(){
  console.log('function2')
}
</code>```

Type - 2 (using then)

```<code>ngOnInit() {
  this.func1().then(() => {
    this.func2();
  })
}

func1(){
  return new Promise((resolve, reject) => {
     return resolve(true);
  });
}

func2(){
  console.log('function2')
}
</code>```

Type - 2 (Simpler one)

```<code>function func2(){
  func1()
  // now wait for firstFunction to finish...
  // do something else
};
</code>```

There are multiple ways to handle this situation depending on first function.

Body:
I have 2 functions one func1 and func2, I need to execute the func2 only after func1 will execute. Here the code below

home.component.ts

import { Component, OnInit } from '@angular/core';
@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css']
})

export class HomeComponent implements OnInit {

 constructor() { }

 ngOnInit() {
    this.func1();
    this.func2();
 }

 func1(){
    console.log('function1')
 }

 func2(){
    console.log('function2')
 }
}

Body:
There are a few things you need to know here.
If your func1 is not an asynchronous function then you don't need to do anything as the func2() will only execute after completion of func1(). But if the func2() is an asynchronous function where you do some HTTP operation then you need to use call back function.

Let me show you.

Type - 1 (using async and await)

async ngOnInit() {
  await this.func1();
  this.func2();
}

func1(){
  this.func1().then(() => {
    this.func2();
  })
}

func2(){
  console.log('function2')
}

Type - 2 (using then)

ngOnInit() {
  this.func1().then(() => {
    this.func2();
  })
}

func1(){
  return new Promise((resolve, reject) => {
     return resolve(true);
  });
}

func2(){
  console.log('function2')
}

Type - 2 (Simpler one)

function func2(){
  func1()
  // now wait for firstFunction to finish...
  // do something else
};

There are multiple ways to handle this situation depending on first function.


问:
Does mpmath support very small numbers? (Python)
I'm trying to solve a numerical maths problem, and for that I need python to handle very small numbers. For that, I installed mpmath.

It doesn't quite work as desired though.
Mpmath is able to handle 1e-300 but not 1e-400 (10^-300 but not 10^-400 respectively)

In the head I have

```<code>from mpmath import mp
from mpmath import mpf

mp.dps = 500
</code>```

If I type

```<code>x = mpf(1e-300)
print(x)
</code>```

I get a thousand digit number, that is close to 1e-300 (which is what I want)

However, if I now type

```<code>y = mpf(1e-400)
print(y)
</code>```

I get the result: 0.0, which is not what I want.

I tried to ramp up the decimal precision (e.g. mp.dps = 3000) but it didn't help, I still got zero in the second case.

Is there a way to circumvent this, or is mpmath just unable to do handle 1e-400?

答:
Issue is you're running into the accuracy of double floating point numbers

Doubles have a range of 1e-300 to 1e+300.

Provide the number to mpmath as a string so it converts it rather than passing a float

Meaning change from:

```<code>y = mpmath(1e-400) # 1e-400 becomes 0 as a
                   # float due to limited
                   # doubles accuracy
</code>```

To:

```<code>y = mpmath('1e-400')
</code>```

Test

```<code>from mpmath import mp
from mpmath import mpf

mp.dps = 500

y = mpf('1e-400')
for k in range(10):
  print(k*y)
</code>```

Output

```<code>1.0e-400
2.0e-400
3.0e-400
4.0e-400
5.0e-400
6.0e-400
7.0e-400
8.0e-400
9.0e-400
</code>```

Body:
I'm trying to solve a numerical maths problem, and for that I need python to handle very small numbers. For that, I installed mpmath.

It doesn't quite work as desired though.
Mpmath is able to handle 1e-300 but not 1e-400 (10^-300 but not 10^-400 respectively)

In the head I have

from mpmath import mp
from mpmath import mpf

mp.dps = 500

If I type

x = mpf(1e-300)
print(x)

I get a thousand digit number, that is close to 1e-300 (which is what I want)

However, if I now type

y = mpf(1e-400)
print(y)

I get the result: 0.0, which is not what I want.

I tried to ramp up the decimal precision (e.g. mp.dps = 3000) but it didn't help, I still got zero in the second case.

Is there a way to circumvent this, or is mpmath just unable to do handle 1e-400?

Body:
Issue is you're running into the accuracy of double floating point numbers

Doubles have a range of 1e-300 to 1e+300.

Provide the number to mpmath as a string so it converts it rather than passing a float

Meaning change from:

y = mpmath(1e-400) # 1e-400 becomes 0 as a
                   # float due to limited
                   # doubles accuracy

To:

y = mpmath('1e-400')

Test

from mpmath import mp
from mpmath import mpf

mp.dps = 500

y = mpf('1e-400')
for k in range(10):
  print(k*y)

Output

1.0e-400
2.0e-400
3.0e-400
4.0e-400
5.0e-400
6.0e-400
7.0e-400
8.0e-400
9.0e-400


问:
Adding multiple key values to a queue for BFS in python
I am implementing BFS in python. In order to add nodes of my graph to my queue, I am using the following lines of code:

graph = {}
graph['you'] = 'Alice','Bob','Claire'
search_queue+=graph['you']
This perfectly stores my key values as separate elements in the queue. However, If my key has a single value, for eg
graph['Alice'] = 'Peggy'
search_queue+=graph['Alice']
The output is a queue with 'p','e','g','g','y' stored as separate values. I am aware that append() should be used to add an element to a queue or a list, but I need to add both multiple and single values for different keys. Is there a way to do this differently? So far, I have used ',' at the end of the value like graph['Alice'] = 'Peggy', to process key value that can be concatenated with a queue or a list without losing the string. But I am sure that there must be a better way. Here is my code-

```<code>from collections import deque

def congratulations_msg():
    '''message to display success'''
    print('Congratulations, we have found the element')

graph = {}
graph['you'] = 'Alice','Bob','Claire',
graph['Bob'] = 'Anuj','Peggy',
graph['Claire'] = 'Johnny','Thom',
graph['Alice'] = 'Peggy',
graph['Peggy']='you',

# Assign element to be searched
seller='Thom'

#Create a dequeue to store nodes
search_queue = deque()

# Initialize queue with values of 'you' key
search_queue+=graph['you']

checked_elements=[]

# Loop while queue is not empty
while search_queue:

    print(search_queue)
    #Check if element in queue already processed
    if  search_queue[0] in checked_elements:
        search_queue.popleft()
        continue
    #Check if queue element is the one that we are looking for
    elif seller == search_queue[0]:
         congratulations_msg()
         break

    else:
    #Store store processed queue element and add its nodes to the queue
         checked_elements+= search_queue[0],
         popped_element = search_queue.popleft()

         checked_elements+= popped_element
         search_queue+=graph.get(popped_element,'')
</code>```

答:
You could define a small function that handles enumerating the right values. Assuming the value elements are either a string or a list of strings

def get_values(element):
    if isinstance(element, str):
        # its a string
        return element,
    return element

# usage
search_queue += get_values(graph['alice'])
```

<p>If you don't assume that the individual elements are string the solution could be more involved. You could use </p>

<pre class="lang-py prettyprint-override"><code>>>> from collections.abc import Iterator
>>> isinstance('abc', Iterator)
False
>>> isinstance(('abc',), Iterator)
True
</code>```

to check if the value is a nested iterator. But at that point I'd seriously consider thinking closely if the types of the dict values can't be homogeneous.

Body:
I am implementing BFS in python. In order to add nodes of my graph to my queue, I am using the following lines of code:

graph = {}
graph['you'] = 'Alice','Bob','Claire'
search_queue+=graph['you']
This perfectly stores my key values as separate elements in the queue. However, If my key has a single value, for eg
graph['Alice'] = 'Peggy'
search_queue+=graph['Alice']
The output is a queue with 'p','e','g','g','y' stored as separate values. I am aware that append() should be used to add an element to a queue or a list, but I need to add both multiple and single values for different keys. Is there a way to do this differently? So far, I have used ',' at the end of the value like graph['Alice'] = 'Peggy', to process key value that can be concatenated with a queue or a list without losing the string. But I am sure that there must be a better way. Here is my code-

from collections import deque

def congratulations_msg():
    '''message to display success'''
    print('Congratulations, we have found the element')

graph = {}
graph['you'] = 'Alice','Bob','Claire',
graph['Bob'] = 'Anuj','Peggy',
graph['Claire'] = 'Johnny','Thom',
graph['Alice'] = 'Peggy',
graph['Peggy']='you',

# Assign element to be searched
seller='Thom'

#Create a dequeue to store nodes
search_queue = deque()

# Initialize queue with values of 'you' key
search_queue+=graph['you']

checked_elements=[]

# Loop while queue is not empty
while search_queue:

    print(search_queue)
    #Check if element in queue already processed
    if  search_queue[0] in checked_elements:
        search_queue.popleft()
        continue
    #Check if queue element is the one that we are looking for
    elif seller == search_queue[0]:
         congratulations_msg()
         break

    else:
    #Store store processed queue element and add its nodes to the queue
         checked_elements+= search_queue[0],
         popped_element = search_queue.popleft()

         checked_elements+= popped_element
         search_queue+=graph.get(popped_element,'')

Body:
You could define a small function that handles enumerating the right values. Assuming the value elements are either a string or a list of strings

def get_values(element):
    if isinstance(element, str):
        # its a string
        return element,
    return element

# usage
search_queue += get_values(graph['alice'])

If you don't assume that the individual elements are string the solution could be more involved. You could use

>>> from collections.abc import Iterator
>>> isinstance('abc', Iterator)
False
>>> isinstance(('abc',), Iterator)
True

to check if the value is a nested iterator. But at that point I'd seriously consider thinking closely if the types of the dict values can't be homogeneous.


问:
Can a class method call an instance method in python?
I am learning to program a binary tree and I want to check if a given number is already in the tree so when I try to add the same number it stops.

```<code>class Node:

    exist = True

    @classmethod
    def num_exist(cls, n):
        cls.exist = cls.find(n)

    def find(self, n):

        if n != self.value:
            if n < self.value:
                if self.right != None:
                    self.right.find(n)

                else:
                    return False

            if n > self.value:
                if self.left != None:
                    self.left.find(n)

                else:
                    return False
        else:
            return self

    def add(self, n):

        self.num_exist(n)

        if self.exist == False:
            if n != self.value:
                if n < self.value:
                    if self.right != None:
                    self.add(n)

                else:
                    self.right = Node(n)

            if n > self.value:
                if self.left != None:
                    self.add(n)

                else:
                    self.left = Node(n)
</code>```

The problem here is that when I call the function num_exist() it gives me the following error:

```<code>TypeError: find() missing 1 required positional argument: 'n'
</code>```

I suppose this error is because the self parameter hasn't been passed, but I don't know how to do it or if it is possible to pass the function find() to the @classmethod. I'm pretty newbie in oop.

答:
Can a class method call an instance method? Technically yes, as long as you pass in a reference to that instance:

```<code>class MyClass:
    def __init__(self, a):
        self.a = a

    def print_a(self):
        print(self.a)

    @classmethod
    def class_print_a(cls, inst):
        inst.print_a()

my_instance = MyClass(a=1)
MyClass.class_print_a(my_instance)  # output: 1
</code>```

... Although you really should have a good reason for doing so. If your class method depends on a particular instance, then it's not really a class method.

Body:
I am learning to program a binary tree and I want to check if a given number is already in the tree so when I try to add the same number it stops.

class Node:

    exist = True

    @classmethod
    def num_exist(cls, n):
        cls.exist = cls.find(n)

    def find(self, n):

        if n != self.value:
            if n < self.value:
                if self.right != None:
                    self.right.find(n)

                else:
                    return False

            if n > self.value:
                if self.left != None:
                    self.left.find(n)

                else:
                    return False
        else:
            return self

    def add(self, n):

        self.num_exist(n)

        if self.exist == False:
            if n != self.value:
                if n < self.value:
                    if self.right != None:
                    self.add(n)

                else:
                    self.right = Node(n)

            if n > self.value:
                if self.left != None:
                    self.add(n)

                else:
                    self.left = Node(n)

The problem here is that when I call the function num_exist() it gives me the following error:

TypeError: find() missing 1 required positional argument: 'n'

I suppose this error is because the self parameter hasn't been passed, but I don't know how to do it or if it is possible to pass the function find() to the @classmethod. I'm pretty newbie in oop.

Body:
Can a class method call an instance method? Technically yes, as long as you pass in a reference to that instance:

class MyClass:
    def __init__(self, a):
        self.a = a

    def print_a(self):
        print(self.a)

    @classmethod
    def class_print_a(cls, inst):
        inst.print_a()

my_instance = MyClass(a=1)
MyClass.class_print_a(my_instance)  # output: 1

... Although you really should have a good reason for doing so. If your class method depends on a particular instance, then it's not really a class method.


问:
Tesseract always missing a text line in picture
I am trying to extract data from a picture with OCR. I use Tesseract API in C++ to achieve this.

The original picture is this:

Now the for me important data is this:

However the marked blue line is never recognized does not matter what I try.

The code to analyze the picture with tesseract looks like this:

```<code>std::string readFromFile(const std::string& filename)
{
    tesseract::TessBaseAPI *api = new tesseract::TessBaseAPI();
    api->SetPageSegMode(tesseract::PSM_AUTO);
    if (api->Init("folder_to_tessdata", "deu+eng")) {
        fprintf(stderr, "Could not initialize tesseract.\n");
        exit(1);
    }

    // Open input image with leptonica library
    Pix *image = pixRead(filename.c_str());
    api->SetImage(image);
    // Get OCR result

    char *outText = api->GetUTF8Text();

    std::string result{ outText };

    api->End();
    delete[] outText;
    pixDestroy(&image);

    return result;
}
</code>```

I tryed to improve the accuracy by preprocessing the image like it is suggested in this question: image processing to improve tesseract OCR accuracy

The Code for the preprocessing:

```<code>cv::Mat image;
image = cv::imread(filename, cv::IMREAD_COLOR);
cv::resize(image, image, cv::Size{}, 1.2, 1.2, cv::INTER_CUBIC);

cv::cvtColor(image, image, cv::COLOR_BGR2GRAY);

auto kernel = cv::Mat(1, 1, CV_8UC1, cv::Scalar(1));
cv::dilate(image, image, kernel);
cv::erode(image, image, kernel);

cv::Mat filter;
cv::bilateralFilter(image, filter, 5, 75, 75);

cv::threshold(filter, image, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU);
</code>```

Am I missing something? Can I tweak Tesseract itself more or should I change the preprocessing of the image?

答:
Tesseract has tendency to drop lines or fragments of text in several circumstances:

There are some non-text things that interfere (lines, artefacts, lighting gradients)

There are too many things that are not recognized as character with enough certainty

Line is uneven (bumps) / badly aligned, also distortions like perspective

There are too big spaces inside line

Text is too near of other text, especially if font size is also uneven

I won't post ready solution or code but can write what I would try out basing on my experience with Tesseract:

Do not threshold scanned images, it often makes worse effect as information is lost, it has more sense when text is not scanned but a photo with light/shadow gradients etc. (in such scenes adaptive threshold or other filters + threshold works relatively well). Otherwise - no reason to do that, Tesseract does some binarization internally (which works rather badly for lightning/shadows gradients as it's not adaptive but rather well for scanned images).

Try to check how it goes with different DPI / image sizes. May work better if you find out optimal (it's more about older version of Tesseract, in current it matters less).

EDIT: To resize in opencv can use:

```<code>cv::resize(inImg, outImg, cv::Size(), 0.7, 0.7);
</code>```

Removing that rectangles around text may help.

It may be done by line detection or rectangle detection or contour detection, filtering by length/size relative to image width (or absolute if it's always same) and drawing white on it so it's removed.

EDIT: There are multiple rectangle detection tutorials on the internet. Most of those detect and draw. For example alyssaq / opencv / squares.cpp on Github. You can detect squares, then filter them by size in c++ and then draw them white so it should draw white over black and remove them effectively.

Alternatively it may be done by copy with masking, but it may be harder to write and worse in performance

It might be helpful to process line by line. If scan is always well-aligned or can align it (for example by measuring angles of boxes) then you can make histogram of dark pixels numbers by Y (vertical) and find out spaces between lines, cut those lines out, add some white padding to each of them and process each of them one by one. Of course all that after removal of boxes lines. It's worse when it comes to performance but looses lines more rarely.

EDIT: for histogram over Y and finding spaces between lines please see this question Find all peaks for Mat() in OpenCV C++ - it should be done similarly but on other axis.

for cropping please see this question and answers How to crop a CvMat in OpenCV?

for adding padding there is a copyMakeBorder() method, please see Adding borders to your images in documentation.

You may also try to find where the text is by other methods and process each field/word individually (which is even less efficient but less likely to drop text). Then can connect back into lines (by matching by Y into lines and sorting in line by X).

may do erode on thresholded image to get letters clumped together, find contours, filter them, take ones of specific sizes to process, cut them out with mask, padd them with white, process each one

EDIT: for this you may find question and answers from this link useful: Extracting text OpenCV

may use that rectangles that you have visible - find their positions with shape detection, cut out content, process individually

You may also try to use Tesseract to get words or symbols bounding boxes + certainties instead of text which is less likely to drop some parts of text (but still it can do that). Then can connect boxes into lines on your own (which is rather hard problem if you have a photo with uneven sheet of paper + different font sizes + perspective but rather easy if you have well aligned scan of normal document). You will also probably need to set a threshold to filter out artifacts that may appear.

EDIT: To find out words or symbols can use this code:

```<code>tesseract::ResultIterator *iter = tess.GetIterator();
tesseract::PageIteratorLevel level = tesseract::RIL_WORD; // may use RIL_SYMBOL

if (iter != 0) {
  do {
    const char *word = iter->GetUTF8Text(level);
    float conf = iter->Confidence(level);
    int x1, y1, x2, y2;
    iter->BoundingBox(level, &x1, &y1, &x2, &y2);

    if (word) {
      printf("word: '%s';  \tconfidence: %.2f\t bounding box: [%d,%d,%d,%d]\n", word, conf, x1, y1, x2, y2);

      // ... use that info

      delete[] word;
    }
  } while (iter->Next(level));
}
</code>```

Code not tested, proper code may differ for different version of Tesseract, this is for 3.0.

Last but not least - if not all images are well aligned scans then of course need to do some processing to make it well aligned and deskewed, also you would need to remove gradients/shadows if images are done by photo instead of scanner. Nevertheless on example I see that those are relatively good scans so no need for that here (I see a problem with some characters that are not printed/xero-ed well, will be hard to do anything about that one).

EDIT: won't put examples or links for this point as it's very broad topic and depends on quality of images, how those are done, how text looks, what is the background etc.

Body:
I am trying to extract data from a picture with OCR. I use Tesseract API in C++ to achieve this.

The original picture is this:

Now the for me important data is this:

However the marked blue line is never recognized does not matter what I try.

The code to analyze the picture with tesseract looks like this:

std::string readFromFile(const std::string& filename)
{
    tesseract::TessBaseAPI *api = new tesseract::TessBaseAPI();
    api->SetPageSegMode(tesseract::PSM_AUTO);
    if (api->Init("folder_to_tessdata", "deu+eng")) {
        fprintf(stderr, "Could not initialize tesseract.\n");
        exit(1);
    }

    // Open input image with leptonica library
    Pix *image = pixRead(filename.c_str());
    api->SetImage(image);
    // Get OCR result

    char *outText = api->GetUTF8Text();

    std::string result{ outText };

    api->End();
    delete[] outText;
    pixDestroy(&image);

    return result;
}

I tryed to improve the accuracy by preprocessing the image like it is suggested in this question: image processing to improve tesseract OCR accuracy

The Code for the preprocessing:

cv::Mat image;
image = cv::imread(filename, cv::IMREAD_COLOR);
cv::resize(image, image, cv::Size{}, 1.2, 1.2, cv::INTER_CUBIC);

cv::cvtColor(image, image, cv::COLOR_BGR2GRAY);

auto kernel = cv::Mat(1, 1, CV_8UC1, cv::Scalar(1));
cv::dilate(image, image, kernel);
cv::erode(image, image, kernel);

cv::Mat filter;
cv::bilateralFilter(image, filter, 5, 75, 75);

cv::threshold(filter, image, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU);

Am I missing something? Can I tweak Tesseract itself more or should I change the preprocessing of the image?

Body:
Tesseract has tendency to drop lines or fragments of text in several circumstances:

There are some non-text things that interfere (lines, artefacts, lighting gradients)

There are too many things that are not recognized as character with enough certainty

Line is uneven (bumps) / badly aligned, also distortions like perspective

There are too big spaces inside line

Text is too near of other text, especially if font size is also uneven

I won't post ready solution or code but can write what I would try out basing on my experience with Tesseract:

Do not threshold scanned images, it often makes worse effect as information is lost, it has more sense when text is not scanned but a photo with light/shadow gradients etc. (in such scenes adaptive threshold or other filters + threshold works relatively well). Otherwise - no reason to do that, Tesseract does some binarization internally (which works rather badly for lightning/shadows gradients as it's not adaptive but rather well for scanned images).

Try to check how it goes with different DPI / image sizes. May work better if you find out optimal (it's more about older version of Tesseract, in current it matters less).

EDIT: To resize in opencv can use:

cv::resize(inImg, outImg, cv::Size(), 0.7, 0.7);

Removing that rectangles around text may help.

It may be done by line detection or rectangle detection or contour detection, filtering by length/size relative to image width (or absolute if it's always same) and drawing white on it so it's removed.

EDIT: There are multiple rectangle detection tutorials on the internet. Most of those detect and draw. For example alyssaq / opencv / squares.cpp on Github. You can detect squares, then filter them by size in c++ and then draw them white so it should draw white over black and remove them effectively.

Alternatively it may be done by copy with masking, but it may be harder to write and worse in performance

It might be helpful to process line by line. If scan is always well-aligned or can align it (for example by measuring angles of boxes) then you can make histogram of dark pixels numbers by Y (vertical) and find out spaces between lines, cut those lines out, add some white padding to each of them and process each of them one by one. Of course all that after removal of boxes lines. It's worse when it comes to performance but looses lines more rarely.

EDIT: for histogram over Y and finding spaces between lines please see this question Find all peaks for Mat() in OpenCV C++ - it should be done similarly but on other axis.

for cropping please see this question and answers How to crop a CvMat in OpenCV?

for adding padding there is a copyMakeBorder() method, please see Adding borders to your images in documentation.

You may also try to find where the text is by other methods and process each field/word individually (which is even less efficient but less likely to drop text). Then can connect back into lines (by matching by Y into lines and sorting in line by X).

may do erode on thresholded image to get letters clumped together, find contours, filter them, take ones of specific sizes to process, cut them out with mask, padd them with white, process each one

EDIT: for this you may find question and answers from this link useful: Extracting text OpenCV

may use that rectangles that you have visible - find their positions with shape detection, cut out content, process individually

You may also try to use Tesseract to get words or symbols bounding boxes + certainties instead of text which is less likely to drop some parts of text (but still it can do that). Then can connect boxes into lines on your own (which is rather hard problem if you have a photo with uneven sheet of paper + different font sizes + perspective but rather easy if you have well aligned scan of normal document). You will also probably need to set a threshold to filter out artifacts that may appear.

EDIT: To find out words or symbols can use this code:

tesseract::ResultIterator *iter = tess.GetIterator();
tesseract::PageIteratorLevel level = tesseract::RIL_WORD; // may use RIL_SYMBOL

if (iter != 0) {
  do {
    const char *word = iter->GetUTF8Text(level);
    float conf = iter->Confidence(level);
    int x1, y1, x2, y2;
    iter->BoundingBox(level, &x1, &y1, &x2, &y2);

    if (word) {
      printf("word: '%s';  \tconfidence: %.2f\t bounding box: [%d,%d,%d,%d]\n", word, conf, x1, y1, x2, y2);

      // ... use that info

      delete[] word;
    }
  } while (iter->Next(level));
}

Code not tested, proper code may differ for different version of Tesseract, this is for 3.0.

Last but not least - if not all images are well aligned scans then of course need to do some processing to make it well aligned and deskewed, also you would need to remove gradients/shadows if images are done by photo instead of scanner. Nevertheless on example I see that those are relatively good scans so no need for that here (I see a problem with some characters that are not printed/xero-ed well, will be hard to do anything about that one).

EDIT: won't put examples or links for this point as it's very broad topic and depends on quality of images, how those are done, how text looks, what is the background etc.


问:
NCRONTAB for every first tuesday of every month for an Azure Function
How could I create an timer trigger with Azure Functions (version 3 and .NET Core) that must be executed every first Tuesday from every month at 8 AM. Starting from now (05/08/2020) this must be the next five occurrences:

2020/06/02 Tue 08:00:00

2020/07/07 Tue 08:00:00

2020/08/04 Tue 08:00:00

2020/09/01 Tue 08:00:00

2020/10/06 Tue 08:00:00

By using www.cronmaker.com, I've next NCRONTAB:

0 0 8 ? 1/1 TUE#1 *
```

But then I've next exception:

The schedule expression 0 0 8 ? 1/1 Tue#1 * was not recognized as a valid CRON expression or TimeSpan string.

Then I've start changing the CRON expression to next varations:

CORN
Result

0 0 8 ? 1/1 Tue#1
Error from above

0 0 8 * 1/1 Tue#1
Error from above

0 0 8 1/1 Tue#1 *
Error from above

0 0 8 * 1/1 Tue 1
Error from above

0 0 8 ? 1/1 Tue 1
Error from above

0 0 8 * 1/1 Tue/1
2020/05/29 08:00:00 - 2020/05/30 08:00:00

0 0 8 * * Tue/2
2020/05/30 08:00:00 - 2020/06/02 08:00:00

0 0 8 * 1/1 Tue/2
2020/05/30 08:00:00 - 2020/06/02 08:00:00

0 0 8 ? 1/1 Tue/2
Error from above

So every expression I've made, would not work as expected. My question is now: What's the correct expression?

答: Unfortunately the timer trigger uses the NCrontab library, which doesn't have the concept of "first Tuesday". I think the best you can do is to set the expression to 0 0 8 * * 2 to trigger at 8am every Tuesday and have a bit of code in the actual function that returns immediately if it's not the first Tuesday of the month.

Body:
How could I create an timer trigger with Azure Functions (version 3 and .NET Core) that must be executed every first Tuesday from every month at 8 AM. Starting from now (05/08/2020) this must be the next five occurrences:

2020/06/02 Tue 08:00:00

2020/07/07 Tue 08:00:00

2020/08/04 Tue 08:00:00

2020/09/01 Tue 08:00:00

2020/10/06 Tue 08:00:00

By using www.cronmaker.com, I've next NCRONTAB:

0 0 8 ? 1/1 TUE#1 *

But then I've next exception:

The schedule expression 0 0 8 ? 1/1 Tue#1 * was not recognized as a valid CRON expression or TimeSpan string.

Then I've start changing the CRON expression to next varations:

CORN
Result

0 0 8 ? 1/1 Tue#1
Error from above

0 0 8 * 1/1 Tue#1
Error from above

0 0 8 1/1 Tue#1 *
Error from above

0 0 8 * 1/1 Tue 1
Error from above

0 0 8 ? 1/1 Tue 1
Error from above

0 0 8 * 1/1 Tue/1
2020/05/29 08:00:00 - 2020/05/30 08:00:00

0 0 8 * * Tue/2
2020/05/30 08:00:00 - 2020/06/02 08:00:00

0 0 8 * 1/1 Tue/2
2020/05/30 08:00:00 - 2020/06/02 08:00:00

0 0 8 ? 1/1 Tue/2
Error from above

So every expression I've made, would not work as expected. My question is now: What's the correct expression?


问:
Conversion from double to string in c++
I'm currently coding a project for my Computer Science module but I'm having the problem of my string value defaulting to scientific notation if there are too many decimal places in the double value.

I've tried the obvious solution with ostringstream and .str() but it makes it into notation. I have to compile to the C++98 standard, so I cannot use modern solutions like std::to_string.

I need the value to be casted into a string but it needs to maintain its formatting. any help would be appreciated.

答:
I would use:</p>

```<code>std::to_string(myDouble);
</code>```

Title: Conversion from double to string in c++

Body:
I would use:

std::to_string(myDouble);