问:
Installing a newer version of PCL on ubuntu
I would like to upgrade my PCL to a newer version to fix a problem I have with QHull related to this issue.
I'm on ubuntu so I installed PCL with sudo apt install libpcl-dev but I can only get the version 1.10.1. How can I install a newer version ?
The problem is apparently fixed by this commit. It's in the tag 1.12.1.

I know that in theory I can use cmake and build my own PCL but from what I saw with the apt install, there is a huge amount of dependencies + I will also need this particular Qhull version that they mention in the issue and commit... I'm not sure I can make this work without the package manager. Any leads on this problem ?

Thanks !

答:
In its simplest form, building and installing PCL goes likes this:

Clone the GitHub repo and cd inside it

Optionally checkout a git tag or stay on the master branch (default)

mkdir build && cd build

Run cmake with cmake ..

Build and install with make -j2 && sudo make install

For more information, see here: https://pcl.readthedocs.io/projects/tutorials/en/master/compiling_pcl_posix.html

When you previously had libpcl-dev installed, you can remove that package without (auto-)removing the dependencies, then you should have most if not all dependencies required for building from source already installed.

You didn't say which Ubuntu version you use, but judging from the version of libpcl-dev, I assume it is focal (20.04). The Qhull version installed there is fine, it already has a reentrant interface.


来源: stackexchange

问:
Is there a way to take averages from data in columns of a data frame in R?
I have a data frame where the first column represents time and the successive columns ( all 49 of them T-T) hold values at those points in time.  I'm trying to define time points t1 and t2 to take averages over within each column, and then arrange those averages in a vector to be able to do vector math with it.  In other words the vector that I'm trying to make would have the average of the values from column 2 (remember column 1 is time) over t1 and t2, followed by the average of the values from t1 to t2 of column 3, followed by the average of the values from t1 to t2 of column 4, etc.  Finally, I need to make multiple vectors (A,B, and C) for different time points, so for example maybe vector A has the averages from each column over t1 and t2, but B would have the averages from each column over t3 and t4.

I'm completely lost and largely a total noob when it comes to programming so I hope this makes sense.  Any advice is appreciated! Thanks so much :)

Not sure if this counts as a reproducible example, but in essence, I have a table like:

t
col1
col2
col3
col4

1
1.1
2.1
3.1
4.1

2
1.2
2.2
3.2
4.2

3
1.3
2.3
3.3
4.3

4
1.4
2.4
3.4
4.4

5
1.5
2.5
3.5
4.5

and I want to define time points like:
t1 = 1 and t2 = 3
so that I can take the average over those points from each column, so that the resulting vector would be of the form:

| 1.2 | 2.2 | 3.2 | 4.2 |

where each entry comes from (1.1+1.2+1.3)/3 , (2.1+2.2+2.3)/3, etc.

Again, super sorry I'm so new to this

答:
There are a few different ways to go about this. I am going to walk through one that will hopefully be easy to understand.

This problem can be broken down into two parts:

Figuring out the row numbers for the two times you are talking about

Taking the averages within those rows over all columns.

Starting with task 1, this should be fairly simple. In your example, the time value matches the row number. If that is true in your dataset too, then you can simply do:

```<code>startRow <- t1
endRow <- t2
</code>```

However, if that is not true, then you have to find those indices. You can do that in R using the match function. Namely, you would do this:

```<code>startRow <- match(t1, df$time)
endRow <- match(t2,df$time)
</code>```

Now that we have our start and end indices for our rows, we can subset our dataframe quite easily. All we have to do to get the rows we want is to ask for df[startRow:endRow,] i.e., ask for all the rows from startRow to endRow, both inclusive. Now, all we have to do is to get our averages. There are two ways I can think of. One is to use the function lapply like this:

```<code>lapply(df[startRow:endRow,],ave)
</code>```

what this does is apply the average function on each column in the dataframe. Just discard the time average since it is useless. Also, it should be noted that average returns a list of the same size that it takes in. That is ave(c(1,2,4)) returns the equivalent of c(2.33,2.33,2.33). So, if you want a x1,x2,....,xn vector, you have to do this:

```<code>averages <- lapply(df[startRow:endRow,],ave)
lapply(averages[2:length(averages)], function(x) x[1])
</code>```

averages[2:length(averages)] selects all the averages except for time, and lapply(averages[2:length(averages)], function(x) x[1]) takes each list of averages and reduces it down to 1.

The other way to do this would be with a loop. You could do something like this to get the result you want:

```<code>averages = c()
for(i in 2:dim(df)[2]){
   colAverage <- ave(df[startRow:endRow,i])[1]
   averages <- c(averages, colAverage)
}
</code>```

What you are doing here is going through each of your columns, taking the average and then adding it to the vector averages.

ContentLicense: CC BY-SA 4.0

Body:
There are a few different ways to go about this. I am going to walk through one that will hopefully be easy to understand.

This problem can be broken down into two parts:

Figuring out the row numbers for the two times you are talking about

Taking the averages within those rows over all columns.

Starting with task 1, this should be fairly simple. In your example, the time value matches the row number. If that is true in your dataset too, then you can simply do:

startRow <- t1
endRow <- t2

However, if that is not true, then you have to find those indices. You can do that in R using the match function. Namely, you would do this:

startRow <- match(t1, df$time)
endRow <- match(t2,df$time)

Now that we have our start and end indices for our rows, we can subset our dataframe quite easily. All we have to do to get the rows we want is to ask for df[startRow:endRow,] i.e., ask for all the rows from startRow to endRow, both inclusive. Now, all we have to do is to get our averages. There are two ways I can think of. One is to use the function lapply like this:

lapply(df[startRow:endRow,],ave)

what this does is apply the average function on each column in the dataframe. Just discard the time average since it is useless. Also, it should be noted that average returns a list of the same size that it takes in. That is ave(c(1,2,4)) returns the equivalent of c(2.33,2.33,2.33). So, if you want a x1,x2,....,xn vector, you have to do this:

averages <- lapply(df[startRow:endRow,],ave)
lapply(averages[2:length(averages)], function(x) x[1])

averages[2:length(averages)] selects all the averages except for time, and lapply(averages[2:length(averages)], function(x) x[1]) takes each list of averages and reduces it down to 1.

The other way to do this would be with a loop. You could do something like this to get the result you want:

averages = c()
for(i in 2:dim(df)[2]){
   colAverage <- ave(df[startRow:endRow,i])[1]
   averages <- c(averages, colAverage)
}

What you are doing here is going through each of your columns, taking the average and then adding it to the vector averages.


问:
Testing a NodeJS function that connects to SQL Server through Tedious with Jest, throws error: Cannot redefine property: Connection
Trying to test a Tedious connector function with Jest.

In code-file db_server.js I have this function below, it works as expected.

```<code>const AWS = require('aws-sdk')
const tedious = require('tedious')
const Request = require('tedious').Request;
const Connection = require('tedious').Connection;

exports.execSQLCmd = async function (conn_store, cmd) {
let config = await exports.getParameter(conn_store)
let conn_cfg = JSON.parse(config)

//connect
const connection = new Connection(conn_cfg);
connection.on('connect', function (err) {
    if (err) {
        console.log('CONNECTION ERROR: ' + err);
    }

    console.log('CONNECTED TO: ' + conn_cfg.server);
    executeStatement();
});
connection.connect();

//execute the sql command
let result = '';
function executeStatement() {
    let request = new Request(cmd, function (err) {
        if (err) {
            console.log('REQUEST ERROR: ' + err);
        }
    });
    //add three event hooks to the request
    request.on('row', function (columns) {
        columns.forEach(function (column) {
            result += (column.value === null ? '' : column.value) + ',';
        });
        result = result.replace(/,$/, '\r\n')
    });
    request.on('done', function (rowCount, more) {
        console.log('SQL COMMAND COMPLETED: ' + rowCount + ' rows returned');
    });
    request.on('requestCompleted', function (rowCount, more) {
        connection.close();
        console.log('CONNECTION TO SERVER CLOSED');
    });

    connection.execSql(request);
}

return result;

}

exports.Request = Request
exports.Connection = Connection
exports.tedious = tedious
</code>```

In the test file index.spec.js, I have the following test:

```<code>describe('Test execSQLCmd', () => {
const server = require("../src/db_server.js")

afterEach(() => {
  jest.restoreAllMocks();
});

test('should query sql', async () => {
server.getParameter = jest.fn().mockReturnValue('{"xxx":123,"yyy":"hello"}')
server.execSQLCmd = jest.fn().mockReturnThis()
const TedConnect = jest.spyOn(server.tedious, 'Connection').mockReturnValue(jest.fn(() => ({
             connect: () => {},
             on: (connect, cb) => cb(),
             close: () => {},
             execSql: () => {}
  })));

  const TedRequest = jest.spyOn(server.tedious, 'Request').mockReturnValue(jest.fn(() => ({
              constructor: (sqlString, cb) => cb('err', null, null),
              on: [
                    (row, cb)=> cb('columns'),
                    (done, cb)=> cb('rowCount', 'more'),
                    (requestCompleted, cb) => cb('rowCount', 'more')
                  ]
  })));

  let exec = server.execSQLCmd("/pstore/name", "select 1")
  expect(TedConnect).toBeCalledTimes(1)
  expect(TedRequest).toBeCalledTimes(1)

})

})
</code>```

When I try to run the test, I get this error:

Test execSQLCmd › should query sql

```<code>TypeError: Cannot redefine property: Connection
    at Function.defineProperty (<anonymous>)

  298 |     server.getParameter = jest.fn().mockReturnValue('{"xxx":123,"yyy":"hello"}')
  299 |     server.execSQLCmd = jest.fn().mockReturnThis()
> 300 |     const TedConnect = jest.spyOn(server.tedious, 'Connection').mockReturnValue(jest.fn(() => ({
      |                             ^
  301 |                  connect: () => {},
  302 |                  on: (connect, cb) => cb(),
  303 |                  close: () => {},

  at ModuleMockerClass.spyOn (node_modules/jest-mock/build/index.js:826:16)
  at Object.<anonymous> (__tests__/index.spec.js:300:29)

  Test Suites: 1 failed, 1 total

"tedious": "^14.1.0"
"jest": "^26.6.3",
</code>```

I'm not seeing why this test fails.

Any help appreciated, thanks!

EDIT

Above error not happening after the fiollowing Test changes:

```<code>test('should query sql', async () => {
    server.getParameter = jest.fn().mockReturnValue('{"xxx":123,"yyy":"hello"}')
    server.execSQLCmd = jest.fn().mockReturnThis()
    server.Connection = jest.fn().mockReturnValue(jest.fn(() => ({
  connect: () => {},
  on: (connect, cb) => cb(),
  close: () => {},
  execSql: () => {}
})))

server.Request = jest.fn().mockReturnValue(jest.fn(() => ({
  constructor: (sqlString, cb) => cb('err', null, null),
  //addParameter: (name, type, value) => {},
  on: [
        (row, cb)=> cb('columns'),
        (done, cb)=> cb('rowCount', 'more'),
        (requestCompleted, cb) => cb('rowCount', 'more')
      ]
  })))

  let exec = server.execSQLCmd("/pstore/name", "select 1")
  expect(server.Connection).toBeCalledTimes(1)
  expect(server.Request).toBeCalledTimes(1)

 })
</code>```

However, now server.execSQLCmd does't run, I cannot step into it with debug, exists right away and returns a large mock object.

Anyone see what I'm doing wrong here?

Thanks!

答:
```<code>exports.execSQLCmd = async function (conn_store, cmd) {

    let config = await exports.getParameter(conn_store)
    let conn_cfg = JSON.parse(config)

    //connect
    exports.connect_exec(conn_cfg, cmd);

    return result;
}

function connect_exec(conn_cfg, cmd) {
    const connection = exports.get_connection(conn_cfg);
    exports.on_connect(connection, cmd);
    connection.connect();
    return connection;
}

function on_connect(connection, cmd) {
    connection.on('connect', function (err) {
        if (err) {
            console.log('CONNECTION ERROR: ' + err);
        }
        console.log('CONNECTED');
        exports.execute_statement(connection, cmd);
    });
}

function get_connection(conn_cfg) {
    return new Connection(conn_cfg);
}

function execute_statement(connection, cmd) {
    let request = exports.get_request(connection, cmd);

    connection.execSql(request);
}

function get_request(connection, cmd) {
    let request = new Request(cmd, function (err) {
        if (err) {
            console.log('REQUEST ERROR: ' + err);
        }
    });
    //add three event hooks to the request
    request.on('row', function (columns) {
        columns.forEach(function (column) {
            result += (column.value === null ? '' : column.value) + ',';
        });
        result = result.replace(/,$/, '\r\n');
    });
    request.on('done', function (rowCount, more) {
        console.log('SQL COMMAND COMPLETED: ' + rowCount + ' rows returned');
    });
    request.on('requestCompleted', function (rowCount, more) {
        connection.close();
        console.log('CONNECTION TO SERVER CLOSED');
    });
    return request;
}

exports.AWS = AWS;

exports.connect_exec = connect_exec
exports.execute_statement = execute_statement
exports.get_request = get_request
exports.get_connection = get_connection
exports.on_connect = on_connect
</code>```

Here's my test:

```<code>describe('Test execSQLCmd', async () => {
    const server = require("../src/opportunity/db_server.js")

      afterEach(() => {
      jest.restoreAllMocks();
    });

   test('should query sql', async () => {
    server.getParameter = jest.fn().mockReturnValue('{"xxx":123,"yyy":"hello"}')

    server.get_connection = jest.fn().mockReturnValue({
      connect: () => {},
      on: (connect, cb) => cb(),
      close: () => {} ,
      execSql: () => {}
    })

    server.get_request = jest.fn().mockReturnValue({
      constructor: (sqlString, cb) => cb('err', null, null),
      on: [
            (row, cb)=> cb('columns'),
            (done, cb)=> cb('rowCount', 'more'),
            (requestCompleted, cb) => cb('rowCount', 'more')
          ]
      })

      await server.execSQLCmd("/pstore/name", "select 1")
      expect(server.get_connection).toHaveBeenCalled()
      expect(server.get_request).toHaveBeenCalled()
   })
})
</code>```

Took me a day to write all the code for main functionality, ore than there is here.

Took me 2.5 days to figure out just this test. Silly!

Body:
Trying to test a Tedious connector function with Jest.

In code-file db_server.js I have this function below, it works as expected.

const AWS = require('aws-sdk')
const tedious = require('tedious')
const Request = require('tedious').Request;
const Connection = require('tedious').Connection;

exports.execSQLCmd = async function (conn_store, cmd) {
let config = await exports.getParameter(conn_store)
let conn_cfg = JSON.parse(config)

//connect
const connection = new Connection(conn_cfg);
connection.on('connect', function (err) {
    if (err) {
        console.log('CONNECTION ERROR: ' + err);
    }

    console.log('CONNECTED TO: ' + conn_cfg.server);
    executeStatement();
});
connection.connect();

//execute the sql command
let result = '';
function executeStatement() {
    let request = new Request(cmd, function (err) {
        if (err) {
            console.log('REQUEST ERROR: ' + err);
        }
    });
    //add three event hooks to the request
    request.on('row', function (columns) {
        columns.forEach(function (column) {
            result += (column.value === null ? '' : column.value) + ',';
        });
        result = result.replace(/,$/, '\r\n')
    });
    request.on('done', function (rowCount, more) {
        console.log('SQL COMMAND COMPLETED: ' + rowCount + ' rows returned');
    });
    request.on('requestCompleted', function (rowCount, more) {
        connection.close();
        console.log('CONNECTION TO SERVER CLOSED');
    });

    connection.execSql(request);
}

return result;

}

exports.Request = Request
exports.Connection = Connection
exports.tedious = tedious

In the test file index.spec.js, I have the following test:

describe('Test execSQLCmd', () => {
const server = require("../src/db_server.js")

afterEach(() => {
  jest.restoreAllMocks();
});

test('should query sql', async () => {
server.getParameter = jest.fn().mockReturnValue('{"xxx":123,"yyy":"hello"}')
server.execSQLCmd = jest.fn().mockReturnThis()
const TedConnect = jest.spyOn(server.tedious, 'Connection').mockReturnValue(jest.fn(() => ({
             connect: () => {},
             on: (connect, cb) => cb(),
             close: () => {},
             execSql: () => {}
  })));

  const TedRequest = jest.spyOn(server.tedious, 'Request').mockReturnValue(jest.fn(() => ({
              constructor: (sqlString, cb) => cb('err', null, null),
              on: [
                    (row, cb)=> cb('columns'),
                    (done, cb)=> cb('rowCount', 'more'),
                    (requestCompleted, cb) => cb('rowCount', 'more')
                  ]
  })));

  let exec = server.execSQLCmd("/pstore/name", "select 1")
  expect(TedConnect).toBeCalledTimes(1)
  expect(TedRequest).toBeCalledTimes(1)

})

})

When I try to run the test, I get this error:

Test execSQLCmd › should query sql

TypeError: Cannot redefine property: Connection
    at Function.defineProperty (<anonymous>)

  298 |     server.getParameter = jest.fn().mockReturnValue('{"xxx":123,"yyy":"hello"}')
  299 |     server.execSQLCmd = jest.fn().mockReturnThis()
> 300 |     const TedConnect = jest.spyOn(server.tedious, 'Connection').mockReturnValue(jest.fn(() => ({
      |                             ^
  301 |                  connect: () => {},
  302 |                  on: (connect, cb) => cb(),
  303 |                  close: () => {},

  at ModuleMockerClass.spyOn (node_modules/jest-mock/build/index.js:826:16)
  at Object.<anonymous> (__tests__/index.spec.js:300:29)

  Test Suites: 1 failed, 1 total

"tedious": "^14.1.0"
"jest": "^26.6.3",

I'm not seeing why this test fails.

Any help appreciated, thanks!

EDIT

Above error not happening after the fiollowing Test changes:

test('should query sql', async () => {
    server.getParameter = jest.fn().mockReturnValue('{"xxx":123,"yyy":"hello"}')
    server.execSQLCmd = jest.fn().mockReturnThis()
    server.Connection = jest.fn().mockReturnValue(jest.fn(() => ({
  connect: () => {},
  on: (connect, cb) => cb(),
  close: () => {},
  execSql: () => {}
})))

server.Request = jest.fn().mockReturnValue(jest.fn(() => ({
  constructor: (sqlString, cb) => cb('err', null, null),
  //addParameter: (name, type, value) => {},
  on: [
        (row, cb)=> cb('columns'),
        (done, cb)=> cb('rowCount', 'more'),
        (requestCompleted, cb) => cb('rowCount', 'more')
      ]
  })))

  let exec = server.execSQLCmd("/pstore/name", "select 1")
  expect(server.Connection).toBeCalledTimes(1)
  expect(server.Request).toBeCalledTimes(1)

 })

However, now server.execSQLCmd does't run, I cannot step into it with debug, exists right away and returns a large mock object.

Anyone see what I'm doing wrong here?

Thanks!

Body:
exports.execSQLCmd = async function (conn_store, cmd) {

    let config = await exports.getParameter(conn_store)
    let conn_cfg = JSON.parse(config)

    //connect
    exports.connect_exec(conn_cfg, cmd);

    return result;
}

function connect_exec(conn_cfg, cmd) {
    const connection = exports.get_connection(conn_cfg);
    exports.on_connect(connection, cmd);
    connection.connect();
    return connection;
}

function on_connect(connection, cmd) {
    connection.on('connect', function (err) {
        if (err) {
            console.log('CONNECTION ERROR: ' + err);
        }
        console.log('CONNECTED');
        exports.execute_statement(connection, cmd);
    });
}

function get_connection(conn_cfg) {
    return new Connection(conn_cfg);
}

function execute_statement(connection, cmd) {
    let request = exports.get_request(connection, cmd);

    connection.execSql(request);
}

function get_request(connection, cmd) {
    let request = new Request(cmd, function (err) {
        if (err) {
            console.log('REQUEST ERROR: ' + err);
        }
    });
    //add three event hooks to the request
    request.on('row', function (columns) {
        columns.forEach(function (column) {
            result += (column.value === null ? '' : column.value) + ',';
        });
        result = result.replace(/,$/, '\r\n');
    });
    request.on('done', function (rowCount, more) {
        console.log('SQL COMMAND COMPLETED: ' + rowCount + ' rows returned');
    });
    request.on('requestCompleted', function (rowCount, more) {
        connection.close();
        console.log('CONNECTION TO SERVER CLOSED');
    });
    return request;
}

exports.AWS = AWS;

exports.connect_exec = connect_exec
exports.execute_statement = execute_statement
exports.get_request = get_request
exports.get_connection = get_connection
exports.on_connect = on_connect

Here's my test:

describe('Test execSQLCmd', async () => {
    const server = require("../src/opportunity/db_server.js")

      afterEach(() => {
      jest.restoreAllMocks();
    });

   test('should query sql', async () => {
    server.getParameter = jest.fn().mockReturnValue('{"xxx":123,"yyy":"hello"}')

    server.get_connection = jest.fn().mockReturnValue({
      connect: () => {},
      on: (connect, cb) => cb(),
      close: () => {} ,
      execSql: () => {}
    })

    server.get_request = jest.fn().mockReturnValue({
      constructor: (sqlString, cb) => cb('err', null, null),
      on: [
            (row, cb)=> cb('columns'),
            (done, cb)=> cb('rowCount', 'more'),
            (requestCompleted, cb) => cb('rowCount', 'more')
          ]
      })

      await server.execSQLCmd("/pstore/name", "select 1")
      expect(server.get_connection).toHaveBeenCalled()
      expect(server.get_request).toHaveBeenCalled()
   })
})

Took me a day to write all the code for main functionality, ore than there is here.

Took me 2.5 days to figure out just this test. Silly!


问:
Replace null values to 0 in array
I need to push 0 in users element if the array's length is less than 7.

Example: If array has 2 elements. The rest should have 0 in it's users and _id as the index number.

Please help me to acheive this

```<code> const newUsers = [
    {
        _id: 1,
        users: 8
    },
    {
        _id: 2,
        users: 6
    },
    {
        _id: 3,
        users: 1
    },
    {
        _id: 4,
        users: 8
    },
    {
        _id: 5,
        users: 0
    },
    {
        _id: 7,
        users: 0
    }
]
</code>```

答:
for (let i = newUsers.length; i < 7; i += 1) {
  newUsers.push({ _id: i + 1, users: 0 });
}
```

Title: Replace null values to 0 in array

Body:
I need to push 0 in users element if the array's length is less than 7.

Example: If array has 2 elements. The rest should have 0 in it's users and _id as the index number.

Please help me to acheive this

 const newUsers = [
    {
        _id: 1,
        users: 8
    },
    {
        _id: 2,
        users: 6
    },
    {
        _id: 3,
        users: 1
    },
    {
        _id: 4,
        users: 8
    },
    {
        _id: 5,
        users: 0
    },
    {
        _id: 7,
        users: 0
    }
]


问:
ASP CKEditorControl's content length on client-side
I'm using CKEditor in my ASP.NET webforms application. I'm using CKEditor control to put it to my page:

```<code><CKEditor:CKEditorControl ID="CKEditorControl" runat="server" />
</code>```

But I'd like to get the editor's content length on client-side. I'm trying to do it this way:

```<code>CKEDITOR.instances['<%= CKEditorControl.ClientID %>'].getData().length;
</code>```

Though it's not working because: "Uncaught TypeError: Cannot call method 'getData' of undefined"

So my question is. What am I doing wrong? And is it possible to get the CKEditor's length on client-side when using CKEditorControl?

答:
this code works:

```<code>$('#cke_<%= CKEditorControl.ClientID %> iframe').contents().find('body').html()
</code>```

I'm not sure now but I guess all my problems were because I was trying to get the data before the editor was loaded.

ContentLicense: CC BY-SA 3.0

Body:
I'm using CKEditor in my ASP.NET webforms application. I'm using CKEditor control to put it to my page:

<CKEditor:CKEditorControl ID="CKEditorControl" runat="server" />

But I'd like to get the editor's content length on client-side. I'm trying to do it this way:

CKEDITOR.instances['<%= CKEditorControl.ClientID %>'].getData().length;

Though it's not working because: "Uncaught TypeError: Cannot call method 'getData' of undefined"

So my question is. What am I doing wrong? And is it possible to get the CKEditor's length on client-side when using CKEditorControl?

Body:
this code works:

$('#cke_<%= CKEditorControl.ClientID %> iframe').contents().find('body').html()

I'm not sure now but I guess all my problems were because I was trying to get the data before the editor was loaded.


问:
Angular routing to open the expansion panel
First off I'm new to Angular, only been learning it for about a month so I just have a quick question that I can't seem to find anything on. So I'm trying to use a routerLink to go from one page to another, but also I want that page to open an expansion panel once it has landed on the desired page. My expansion panels aren't labeled in any way that would show up in the console, it just has the basic information. Would I have to create a method in order to open the tab once the routerLink is clicked?

Thanks in advance!

答:
First of all don't worry if you are new to Angular, we all start from scratch.
If you want to open an expansion panel try to use this and see if it works for you.

In your .ts file:

```<code>openExpansionPanel: boolean = false;

toggleExpansionPanel(checked: boolean) {
    this.openExpansionPanel = checked;
}
</code>```

In your .html file:

```<code><div class="form-group">
      <label class="switch">
          <input
            type="checkbox"
            [value]="false"
            [ngModel]="openExpansionPanel"
            (ngModelChange)="toggleExpansionPanel($event)"
            data-toggle="collapse"
            href="#collapseFilters"
            aria-expanded="false"
            aria-controls="collapseFilters">
          <label>Expand Panel</label>
    </div>

    <!-- Your panel expands here -->
    <div class="collapse" id="collapseFilters">
    </div>
</code>```

Everything inside the div with the id collapseFilters will expand or collapse when you click the checkbox.
Let me know if it was useful to you

Body:
First of all don't worry if you are new to Angular, we all start from scratch.
If you want to open an expansion panel try to use this and see if it works for you.

In your .ts file:

openExpansionPanel: boolean = false;

toggleExpansionPanel(checked: boolean) {
    this.openExpansionPanel = checked;
}

In your .html file:

<div class="form-group">
      <label class="switch">
          <input
            type="checkbox"
            [value]="false"
            [ngModel]="openExpansionPanel"
            (ngModelChange)="toggleExpansionPanel($event)"
            data-toggle="collapse"
            href="#collapseFilters"
            aria-expanded="false"
            aria-controls="collapseFilters">
          <label>Expand Panel</label>
    </div>

    <!-- Your panel expands here -->
    <div class="collapse" id="collapseFilters">
    </div>

Everything inside the div with the id collapseFilters will expand or collapse when you click the checkbox.
Let me know if it was useful to you


问:
How do I make sidebar automatically disappear once a menu item clicked

I implemented a some Sidebar code and would like the sidebar to automatically close once an item is clicked. Currently have to click the 'X' to hide sidebar.  Below is the existing code for the Sidebar and Sidebar sub-menu.

Probably a one line fix if you know what you are doing, but I am new to React, so any help would be appreciated.

...

```<code>import React, { useState } from 'react';
import styled from 'styled-components';
import { Link } from 'react-router-dom';
import * as FaIcons from 'react-icons/fa';
import * as AiIcons from 'react-icons/ai';
import { SidebarData } from './SidebarData';
import SubMenu from './SubMenu';
import { IconContext } from 'react-icons/lib';

const Nav = styled.div`
  // background: #15171c;
  background: black;
  height: 60px;
  display: flex;
  justify-content: flex-start;
  align-items: center;
`;

const NavIcon = styled(Link)`
  margin-left: 2rem;
  font-size: 2rem;
  height: 60px;
  display: flex;
  justify-content: flex-start;
  align-items: center;
`;
//  background: #15171c;

const SidebarNav = styled.nav`
  background: #15171c;
  width: 250px;
  height: 150vh;
  display: flex;
  justify-content: center;
  position: fixed;
  top: 0;
  left: ${({ sidebar }) => (sidebar ? '0' : '-100%')};
  transition: 350ms;
  z-index: 10;
`;

const SidebarWrap = styled.div`
  width: 100%;
`;

const Sidebar = () => {
  const [sidebar, setSidebar] = useState(false);

  const showSidebar = () => setSidebar(!sidebar);

  return (
    <>
      <IconContext.Provider value={{ color: '#fff' }}>

        <Nav>
          <NavIcon to='#'>
            <FaIcons.FaBars onClick={showSidebar} />
          </NavIcon>
        </Nav>
        <SidebarNav sidebar={sidebar}>
          <SidebarWrap>
            <NavIcon to='#'>
              <AiIcons.AiOutlineClose onClick={showSidebar} />
            </NavIcon>
            {SidebarData.map((item, index) => {
              return <SubMenu item={item} key={index} />;
            })}
          </SidebarWrap>
        </SidebarNav>
      </IconContext.Provider>
    </>
  );
};

export default Sidebar;

import React, { useState } from 'react';
import { Link } from 'react-router-dom';
import styled from 'styled-components';

const SidebarLink = styled(Link)`
  display: flex;
  color: #e1e9fc;
  justify-content: space-between;
  align-items: center;
  padding: 20px;
  list-style: none;
  height: 40px;
  text-decoration: none;
  font-size: 18px;

  //#c6c8cf
  //#252831
  &:hover {
    background: #c6c8cf;
    border-left: 4px solid #632ce4;
    cursor: pointer;
  }
`;

const SidebarLabel = styled.span`
  margin-left: 16px;
`;

const DropdownLink = styled(Link)`
  background: #414757;
  height: 40px;
  padding-left: 3rem;
  display: flex;
  align-items: center;
  text-decoration: none;
  color: #f5f5f5;
  font-size: 18px;

//  background: #632ce4;

  &:hover {
    background: #d9dbd5;
    cursor: pointer;
  }
`;

const SubMenu = ({ item }) => {
  const [subnav, setSubnav] = useState(false);

  const showSubnav = () => setSubnav(!subnav);

  return (
    <>
      <SidebarLink to={item.path} onClick={item.subNav && showSubnav}>
        <div>
          {item.icon}
          <SidebarLabel>{item.title}</SidebarLabel>
        </div>
        <div>
          {item.subNav && subnav
            ? item.iconOpened
            : item.subNav
            ? item.iconClosed
            : null}
        </div>
      </SidebarLink>
      {subnav &&
        item.subNav.map((item, index) => {
          return (
            <DropdownLink to={item.path} key={index}>
              {item.icon}
              <SidebarLabel>{item.title}</SidebarLabel>
            </DropdownLink>
          );
        })}
    </>
  );
};

export default SubMenu;

import React from 'react';
// import * as FaIcons from 'react-icons/fa';
import * as AiIcons from 'react-icons/ai';
import * as IoIcons from 'react-icons/io';
import * as RiIcons from 'react-icons/ri';
import * as FaIcons from 'react-icons/fa';

export const SidebarData = [
  {
    title: 'Login',
    path: '/login',
    icon: <AiIcons.AiOutlineLogin />,
  },
  {
    title: 'Site Master',
    path: '/list-sitemaster',
    icon: <FaIcons.FaBroadcastTower />,
  },
  {
    title: 'Site Report Cards',
    path: '/sitereportcardmaster',
    icon: <IoIcons.IoIosPaper />,

  },
  {
    title: 'Report Card Master',
    path: '/reportcardmaster',
    icon: <IoIcons.IoIosPaper />
  },
  {
    title: 'Categories',
    path: '/categories',
    icon: <IoIcons.IoIosClipboard />,

    iconClosed: <RiIcons.RiArrowDownSFill />,
    iconOpened: <RiIcons.RiArrowUpSFill />,

    subNav: [
      {
        title: 'Asset Type',
        path: '/assettype',
        icon: <IoIcons.IoIosPaper />,
        cName: 'sub-nav'
      },
      {
        title: 'Asset Sub Type',
        path: '/assetsubtype',
        icon: <IoIcons.IoIosPaper />,
        cName: 'sub-nav'
      },
      {
        title: 'Document Type',
        path: '/documenttype',
        icon: <IoIcons.IoIosPaper />,
        cName: 'sub-nav'
      },
      {
        title: 'Document Sub Type',
        path: '/documentsubtype',
        icon: <IoIcons.IoIosPaper />,
        cName: 'sub-nav'
      },
      {
        title: 'Report Card Category',
        path: '/reportcarddetailcategory',
        icon: <IoIcons.IoIosPaper />,
        cName: 'sub-nav'
      },
      {
        title: 'Contact Detail Type',
        path: '/contactdetailtype',
        icon: <IoIcons.IoIosPaper />,
        cName: 'sub-nav'
      },
      {
        title: 'Lighting Type',
        path: '/lightingtype',
        icon: <IoIcons.IoIosPaper />,
        cName: 'sub-nav'
      }
    ]
  },
  {
    title: 'Company Master',
    path: '/cpymaster-toplevel',
    icon: <AiIcons.AiFillHome />,
    iconClosed: <RiIcons.RiArrowDownSFill />,
    iconOpened: <RiIcons.RiArrowUpSFill />,

    subNav: [
      {
        title: 'CompanyMaster',
        path: '/cpymaster',
        icon: <AiIcons.AiFillHome />,
        cName: 'sub-nav'
      },
      {
        title: 'Users',
        path: '/users',
        icon: <IoIcons.IoIosPerson />,
        cName: 'sub-nav'
      },
      {
        title: 'Contacts',
        path: '/contactmaster',
        icon: <IoIcons.IoIosPeople />,
        cName: 'sub-nav'
      }
    ]
  },
  {
    title: 'My Profile',
    path: '/add-usersmall',
    icon: <AiIcons.AiOutlineUser/>,
  },
  {
    title: 'PDF',
    path: '/pdfcomponent',
    icon: <AiIcons.AiOutlineUser/>,
  },
  {
    title: 'Users PageSort Test',
    path: '/userstable',
    icon: <AiIcons.AiOutlineUser/>,
  },
  {
    title: 'Logout',
    path: '/logout',
    icon: <AiIcons.AiOutlineLogin />,
  }
];
</code>```

...

答:
The following code in the subMenu.js along with @Daniel toggleSidebar code in sideBar.js rendered the desired results.

...

```<code>  return (
    <>
      <SidebarLink to={item.path} onClick={item.subNav && showSubnav}>
        <div>
          {item.icon}
          {/*following onClick={toggleSidebar} allows mainm menu items without subnav to close sidebar */}
          <SidebarLabel onClick={toggleSidebar}>{item.title}</SidebarLabel>
        </div>
        <div>
          {item.subNav && subnav
            ? item.iconOpened
            : item.subNav
            ? item.iconClosed
            : null}
        </div>
      </SidebarLink>
      {subnav &&
        item.subNav.map((item, index) => {
          return (
            //following onClick={toggleSidebar} allows submenu selections to close sidebar
            <DropdownLink to={item.path} key={index} onClick={toggleSidebar}>
              {item.icon}
              <SidebarLabel>{item.title}</SidebarLabel>
            </DropdownLink>
          );
        })}
    </>
  );
</code>```

...

Body:
I implemented a some Sidebar code and would like the sidebar to automatically close once an item is clicked. Currently have to click the 'X' to hide sidebar.  Below is the existing code for the Sidebar and Sidebar sub-menu.

Probably a one line fix if you know what you are doing, but I am new to React, so any help would be appreciated.

...

import React, { useState } from 'react';
import styled from 'styled-components';
import { Link } from 'react-router-dom';
import * as FaIcons from 'react-icons/fa';
import * as AiIcons from 'react-icons/ai';
import { SidebarData } from './SidebarData';
import SubMenu from './SubMenu';
import { IconContext } from 'react-icons/lib';

const Nav = styled.div`
  // background: #15171c;
  background: black;
  height: 60px;
  display: flex;
  justify-content: flex-start;
  align-items: center;
`;

const NavIcon = styled(Link)`
  margin-left: 2rem;
  font-size: 2rem;
  height: 60px;
  display: flex;
  justify-content: flex-start;
  align-items: center;
`;
//  background: #15171c;

const SidebarNav = styled.nav`
  background: #15171c;
  width: 250px;
  height: 150vh;
  display: flex;
  justify-content: center;
  position: fixed;
  top: 0;
  left: ${({ sidebar }) => (sidebar ? '0' : '-100%')};
  transition: 350ms;
  z-index: 10;
`;

const SidebarWrap = styled.div`
  width: 100%;
`;

const Sidebar = () => {
  const [sidebar, setSidebar] = useState(false);

  const showSidebar = () => setSidebar(!sidebar);

  return (
    <>
      <IconContext.Provider value={{ color: '#fff' }}>

          <NavIcon to='#'>
            <FaIcons.FaBars onClick={showSidebar} />
          </NavIcon>

        <SidebarNav sidebar={sidebar}>
          <SidebarWrap>
            <NavIcon to='#'>
              <AiIcons.AiOutlineClose onClick={showSidebar} />
            </NavIcon>
            {SidebarData.map((item, index) => {
              return <SubMenu item={item} key={index} />;
            })}
          </SidebarWrap>
        </SidebarNav>
      </IconContext.Provider>
    </>
  );
};

export default Sidebar;

import React, { useState } from 'react';
import { Link } from 'react-router-dom';
import styled from 'styled-components';

const SidebarLink = styled(Link)`
  display: flex;
  color: #e1e9fc;
  justify-content: space-between;
  align-items: center;
  padding: 20px;
  list-style: none;
  height: 40px;
  text-decoration: none;
  font-size: 18px;

  //#c6c8cf
  //#252831
  &:hover {
    background: #c6c8cf;
    border-left: 4px solid #632ce4;
    cursor: pointer;
  }
`;

const SidebarLabel = styled.span`
  margin-left: 16px;
`;

const DropdownLink = styled(Link)`
  background: #414757;
  height: 40px;
  padding-left: 3rem;
  display: flex;
  align-items: center;
  text-decoration: none;
  color: #f5f5f5;
  font-size: 18px;

//  background: #632ce4;

  &:hover {
    background: #d9dbd5;
    cursor: pointer;
  }
`;

const SubMenu = ({ item }) => {
  const [subnav, setSubnav] = useState(false);

  const showSubnav = () => setSubnav(!subnav);

  return (
    <>
      <SidebarLink to={item.path} onClick={item.subNav && showSubnav}>

          {item.icon}
          <SidebarLabel>{item.title}</SidebarLabel>

          {item.subNav && subnav
            ? item.iconOpened
            : item.subNav
            ? item.iconClosed
            : null}

      </SidebarLink>
      {subnav &&
        item.subNav.map((item, index) => {
          return (
            <DropdownLink to={item.path} key={index}>
              {item.icon}
              <SidebarLabel>{item.title}</SidebarLabel>
            </DropdownLink>
          );
        })}
    </>
  );
};

export default SubMenu;

import React from 'react';
// import * as FaIcons from 'react-icons/fa';
import * as AiIcons from 'react-icons/ai';
import * as IoIcons from 'react-icons/io';
import * as RiIcons from 'react-icons/ri';
import * as FaIcons from 'react-icons/fa';

export const SidebarData = [
  {
    title: 'Login',
    path: '/login',
    icon: <AiIcons.AiOutlineLogin />,
  },
  {
    title: 'Site Master',
    path: '/list-sitemaster',
    icon: <FaIcons.FaBroadcastTower />,
  },
  {
    title: 'Site Report Cards',
    path: '/sitereportcardmaster',
    icon: <IoIcons.IoIosPaper />,

  },
  {
    title: 'Report Card Master',
    path: '/reportcardmaster',
    icon: <IoIcons.IoIosPaper />
  },
  {
    title: 'Categories',
    path: '/categories',
    icon: <IoIcons.IoIosClipboard />,

    iconClosed: <RiIcons.RiArrowDownSFill />,
    iconOpened: <RiIcons.RiArrowUpSFill />,

    subNav: [
      {
        title: 'Asset Type',
        path: '/assettype',
        icon: <IoIcons.IoIosPaper />,
        cName: 'sub-nav'
      },
      {
        title: 'Asset Sub Type',
        path: '/assetsubtype',
        icon: <IoIcons.IoIosPaper />,
        cName: 'sub-nav'
      },
      {
        title: 'Document Type',
        path: '/documenttype',
        icon: <IoIcons.IoIosPaper />,
        cName: 'sub-nav'
      },
      {
        title: 'Document Sub Type',
        path: '/documentsubtype',
        icon: <IoIcons.IoIosPaper />,
        cName: 'sub-nav'
      },
      {
        title: 'Report Card Category',
        path: '/reportcarddetailcategory',
        icon: <IoIcons.IoIosPaper />,
        cName: 'sub-nav'
      },
      {
        title: 'Contact Detail Type',
        path: '/contactdetailtype',
        icon: <IoIcons.IoIosPaper />,
        cName: 'sub-nav'
      },
      {
        title: 'Lighting Type',
        path: '/lightingtype',
        icon: <IoIcons.IoIosPaper />,
        cName: 'sub-nav'
      }
    ]
  },
  {
    title: 'Company Master',
    path: '/cpymaster-toplevel',
    icon: <AiIcons.AiFillHome />,
    iconClosed: <RiIcons.RiArrowDownSFill />,
    iconOpened: <RiIcons.RiArrowUpSFill />,

    subNav: [
      {
        title: 'CompanyMaster',
        path: '/cpymaster',
        icon: <AiIcons.AiFillHome />,
        cName: 'sub-nav'
      },
      {
        title: 'Users',
        path: '/users',
        icon: <IoIcons.IoIosPerson />,
        cName: 'sub-nav'
      },
      {
        title: 'Contacts',
        path: '/contactmaster',
        icon: <IoIcons.IoIosPeople />,
        cName: 'sub-nav'
      }
    ]
  },
  {
    title: 'My Profile',
    path: '/add-usersmall',
    icon: <AiIcons.AiOutlineUser/>,
  },
  {
    title: 'PDF',
    path: '/pdfcomponent',
    icon: <AiIcons.AiOutlineUser/>,
  },
  {
    title: 'Users PageSort Test',
    path: '/userstable',
    icon: <AiIcons.AiOutlineUser/>,
  },
  {
    title: 'Logout',
    path: '/logout',
    icon: <AiIcons.AiOutlineLogin />,
  }
];

...

Body:
The following code in the subMenu.js along with @Daniel toggleSidebar code in sideBar.js rendered the desired results.

...

  return (
    <>
      <SidebarLink to={item.path} onClick={item.subNav && showSubnav}>
        <div>
          {item.icon}
          {/*following onClick={toggleSidebar} allows mainm menu items without subnav to close sidebar */}
          <SidebarLabel onClick={toggleSidebar}>{item.title}</SidebarLabel>
        </div>
        <div>
          {item.subNav && subnav
            ? item.iconOpened
            : item.subNav
            ? item.iconClosed
            : null}
        </div>
      </SidebarLink>
      {subnav &&
        item.subNav.map((item, index) => {
          return (
            //following onClick={toggleSidebar} allows submenu selections to close sidebar
            <DropdownLink to={item.path} key={index} onClick={toggleSidebar}>
              {item.icon}
              <SidebarLabel>{item.title}</SidebarLabel>
            </DropdownLink>
          );
        })}
    </>
  );

...


问:
Unsupported Media Type - Spring Boot Rest Controller has consumes/produces JSON and XML but only accepts Json
I have a requirement that needs to the controller be able to receive both JSON and XML.

I have put the produces and consumes tags in the RequestMapping but it is not working. When i do a POST to the endpoint using JSON as the body, it work fine.

When i do a POST using a XML as the body the HTTP message 415 Unsupported Media Type is thrown.

@RestController
@AllArgsConstructor
@NoArgsConstructor
@RequestMapping(value = "/calendarios-publicacao",
        produces = { MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE },
        consumes = { MediaType.APPLICATION_XML_VALUE,  MediaType.APPLICATION_JSON_VALUE } )
public class CalendarioPublicacaoController implements ControllerFacade<CalendarioPublicacaoDto, CalendarioPublicacaoDto> {

    @Autowired
    private CalendarioPublicacaoService calendarioPublicacaoService;

    @Override
    @PostMapping
    @ApiResponses({
            @ApiResponse(code = 201, message = "Calendário de publicação criado com sucesso."),
            @ApiResponse(code = 400, message = "Dados enviados incorretamente."),
            @ApiResponse(code = 403, message = "Sem permissões para criar calendários de publicação."),
            @ApiResponse(code = 409, message = "Já existe um calendário para este módulo.")
    })
    public ResponseEntity<CalendarioPublicacaoDto> create(@RequestBody  CalendarioPublicacaoDto object, HttpServletRequest request) {
        return ResponseEntity.created(URI.create(request.getRequestURL().append("/").append(calendarioPublicacaoService.create(object).getId()).toString())).build();
    }

}
```
<p>Example of the request with curl:</p>
<p>I receive 415.</p>
```curl -v -XPOST -d '<?xml version="1.0" encoding="UTF-8"?>
<CalendarioPublicacaoDto>
<anoReferencia>0</anoReferencia>
<dataSensibilizacao>2022-02-09T18:56:36.525Z</dataSensibilizacao>
<entidade>SESI</entidade>
<modulo>
<id>4</id>
</modulo>
<periodicidade>AUTOMATICO</periodicidade>
<periodoReferencia>0</periodoReferencia>
</CalendarioPublicacaoDto>' 'localhost:9090/calendarios-publicacao'
```

And via Insomnia the same 415 error.

Should I create an configuration class?

答:
SOLVED

I only needed to add the @XmlRootElement(name="") annotation in my Dto.

Body:
I have a requirement that needs to the controller be able to receive both JSON and XML.

I have put the produces and consumes tags in the RequestMapping but it is not working. When i do a POST to the endpoint using JSON as the body, it work fine.

When i do a POST using a XML as the body the HTTP message 415 Unsupported Media Type is thrown.

@RestController
@AllArgsConstructor
@NoArgsConstructor
@RequestMapping(value = "/calendarios-publicacao",
        produces = { MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE },
        consumes = { MediaType.APPLICATION_XML_VALUE,  MediaType.APPLICATION_JSON_VALUE } )
public class CalendarioPublicacaoController implements ControllerFacade<CalendarioPublicacaoDto, CalendarioPublicacaoDto> {

    @Autowired
    private CalendarioPublicacaoService calendarioPublicacaoService;

    @Override
    @PostMapping
    @ApiResponses({
            @ApiResponse(code = 201, message = "Calendário de publicação criado com sucesso."),
            @ApiResponse(code = 400, message = "Dados enviados incorretamente."),
            @ApiResponse(code = 403, message = "Sem permissões para criar calendários de publicação."),
            @ApiResponse(code = 409, message = "Já existe um calendário para este módulo.")
    })
    public ResponseEntity<CalendarioPublicacaoDto> create(@RequestBody  CalendarioPublicacaoDto object, HttpServletRequest request) {
        return ResponseEntity.created(URI.create(request.getRequestURL().append("/").append(calendarioPublicacaoService.create(object).getId()).toString())).build();
    }

}

Example of the request with curl:

I receive 415.

curl -v -XPOST -d '<?xml version="1.0" encoding="UTF-8"?>
<CalendarioPublicacaoDto>
<anoReferencia>0</anoReferencia>
<dataSensibilizacao>2022-02-09T18:56:36.525Z</dataSensibilizacao>
<entidade>SESI</entidade>
<modulo>
<id>4</id>
</modulo>
<periodicidade>AUTOMATICO</periodicidade>
<periodoReferencia>0</periodoReferencia>
</CalendarioPublicacaoDto>' 'localhost:9090/calendarios-publicacao'

And via Insomnia the same 415 error.

Should I create an configuration class?


问:
Increase Java heap space for language-identifier plugin-in in nutch
I am trying to add a new language To Automatic Language Detection tool Apache's tika. It needs to build a language profile for adding a new language. So i am using nutch language-identifier plug-in to build this profile.

The command is the following:

```
bin/nutch plugin language-identifier org.apache.nutch.analysis.lang.NGramProfile -create ./language-detection-profile/jp ./language-detection-profile/japanese4ngram-1.txt utf-8
```

Where ./language-detection-profile/japanese4ngram-1.txt is the new language corpus.

I have tested on a small size corpus (1 MB), and everything is fine, the profile is created as I expected.

However, when the corpus is large (> 1 GB). I have the problem of out of memory (heap space), like

```
Exception in thread "main" java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.apache.nutch.plugin.PluginRepository.main(PluginRepository.java:421)
Caused by: java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOf(Arrays.java:2882)
    at java.lang.AbstractStringBuilder.expandCapacity(AbstractStringBuilder.java:100)
    at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:390)
    at java.lang.StringBuilder.append(StringBuilder.java:119)
    at org.apache.nutch.analysis.lang.NGramProfile.create(NGramProfile.java:374)
    at org.apache.nutch.analysis.lang.NGramProfile.main(NGramProfile.java:484)
    ... 5 more

```

Does anyone know how to specify heap space size for nutch's plugin? Thanks.

Edit:
With the help from Mikaveli.
In Ubuntu:
set

```
if [ "x$JAVA_LIBRARY_PATH" != "x" ]; then
  NUTCH_OPTS="$NUTCH_OPTS -Djava.library.path=$JAVA_LIBRARY_PATH -Xmx2048m"
fi
```

答:
Assuming you're developing on a Windows box, edit nutch.bat and add the following after the rem NUTCH_OPTS line:

```<code>set NUTCH_OPTS=%NUTCH_OPTS% -Xmx1024m
</code>```

Obviously set the amount of RAM within the physical limit of your machine - note that Nutch can easily require 4g, depending on what you're doing with it.

Body:
I am trying to add a new language To Automatic Language Detection tool Apache's tika. It needs to build a language profile for adding a new language. So i am using nutch language-identifier plug-in to build this profile.

The command is the following:

bin/nutch plugin language-identifier org.apache.nutch.analysis.lang.NGramProfile -create ./language-detection-profile/jp ./language-detection-profile/japanese4ngram-1.txt utf-8

Where ./language-detection-profile/japanese4ngram-1.txt is the new language corpus.

I have tested on a small size corpus (1 MB), and everything is fine, the profile is created as I expected.

However, when the corpus is large (> 1 GB). I have the problem of out of memory (heap space), like

Exception in thread "main" java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.apache.nutch.plugin.PluginRepository.main(PluginRepository.java:421)
Caused by: java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOf(Arrays.java:2882)
    at java.lang.AbstractStringBuilder.expandCapacity(AbstractStringBuilder.java:100)
    at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:390)
    at java.lang.StringBuilder.append(StringBuilder.java:119)
    at org.apache.nutch.analysis.lang.NGramProfile.create(NGramProfile.java:374)
    at org.apache.nutch.analysis.lang.NGramProfile.main(NGramProfile.java:484)
    ... 5 more

Does anyone know how to specify heap space size for nutch's plugin? Thanks.

Edit:
With the help from Mikaveli.
In Ubuntu:
set

if [ "x$JAVA_LIBRARY_PATH" != "x" ]; then
  NUTCH_OPTS="$NUTCH_OPTS -Djava.library.path=$JAVA_LIBRARY_PATH -Xmx2048m"
fi

Body:
Assuming you're developing on a Windows box, edit nutch.bat and add the following after the rem NUTCH_OPTS line:

set NUTCH_OPTS=%NUTCH_OPTS% -Xmx1024m

Obviously set the amount of RAM within the physical limit of your machine - note that Nutch can easily require 4g, depending on what you're doing with it.


问:
C++ vector of vector conversion
I am fairly new to C++ and this might be a dumb question.

If I have 2 vectors,

vector<vector< double >> v1 , has values

and

const vector<vector< double> * > * v2,  has no values

.

How would I go about storing the elements from v1 to v2 or would it be possible to cast v1 as

const vector<vector< double> * > *

答:
v1 is a vector of vectors, i.e. each element of v1 is a vector of type vector<double>.

v2 is a pointer to a vector of pointers, that is it points to a vector, which has pointers (to other vectors) as elements.

As you can see, v1 and v2 are completely different, in terms of types and binary layout, so no, you cannot cast one to another and have a valid program.

Assuming that with v2 you want to pass a list of pointers to v1, e.g. as a function argument, the way to do this is to construct a vector of pointers, where each element would be a pointer to the corresponding element of v1:

```<code>void foo(const vector<vector<double>*>* v2);

void bar(vector<vector<double>> const& v1)
{
    // Allocate a vector of pointers
    vector<vector<double>*> vp(v1.size(), nullptr);

    // Initialize the pointers to point to v1 elements
    for (std::size_t i = 0u, n = v1.size(); i < n; ++i)
    {
        vp[i] = &v1[i];
    }

    // Pass the pointer to the vector of pointers to your destination
    foo(&vp);
}
</code>```

It should be noted that this code is not cheap as it will have to allocate dynamic memory and initialize the vector of pointers. If your goal was to save performance on copying the data, you should pass a reference to the original vector instead (i.e. vector<vector<double>> const&).

Title: C++ vector of vector conversion

Body:
v1 is a vector of vectors, i.e. each element of v1 is a vector of type vector<double>.

v2 is a pointer to a vector of pointers, that is it points to a vector, which has pointers (to other vectors) as elements.

As you can see, v1 and v2 are completely different, in terms of types and binary layout, so no, you cannot cast one to another and have a valid program.

Assuming that with v2 you want to pass a list of pointers to v1, e.g. as a function argument, the way to do this is to construct a vector of pointers, where each element would be a pointer to the corresponding element of v1:

void foo(const vector<vector<double>*>* v2);

void bar(vector<vector<double>> const& v1)
{
    // Allocate a vector of pointers
    vector<vector<double>*> vp(v1.size(), nullptr);

    // Initialize the pointers to point to v1 elements
    for (std::size_t i = 0u, n = v1.size(); i < n; ++i)
    {
        vp[i] = &v1[i];
    }

    // Pass the pointer to the vector of pointers to your destination
    foo(&vp);
}

It should be noted that this code is not cheap as it will have to allocate dynamic memory and initialize the vector of pointers. If your goal was to save performance on copying the data, you should pass a reference to the original vector instead (i.e. vector<vector<double>> const&).


问:
JS Discord Bot Get Role
I'm trying to get a role without using messages, like:

```<code>     const Discord = require('discord.js');
     const Bot = new Discord.Client();
     const Role = Discord.roles.find('name,'Exemple')

     Role.delete()
</code>```

Is this possible to do that?

答:
To get an specific role i use this code.
Replace SERVER_ID with your server id and ROLE_NAME with the name of the role</p>
```<code>const guild = client.guilds.cache.get("SERVER_ID");
const role = guild.roles.cache.find((r) => r.name === "ROLE_NAME");

console.log(`Found the role ${role.name}`);
console.log(`Found the role ${role.id}`);
</code>```

Title: JS Discord Bot Get Role

Body:
I'm trying to get a role without using messages, like:

     const Discord = require('discord.js');
     const Bot = new Discord.Client();
     const Role = Discord.roles.find('name,'Exemple')

     Role.delete()

Is this possible to do that?

Body:
To get an specific role i use this code.
Replace SERVER_ID with your server id and ROLE_NAME with the name of the role

const guild = client.guilds.cache.get("SERVER_ID");
const role = guild.roles.cache.find((r) => r.name === "ROLE_NAME");

console.log(`Found the role ${role.name}`);
console.log(`Found the role ${role.id}`);


问:
PEM_read_bio_X509_AUX() failed (SSL: error:0909006C:PEM routines:get_name:no start line:Expecting: TRUSTED CERTIFICATE)
when I am using this command to generate a certificate of my website:

```<code>/usr/local/bin/certbot certonly -d '*.poemhub.top' \
--manual --preferred-challenges dns \
--cert-name=poemhub \
--key-type=ecdsa \
--server https://acme-v02.api.letsencrypt.org/directory
</code>```

it tell me generate success:

```<code>IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/poemhub/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/poemhub/privkey.pem
   Your certificate will expire on 2021-10-10. To obtain a new or
   tweaked version of this certificate in the future, simply run
   certbot again. To non-interactively renew *all* of your
   certificates, run "certbot renew"
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le
</code>```

now I am using this command to reload the nginx:

```<code>nginx -s reload
</code>```

and tell me this error:

```<code>nginx: [emerg] cannot load certificate "/etc/letsencrypt/live/poemhub.top/fullchain.pem": PEM_read_bio_X509_AUX() failed (SSL: error:0909006C:PEM routines:get_name:no start line:Expecting: TRUSTED CERTIFICATE)
</code>```

where is going wrong? what should I do to fix the problem?

答: It is possible to get this error if you have swapped the key and cert files around ( wasn't me :) ).</p>

Body:
when I am using this command to generate a certificate of my website:

/usr/local/bin/certbot certonly -d '*.poemhub.top' \
--manual --preferred-challenges dns \
--cert-name=poemhub \
--key-type=ecdsa \
--server https://acme-v02.api.letsencrypt.org/directory

it tell me generate success:

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/poemhub/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/poemhub/privkey.pem
   Your certificate will expire on 2021-10-10. To obtain a new or
   tweaked version of this certificate in the future, simply run
   certbot again. To non-interactively renew *all* of your
   certificates, run "certbot renew"
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

now I am using this command to reload the nginx:

nginx -s reload

and tell me this error:

nginx: [emerg] cannot load certificate "/etc/letsencrypt/live/poemhub.top/fullchain.pem": PEM_read_bio_X509_AUX() failed (SSL: error:0909006C:PEM routines:get_name:no start line:Expecting: TRUSTED CERTIFICATE)

where is going wrong? what should I do to fix the problem?


问:
How can I run a mutually exclusive COUNT in Postgres?
Say I have a (virtual) table like the following:

firstColumn
secondColumn

fcVal1
scVal1

fcVal1
scVal2

fcVal2
scVal1

fcVal3
scVal2

I want to find the following counts:

Values in firstColumn that have both scVal1 and scVal2

Values in firstColumn that have only scVal1

Values in firstColumn that have only scVal2

So the result would be:

scVals
counts

scVal1 + scVal2
1

scVal1
1

scVal2
1

Note that these counts are mutually exclusive - fcVal1 is NOT included in the counts for having only scVal1 or scVal2

Preserving which firstColumn vals are associated with the secondColumn vals is not important, just the aggregate counts.

Thanks!

答:
If you are willing to hard code the combinations it's trivial to find out the counts. For example:

```<code>with
s as (
  select
    firstColumn,
    count(case when secondColumn = 'scVal1' then 1 end) as c1,
    count(case when secondColumn = 'scVal2' then 1 end) as c2
  from t
  group by firstColumn
)
select 'scVal1', count(*) from s where c1 > 0 and c2 = 0
union all select 'scVal2', count(*) from s where c1 = 0 and c2 > 0
union all select 'scVal1 + scVal2', count(*) from s where c1 > 0 and c2 > 0
</code>```

Result:

```<code> ?column?         count
 ---------------- -----
 scVal1           1
 scVal2           1
 scVal1 + scVal2  1
</code>```

See running example at DB Fiddle.

A more generic solution where the combinations are not known from the beginning is also possible (though more complex) for low numbers of distinct values.

Body:
If you are willing to hard code the combinations it's trivial to find out the counts. For example:

with
s as (
  select
    firstColumn,
    count(case when secondColumn = 'scVal1' then 1 end) as c1,
    count(case when secondColumn = 'scVal2' then 1 end) as c2
  from t
  group by firstColumn
)
select 'scVal1', count(*) from s where c1 > 0 and c2 = 0
union all select 'scVal2', count(*) from s where c1 = 0 and c2 > 0
union all select 'scVal1 + scVal2', count(*) from s where c1 > 0 and c2 > 0

Result:

 ?column?         count
 ---------------- -----
 scVal1           1
 scVal2           1
 scVal1 + scVal2  1

See running example at DB Fiddle.

A more generic solution where the combinations are not known from the beginning is also possible (though more complex) for low numbers of distinct values.


问:
How to make a vector PDF searchable?
My workflow includes making figures in Inkscape, which are then converted to PDF and included into LaTeX documents. In these figures, I often have to include mathematical formulas. For that, I use TexText. For font consistency and simplicity, when I want to add some plain text to my figure, I also use TexText. When the resulting SVG is converted to PDF, the TexText-generated text is not searchable.

How can I make a PDF from the SVG such that it is searchable while remaining a vector PDF?

I know I could rasterize the figure and then use e.g. Tesseract to create a searchable PDF. But the resulting PDF will of course contain a rasterized version of my figure. I would like the figure itself to remain vector graphics.

I am guessing there has to be a way that would go something like this: indeed rasterize the PDF and use Tesseract to extract the text. But then take the output of Tesseract and somehow add it to the original vector PDF. Unfortunately, I don't know how to do this.

答:
It turns out a question that is directly relevant to mine was answered on another StackExchange, here. The script that answers my actual question is svgToSearchablePDF.sh, and I post it below. It uses, as the key element, the script pdf-merge-text.sh from the accepted answer to that other question. For completeness, I will repost pdf-merge-text.sh in this answer.

The solution

Note that perhaps you will need to magnify the SVG file before converting it to a searchable PDF: larger image sizes help the OCR process. To magnify, in Inkscape, select the entire image, then go to Object -> Transform… . In the Transform tab, select Scale. Then select 'Scale proportionally', and finally, in either 'Width' or 'Height', enter something like '300' (make sure % is selected in the menu immediately to the right of the 'Width' field). Next, File->Document Properties…. In the 'Document Properties' tab, under Custom size, click on Resize page to content. Make sure that either nothing is selected or else that the entire image is selected. Then click the button 'Resize page to drawing or selection'. Save the SVG.

The script svgToSearchablePDF.sh uses an SVG file as input and produces a searchable vector PDF file as output. It is assumed that all of the following are installed: Tesseract, Inkscape, and Ghostscript.

For example, assume that we used Inkscape to create the file mygraphics.svg. Then the following command will produce a searchable PDF file mygraphics.pdf:

```<code>svgToSearchablePDF.sh mygraphics.svg
</code>```

The scripts

First, svgToSearchablePDF.sh:

```<code>#!/bin/bash
filename="$1"

inkscape ${filename%.*}.svg -o ${filename%.*}_auxfile.png
inkscape ${filename%.*}.svg -o ${filename%.*}_auxfileVCT.pdf
tesseract ${filename%.*}_auxfile.png ${filename%.*}_auxfileTXT -l eng pdf
pdf-merge-text.sh ${filename%.*}_auxfileTXT.pdf ${filename%.*}_auxfileVCT.pdf ${filename%.*}.pdf

rm -f ${filename%.*}_auxfile.png ${filename%.*}_auxfileVCT.pdf ${filename%.*}_auxfileTXT.pdf
</code>```

As I said, that script uses the script pdf-merge-text.sh from here. For completeness, here it is:

```<code>#!/usr/bin/env bash

set -eu

pdf_merge_text() {
    local txtpdf; txtpdf="$1"
    local imgpdf; imgpdf="$2"
    local outpdf; outpdf="${3--}"
    if [ "-" != "${txtpdf}" ] && [ ! -f "${txtpdf}" ]; then echo "error: text PDF does not exist: ${txtpdf}" 1>&2; return 1; fi
    if [ "-" != "${imgpdf}" ] && [ ! -f "${imgpdf}" ]; then echo "error: image PDF does not exist: ${imgpdf}" 1>&2; return 1; fi
    if [ "-" != "${outpdf}" ] && [ -e "${outpdf}" ]; then echo "error: not overwriting existing output file: ${outpdf}" 1>&2; return 1; fi
    (
        local txtonlypdf; txtonlypdf="$(TMPDIR=. mktemp --suffix=.pdf)"
        trap "rm -f -- '${txtonlypdf//'/'\\''}'" EXIT
        gs -o "${txtonlypdf}" -sDEVICE=pdfwrite -dFILTERIMAGE "${txtpdf}"
        pdftk "${txtonlypdf}" multistamp "${imgpdf}" output "${outpdf}"
    )
}

pdf_merge_text "$@"
</code>```

Title: How to make a vector PDF searchable?

Body:
It turns out a question that is directly relevant to mine was answered on another StackExchange, here. The script that answers my actual question is svgToSearchablePDF.sh, and I post it below. It uses, as the key element, the script pdf-merge-text.sh from the accepted answer to that other question. For completeness, I will repost pdf-merge-text.sh in this answer.

The solution

Note that perhaps you will need to magnify the SVG file before converting it to a searchable PDF: larger image sizes help the OCR process. To magnify, in Inkscape, select the entire image, then go to Object -> Transform… . In the Transform tab, select Scale. Then select 'Scale proportionally', and finally, in either 'Width' or 'Height', enter something like '300' (make sure % is selected in the menu immediately to the right of the 'Width' field). Next, File->Document Properties…. In the 'Document Properties' tab, under Custom size, click on Resize page to content. Make sure that either nothing is selected or else that the entire image is selected. Then click the button 'Resize page to drawing or selection'. Save the SVG.

The script svgToSearchablePDF.sh uses an SVG file as input and produces a searchable vector PDF file as output. It is assumed that all of the following are installed: Tesseract, Inkscape, and Ghostscript.

For example, assume that we used Inkscape to create the file mygraphics.svg. Then the following command will produce a searchable PDF file mygraphics.pdf:

svgToSearchablePDF.sh mygraphics.svg

The scripts

First, svgToSearchablePDF.sh:

#!/bin/bash
filename="$1"

inkscape ${filename%.*}.svg -o ${filename%.*}_auxfile.png
inkscape ${filename%.*}.svg -o ${filename%.*}_auxfileVCT.pdf
tesseract ${filename%.*}_auxfile.png ${filename%.*}_auxfileTXT -l eng pdf
pdf-merge-text.sh ${filename%.*}_auxfileTXT.pdf ${filename%.*}_auxfileVCT.pdf ${filename%.*}.pdf

rm -f ${filename%.*}_auxfile.png ${filename%.*}_auxfileVCT.pdf ${filename%.*}_auxfileTXT.pdf

As I said, that script uses the script pdf-merge-text.sh from here. For completeness, here it is:

#!/usr/bin/env bash

set -eu

pdf_merge_text() {
    local txtpdf; txtpdf="$1"
    local imgpdf; imgpdf="$2"
    local outpdf; outpdf="${3--}"
    if [ "-" != "${txtpdf}" ] && [ ! -f "${txtpdf}" ]; then echo "error: text PDF does not exist: ${txtpdf}" 1>&2; return 1; fi
    if [ "-" != "${imgpdf}" ] && [ ! -f "${imgpdf}" ]; then echo "error: image PDF does not exist: ${imgpdf}" 1>&2; return 1; fi
    if [ "-" != "${outpdf}" ] && [ -e "${outpdf}" ]; then echo "error: not overwriting existing output file: ${outpdf}" 1>&2; return 1; fi
    (
        local txtonlypdf; txtonlypdf="$(TMPDIR=. mktemp --suffix=.pdf)"
        trap "rm -f -- '${txtonlypdf//'/'\\''}'" EXIT
        gs -o "${txtonlypdf}" -sDEVICE=pdfwrite -dFILTERIMAGE "${txtpdf}"
        pdftk "${txtonlypdf}" multistamp "${imgpdf}" output "${outpdf}"
    )
}

pdf_merge_text "$@"


问:
vector::push_back using std::move for internal reallocations
A type X has a non-trivial move-constructor, which is not declared noexcept (ie. it can throw):

```<code>#include <iostream>
#include <vector>
#include <memory>

struct X {
    X()=default;
    X(X&&) { std::cout << "X move constructed\n"; } // not 'noexcept'
    X(const X&) { std::cout << "X copy constructed\n"; }
};

struct test {
    X x;
};

int main()
{
    static_assert(std::is_nothrow_move_constructible_v<X> == false);
    static_assert(std::is_nothrow_move_constructible_v<test> == false);

    std::vector<test> v(1);
    v.push_back(test{}); // internal object re-allocation, uses copy-constructor
}
</code>```

When calling push_back on a vector<test>, internal reallocations cause existing objects to be copied, which is expected.
The output is:

```<code>X move constructed
X copy constructed
</code>```

Apparently, the second line is related to internal object reallocation.

Now an unrelated std::unique_ptr<int> is added to test:

```<code>struct test {
    std::unique_ptr<int> up;
    X x;
};
</code>```

The output becomes:

```<code>X move constructed
X move constructed
</code>```

Why is internal reallocation using the move-constructor this time ?

Technically, X(X&&) can still throw an exception; wouldn't that violate the strong exception guarantee of push_back ?

compiler is gcc 11.2.1 and/or clang 12.0.1

答:
According to [vector.modifiers]/2 if the element type of std::vector is not copy-insertable and not nothrow-move-constructible, then an exception thrown from a move constructor of the element type results in an unspecified state of the container.

std::vector must prefer the copy constructor if the type isn't nothrow-movable, so that the exception guarantees can be preserved, but if that isn't possible, it is impossible to give strong exception guarantees.

Body:
A type X has a non-trivial move-constructor, which is not declared noexcept (ie. it can throw):

#include <iostream>
#include <vector>
#include <memory>

struct X {
    X()=default;
    X(X&&) { std::cout << "X move constructed\n"; } // not 'noexcept'
    X(const X&) { std::cout << "X copy constructed\n"; }
};

struct test {
    X x;
};

int main()
{
    static_assert(std::is_nothrow_move_constructible_v<X> == false);
    static_assert(std::is_nothrow_move_constructible_v<test> == false);

    std::vector<test> v(1);
    v.push_back(test{}); // internal object re-allocation, uses copy-constructor
}

When calling push_back on a vector<test>, internal reallocations cause existing objects to be copied, which is expected.
The output is:

X move constructed
X copy constructed

Apparently, the second line is related to internal object reallocation.

Now an unrelated std::unique_ptr<int> is added to test:

struct test {
    std::unique_ptr<int> up;
    X x;
};

The output becomes:

X move constructed
X move constructed

Why is internal reallocation using the move-constructor this time ?

Technically, X(X&&) can still throw an exception; wouldn't that violate the strong exception guarantee of push_back ?

compiler is gcc 11.2.1 and/or clang 12.0.1


问:
invalid identifier while parsing json
I am compiling a dbt base model. Currently I get this error below. Line 6 looks the same as other lines above. Might a small syntax error that I could not spot.

```<code>15:40:22  Database Error in model base_datacenter_handling_unit (models/l10_staging_datacenter/base_unit.sql)
15:40:22    000904 (42000): SQL compilation error: error line 6 at position 3
15:40:22    invalid identifier 'VALUE'
15:40:22    compiled SQL at target/run/dbt/models/l10_staging_datacenter/base_unit.sql
</code>```

This is how my file looks like:

```<code>SELECT
    JSON_DATA:"key"::text AS KEY
    , value:"description"::text AS DESCRIPTION
  , value:"globalHandlingUnitId"::text AS GLOBAL_HANDLING_UNIT_ID
  , value:"tareWeight"::NUMBER(38,0) AS TARTE_WEIGHT
  , value:"tareWeight_unit"::text AS TARTE_WEIGHT_UNIT
  , value:"width"::NUMBER(38,0) AS WIDTH
  , value:"width_unit"::text AS WIDTH_UNIT
  , value:"length"::NUMBER(38,0) AS LENGTH
    , value:"validFrom"::TIMESTAMP_NTZ AS VALID_FROM_TS_UTC
    , value:"validTo"::TIMESTAMP_NTZ AS VALID_TO_TS_UTC
    , value:"lastModified"::TIMESTAMP_NTZ AS LAST_MODIFIED_TS_UTC
  , value:"status"::text AS STATUS
    , md5(KEY::STRING || MASTERCLIENT_ID) AS HANDLING_UNIT_KEY --different logic than in POSTGRESDWH!
    ,MASTERCLIENT_ID
    ,{{ extract_masterclientname_clause('META_FILENAME') }} AS MASTERCLIENT_NAME
    ,META_ROW_NUM
  ,META_FILENAME
  ,META_LOAD_TS_UTC
  ,META_FILE_TS_UTC
  ,CASE WHEN {{table_dedup_clause('HANDLING_UNIT_KEY')}}
    THEN True
    ELSE False
  END AS IS_RECORD_CURRENT
FROM {{ source('INGEST_DATACENTER', 'HANDLING_UNIT') }} src
QUALIFY {{table_dedup_clause('HANDLING_UNIT_KEY')}}
</code>```

It could also be because of the STRING type md5(KEY::STRING || MASTERCLIENT_ID)  I am using with md5 but I have another file, which is based on the same pattern but it does not throw an error tho:

```<code>SELECT
    JSON_DATA:"issueId"::NUMBER(38,0) AS ISSUE_ID
    , value:"slaName"::text AS SLA_NAME
    , value:"slaTimeLeft"::NUMBER(38,0) AS SLA_TIME_USED_SECONDS
    , md5(ISSUE_ID::STRING || SLA_NAME) AS ISSUE_SLA_ID
    ,MASTERCLIENT_ID
    ,{{ extract_masterclientname_clause('META_FILENAME') }} AS MASTERCLIENT_NAME
    ,META_ROW_NUM
  ,META_FILENAME
  ,META_LOAD_TS_UTC
  ,META_FILE_TS_UTC
,CASE WHEN {{table_dedup_clause('ISSUE_SLA_ID')}}
    THEN True
    ELSE False
  END AS IS_RECORD_CURRENT
FROM {{ source('INGEST_EMS', 'ISSUES') }} src
    , lateral flatten ( input => JSON_DATA:slas)
QUALIFY {{table_dedup_clause('ISSUE_SLA_ID')}}
</code>```

I don't see any significant difference between the two

答: The most likely reason is the column is not named "tareWeight_unit". Snowflake creates column names in upper case regardless of how they are written unless the original create statement puts the columns names in double quotes (e.g. "MyColumn") in which case it will create the column names with the exact case specified. Use SHOW COLUMNS IN TABLE  and check the actual column name.

Title: invalid identifier while parsing json

Body:
I am compiling a dbt base model. Currently I get this error below. Line 6 looks the same as other lines above. Might a small syntax error that I could not spot.

15:40:22  Database Error in model base_datacenter_handling_unit (models/l10_staging_datacenter/base_unit.sql)
15:40:22    000904 (42000): SQL compilation error: error line 6 at position 3
15:40:22    invalid identifier 'VALUE'
15:40:22    compiled SQL at target/run/dbt/models/l10_staging_datacenter/base_unit.sql

This is how my file looks like:

SELECT
    JSON_DATA:"key"::text AS KEY
    , value:"description"::text AS DESCRIPTION
  , value:"globalHandlingUnitId"::text AS GLOBAL_HANDLING_UNIT_ID
  , value:"tareWeight"::NUMBER(38,0) AS TARTE_WEIGHT
  , value:"tareWeight_unit"::text AS TARTE_WEIGHT_UNIT
  , value:"width"::NUMBER(38,0) AS WIDTH
  , value:"width_unit"::text AS WIDTH_UNIT
  , value:"length"::NUMBER(38,0) AS LENGTH
    , value:"validFrom"::TIMESTAMP_NTZ AS VALID_FROM_TS_UTC
    , value:"validTo"::TIMESTAMP_NTZ AS VALID_TO_TS_UTC
    , value:"lastModified"::TIMESTAMP_NTZ AS LAST_MODIFIED_TS_UTC
  , value:"status"::text AS STATUS
    , md5(KEY::STRING || MASTERCLIENT_ID) AS HANDLING_UNIT_KEY --different logic than in POSTGRESDWH!
    ,MASTERCLIENT_ID
    ,{{ extract_masterclientname_clause('META_FILENAME') }} AS MASTERCLIENT_NAME
    ,META_ROW_NUM
  ,META_FILENAME
  ,META_LOAD_TS_UTC
  ,META_FILE_TS_UTC
  ,CASE WHEN {{table_dedup_clause('HANDLING_UNIT_KEY')}}
    THEN True
    ELSE False
  END AS IS_RECORD_CURRENT
FROM {{ source('INGEST_DATACENTER', 'HANDLING_UNIT') }} src
QUALIFY {{table_dedup_clause('HANDLING_UNIT_KEY')}}

It could also be because of the STRING type md5(KEY::STRING || MASTERCLIENT_ID)  I am using with md5 but I have another file, which is based on the same pattern but it does not throw an error tho:

SELECT
    JSON_DATA:"issueId"::NUMBER(38,0) AS ISSUE_ID
    , value:"slaName"::text AS SLA_NAME
    , value:"slaTimeLeft"::NUMBER(38,0) AS SLA_TIME_USED_SECONDS
    , md5(ISSUE_ID::STRING || SLA_NAME) AS ISSUE_SLA_ID
    ,MASTERCLIENT_ID
    ,{{ extract_masterclientname_clause('META_FILENAME') }} AS MASTERCLIENT_NAME
    ,META_ROW_NUM
  ,META_FILENAME
  ,META_LOAD_TS_UTC
  ,META_FILE_TS_UTC
,CASE WHEN {{table_dedup_clause('ISSUE_SLA_ID')}}
    THEN True
    ELSE False
  END AS IS_RECORD_CURRENT
FROM {{ source('INGEST_EMS', 'ISSUES') }} src
    , lateral flatten ( input => JSON_DATA:slas)
QUALIFY {{table_dedup_clause('ISSUE_SLA_ID')}}

I don't see any significant difference between the two


问:
ESP32 webserver slows/hangs with more than 1 device accessing pages
I'm writing a webserver for an ESP32, written primarily in C and using platformio and ESP-IDF on VSCode. With a single client, the server works great, but as soon as I try to load a page on more than 1 device (doesn't matter if all the same page or different), everything slows to a crawl. I can see the page requests arriving on the server nice and snappily, but the pages won't load/be sent for up to a minute.

When this is happening, the server seems to favour an arbitrary device; my android phone, for example, will load pages at normal speeds while my PC and iPhone will be stuck, or on another occasion the PC will be loading fast and the other two devices stuck. This makes me wonder if it's related to my server/socket handling task, but ESP-IDF is such a tangled web of dependencies I'm not sure where to begin looking. I've made a post on the Espressif forum, but haven't had any responses yet. It's not the wifi connection alone, as if I connect all 3 devices but only access the webpages from one, that device still loads everything fine.

Updates:

07/02 - I'm more and more convinced that the culprit is the socket task, as it doesn't seem to allow for multiple sockets simultaneously; after accepting one it handles everything for that one socket before looping back and accepting another one.

08/02 - I modified tcp_server_task to start a new task for each socket (below is now the modified function and additional task), but this if anything made things worse, leaving me more confused than before.

09/02 - I tried increasing the backlog argument of listen() from 1 to 32, this also made no difference.

Attempted (failed) solutions now include:

Setting keepAlive to 0

changing dest_addr_ip4 from INADDR_ANY to 192.168.4.1, the desired address for devices to connect to

pinning the socket handling task to a different core to the tcp_server_task

adding vTaskDelay(pdMS_TO_TICKS(x)) at various points with various values of x

Stuck devices are still consistently loading simultaneously after however long it takes (usually 30 to 60 seconds, sometimes longer)

10/02 - I forgot to mention, the ESP has bluetooth enabled as well, as we want users to be able to control stuff over both wireless methods.

socket handling task(s):

```<code>// wifi_functions.c
void tcp_server_task(void *pvParameters)
{
    char addr_str[128];
    int addr_family = (int)pvParameters;
    int ip_protocol = 0;
    int keepAlive = 0;
    int keepIdle = KEEPALIVE_IDLE;
    int keepInterval = KEEPALIVE_INTERVAL;
    int keepCount = KEEPALIVE_COUNT;
    struct sockaddr_storage dest_addr;

    if (addr_family == AF_INET) {
        struct sockaddr_in *dest_addr_ip4 = (struct sockaddr_in *)&dest_addr;
        dest_addr_ip4->sin_addr.s_addr = htonl(INADDR_ANY);
        dest_addr_ip4->sin_family = AF_INET;
        dest_addr_ip4->sin_port = htons(PORT);
        ip_protocol = IPPROTO_IP;
    }
#ifdef CONFIG_EXAMPLE_IPV6
    else if (addr_family == AF_INET6) {
        struct sockaddr_in6 *dest_addr_ip6 = (struct sockaddr_in6 *)&dest_addr;
        bzero(&dest_addr_ip6->sin6_addr.un, sizeof(dest_addr_ip6->sin6_addr.un));
        dest_addr_ip6->sin6_family = AF_INET6;
        dest_addr_ip6->sin6_port = htons(PORT);
        ip_protocol = IPPROTO_IPV6;
    }
#endif

    int listen_sock = socket(addr_family, SOCK_STREAM, ip_protocol);
    if (listen_sock < 0) {
        // ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);
        vTaskDelete(NULL);
        return;
    }
    int opt = 1;
    setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
#if defined(CONFIG_EXAMPLE_IPV4) && defined(CONFIG_EXAMPLE_IPV6)
    // Note that by default IPV6 binds to both protocols, it is must be disabled
    // if both protocols used at the same time (used in CI)
    setsockopt(listen_sock, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt));
#endif

    // ESP_LOGI(TAG, "Socket created");

    int err = bind(listen_sock, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
    if (err != 0) {
        // ESP_LOGE(TAG, "Socket unable to bind: errno %d", errno);
        // ESP_LOGE(TAG, "IPPROTO: %d", addr_family);
        goto CLEAN_UP;
    }
    // ESP_LOGI(TAG, "Socket bound, port %d", PORT);

    err = listen(listen_sock, 1);
    if (err != 0) {
        // ESP_LOGE(TAG, "Error occurred during listen: errno %d", errno);
        goto CLEAN_UP;
    }

    while (1) {

        // ESP_LOGI("socket task", "Socket listening");

        struct sockaddr_storage source_addr; // Large enough for both IPv4 or IPv6
        socklen_t addr_len = sizeof(source_addr);
        int sock = accept(listen_sock, (struct sockaddr *)&source_addr, &addr_len);
        if (sock < 0) {
            // ESP_LOGE(TAG, "Unable to accept connection: errno %d", errno);
            break;
        }

        set_sock(sock);

        // Set tcp keepalive option
        setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &keepAlive, sizeof(int));
        setsockopt(sock, IPPROTO_TCP, TCP_KEEPIDLE, &keepIdle, sizeof(int));
        setsockopt(sock, IPPROTO_TCP, TCP_KEEPINTVL, &keepInterval, sizeof(int));
        setsockopt(sock, IPPROTO_TCP, TCP_KEEPCNT, &keepCount, sizeof(int));
        // Convert ip address to string
        if (source_addr.ss_family == PF_INET) {
            inet_ntoa_r(((struct sockaddr_in *)&source_addr)->sin_addr, addr_str, sizeof(addr_str) - 1);
        }
#ifdef CONFIG_EXAMPLE_IPV6
        else if (source_addr.ss_family == PF_INET6) {
            inet6_ntoa_r(((struct sockaddr_in6 *)&source_addr)->sin6_addr, addr_str, sizeof(addr_str) - 1);
        }
#endif
        // ESP_LOGI(TAG, "Socket accepted ip address: %s", addr_str);
        xTaskCreate(socket_handler_task, "socket_handler", 10*1024, &sock, 10, NULL);
    }

CLEAN_UP:
    close(listen_sock);
    vTaskDelete(NULL);
}

void socket_handler_task(void *params)
{
    int sock = *((int*)params);
    do_retransmit(sock);

    shutdown(sock, 0);
    close(sock);
    vTaskDelete(NULL);
}

...

// main.c
xTaskCreatePinnedToCore(tcp_server_task, "tcp_server1", 4096, (void*)AF_INET, 10, NULL, 1);
</code>```

Changing priority or switching to core 0 doesn't appear to have any impact.

This function is part of the hppt server that handles file/page requests:

```<code>// file_server.c
/* Handler to download a file kept on the server */
static esp_err_t download_get_handler(httpd_req_t *req)
{
    char filepath[FILE_PATH_MAX];
    FILE *fd = NULL;
    struct stat file_stat;

    const char *filename = get_path_from_uri(filepath, ((struct file_server_data *)req->user_ctx)->base_path,
                                             req->uri, sizeof(filepath));

    esp_log_buffer_char_internal("path", filename, strlen(filename), ESP_LOG_INFO);
    if (!filename) {
        // ESP_LOGE(TAG, "Filename is too long");
        /* Respond with 500 Internal Server Error */
        httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Filename too long");
        return ESP_FAIL;
    }
    if(strlen(filename) == 1 || strcmp(filename, "/index.html") == 0){
        strcpy(filepath, "/spiffs/index.htm");
    }
    /* If name has trailing '/', respond with directory contents */
    if (filename[strlen(filename) - 1] == '/') {
        return http_resp_dir_html(req, filepath);
    }
    if(strcmp(filename, "/setup.txt") == 0){
        httpd_resp_send_err(req, HTTPD_403_FORBIDDEN, "This file is not accessible");
        return ESP_FAIL;
    }
    if (stat(filepath, &file_stat) == -1) {
        /* If file not present on SPIFFS check if URI
         * corresponds to one of the hardcoded paths */
        if (strcmp(filename, "/favicon.ico") == 0) {
            return favicon_get_handler(req);
        } else if (strcmp(filename, "/config") == 0) {
            return config_get_handler(req);
        } else if (strcmp(filename, "/rits") == 0) {
            return rits_get_handler(req);
        } else if (strcmp(filename, "/setup") == 0) {
            return setup_get_handler(req);
        } else if (strcmp(filename, "/access") == 0) {
            return access_get_handler(req);
        } else if (strcmp(filename, "/login") == 0) {
            return login_get_handler(req);
        } else if (strcmp(filename, "/check") == 0) {
            return debug_get_handler(req);
        } else if (strcmp(filename, "/funeral") == 0) {
            return debug_get_handler(req);
        } else if (strcmp(filename, "/imageEdit") == 0) {
            // No need to do anything
            return debug_get_handler(req);
        } else if (strcmp(filename, "/restart") == 0) {
            return restart_handler(req);
        }
        // ESP_LOGE(TAG, "Failed to stat file : %s", filepath);
        /* Respond with 404 Not Found */
        httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, "File does not exist");
        return ESP_FAIL;
    }

    fd = fopen(filepath, "r");
    if (!fd) {
        // ESP_LOGE(TAG, "Failed to read existing file : %s", filepath);
        /* Respond with 500 Internal Server Error */
        httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to read existing file");
        return ESP_FAIL;
    }

    // ESP_LOGI(TAG, "Sending file : %s (%ld bytes)...", filename, file_stat.st_size);
    set_content_type_from_file(req, filename);

    /* Retrieve the pointer to scratch buffer for temporary storage */
    char *chunk = ((struct file_server_data *)req->user_ctx)->scratch;
    size_t chunksize;
    do {
        /* Read file in chunks into the scratch buffer */
        chunksize = fread(chunk, 1, SCRATCH_BUFSIZE, fd);

        if (chunksize > 0) {
            /* Send the buffer contents as HTTP response chunk */
            if (httpd_resp_send_chunk(req, chunk, chunksize) != ESP_OK) {
                fclose(fd);
                // ESP_LOGE(TAG, "File sending failed!");
                /* Abort sending file */
                httpd_resp_sendstr_chunk(req, NULL);
                /* Respond with 500 Internal Server Error */
                httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to send file");
               return ESP_FAIL;
           }
        }

        /* Keep looping till the whole file is sent */
    } while (chunksize != 0);

    /* Close file after sending complete */
    fclose(fd);
    // ESP_LOGI(TAG, "File sending complete");

    /* Respond with an empty chunk to signal HTTP response completion */
#ifdef CONFIG_EXAMPLE_HTTPD_CONN_CLOSE_HEADER
    httpd_resp_set_hdr(req, "Connection", "close");
#endif
    httpd_resp_send_chunk(req, NULL, 0);
    return ESP_OK;
}
</code>```

答: Fixed it! The solution that worked in the end wasn't actually anything to do with sockets, all I did was set the lru_purge_enable of my httpd_config_t to true. All 3 devices are now very happily loading everything. I'd still be curious if anyone knows why the http (connections?) weren't being dropped and required purging.

Body:
I'm writing a webserver for an ESP32, written primarily in C and using platformio and ESP-IDF on VSCode. With a single client, the server works great, but as soon as I try to load a page on more than 1 device (doesn't matter if all the same page or different), everything slows to a crawl. I can see the page requests arriving on the server nice and snappily, but the pages won't load/be sent for up to a minute.

When this is happening, the server seems to favour an arbitrary device; my android phone, for example, will load pages at normal speeds while my PC and iPhone will be stuck, or on another occasion the PC will be loading fast and the other two devices stuck. This makes me wonder if it's related to my server/socket handling task, but ESP-IDF is such a tangled web of dependencies I'm not sure where to begin looking. I've made a post on the Espressif forum, but haven't had any responses yet. It's not the wifi connection alone, as if I connect all 3 devices but only access the webpages from one, that device still loads everything fine.

Updates:

07/02 - I'm more and more convinced that the culprit is the socket task, as it doesn't seem to allow for multiple sockets simultaneously; after accepting one it handles everything for that one socket before looping back and accepting another one.

08/02 - I modified tcp_server_task to start a new task for each socket (below is now the modified function and additional task), but this if anything made things worse, leaving me more confused than before.

09/02 - I tried increasing the backlog argument of listen() from 1 to 32, this also made no difference.

Attempted (failed) solutions now include:

Setting keepAlive to 0

changing dest_addr_ip4 from INADDR_ANY to 192.168.4.1, the desired address for devices to connect to

pinning the socket handling task to a different core to the tcp_server_task

adding vTaskDelay(pdMS_TO_TICKS(x)) at various points with various values of x

Stuck devices are still consistently loading simultaneously after however long it takes (usually 30 to 60 seconds, sometimes longer)

10/02 - I forgot to mention, the ESP has bluetooth enabled as well, as we want users to be able to control stuff over both wireless methods.

socket handling task(s):

// wifi_functions.c
void tcp_server_task(void *pvParameters)
{
    char addr_str[128];
    int addr_family = (int)pvParameters;
    int ip_protocol = 0;
    int keepAlive = 0;
    int keepIdle = KEEPALIVE_IDLE;
    int keepInterval = KEEPALIVE_INTERVAL;
    int keepCount = KEEPALIVE_COUNT;
    struct sockaddr_storage dest_addr;

    if (addr_family == AF_INET) {
        struct sockaddr_in *dest_addr_ip4 = (struct sockaddr_in *)&dest_addr;
        dest_addr_ip4->sin_addr.s_addr = htonl(INADDR_ANY);
        dest_addr_ip4->sin_family = AF_INET;
        dest_addr_ip4->sin_port = htons(PORT);
        ip_protocol = IPPROTO_IP;
    }
#ifdef CONFIG_EXAMPLE_IPV6
    else if (addr_family == AF_INET6) {
        struct sockaddr_in6 *dest_addr_ip6 = (struct sockaddr_in6 *)&dest_addr;
        bzero(&dest_addr_ip6->sin6_addr.un, sizeof(dest_addr_ip6->sin6_addr.un));
        dest_addr_ip6->sin6_family = AF_INET6;
        dest_addr_ip6->sin6_port = htons(PORT);
        ip_protocol = IPPROTO_IPV6;
    }
#endif

    int listen_sock = socket(addr_family, SOCK_STREAM, ip_protocol);
    if (listen_sock < 0) {
        // ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);
        vTaskDelete(NULL);
        return;
    }
    int opt = 1;
    setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
#if defined(CONFIG_EXAMPLE_IPV4) && defined(CONFIG_EXAMPLE_IPV6)
    // Note that by default IPV6 binds to both protocols, it is must be disabled
    // if both protocols used at the same time (used in CI)
    setsockopt(listen_sock, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt));
#endif

    // ESP_LOGI(TAG, "Socket created");

    int err = bind(listen_sock, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
    if (err != 0) {
        // ESP_LOGE(TAG, "Socket unable to bind: errno %d", errno);
        // ESP_LOGE(TAG, "IPPROTO: %d", addr_family);
        goto CLEAN_UP;
    }
    // ESP_LOGI(TAG, "Socket bound, port %d", PORT);

    err = listen(listen_sock, 1);
    if (err != 0) {
        // ESP_LOGE(TAG, "Error occurred during listen: errno %d", errno);
        goto CLEAN_UP;
    }

    while (1) {

        // ESP_LOGI("socket task", "Socket listening");

        struct sockaddr_storage source_addr; // Large enough for both IPv4 or IPv6
        socklen_t addr_len = sizeof(source_addr);
        int sock = accept(listen_sock, (struct sockaddr *)&source_addr, &addr_len);
        if (sock < 0) {
            // ESP_LOGE(TAG, "Unable to accept connection: errno %d", errno);
            break;
        }

        set_sock(sock);

        // Set tcp keepalive option
        setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &keepAlive, sizeof(int));
        setsockopt(sock, IPPROTO_TCP, TCP_KEEPIDLE, &keepIdle, sizeof(int));
        setsockopt(sock, IPPROTO_TCP, TCP_KEEPINTVL, &keepInterval, sizeof(int));
        setsockopt(sock, IPPROTO_TCP, TCP_KEEPCNT, &keepCount, sizeof(int));
        // Convert ip address to string
        if (source_addr.ss_family == PF_INET) {
            inet_ntoa_r(((struct sockaddr_in *)&source_addr)->sin_addr, addr_str, sizeof(addr_str) - 1);
        }
#ifdef CONFIG_EXAMPLE_IPV6
        else if (source_addr.ss_family == PF_INET6) {
            inet6_ntoa_r(((struct sockaddr_in6 *)&source_addr)->sin6_addr, addr_str, sizeof(addr_str) - 1);
        }
#endif
        // ESP_LOGI(TAG, "Socket accepted ip address: %s", addr_str);
        xTaskCreate(socket_handler_task, "socket_handler", 10*1024, &sock, 10, NULL);
    }

CLEAN_UP:
    close(listen_sock);
    vTaskDelete(NULL);
}

void socket_handler_task(void *params)
{
    int sock = *((int*)params);
    do_retransmit(sock);

    shutdown(sock, 0);
    close(sock);
    vTaskDelete(NULL);
}

...

// main.c
xTaskCreatePinnedToCore(tcp_server_task, "tcp_server1", 4096, (void*)AF_INET, 10, NULL, 1);

Changing priority or switching to core 0 doesn't appear to have any impact.

This function is part of the hppt server that handles file/page requests:

// file_server.c
/* Handler to download a file kept on the server */
static esp_err_t download_get_handler(httpd_req_t *req)
{
    char filepath[FILE_PATH_MAX];
    FILE *fd = NULL;
    struct stat file_stat;

    const char *filename = get_path_from_uri(filepath, ((struct file_server_data *)req->user_ctx)->base_path,
                                             req->uri, sizeof(filepath));

    esp_log_buffer_char_internal("path", filename, strlen(filename), ESP_LOG_INFO);
    if (!filename) {
        // ESP_LOGE(TAG, "Filename is too long");
        /* Respond with 500 Internal Server Error */
        httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Filename too long");
        return ESP_FAIL;
    }
    if(strlen(filename) == 1 || strcmp(filename, "/index.html") == 0){
        strcpy(filepath, "/spiffs/index.htm");
    }
    /* If name has trailing '/', respond with directory contents */
    if (filename[strlen(filename) - 1] == '/') {
        return http_resp_dir_html(req, filepath);
    }
    if(strcmp(filename, "/setup.txt") == 0){
        httpd_resp_send_err(req, HTTPD_403_FORBIDDEN, "This file is not accessible");
        return ESP_FAIL;
    }
    if (stat(filepath, &file_stat) == -1) {
        /* If file not present on SPIFFS check if URI
         * corresponds to one of the hardcoded paths */
        if (strcmp(filename, "/favicon.ico") == 0) {
            return favicon_get_handler(req);
        } else if (strcmp(filename, "/config") == 0) {
            return config_get_handler(req);
        } else if (strcmp(filename, "/rits") == 0) {
            return rits_get_handler(req);
        } else if (strcmp(filename, "/setup") == 0) {
            return setup_get_handler(req);
        } else if (strcmp(filename, "/access") == 0) {
            return access_get_handler(req);
        } else if (strcmp(filename, "/login") == 0) {
            return login_get_handler(req);
        } else if (strcmp(filename, "/check") == 0) {
            return debug_get_handler(req);
        } else if (strcmp(filename, "/funeral") == 0) {
            return debug_get_handler(req);
        } else if (strcmp(filename, "/imageEdit") == 0) {
            // No need to do anything
            return debug_get_handler(req);
        } else if (strcmp(filename, "/restart") == 0) {
            return restart_handler(req);
        }
        // ESP_LOGE(TAG, "Failed to stat file : %s", filepath);
        /* Respond with 404 Not Found */
        httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, "File does not exist");
        return ESP_FAIL;
    }

    fd = fopen(filepath, "r");
    if (!fd) {
        // ESP_LOGE(TAG, "Failed to read existing file : %s", filepath);
        /* Respond with 500 Internal Server Error */
        httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to read existing file");
        return ESP_FAIL;
    }

    // ESP_LOGI(TAG, "Sending file : %s (%ld bytes)...", filename, file_stat.st_size);
    set_content_type_from_file(req, filename);

    /* Retrieve the pointer to scratch buffer for temporary storage */
    char *chunk = ((struct file_server_data *)req->user_ctx)->scratch;
    size_t chunksize;
    do {
        /* Read file in chunks into the scratch buffer */
        chunksize = fread(chunk, 1, SCRATCH_BUFSIZE, fd);

        if (chunksize > 0) {
            /* Send the buffer contents as HTTP response chunk */
            if (httpd_resp_send_chunk(req, chunk, chunksize) != ESP_OK) {
                fclose(fd);
                // ESP_LOGE(TAG, "File sending failed!");
                /* Abort sending file */
                httpd_resp_sendstr_chunk(req, NULL);
                /* Respond with 500 Internal Server Error */
                httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to send file");
               return ESP_FAIL;
           }
        }

        /* Keep looping till the whole file is sent */
    } while (chunksize != 0);

    /* Close file after sending complete */
    fclose(fd);
    // ESP_LOGI(TAG, "File sending complete");

    /* Respond with an empty chunk to signal HTTP response completion */
#ifdef CONFIG_EXAMPLE_HTTPD_CONN_CLOSE_HEADER
    httpd_resp_set_hdr(req, "Connection", "close");
#endif
    httpd_resp_send_chunk(req, NULL, 0);
    return ESP_OK;
}