问:
Typescript definitions of nested function
I am trying to create a type for my (nodejs)controller function like below

```<code>export const registerUser = asyncWrap(async function(req:Request, res:Response, next:NextFunction) {
    res.status(200).json({ success: true});
})
</code>```

and the above code is fine, but I want to create a type so I can stop giving the type for the function params which is kinda redundant

What I've tried

```<code>type NormTyped = (fn:Promise<any>) => (req: Request, res: Response, next: NextFunction) => any;

export const registerUser:NormTyped = asyncWrap(async function(req, res, next) {
    res.status(200).json({ success: true});
})
</code>```

But it gives me errors

```<code>Type '(...args: any) => Promise<any>' is not assignable to type 'NormTyped'.
  Type 'Promise<any>' is not assignable to type '(req: Request<ParamsDictionary, any, any, ParsedQs>,         res: Response<any>, next: NextFunction) => any'.
Type 'Promise<any>' provides no match for the signature '(req: Request<ParamsDictionary, any, any, ParsedQs>, res: Response<any>, next: NextFunction): any'.
</code>```

This is how my asyncWrap looks like(in-case)

```<code>const asyncWrap = (fn: (...args: any) => any) =>
function asyncHandlerWrap(...args: any){
    const fnReturn = fn(...args)
    const next = args[args.length-1]
    return Promise.resolve(fnReturn).catch(next)
}
</code>```

答:
NormTyped should be a function which accepts a function as an argument.

```<code>type NormTyped = (fn: (req: Request, res: Response, next: NextFunction) => any) => Promise<any>;

const asyncWrap = (fn: (...args: any) => any) =>
function asyncHandlerWrap(...args: any){
    const fnReturn = fn(...args)
    const next = args[args.length-1]
    return Promise.resolve(fnReturn).catch(next)
}

export const registerUser: NormTyped = asyncWrap(async function(req, res, next) {
    res.status(200).json({ success: true});
})
</code>```

Body:
I am trying to create a type for my (nodejs)controller function like below

export const registerUser = asyncWrap(async function(req:Request, res:Response, next:NextFunction) {
    res.status(200).json({ success: true});
})

and the above code is fine, but I want to create a type so I can stop giving the type for the function params which is kinda redundant

What I've tried

type NormTyped = (fn:Promise<any>) => (req: Request, res: Response, next: NextFunction) => any;

export const registerUser:NormTyped = asyncWrap(async function(req, res, next) {
    res.status(200).json({ success: true});
})

But it gives me errors

Type '(...args: any) => Promise<any>' is not assignable to type 'NormTyped'.
  Type 'Promise<any>' is not assignable to type '(req: Request<ParamsDictionary, any, any, ParsedQs>,         res: Response<any>, next: NextFunction) => any'.
Type 'Promise<any>' provides no match for the signature '(req: Request<ParamsDictionary, any, any, ParsedQs>, res: Response<any>, next: NextFunction): any'.

This is how my asyncWrap looks like(in-case)

const asyncWrap = (fn: (...args: any) => any) =>
function asyncHandlerWrap(...args: any){
    const fnReturn = fn(...args)
    const next = args[args.length-1]
    return Promise.resolve(fnReturn).catch(next)
}

Body:
NormTyped should be a function which accepts a function as an argument.

type NormTyped = (fn: (req: Request, res: Response, next: NextFunction) => any) => Promise<any>;

const asyncWrap = (fn: (...args: any) => any) =>
function asyncHandlerWrap(...args: any){
    const fnReturn = fn(...args)
    const next = args[args.length-1]
    return Promise.resolve(fnReturn).catch(next)
}

export const registerUser: NormTyped = asyncWrap(async function(req, res, next) {
    res.status(200).json({ success: true});
})


来源: stackexchange

问:
VBScript Function as Parameter, or similar Construct
I'm trying to put together tests in HP Unified Functional Testing
the way a programmer would.
For those unaware, the tool uses VBScript as its driver.

Because I want to use data from the same DataTable across multiple UFT actions
-- and because the Global table already has a different set of data on it
-- I want to retrieve data from an external file.
UFT happily supports this function.

My current plan is that, depending on which test I'm running,
I will iterate through only a range of rows in that table.

This is the script I've come up with:

```<code>' targets the local sheet, but
' not the same value as dtLocalSheet
Const sheetNum = 2

dim sheetRowCount
DataTable.ImportSheet "PersonFile.xlsx", 1, sheetNum
sheetRowCount = DataTable.GetSheet(sheetNum).GetRowCount

dim firstRow, lastRow
firstRow = Parameter("FirstPersonIndex")
lastRow = Parameter("LastPersonIndex")
If sheetRowCount < lastRow Then
    lastRow = sheetRowCount
End If

If sheetRowCount >= firstRow Then
    Dim i
    For i = firstRow To lastRow
        DataTable.SetCurrentRow i

        ' begin payload
        MsgBox(DataTable.Value("LastName", dtLocalSheet))
        ' end payload

    Next
End if
</code>```

I don't want to have to repeat all this boilerplate
every time I want to use this pattern.
I'd really like to have something like:

In a Function Library:

```<code>sub LoopThroughSheetAnd(sheetFile, doThis)
    ' targets the local sheet, but
    ' not the same value as dtLocalSheet
    Const sheetNum = 2

    dim sheetRowCount
    DataTable.ImportSheet sheetFile, 1, sheetNum
    sheetRowCount = DataTable.GetSheet(sheetNum).GetRowCount

    dim firstRow, lastRow
    firstRow = Parameter("FirstRow")
    lastRow = Parameter("LastRow")
    If sheetRowCount < lastRow Then
        lastRow = sheetRowCount
    End If

    If sheetRowCount >= firstRow Then
        Dim i
        For i = firstRow To lastRow
            DataTable.SetCurrentRow i

            call doThis()
        Next
    End if
end sub
</code>```

In the original action...

```<code>sub Payload1()
    MsgBox(DataTable.Value("LastName", dtLocalSheet))
end sub
LoopThroughSheetAnd "PersonFile.xlsx", Payload1
</code>```

In a separate action, 3 or 4 steps later...

```<code>sub Payload2()
    ' compare the data against another data source
end sub
LoopThroughSheetAnd "PersonFile.xlsx", Payload2
</code>```

The above code doesn't work in VBScript.
A type mismatch error is thrown
as soon as we try to pass Payload1 as a parameter.

How could one reasonably pull this off in VBScript?
Bonus points if the answer also works in UFT.

答:
When using objects, you can wrap a call to a method in an object, and then you can pass the object. (This is approximately what happens in other languages already, you just have to do it manually in VBScript.)

The only issue is that any method called this way has to be Public.

I would use a naming scheme of something like "Func1", "Func2", "Action1", "Action2", etc., depending on the arity of the functions and whether they return values or not.

Dim s : Set s = New Something : s.Run

Class Something
   Public Sub HowToPassMe(pValue)
      WScript.Echo pValue
   End Sub

   Public Sub Run
      Dim action : Set action = New Action1Wrapper
      Set action.Target = Me
      Dim se : Set se = New SomethingElse
      se.DoSomethingElse action
   End Sub
End Class

Class SomethingElse
   Public Sub DoSomethingElse(pAction1)
      pAction1.Action1("something")
   End Sub
End Class

Class Action1Wrapper
   Private mTarget
   Public Property Set Target(value) : Set mTarget = value : End Property

   Public Sub Action1(p1)
      mTarget.HowToPassMe(p1)
   End Sub
End Class
```

<p>Using <code>Execute</code>, <code>Action1Wrapper</code> can also be written something like the following. You can also write a factory class for easier use.</p>

<pre class="lang-vb prettyprint-override"><code>Class Action1Wrapper
   Private mTarget
   Public Property Set Target(value) : Set mTarget = value : End Property

   Private mName
   Public Property Let Name(value) : mName = value : End Property

   Public Sub Action1(p1)
      Execute "mTarget." & mName & "(p1)"
   End Sub
End Class

Class Action1Factory_
   Public Function Create(pTarget, pName)
      Dim a1 : Set a1 = New Action1Wrapper
      Set a1.Target = pTarget
      a1.Name = pName
      Set Create = a1
   End Function
End Class
Dim Action1Factory : Set Action1Factory = New Action1Factory_
</code>```

Used as:

Dim action : Set action = Action1Factory.Create(Me, "HowToPassMe")
Dim se : Set se = New SomethingElse
se.DoSomethingElse action
```

ContentLicense: CC BY-SA 3.0

Body:
I'm trying to put together tests in HP Unified Functional Testing
the way a programmer would.
For those unaware, the tool uses VBScript as its driver.

Because I want to use data from the same DataTable across multiple UFT actions
-- and because the Global table already has a different set of data on it
-- I want to retrieve data from an external file.
UFT happily supports this function.

My current plan is that, depending on which test I'm running,
I will iterate through only a range of rows in that table.

This is the script I've come up with:

' targets the local sheet, but
' not the same value as dtLocalSheet
Const sheetNum = 2

dim sheetRowCount
DataTable.ImportSheet "PersonFile.xlsx", 1, sheetNum
sheetRowCount = DataTable.GetSheet(sheetNum).GetRowCount

dim firstRow, lastRow
firstRow = Parameter("FirstPersonIndex")
lastRow = Parameter("LastPersonIndex")
If sheetRowCount < lastRow Then
    lastRow = sheetRowCount
End If

If sheetRowCount >= firstRow Then
    Dim i
    For i = firstRow To lastRow
        DataTable.SetCurrentRow i

        ' begin payload
        MsgBox(DataTable.Value("LastName", dtLocalSheet))
        ' end payload

    Next
End if

I don't want to have to repeat all this boilerplate
every time I want to use this pattern.
I'd really like to have something like:

In a Function Library:

sub LoopThroughSheetAnd(sheetFile, doThis)
    ' targets the local sheet, but
    ' not the same value as dtLocalSheet
    Const sheetNum = 2

    dim sheetRowCount
    DataTable.ImportSheet sheetFile, 1, sheetNum
    sheetRowCount = DataTable.GetSheet(sheetNum).GetRowCount

    dim firstRow, lastRow
    firstRow = Parameter("FirstRow")
    lastRow = Parameter("LastRow")
    If sheetRowCount < lastRow Then
        lastRow = sheetRowCount
    End If

    If sheetRowCount >= firstRow Then
        Dim i
        For i = firstRow To lastRow
            DataTable.SetCurrentRow i

            call doThis()
        Next
    End if
end sub

In the original action...

sub Payload1()
    MsgBox(DataTable.Value("LastName", dtLocalSheet))
end sub
LoopThroughSheetAnd "PersonFile.xlsx", Payload1

In a separate action, 3 or 4 steps later...

sub Payload2()
    ' compare the data against another data source
end sub
LoopThroughSheetAnd "PersonFile.xlsx", Payload2

The above code doesn't work in VBScript.
A type mismatch error is thrown
as soon as we try to pass Payload1 as a parameter.

How could one reasonably pull this off in VBScript?
Bonus points if the answer also works in UFT.

Body:
When using objects, you can wrap a call to a method in an object, and then you can pass the object. (This is approximately what happens in other languages already, you just have to do it manually in VBScript.)

The only issue is that any method called this way has to be Public.

I would use a naming scheme of something like "Func1", "Func2", "Action1", "Action2", etc., depending on the arity of the functions and whether they return values or not.

Dim s : Set s = New Something : s.Run

Class Something
   Public Sub HowToPassMe(pValue)
      WScript.Echo pValue
   End Sub

   Public Sub Run
      Dim action : Set action = New Action1Wrapper
      Set action.Target = Me
      Dim se : Set se = New SomethingElse
      se.DoSomethingElse action
   End Sub
End Class

Class SomethingElse
   Public Sub DoSomethingElse(pAction1)
      pAction1.Action1("something")
   End Sub
End Class

Class Action1Wrapper
   Private mTarget
   Public Property Set Target(value) : Set mTarget = value : End Property

   Public Sub Action1(p1)
      mTarget.HowToPassMe(p1)
   End Sub
End Class

Using Execute, Action1Wrapper can also be written something like the following. You can also write a factory class for easier use.

Class Action1Wrapper
   Private mTarget
   Public Property Set Target(value) : Set mTarget = value : End Property

   Private mName
   Public Property Let Name(value) : mName = value : End Property

   Public Sub Action1(p1)
      Execute "mTarget." & mName & "(p1)"
   End Sub
End Class

Class Action1Factory_
   Public Function Create(pTarget, pName)
      Dim a1 : Set a1 = New Action1Wrapper
      Set a1.Target = pTarget
      a1.Name = pName
      Set Create = a1
   End Function
End Class
Dim Action1Factory : Set Action1Factory = New Action1Factory_

Used as:

Dim action : Set action = Action1Factory.Create(Me, "HowToPassMe")
Dim se : Set se = New SomethingElse
se.DoSomethingElse action

ContentLicense: CC BY-SA 4.0


问:
Mixins in loopback4
I want to add createdAt and updatedAt to each model on loopback 4

can not find name 'MixinTarget'.

Type parameter 'T' of exported function has or is using private name 'MixinTarget'.

If I try from documentation above error occurs.

答:
To resolve this issue, I didn't use the mixin approach. I added the following fields to my model.

```<code>  @property({
    type: 'date',
    default: () => new Date(),
    postgresql: {
      columnName: 'updated_at',
    },
  })
  updatedAt?: Date;
</code>```

It should work as expected

Title: Mixins in loopback4

Body:
To resolve this issue, I didn't use the mixin approach. I added the following fields to my model.

  @property({
    type: 'date',
    default: () => new Date(),
    postgresql: {
      columnName: 'updated_at',
    },
  })
  updatedAt?: Date;

It should work as expected


问:
Optimize Server Side Blazor application
I've try to improve performance of a server side blazor application and got a result from Google Chrome Lighthouse, which shows very much work in parsing / Script Evaluation.

Has someone experience if this is normal in with server blazor or how to improve this thing in production mode?

Just want to know some hints or experiences which part of application could cause this behaviour.

Thanks!

答:
With server side blazor the browser just acts as a dumb terminal. Whenever you set a DOM event @onclick @onmousemove etc or is sent back to the server by some javascript. The server deals with the event and then the javascript receives delta html to update the body.

If you can, avoid events that occur regularly such as @onmousemove, use the default binding settings rather than every time a key is pressed etc.

But basically, expect a lot of time to be spent on javascript because javascript is the basis of the whole experience.

Title: Optimize Server Side Blazor application


问:
Display paragraph
I insert the below paragraph into the database .However while displaying it is displayed as (which is not desired one):

The use of this website is subject to the following terms of use: • The content of the pages of this website is for your general information and use only. It is subject to change without notice. • Neither we nor any third parties provide any warranty or guarantee as to the accuracy,

Desired paragraph view:
The use of this website is subject to the following terms of use:

•   The content of the pages of this website is for your general information and use only. It is subject to change without notice.
•   Neither we nor any third parties provide any warranty or guarantee as to the accuracy.

How can we achieve this in asp.net/C#

答:
Insert the complete html into database and set into div as innerhtml</p>

```<code><div id="div" runat="server"></div>

div.InnerHtml = "paragraph from Database which saved as HTML";"
</code>```

Title: Display paragraph

Body:
Insert the complete html into database and set into div as innerhtml

<div id="div" runat="server"></div>

div.InnerHtml = "paragraph from Database which saved as HTML";"


问:
How to run javascript code from string in safe way
I found some answers, but very old one and I wondered how can it be done?

I've seen that eval() function isn't safe:

Alternate for eval() to execute auto-generated JS code from the server

So what are my options in order to run a javascript code in isolated secured way?

答:
(as pointed out, this answer is outdated and the proposed solution could be easily broken).

Currently, draft for secure ecmascript has not been approved/implemented yet.
One hack that has decent browser support (proxy is es6 feature) is using proxies and with to create a sandbox.

You just have to write a proxy which returns null for every requested key except for some safe functions.
with would ask the proxy every time a var outside eval is required (for example, window) and so, provide null instead of the real var.

Check this website for a tutorial:
code sandbox


问:
Finding the shortest path between a number of nodes (not just distance)
I am trying to find the shortest path that travels through specified nodes in a graph (A -> B -> C instead of just A -> C). Currently, my code will return the shortest path rather than going through all specified nodes.

Code:

```<code>from networkx import DiGraph
from networkx.algorithms.shortest_paths import multi_source_dijkstra

graph = {'c1': {'c2': 4, 'L1': 3},
         'c2': {'c1': 4, 'c3': 3, 'L1': 2.5},
         'c3': {'c2': 3, 'L1': 2},
         'L1': {'c1': 3, 'c2': 2.5, 'c3': 2}}

# Build the graph
G = DiGraph()
G.add_weighted_edges_from(((source, target, weight)
                           for source, d in graph.items()
                           for target, weight in d.items()))

# Find shortest path (using Dijkstra algorithm)
#result = shortest_path(G, source='c1', target='c3', weight='weight')
result = multi_source_dijkstra(G, sources=['c2','c3'], target='L1')

print(result)
# result: (2, ['c3', 'L1'])
</code>```

Library and function I am using: https://networkx.github.io/documentation/stable/reference/algorithms/generated/networkx.algorithms.shortest_paths.weighted.multi_source_dijkstra_path.html#networkx.algorithms.shortest_paths.weighted.multi_source_dijkstra_path

I noticed networkx have two traveling salesman functions, but neither of them can return the path, only the distance so I don't think I can use them.

答:
You should make multiple calls of shortest_path, one for each subpath you need. So when the request is A->B->C, then find the shortest path from A to B, and the one from B to C and concatenate the two results.

multi_source_dijkstra does something different: it finds a path from one of the source nodes to the target node.

Body:
I am trying to find the shortest path that travels through specified nodes in a graph (A -> B -> C instead of just A -> C). Currently, my code will return the shortest path rather than going through all specified nodes.

Code:

from networkx import DiGraph
from networkx.algorithms.shortest_paths import multi_source_dijkstra

graph = {'c1': {'c2': 4, 'L1': 3},
         'c2': {'c1': 4, 'c3': 3, 'L1': 2.5},
         'c3': {'c2': 3, 'L1': 2},
         'L1': {'c1': 3, 'c2': 2.5, 'c3': 2}}

# Build the graph
G = DiGraph()
G.add_weighted_edges_from(((source, target, weight)
                           for source, d in graph.items()
                           for target, weight in d.items()))

# Find shortest path (using Dijkstra algorithm)
#result = shortest_path(G, source='c1', target='c3', weight='weight')
result = multi_source_dijkstra(G, sources=['c2','c3'], target='L1')

print(result)
# result: (2, ['c3', 'L1'])

Library and function I am using: https://networkx.github.io/documentation/stable/reference/algorithms/generated/networkx.algorithms.shortest_paths.weighted.multi_source_dijkstra_path.html#networkx.algorithms.shortest_paths.weighted.multi_source_dijkstra_path

I noticed networkx have two traveling salesman functions, but neither of them can return the path, only the distance so I don't think I can use them.


问:
Toggle Button value when onClick() is invoked React
When the App starts, the button's text is initially 'c'. When the button is clicked, it goes to toggleDisplay() and checks if unit === 'c'. If it's true, then update the unit variable to 'f'. This part works as I tested it using console.log. But the unit variable that in inside <button> tag is not updating. It's only showing 'c' but it has to toggle between 'c' and 'f'

```<code>function App() {
...
...
let unit = "c";
const toggleDisplay = () =>{
if(unit === 'c'){
    unit = "f";
    console.log(unit)
}
else{
    unit = "c";
    console.log(unit)
 }
}

return(
    <button className="temp" onClick={toggleDisplay}>
        {unit}
    </button>
)
</code>```

Ps. This is actually a weather app and the toggle between 'c' and 'f' is the toggle between values of celsius and fahrenheit.

答:
An easy way to create a toggle between two elements</p>

```<code>import {useState} from 'react'
function App() {
  const [isToggled,setToggle] = useState(false);
  const [unit,setUnit] = useState('c');

  const toggle = () => {
    setToggle(!isToggled)
    isToggled ? setUnit('c') : setUnit('f') // use ternary operator for readability
  }
}
</code>```

Body:
When the App starts, the button's text is initially 'c'. When the button is clicked, it goes to toggleDisplay() and checks if unit === 'c'. If it's true, then update the unit variable to 'f'. This part works as I tested it using console.log. But the unit variable that in inside <button> tag is not updating. It's only showing 'c' but it has to toggle between 'c' and 'f'

function App() {
...
...
let unit = "c";
const toggleDisplay = () =>{
if(unit === 'c'){
    unit = "f";
    console.log(unit)
}
else{
    unit = "c";
    console.log(unit)
 }
}

return(
    <button className="temp" onClick={toggleDisplay}>
        {unit}
    </button>
)

Ps. This is actually a weather app and the toggle between 'c' and 'f' is the toggle between values of celsius and fahrenheit.

Body:
An easy way to create a toggle between two elements

import {useState} from 'react'
function App() {
  const [isToggled,setToggle] = useState(false);
  const [unit,setUnit] = useState('c');

  const toggle = () => {
    setToggle(!isToggled)
    isToggled ? setUnit('c') : setUnit('f') // use ternary operator for readability
  }
}


问:
Why i cant see my log4j result in my log file?
I am trying to use log4j at my Java project and print out the result to my log.txt and and its dosnt works, i cant find any reason why.

my Logger:

```<code>import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class Log4J2PropertiesConf {
    private static Logger logger = LogManager.getLogger();

    public void performSomeTask() {
        logger.debug("This is a debug message");
        logger.info("This is an info message");
        logger.warn("This is a warn message");
        logger.error("This is an error message");
        logger.fatal("This is a fatal message");
    }
}
</code>```

my properties:

```<code>property.filename = logs
appenders = console, file
appender.console.type = Console
appender.console.name = STDOUT
appender.console.layout.type = PatternLayout
appender.console.layout.pattern = [%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n
appender.file.type = File
appender.file.name = LOGFILE
appender.file.fileName=${filename}/propertieslogs.log
appender.file.layout.type=PatternLayout
appender.file.layout.pattern=[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n
loggers=file
logger.file.name=guru.springframework.blog.log4j2properties
logger.file.level = debug
logger.file.appenderRefs = file
logger.file.appenderRef.file.ref = LOGFILE
rootLogger.level = debug
rootLogger.appenderRefs = stdout
rootLogger.appenderRef.stdout.ref = STDOUT
</code>```

pom.xml:

```<code><?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <dependencies>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.5</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.5</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>RELEASE</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>RELEASE</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <groupId>org.example</groupId>
    <artifactId>untitled</artifactId>
    <version>1.0-SNAPSHOT</version>

</project>
</code>```

the console print the correct output and the propertieslogs.log is propertly created , but he is empty.

i am used this documantation :
https://springframework.guru/log4j-2-configuration-using-properties-file/

答: There is no org.springframework.boot:spring-boot-starter-log4j2 in your dependencies.

Body:
I am trying to use log4j at my Java project and print out the result to my log.txt and and its dosnt works, i cant find any reason why.

my Logger:

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class Log4J2PropertiesConf {
    private static Logger logger = LogManager.getLogger();

    public void performSomeTask() {
        logger.debug("This is a debug message");
        logger.info("This is an info message");
        logger.warn("This is a warn message");
        logger.error("This is an error message");
        logger.fatal("This is a fatal message");
    }
}

my properties:

property.filename = logs
appenders = console, file
appender.console.type = Console
appender.console.name = STDOUT
appender.console.layout.type = PatternLayout
appender.console.layout.pattern = [%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n
appender.file.type = File
appender.file.name = LOGFILE
appender.file.fileName=${filename}/propertieslogs.log
appender.file.layout.type=PatternLayout
appender.file.layout.pattern=[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n
loggers=file
logger.file.name=guru.springframework.blog.log4j2properties
logger.file.level = debug
logger.file.appenderRefs = file
logger.file.appenderRef.file.ref = LOGFILE
rootLogger.level = debug
rootLogger.appenderRefs = stdout
rootLogger.appenderRef.stdout.ref = STDOUT

pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <dependencies>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.5</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.5</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>RELEASE</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>RELEASE</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <groupId>org.example</groupId>
    <artifactId>untitled</artifactId>
    <version>1.0-SNAPSHOT</version>

</project>

the console print the correct output and the propertieslogs.log is propertly created , but he is empty.

i am used this documantation :
https://springframework.guru/log4j-2-configuration-using-properties-file/


问:
Protecting Java data (saving items to a secure file)?
I am making a simple text game in Java and I wanted a safe way to save statistics (money, etc).

I could do a text file but then it could just be modified. I was wondering if there was a simple way to make it a little more difficult for someone to mess around with the saved statistics.

答:
If you're just interested in stopping people modifying the contents of the file (but don't care if they are able to read it), then have a look at using SHA1 to generate a simple signature for the file so you can tell if anyone has tampered with it.

That way anyone who opens it can see what's inside, but they can't modify it without you knowing (as the content will not match attached signature).

If you want full encryption of the file, that's doable too. Google something like java encryption to see more.

Pseudo code would look something like:

```<code>public class SignedFileSaver {

  private static final String SECRET = "Y0UR_S3CR3T_HERE";

  public void save(String content, String fileName) {
    String signature = sha1(content + SECRET);
    String signedContent = content + "\n----END CONTENT----\n" + signature;
    writeFile(content, fileName);
  }

  public String load(fileName) {
    String signedContent = readFile(fileName);
    String content = signedContent.whateverTextIsBefore("\n----END CONTENT----\n");
    String signature = signedContent.whateverTextIsAfter("\n----END CONTENT----\n");

    String expectedSignature = sha1(content + SECRET);
    if (!signature.equals(expectedSignature)) {
      throw new SignedFileTamperedWith(fileName + " has been tampered with");
    }
    return content;
  }
}
</code>```

Of course all they need to do is decompile your compiled source to see the secret, but it's an extra hoop they have to jump through.

Body:
If you're just interested in stopping people modifying the contents of the file (but don't care if they are able to read it), then have a look at using SHA1 to generate a simple signature for the file so you can tell if anyone has tampered with it.

That way anyone who opens it can see what's inside, but they can't modify it without you knowing (as the content will not match attached signature).

If you want full encryption of the file, that's doable too. Google something like java encryption to see more.

Pseudo code would look something like:

public class SignedFileSaver {

  private static final String SECRET = "Y0UR_S3CR3T_HERE";

  public void save(String content, String fileName) {
    String signature = sha1(content + SECRET);
    String signedContent = content + "\n----END CONTENT----\n" + signature;
    writeFile(content, fileName);
  }

  public String load(fileName) {
    String signedContent = readFile(fileName);
    String content = signedContent.whateverTextIsBefore("\n----END CONTENT----\n");
    String signature = signedContent.whateverTextIsAfter("\n----END CONTENT----\n");

    String expectedSignature = sha1(content + SECRET);
    if (!signature.equals(expectedSignature)) {
      throw new SignedFileTamperedWith(fileName + " has been tampered with");
    }
    return content;
  }
}

Of course all they need to do is decompile your compiled source to see the secret, but it's an extra hoop they have to jump through.


问:
ERROR TypeError: Cannot read property 'map' of undefined while trying to use formArray
I'm trying to display add a playlist in Mat-dialog that has songs in a list using (formArray) like this:

but I keep getting :

ERROR TypeError: Cannot read property 'map' of undefined

and my dialogue look this way:

here's my code:

my Dialog.component.html

```<code><h1 mat-dialog-title>Create New Playlist
</h1>
<form [formGroup]='form'>
<div>

  <div mat-dialog-content>

      <mat-form-field class="input-width" appearance="standard">
        <mat-label>Playlist name</mat-label>
        <input  matInput placeholder="" required formControlName="name"  [(ngModel)]="data.name">

      </mat-form-field>
      <mat-form-field class="input-width" appearance="standard">
        <mat-label>Description</mat-label>
        <input  matInput placeholder="" required formControlName="description" [(ngModel)]="data.description" >

      </mat-form-field>
        <mat-dialog-actions class="action-buttons">
    <button mat-raised-button  color="warn" (click)="close()" >Cancel </button>
  <button mat-raised-button color="primary"  [disabled] = "form.invalid" (click)="onSubmit()" [mat-dialog-close]="data">Submit</button>

  </mat-dialog-actions>
  <div formArrayName="songs" *ngIf="this.form">
    <div *ngFor = "let song of songsform().controls; let i = index">
      <div class="song-input-wrapper" [formGroupName]="i">
        <mat-form-field  appearance="standard">
          <mat-label>Song Title</mat-label>
          <input  matInput placeholder="" required formControlName="title">

        </mat-form-field>
        <mat-form-field  appearance="standard">
          <mat-label>Artist</mat-label>
          <input matInput placeholder="" required formControlName="artist">

        </mat-form-field>
        <mat-form-field appearance="standard">
          <mat-label>Duration</mat-label>
          <input matInput type="number" required  formControlName="duration">
          <span matSuffix>minutes</span>
        </mat-form-field>
          <button mat-icon-button color="primary" (click)="addSong()">
            <mat-icon>add_circle</mat-icon>
          </button>
          <button
          *ngIf="songsform().controls.length > 1"
          mat-icon-button
          color="warn"
          (click)="removeSong(i)"
        >
          <mat-icon>remove_circle</mat-icon>
        </button>

      </div>
    </div>
  </div>

</div>

  </div>

</form>
</code>```

and my dialog.componenet.ts:

```<code>export class DialogComponent implements OnInit {

  description:string;
  songs: FormArray;

  constructor(public service: PlaylistService,public dialogRef: MatDialogRef<DialogComponent>, private formBuilder: FormBuilder, @Inject(MAT_DIALOG_DATA) public data: Playlist  )
   {
   }
   form : FormGroup

  songsform() :FormArray {
    return this.form.get('songs') as FormArray ;
  }

  ngOnInit(): void {

       if (!this.data) {
      this.form = this.formBuilder.group({
        name: [null, Validators.required],
        description: [null, Validators.required],
        songs: this.formBuilder.array([ this.createSong() ]),
      });
    } else {
      this.form = this.formBuilder.group({
        name: [this.data.name, Validators.required],
        description: [this.data.description, Validators.required],
        songs: this.formBuilder.array(
          this.data.songs.map(song => this.formBuilder.group({
            title: [song.title, Validators.required],
            artist: [song.artist, Validators.required],
            duration: [song.duration, Validators.compose([Validators.required, Validators.min(0)])],
          }))
        ),
      })}

  }
  close() {
    this.dialogRef.close();
}

createSong(): FormGroup {
  return this.formBuilder.group({
    title: [null, Validators.required],
    artist: [null, Validators.required],
    duration: [null, Validators.compose([Validators.required, Validators.min(0)])],
  });
}
addSong(): void {
  this.songs.push(this.createSong());
}
removeSong(index: number): void {
  if (this.songs.controls.length > 1) {
    this.songs.removeAt(index);
  }
}
  onSubmit(){

      this.dialogRef.close(this.form.value);

  }
  }
</code>```

and finally, the component where I open the dialog and where my playlist class exist:

```<code>export interface Playlist {
  name: string;
  totalDuration: number;
  totalSongs: number;
  description: string;
  songs: Song[];
}

export interface Song {
  title: string;
  artist: string;
  duration: number;
}
@Component({
  selector: 'app-playlist',
  templateUrl: './playlist.component.html',
  styleUrls: ['./playlist.component.css']
})

export class PlaylistComponent implements OnInit {

  constructor(public dialog: MatDialog,public service: PlaylistService) { }

  ngOnInit(): void {
  }

  playlists: Playlist[] = [
    {
      name: 'Kopikustik',
      totalDuration: 5,
      totalSongs: 2,
      description: 'More than a coffee, this is all of your favorite accoustic songs.',
      songs: [
        {
          title: 'Cigarettes of ours',
          artist: 'Ardhito Pramono',
          duration: 3
        },
        {
          title: 'Walking Back Home',
          artist: 'Vira Talisa',
          duration: 2
        },
      ]
    },
    {
      name: 'Anime Hits',
      totalDuration: 13,
      totalSongs: 3,
      description: 'Listen to your favorite Anime songs, all in one playlist.',
      songs: [
        {
          title: 'Renai Circulation',
          artist: 'Kana Hanazawa',
          duration: 4
        },
        {
          title: 'Platinum Disco',
          artist: 'Tsukihi Phoenix',
          duration: 4
        },
        {
          title: 'Silhouette',
          artist: 'KANA-BOON',
          duration: 5
        },
      ]
    }
  ];
  name:String
  @Input() data: Playlist
  openDialog(): void {
    const dialogConfig = new MatDialogConfig();
    dialogConfig.autoFocus = false;
    const dialogRef = this.dialog.open(DialogComponent, {

      width: '900px',
      data: {
        name : this.name,
      /*  description:'',
        title:'',
        artist:'',
        duration:0*/
      }
    });

    dialogRef.afterClosed().subscribe(result => {
      console.log('The dialog was closed');
      if (result) {
        this.name = result.name;
        alert("name is :"+ this.name)
        }
    });
  }

  deletePlaylist(i)
  {
    this.playlists.splice(i, 1);
  }

}
</code>```

I don't understand why he's having a problem with

this.data.songs.map(song => this.formBuilder.group())

if anyone is familiar or can see what I'm missing please help me

答:
songs is not initialized in the data being injected into DialogComponent. You can initialize it to an empty array when constructing the dialog data:

const dialogRef = this.dialog.open(DialogComponent, {
  width: '900px',
  data: {
    name: this.name,
    songs: []
  }
});
```

Body:
I'm trying to display add a playlist in Mat-dialog that has songs in a list using (formArray) like this:

but I keep getting :

ERROR TypeError: Cannot read property 'map' of undefined

and my dialogue look this way:

here's my code:

my Dialog.component.html

Create New Playlist

<form [formGroup]='form'>

      <mat-form-field class="input-width" appearance="standard">
        <mat-label>Playlist name</mat-label>
        <input  matInput placeholder="" required formControlName="name"  [(ngModel)]="data.name">

      </mat-form-field>
      <mat-form-field class="input-width" appearance="standard">
        <mat-label>Description</mat-label>
        <input  matInput placeholder="" required formControlName="description" [(ngModel)]="data.description" >

      </mat-form-field>
        <mat-dialog-actions class="action-buttons">
    <button mat-raised-button  color="warn" (click)="close()" >Cancel </button>
  <button mat-raised-button color="primary"  [disabled] = "form.invalid" (click)="onSubmit()" [mat-dialog-close]="data">Submit</button>

  </mat-dialog-actions>

        <mat-form-field  appearance="standard">
          <mat-label>Song Title</mat-label>
          <input  matInput placeholder="" required formControlName="title">

        </mat-form-field>
        <mat-form-field  appearance="standard">
          <mat-label>Artist</mat-label>
          <input matInput placeholder="" required formControlName="artist">

        </mat-form-field>
        <mat-form-field appearance="standard">
          <mat-label>Duration</mat-label>
          <input matInput type="number" required  formControlName="duration">
          minutes
        </mat-form-field>
          <button mat-icon-button color="primary" (click)="addSong()">
            <mat-icon>add_circle</mat-icon>
          </button>
          <button
          *ngIf="songsform().controls.length > 1"
          mat-icon-button
          color="warn"
          (click)="removeSong(i)"
        >
          <mat-icon>remove_circle</mat-icon>
        </button>

</form>

and my dialog.componenet.ts:

export class DialogComponent implements OnInit {

  description:string;
  songs: FormArray;

  constructor(public service: PlaylistService,public dialogRef: MatDialogRef<DialogComponent>, private formBuilder: FormBuilder, @Inject(MAT_DIALOG_DATA) public data: Playlist  )
   {
   }
   form : FormGroup

  songsform() :FormArray {
    return this.form.get('songs') as FormArray ;
  }

  ngOnInit(): void {

       if (!this.data) {
      this.form = this.formBuilder.group({
        name: [null, Validators.required],
        description: [null, Validators.required],
        songs: this.formBuilder.array([ this.createSong() ]),
      });
    } else {
      this.form = this.formBuilder.group({
        name: [this.data.name, Validators.required],
        description: [this.data.description, Validators.required],
        songs: this.formBuilder.array(
          this.data.songs.map(song => this.formBuilder.group({
            title: [song.title, Validators.required],
            artist: [song.artist, Validators.required],
            duration: [song.duration, Validators.compose([Validators.required, Validators.min(0)])],
          }))
        ),
      })}

  }
  close() {
    this.dialogRef.close();
}

createSong(): FormGroup {
  return this.formBuilder.group({
    title: [null, Validators.required],
    artist: [null, Validators.required],
    duration: [null, Validators.compose([Validators.required, Validators.min(0)])],
  });
}
addSong(): void {
  this.songs.push(this.createSong());
}
removeSong(index: number): void {
  if (this.songs.controls.length > 1) {
    this.songs.removeAt(index);
  }
}
  onSubmit(){

      this.dialogRef.close(this.form.value);

  }
  }

and finally, the component where I open the dialog and where my playlist class exist:

export interface Playlist {
  name: string;
  totalDuration: number;
  totalSongs: number;
  description: string;
  songs: Song[];
}

export interface Song {
  title: string;
  artist: string;
  duration: number;
}
@Component({
  selector: 'app-playlist',
  templateUrl: './playlist.component.html',
  styleUrls: ['./playlist.component.css']
})

export class PlaylistComponent implements OnInit {

  constructor(public dialog: MatDialog,public service: PlaylistService) { }

  ngOnInit(): void {
  }

  playlists: Playlist[] = [
    {
      name: 'Kopikustik',
      totalDuration: 5,
      totalSongs: 2,
      description: 'More than a coffee, this is all of your favorite accoustic songs.',
      songs: [
        {
          title: 'Cigarettes of ours',
          artist: 'Ardhito Pramono',
          duration: 3
        },
        {
          title: 'Walking Back Home',
          artist: 'Vira Talisa',
          duration: 2
        },
      ]
    },
    {
      name: 'Anime Hits',
      totalDuration: 13,
      totalSongs: 3,
      description: 'Listen to your favorite Anime songs, all in one playlist.',
      songs: [
        {
          title: 'Renai Circulation',
          artist: 'Kana Hanazawa',
          duration: 4
        },
        {
          title: 'Platinum Disco',
          artist: 'Tsukihi Phoenix',
          duration: 4
        },
        {
          title: 'Silhouette',
          artist: 'KANA-BOON',
          duration: 5
        },
      ]
    }
  ];
  name:String
  @Input() data: Playlist
  openDialog(): void {
    const dialogConfig = new MatDialogConfig();
    dialogConfig.autoFocus = false;
    const dialogRef = this.dialog.open(DialogComponent, {

      width: '900px',
      data: {
        name : this.name,
      /*  description:'',
        title:'',
        artist:'',
        duration:0*/
      }
    });

    dialogRef.afterClosed().subscribe(result => {
      console.log('The dialog was closed');
      if (result) {
        this.name = result.name;
        alert("name is :"+ this.name)
        }
    });
  }

  deletePlaylist(i)
  {
    this.playlists.splice(i, 1);
  }

}

I don't understand why he's having a problem with

this.data.songs.map(song => this.formBuilder.group())

if anyone is familiar or can see what I'm missing please help me


问:
Redshift REGEXP_SUBSTR get last occurrence of a match
I have a list of page events of all types in a column value ordered by time asc that I got using listagg method.
listagg(page,';') within group (order by time)

I want to get the occurrence of the last match that matches the regex
regexp_substr(event_list,'/step[0-9]+[^;]*')

According to the docs "A positive integer that indicates the position within source_string to begin searching. The position is based on the number of characters, not bytes, so that multibyte characters are counted as single characters. The default is 1. If position is less than 1, the search begins at the first character of source_string. If position is greater than the number of characters in source_string, the result is source_string."

Based on this I need to know the exact occurrence number which I do not know.
How to get the last match in this case?
eg :
/step1;somethging;somethig;/step2;something;/step3;something;

I want to match step3.

PS:  Ordering by time desc and getting the first match is not an option here.

答:
Use regexp_count to determine how many matches there are (n) & then use regexp_substr to get the nth match.

```<code>select
  '/step1;somethging;somethig;/step2;something;/step3;something;' string
, '/step[0-9]+[^;]*' pat
, regexp_count(string, pat) n
, regexp_substr(string, pat, 1, n) last_part
</code>```

outputs:

```<code>                                                       string                pat    n    last_part
/step1;somethging;somethig;/step2;something;/step3;something;   /step[0-9]+[^;]*    3       /step3
</code>```

if / could be treated as a delimiter, then you may alternatively employ the following strategy

reverse the string, split by / & take the first part. reverse again, prefixing / and apply the regular expression to extract the step:

example:

```<code>select
  '/step1;somethging;somethig;/step2;something;/step3;something;' string
, '/' || reverse(split_part(reverse(string), '/', 1)) last_part
, regexp_substr(last_part, '/step[0-9]+[^;]*') extract_step
</code>```

outputs:

```<code>                                                       string           last_part   extract_step
/step1;somethging;somethig;/step2;something;/step3;something;   /step3;something;         /step3
</code>```

Body:
Use regexp_count to determine how many matches there are (n) & then use regexp_substr to get the nth match.

select
  '/step1;somethging;somethig;/step2;something;/step3;something;' string
, '/step[0-9]+[^;]*' pat
, regexp_count(string, pat) n
, regexp_substr(string, pat, 1, n) last_part

outputs:

                                                       string                pat    n    last_part
/step1;somethging;somethig;/step2;something;/step3;something;   /step[0-9]+[^;]*    3       /step3

if / could be treated as a delimiter, then you may alternatively employ the following strategy

reverse the string, split by / & take the first part. reverse again, prefixing / and apply the regular expression to extract the step:

example:

select
  '/step1;somethging;somethig;/step2;something;/step3;something;' string
, '/' || reverse(split_part(reverse(string), '/', 1)) last_part
, regexp_substr(last_part, '/step[0-9]+[^;]*') extract_step

outputs:

                                                       string           last_part   extract_step
/step1;somethging;somethig;/step2;something;/step3;something;   /step3;something;         /step3


问:
MatplotLib 'saveFig()' Fullscreen
I used MatplotLib with Cartopy to generate some data images.
The problem is that when I set the frame size to fullscreen and use plt.show() the image is perfect and the resolution is fine.

However, when I save this figure using 'plt.savefig()' the image saved keeps with its original size (not fullscreen).

Showing outcome images:

My code is the following:

def plot_tec_cartopy(descfile):
    global matrixLon, matrixLat, matrixTec

```<code>ax = plt.axes(projection=cartopy.crs.PlateCarree())

v = np.linspace(0, 80, 46, endpoint=True)
cp = plt.contourf(matrixLon, matrixLat, matrixTec, v, cmap=plt.cm.rainbow)
plt.clim(0, 80)
plt.colorbar(cp)

ax.add_feature(cartopy.feature.COASTLINE)
ax.add_feature(cartopy.feature.BORDERS, linestyle=':')
ax.set_extent([-85, -30, -60, 15])

# Setting X and Y labels using LON/LAT format
ax.set_xticks([-85, -75, -65, -55, -45, -35])
ax.set_yticks([-60, -55, -50, -45, -40, -35, -30, -25, -20, -15, -10, -5, 0, 5, 10, 15])
lon_formatter = LongitudeFormatter(number_format='.0f',
                                   degree_symbol='',
                                   dateline_direction_label=True)
lat_formatter = LatitudeFormatter(number_format='.0f',
                                  degree_symbol='')
ax.xaxis.set_major_formatter(lon_formatter)
ax.yaxis.set_major_formatter(lat_formatter)

plt.title('Conteúdo Eletrônico Total', style='normal', fontsize='12')

# Acquiring Date
year, julianday = check_for_zero(descfile.split('.')[2]), descfile.split('.')[3]
hour, minute = descfile.split('.')[4], descfile.split('.')[5].replace('h','')
date = datetime.datetime(int(year), 1, 1, int(hour), int(minute)) + datetime.timedelta(int(julianday)-1)
month = date.month
day = date.day

# Set common labels
ax.text(1.22, 1.05, 'TEC', style='normal',
    verticalalignment='top', horizontalalignment='right',
    transform=ax.transAxes,
    color='black', fontsize=11)
ax.text(1, 0.005, 'EMBRACE/INPE', style='italic',
    verticalalignment='bottom', horizontalalignment='right',
    transform=ax.transAxes,
    color='black', fontsize=10)
ax.text(1, 0.995, str(date) + ' UT', style='italic',
    verticalalignment='top', horizontalalignment='right',
    transform=ax.transAxes,
    color='black', fontsize=10)
ax.text(0.5, -0.08, 'Copyright \N{COPYRIGHT SIGN} 2017 INPE - Instituto Nacional de',
    style='oblique', transform=ax.transAxes,
    verticalalignment='bottom', horizontalalignment='center',
    color='black', fontsize=8)
ax.text(0.5, -0.108, 'Pesquisas Espacias. Todos direitos reservados',
    style='oblique', transform=ax.transAxes,
    verticalalignment='bottom', horizontalalignment='center',
    color='black', fontsize=8)

manager = plt.get_current_fig_manager()
manager.resize(*manager.window.maxsize())

figName = 'tec.map' + '.' + str(year) + '.' + str(julianday) + '.' + str(hour) + '.' + str(minute) + 'h.png'
#plt.show()
plt.savefig(figName, dpi=500)
plt.clf()
</code>```

Maybe I need to set some parameter into savefig() to say it that it needs to save my modified frame? Can someone help me with this issue?

Thanks in advance.

答:
Just to add some context on @Mad Physicist answer. If someone is trying to use it with a new version of matplotlib, you will get an AttributeError: 'Figure' object has no attribute 'save'. You also need to be careful about when you call plt.show() otherwise you will get a blank image. You need to update the code as follow:

# Create a plot
plt.barh(range(top), imp, align='center')
plt.yticks(range(top), names)

# Get the current figure like in MATLAB
fig = plt.gcf()
plt.show() # show it here (important, if done before you will get blank picture)
fig.set_size_inches((8.5, 11), forward=False)
fig.savefig(figName, dpi=500) # Change is over here
```

Hope it helps!

Title: MatplotLib 'saveFig()' Fullscreen

Body:
I used MatplotLib with Cartopy to generate some data images.
The problem is that when I set the frame size to fullscreen and use plt.show() the image is perfect and the resolution is fine.

However, when I save this figure using 'plt.savefig()' the image saved keeps with its original size (not fullscreen).

Showing outcome images:

My code is the following:

def plot_tec_cartopy(descfile):
    global matrixLon, matrixLat, matrixTec

ax = plt.axes(projection=cartopy.crs.PlateCarree())

v = np.linspace(0, 80, 46, endpoint=True)
cp = plt.contourf(matrixLon, matrixLat, matrixTec, v, cmap=plt.cm.rainbow)
plt.clim(0, 80)
plt.colorbar(cp)

ax.add_feature(cartopy.feature.COASTLINE)
ax.add_feature(cartopy.feature.BORDERS, linestyle=':')
ax.set_extent([-85, -30, -60, 15])

# Setting X and Y labels using LON/LAT format
ax.set_xticks([-85, -75, -65, -55, -45, -35])
ax.set_yticks([-60, -55, -50, -45, -40, -35, -30, -25, -20, -15, -10, -5, 0, 5, 10, 15])
lon_formatter = LongitudeFormatter(number_format='.0f',
                                   degree_symbol='',
                                   dateline_direction_label=True)
lat_formatter = LatitudeFormatter(number_format='.0f',
                                  degree_symbol='')
ax.xaxis.set_major_formatter(lon_formatter)
ax.yaxis.set_major_formatter(lat_formatter)

plt.title('Conteúdo Eletrônico Total', style='normal', fontsize='12')

# Acquiring Date
year, julianday = check_for_zero(descfile.split('.')[2]), descfile.split('.')[3]
hour, minute = descfile.split('.')[4], descfile.split('.')[5].replace('h','')
date = datetime.datetime(int(year), 1, 1, int(hour), int(minute)) + datetime.timedelta(int(julianday)-1)
month = date.month
day = date.day

# Set common labels
ax.text(1.22, 1.05, 'TEC', style='normal',
    verticalalignment='top', horizontalalignment='right',
    transform=ax.transAxes,
    color='black', fontsize=11)
ax.text(1, 0.005, 'EMBRACE/INPE', style='italic',
    verticalalignment='bottom', horizontalalignment='right',
    transform=ax.transAxes,
    color='black', fontsize=10)
ax.text(1, 0.995, str(date) + ' UT', style='italic',
    verticalalignment='top', horizontalalignment='right',
    transform=ax.transAxes,
    color='black', fontsize=10)
ax.text(0.5, -0.08, 'Copyright \N{COPYRIGHT SIGN} 2017 INPE - Instituto Nacional de',
    style='oblique', transform=ax.transAxes,
    verticalalignment='bottom', horizontalalignment='center',
    color='black', fontsize=8)
ax.text(0.5, -0.108, 'Pesquisas Espacias. Todos direitos reservados',
    style='oblique', transform=ax.transAxes,
    verticalalignment='bottom', horizontalalignment='center',
    color='black', fontsize=8)

manager = plt.get_current_fig_manager()
manager.resize(*manager.window.maxsize())

figName = 'tec.map' + '.' + str(year) + '.' + str(julianday) + '.' + str(hour) + '.' + str(minute) + 'h.png'
#plt.show()
plt.savefig(figName, dpi=500)
plt.clf()

Maybe I need to set some parameter into savefig() to say it that it needs to save my modified frame? Can someone help me with this issue?

Thanks in advance.

Body:
Just to add some context on @Mad Physicist answer. If someone is trying to use it with a new version of matplotlib, you will get an AttributeError: 'Figure' object has no attribute 'save'. You also need to be careful about when you call plt.show() otherwise you will get a blank image. You need to update the code as follow:

# Create a plot
plt.barh(range(top), imp, align='center')
plt.yticks(range(top), names)

# Get the current figure like in MATLAB
fig = plt.gcf()
plt.show() # show it here (important, if done before you will get blank picture)
fig.set_size_inches((8.5, 11), forward=False)
fig.savefig(figName, dpi=500) # Change is over here

Hope it helps!


问:
Get related ID collections from a json array react native
I have a array of objects as a json file, I used the objects to display them on the list, When getting to details of that item it has a related items also.
I want to show related items for this item
Heres the json file

```<code>[
{
    "id": 1,
    "name": "Kling-Spencer",
    "description": "sed justo pellentesque viverra pede ac diam cras pellentesque volutpat dui maecenas tristique est et tempus semper est quam pharetra magna",
    "email": "fdory0@opera.com",
    "image": "http://dummyimage.com/300x300.bmp/cc0000/ffffff&text=Kling-Spencer",
    "related": [
        2,
        3,
        6,
        8,
        23
    ]
},
{
    "id": 2,
    "name": "Donnelly, Lockman and Dare",
    "description": "in felis donec semper sapien a libero nam dui proin leo odio porttitor id consequat in consequat ut nulla sed accumsan felis ut at dolor quis odio consequat varius integer",
    "email": "amcglaughn1@indiatimes.com",
    "image": "http://dummyimage.com/300x300.png/5fa2dd/ffffff&text=Donnelly",
    "related": null
},
{
    "id": 3,
    "name": "Klein LLC",
    "description": "dictumst aliquam augue quam sollicitudin vitae consectetuer eget rutrum at lorem integer tincidunt ante vel ipsum praesent blandit lacinia erat",
    "email": "kcaso2@miibeian.gov.cn",
    "image": "http://dummyimage.com/300x300.jpg/cc0000/ffffff&text=Klein%20LLC",
    "related": [
        15,
        13,
        1,
        5,
        4
    ]
},
{
    "id": 4,
    "name": "Aufderhar Group",
    "description": "id justo sit amet sapien dignissim vestibulum vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae nulla dapibus dolor",
    "email": "ageleman3@zdnet.com",
    "image": "http://dummyimage.com/300x300.bmp/dddddd/000000&text=Aufderhar%20Group",
    "related": null
},
{
    "id": 5,
    "name": "Lynch, Raynor and Mayer",
    "description": "ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae nulla dapibus dolor vel est donec odio justo sollicitudin ut suscipit a feugiat et eros vestibulum",
    "email": "dleece4@apache.org",
    "image": "http://dummyimage.com/300x300.jpg/dddddd/000000",
    "related": null
},
{
    "id": 6,
    "name": "Kuhn, Miller and Carroll",
    "description": "in felis eu sapien cursus vestibulum proin eu mi nulla ac enim in tempor turpis nec euismod scelerisque quam turpis adipiscing",
    "email": "bgotliffe5@seesaa.net",
    "image": "http://dummyimage.com/300x300.png/5fa2dd/ffffff&text=Kuhn,%20Miller%20and%20Carroll",
    "related": [
        1,
        29,
        15
    ]
},
{
    "id": 7,
    "name": "Feest-Brown",
    "description": "ac enim in tempor turpis nec euismod scelerisque quam turpis adipiscing lorem vitae mattis nibh ligula nec sem duis aliquam convallis",
    "email": "mbridges6@deviantart.com",
    "image": "http://dummyimage.com/300x300.bmp/dddddd/000000&text=Feest-Brown",
    "related": null
},
{
    "id": 8,
    "name": "Gutmann, Buckridge and Kris",
    "description": "quis lectus suspendisse potenti in eleifend quam a odio in hac habitasse platea dictumst maecenas ut massa quis augue luctus tincidunt nulla mollis molestie lorem",
    "email": "tdumbrell7@ted.com",
    "image": "http://dummyimage.com/300x300.bmp/ff4444/ffffff&text=Gutmann",
    "related": [
        14,
        20,
        23,
        27
    ]
},
{
    "id": 9,
    "name": "McLaughlin-Bogan",
    "description": "morbi quis tortor id nulla ultrices aliquet maecenas leo odio condimentum id luctus nec molestie sed justo pellentesque viverra pede ac diam cras pellentesque",
    "email": "lgadsdon8@joomla.org",
    "image": "http://dummyimage.com/300x300.jpg/dddddd/000000&text=McLaughlin-Bogan",
    "related": [
        6,
        9,
        12,
        30
    ]
},
{
    "id": 10,
    "name": "Kilback-Padberg",
    "description": "leo odio condimentum id luctus nec molestie sed justo pellentesque viverra pede ac diam cras pellentesque volutpat dui maecenas tristique est et tempus semper est quam pharetra magna ac",
    "email": "eodegaard9@dailymail.co.uk",
    "image": "http://dummyimage.com/300x300.png/ff4444/ffffff&text=Kilback-Padberg",
    "related": null
},
{
    "id": 11,
    "name": "Skiles LLC",
    "description": "rutrum at lorem integer tincidunt ante vel ipsum praesent blandit lacinia erat vestibulum sed magna at nunc commodo placerat praesent blandit nam nulla integer pede justo lacinia eget tincidunt eget",
    "email": "marchibolda@apple.com",
    "image": "http://dummyimage.com/300x300.bmp/dddddd/000000&text=Skiles%20LLC",
    "related": [
        21,
        27,
        28,
        5
    ]
},
{
    "id": 12,
    "name": "McGlynn Group",
    "description": "nulla integer pede justo lacinia eget tincidunt eget tempus vel pede morbi porttitor lorem id ligula suspendisse ornare consequat lectus in est risus",
    "email": "eraggettb@nba.com",
    "image": "http://dummyimage.com/300x300.bmp/cc0000/ffffff&text=McGlynn%20Group",
    "related": [
        10,
        18,
        26
    ]
},
{
    "id": 13,
    "name": "Cassin-Kling",
    "description": "ac enim in tempor turpis nec euismod scelerisque quam turpis adipiscing lorem vitae mattis nibh ligula nec sem duis aliquam convallis",
    "email": "cdunbletonc@indiatimes.com",
    "image": "http://dummyimage.com/300x300.jpg/cc0000/ffffff&text=Cassin-Kling",
    "related": [
        17,
        29,
        1,
        3,
        8
    ]
},
{
    "id": 14,
    "name": "Greenfelder, Conroy and Schinner",
    "description": "imperdiet nullam orci pede venenatis non sodales sed tincidunt eu felis fusce posuere felis sed lacus morbi sem mauris laoreet ut rhoncus aliquet pulvinar sed nisl nunc rhoncus",
    "email": "njamiesond@ehow.com",
    "image": "http://dummyimage.com/300x300.bmp/dddddd/000000&text=Greenfelder",
    "related": [
        18,
        21,
        27
    ]
},
{
    "id": 15,
    "name": "MacGyver, Huel and Lind",
    "description": "cubilia curae duis faucibus accumsan odio curabitur convallis duis consequat dui nec nisi volutpat eleifend donec ut dolor morbi vel lectus in",
    "email": "tclinche@soundcloud.com",
    "image": "http://dummyimage.com/300x300.bmp/ff4444/ffffff&text=MacGyver",
    "related": null
},
{
    "id": 16,
    "name": "Aufderhar-Little",
    "description": "nisl aenean lectus pellentesque eget nunc donec quis orci eget orci vehicula condimentum curabitur in libero ut massa volutpat convallis morbi odio odio elementum eu",
    "email": "epennellsf@symantec.com",
    "image": "http://dummyimage.com/300x300.png/dddddd/000000&text=Aufderhar-Little",
    "related": null
},
{
    "id": 17,
    "name": "Graham-Berge",
    "description": "non ligula pellentesque ultrices phasellus id sapien in sapien iaculis congue vivamus metus arcu adipiscing molestie hendrerit at vulputate vitae nisl aenean lectus pellentesque eget nunc donec quis orci",
    "email": "rvielg@weibo.com",
    "image": "http://dummyimage.com/300x300.bmp/ff4444/ffffff&text=Graham-Berge",
    "related": [
        12,
        16,
        29,
        30
    ]
},
{
    "id": 18,
    "name": "Gaylord, Klein and Donnelly",
    "description": "ac est lacinia nisi venenatis tristique fusce congue diam id ornare imperdiet sapien urna pretium nisl ut volutpat sapien arcu sed augue",
    "email": "estoyellh@bing.com",
    "image": "http://dummyimage.com/300x300.jpg/cc0000/ffffff&text=Klein%20and%20Donnelly",
    "related": [
        6,
        7,
        9,
        18,
        21
    ]
},
{
    "id": 19,
    "name": "Gusikowski Group",
    "description": "lacus morbi quis tortor id nulla ultrices aliquet maecenas leo odio condimentum id luctus nec molestie sed justo pellentesque viverra pede ac diam cras pellentesque volutpat dui maecenas tristique",
    "email": "kpalatinoi@toplist.cz",
    "image": "http://dummyimage.com/300x300.jpg/ff4444/ffffff&text=Gusikowski",
    "related": [
        16,
        29,
        3
    ]
},
{
    "id": 20,
    "name": "Jaskolski-McKenzie",
    "description": "a nibh in quis justo maecenas rhoncus aliquam lacus morbi quis tortor id nulla ultrices aliquet maecenas leo odio condimentum id luctus nec",
    "email": "sloganj@japanpost.jp",
    "image": "http://dummyimage.com/300x300.bmp/cc0000/ffffff&text=Jaskolski-McKenzie",
    "related": [
        12,
        14,
        18
    ]
},
{
    "id": 21,
    "name": "Kautzer, Dooley and Kuhic",
    "description": "hac habitasse platea dictumst maecenas ut massa quis augue luctus tincidunt nulla mollis molestie lorem quisque ut erat curabitur gravida nisi at nibh in",
    "email": "snoodsk@over-blog.com",
    "image": "http://dummyimage.com/300x300.jpg/dddddd/000000&text=Kautzer",
    "related": [
        3,
        5,
        17,
        29,
        30
    ]
},
{
    "id": 22,
    "name": "Kohler, Tremblay and Bernier",
    "description": "in lacus curabitur at ipsum ac tellus semper interdum mauris ullamcorper purus sit amet nulla quisque arcu libero rutrum ac lobortis vel dapibus at",
    "email": "zsorriel@arizona.edu",
    "image": "http://dummyimage.com/300x300.png/ff4444/ffffff&text=Kohler",
    "related": null
},
{
    "id": 23,
    "name": "Cummerata, Trantow and Huels",
    "description": "potenti nullam porttitor lacus at turpis donec posuere metus vitae ipsum aliquam non mauris morbi non lectus aliquam sit amet diam in magna bibendum imperdiet nullam orci pede venenatis non",
    "email": "rshillingtonm@people.com.cn",
    "image": "http://dummyimage.com/300x300.jpg/dddddd/000000&text=Cummerata",
    "related": [
        5,
        4,
        13,
        23,
        27
    ]
},
{
    "id": 24,
    "name": "O'Reilly LLC",
    "description": "eu orci mauris lacinia sapien quis libero nullam sit amet turpis elementum ligula vehicula consequat morbi a ipsum integer a",
    "email": "tstaten@symantec.com",
    "image": "http://dummyimage.com/300x300.png/5fa2dd/ffffff&text=O'Reilly%20LLC",
    "related": [
        4,
        5,
        6,
        10
    ]
},
{
    "id": 25,
    "name": "Grant-Spencer",
    "description": "augue vel accumsan tellus nisi eu orci mauris lacinia sapien quis libero nullam sit amet turpis elementum ligula vehicula consequat morbi a ipsum integer a",
    "email": "bgrzegorczyko@vk.com",
    "image": "http://dummyimage.com/300x300.png/ff4444/ffffff&text=Grant-Spencer",
    "related": null
},
{
    "id": 26,
    "name": "Jacobi-Jaskolski",
    "description": "orci nullam molestie nibh in lectus pellentesque at nulla suspendisse potenti cras in purus eu magna vulputate luctus cum sociis natoque penatibus et magnis dis parturient montes",
    "email": "afranktonp@uol.com.br",
    "image": "http://dummyimage.com/300x300.bmp/5fa2dd/ffffff&text=Jacobi-Jaskolski",
    "related": null
},
{
    "id": 27,
    "name": "Heathcote LLC",
    "description": "curabitur in libero ut massa volutpat convallis morbi odio odio elementum eu interdum eu tincidunt in leo maecenas pulvinar lobortis est phasellus",
    "email": "sgeggusq@weather.com",
    "image": "http://dummyimage.com/300x300.bmp/5fa2dd/ffffff&text=Heathcote%20LLC",
    "related": [
        15,
        20,
        1,
        3
    ]
},
{
    "id": 28,
    "name": "Towne, Schaefer and Reichert",
    "description": "congue elementum in hac habitasse platea dictumst morbi vestibulum velit id pretium iaculis diam erat fermentum justo nec condimentum neque sapien placerat ante nulla justo aliquam quis",
    "email": "msnoadr@army.mil",
    "image": "http://dummyimage.com/300x300.jpg/ff4444/ffffff&text=Towne",
    "related": null
},
{
    "id": 29,
    "name": "Graham, Green and Roberts",
    "description": "vestibulum sagittis sapien cum sociis natoque penatibus et magnis dis parturient montes nascetur ridiculus mus etiam vel augue vestibulum rutrum rutrum neque aenean auctor gravida",
    "email": "aflecknoes@redcross.org",
    "image": "http://dummyimage.com/300x300.jpg/dddddd/000000&text=Graham",
    "related": null
},
{
    "id": 30,
    "name": "Commings Group",
    "description": "luctus tincidunt nulla mollis molestie lorem quisque ut erat curabitur gravida nisi at nibh in hac habitasse platea dictumst aliquam augue",
    "email": "gmationt@slideshare.net",
    "image": "http://dummyimage.com/300x300.jpg/cc0000/ffffff&text=Commings%20Group",
    "related": null
}
</code>```

]

As you can see for every item has a related, but related are just ID's how can i find each related item object and show them heres what i tried

this is the item details screen

```<code>   import React from "react";
import { View, Image, StyleSheet, Text, FlatList } from "react-native";

import RelatedList from "../components/RelatedList";

import api from "../apis/stores.json";

function StoreDetails(props) {
  const { navigation } = props;
  const id = navigation.getParam("id");
  const name = navigation.getParam("name");
  const email = navigation.getParam("email");
  const description = navigation.getParam("description");
  const image = navigation.getParam("image");
  const data = [api[0]];

  data.filter(value => value.id == id)
  const related = [
    data
  ];
  return (
    <View>
      <Image style={styles.image} source={{ uri: image }} />
      <View style={styles.detailsContainer}>
        <Text style={styles.name}>{name}</Text>
        <Text>{email}</Text>
        <Text>{description}</Text>
        <FlatList
          data={related}
          keyExtractor={(related) => related.id.toString()}
          renderItem={({ item }) => (
            <RelatedList
              image={item.image}
              name={item.name}
              status={item.status}
            />
          )}
        />
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  image: {
    width: "100%",
    height: 300,
  },
  detailsContainer: {
    padding: 20,
  },
  name: {
    fontWeight: "bold",
    fontSize: 25,
  },
});

export default StoreDetails;
</code>```

答:
use this function in your code
I think, it's one of the fastest way to find related data

```<code>const findRelatedData = (data, id) => {
      const mainItem = data.find(item => item.id === id)
      if (!mainItem || !Array.isArray(mainItem.related)) {
        return []
      }
      const dataLength = data.length
      const relatedLength = mainItem.related.length
      let jInitVal = 0;
      const result = []
      for (let i = 0; i < dataLength && jInitVal < relatedLength; i++) {
        for (let j = jInitVal; j < relatedLength; j++) {
          if (data[i].id === mainItem.related[j]) {
            result.push(data[i])
            // if the related list isn't sort this condition would be true
            // it likes a buble sort
            if (j > jInitVal ) {
             let tmp = mainItem.related[j]
              mainItem.related[j] = mainItem.related[jInitVal]
              mainItem.related[jInitVal] = tmp
            }
            jInitVal++
            break;
          }
        }
      }
      return result;
    }
</code>```

I call this function in your code

```<code>import React from "react";
import { View, Image, StyleSheet, Text, FlatList } from "react-native";

import RelatedList from "../components/RelatedList";

import api from "../apis/stores.json";

// here you can past 'findRelatedData' function

function StoreDetails(props) {
  const { navigation } = props;
  const id = navigation.getParam("id");
  const name = navigation.getParam("name");
  const email = navigation.getParam("email");
  const description = navigation.getParam("description");
  const image = navigation.getParam("image");
  const data = [api[0]];

  /*data.filter(value => value.id == id)
  const related = [
    data
  ];*/
  const related = findRelatedData(data , id)

  return (
    <View>
      <Image style={styles.image} source={{ uri: image }} />
      <View style={styles.detailsContainer}>
        <Text style={styles.name}>{name}</Text>
        <Text>{email}</Text>
        <Text>{description}</Text>
        <FlatList
          data={related}
          keyExtractor={(related) => related.id.toString()}
          renderItem={({ item }) => (
            <RelatedList
              image={item.image}
              name={item.name}
              status={item.status}
            />
          )}
        />
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  image: {
    width: "100%",
    height: 300,
  },
  detailsContainer: {
    padding: 20,
  },
  name: {
    fontWeight: "bold",
    fontSize: 25,
  },
});

export default StoreDetails;
</code>```

Body:
I have a array of objects as a json file, I used the objects to display them on the list, When getting to details of that item it has a related items also.
I want to show related items for this item
Heres the json file

[
{
    "id": 1,
    "name": "Kling-Spencer",
    "description": "sed justo pellentesque viverra pede ac diam cras pellentesque volutpat dui maecenas tristique est et tempus semper est quam pharetra magna",
    "email": "fdory0@opera.com",
    "image": "http://dummyimage.com/300x300.bmp/cc0000/ffffff&text=Kling-Spencer",
    "related": [
        2,
        3,
        6,
        8,
        23
    ]
},
{
    "id": 2,
    "name": "Donnelly, Lockman and Dare",
    "description": "in felis donec semper sapien a libero nam dui proin leo odio porttitor id consequat in consequat ut nulla sed accumsan felis ut at dolor quis odio consequat varius integer",
    "email": "amcglaughn1@indiatimes.com",
    "image": "http://dummyimage.com/300x300.png/5fa2dd/ffffff&text=Donnelly",
    "related": null
},
{
    "id": 3,
    "name": "Klein LLC",
    "description": "dictumst aliquam augue quam sollicitudin vitae consectetuer eget rutrum at lorem integer tincidunt ante vel ipsum praesent blandit lacinia erat",
    "email": "kcaso2@miibeian.gov.cn",
    "image": "http://dummyimage.com/300x300.jpg/cc0000/ffffff&text=Klein%20LLC",
    "related": [
        15,
        13,
        1,
        5,
        4
    ]
},
{
    "id": 4,
    "name": "Aufderhar Group",
    "description": "id justo sit amet sapien dignissim vestibulum vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae nulla dapibus dolor",
    "email": "ageleman3@zdnet.com",
    "image": "http://dummyimage.com/300x300.bmp/dddddd/000000&text=Aufderhar%20Group",
    "related": null
},
{
    "id": 5,
    "name": "Lynch, Raynor and Mayer",
    "description": "ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae nulla dapibus dolor vel est donec odio justo sollicitudin ut suscipit a feugiat et eros vestibulum",
    "email": "dleece4@apache.org",
    "image": "http://dummyimage.com/300x300.jpg/dddddd/000000",
    "related": null
},
{
    "id": 6,
    "name": "Kuhn, Miller and Carroll",
    "description": "in felis eu sapien cursus vestibulum proin eu mi nulla ac enim in tempor turpis nec euismod scelerisque quam turpis adipiscing",
    "email": "bgotliffe5@seesaa.net",
    "image": "http://dummyimage.com/300x300.png/5fa2dd/ffffff&text=Kuhn,%20Miller%20and%20Carroll",
    "related": [
        1,
        29,
        15
    ]
},
{
    "id": 7,
    "name": "Feest-Brown",
    "description": "ac enim in tempor turpis nec euismod scelerisque quam turpis adipiscing lorem vitae mattis nibh ligula nec sem duis aliquam convallis",
    "email": "mbridges6@deviantart.com",
    "image": "http://dummyimage.com/300x300.bmp/dddddd/000000&text=Feest-Brown",
    "related": null
},
{
    "id": 8,
    "name": "Gutmann, Buckridge and Kris",
    "description": "quis lectus suspendisse potenti in eleifend quam a odio in hac habitasse platea dictumst maecenas ut massa quis augue luctus tincidunt nulla mollis molestie lorem",
    "email": "tdumbrell7@ted.com",
    "image": "http://dummyimage.com/300x300.bmp/ff4444/ffffff&text=Gutmann",
    "related": [
        14,
        20,
        23,
        27
    ]
},
{
    "id": 9,
    "name": "McLaughlin-Bogan",
    "description": "morbi quis tortor id nulla ultrices aliquet maecenas leo odio condimentum id luctus nec molestie sed justo pellentesque viverra pede ac diam cras pellentesque",
    "email": "lgadsdon8@joomla.org",
    "image": "http://dummyimage.com/300x300.jpg/dddddd/000000&text=McLaughlin-Bogan",
    "related": [
        6,
        9,
        12,
        30
    ]
},
{
    "id": 10,
    "name": "Kilback-Padberg",
    "description": "leo odio condimentum id luctus nec molestie sed justo pellentesque viverra pede ac diam cras pellentesque volutpat dui maecenas tristique est et tempus semper est quam pharetra magna ac",
    "email": "eodegaard9@dailymail.co.uk",
    "image": "http://dummyimage.com/300x300.png/ff4444/ffffff&text=Kilback-Padberg",
    "related": null
},
{
    "id": 11,
    "name": "Skiles LLC",
    "description": "rutrum at lorem integer tincidunt ante vel ipsum praesent blandit lacinia erat vestibulum sed magna at nunc commodo placerat praesent blandit nam nulla integer pede justo lacinia eget tincidunt eget",
    "email": "marchibolda@apple.com",
    "image": "http://dummyimage.com/300x300.bmp/dddddd/000000&text=Skiles%20LLC",
    "related": [
        21,
        27,
        28,
        5
    ]
},
{
    "id": 12,
    "name": "McGlynn Group",
    "description": "nulla integer pede justo lacinia eget tincidunt eget tempus vel pede morbi porttitor lorem id ligula suspendisse ornare consequat lectus in est risus",
    "email": "eraggettb@nba.com",
    "image": "http://dummyimage.com/300x300.bmp/cc0000/ffffff&text=McGlynn%20Group",
    "related": [
        10,
        18,
        26
    ]
},
{
    "id": 13,
    "name": "Cassin-Kling",
    "description": "ac enim in tempor turpis nec euismod scelerisque quam turpis adipiscing lorem vitae mattis nibh ligula nec sem duis aliquam convallis",
    "email": "cdunbletonc@indiatimes.com",
    "image": "http://dummyimage.com/300x300.jpg/cc0000/ffffff&text=Cassin-Kling",
    "related": [
        17,
        29,
        1,
        3,
        8
    ]
},
{
    "id": 14,
    "name": "Greenfelder, Conroy and Schinner",
    "description": "imperdiet nullam orci pede venenatis non sodales sed tincidunt eu felis fusce posuere felis sed lacus morbi sem mauris laoreet ut rhoncus aliquet pulvinar sed nisl nunc rhoncus",
    "email": "njamiesond@ehow.com",
    "image": "http://dummyimage.com/300x300.bmp/dddddd/000000&text=Greenfelder",
    "related": [
        18,
        21,
        27
    ]
},
{
    "id": 15,
    "name": "MacGyver, Huel and Lind",
    "description": "cubilia curae duis faucibus accumsan odio curabitur convallis duis consequat dui nec nisi volutpat eleifend donec ut dolor morbi vel lectus in",
    "email": "tclinche@soundcloud.com",
    "image": "http://dummyimage.com/300x300.bmp/ff4444/ffffff&text=MacGyver",
    "related": null
},
{
    "id": 16,
    "name": "Aufderhar-Little",
    "description": "nisl aenean lectus pellentesque eget nunc donec quis orci eget orci vehicula condimentum curabitur in libero ut massa volutpat convallis morbi odio odio elementum eu",
    "email": "epennellsf@symantec.com",
    "image": "http://dummyimage.com/300x300.png/dddddd/000000&text=Aufderhar-Little",
    "related": null
},
{
    "id": 17,
    "name": "Graham-Berge",
    "description": "non ligula pellentesque ultrices phasellus id sapien in sapien iaculis congue vivamus metus arcu adipiscing molestie hendrerit at vulputate vitae nisl aenean lectus pellentesque eget nunc donec quis orci",
    "email": "rvielg@weibo.com",
    "image": "http://dummyimage.com/300x300.bmp/ff4444/ffffff&text=Graham-Berge",
    "related": [
        12,
        16,
        29,
        30
    ]
},
{
    "id": 18,
    "name": "Gaylord, Klein and Donnelly",
    "description": "ac est lacinia nisi venenatis tristique fusce congue diam id ornare imperdiet sapien urna pretium nisl ut volutpat sapien arcu sed augue",
    "email": "estoyellh@bing.com",
    "image": "http://dummyimage.com/300x300.jpg/cc0000/ffffff&text=Klein%20and%20Donnelly",
    "related": [
        6,
        7,
        9,
        18,
        21
    ]
},
{
    "id": 19,
    "name": "Gusikowski Group",
    "description": "lacus morbi quis tortor id nulla ultrices aliquet maecenas leo odio condimentum id luctus nec molestie sed justo pellentesque viverra pede ac diam cras pellentesque volutpat dui maecenas tristique",
    "email": "kpalatinoi@toplist.cz",
    "image": "http://dummyimage.com/300x300.jpg/ff4444/ffffff&text=Gusikowski",
    "related": [
        16,
        29,
        3
    ]
},
{
    "id": 20,
    "name": "Jaskolski-McKenzie",
    "description": "a nibh in quis justo maecenas rhoncus aliquam lacus morbi quis tortor id nulla ultrices aliquet maecenas leo odio condimentum id luctus nec",
    "email": "sloganj@japanpost.jp",
    "image": "http://dummyimage.com/300x300.bmp/cc0000/ffffff&text=Jaskolski-McKenzie",
    "related": [
        12,
        14,
        18
    ]
},
{
    "id": 21,
    "name": "Kautzer, Dooley and Kuhic",
    "description": "hac habitasse platea dictumst maecenas ut massa quis augue luctus tincidunt nulla mollis molestie lorem quisque ut erat curabitur gravida nisi at nibh in",
    "email": "snoodsk@over-blog.com",
    "image": "http://dummyimage.com/300x300.jpg/dddddd/000000&text=Kautzer",
    "related": [
        3,
        5,
        17,
        29,
        30
    ]
},
{
    "id": 22,
    "name": "Kohler, Tremblay and Bernier",
    "description": "in lacus curabitur at ipsum ac tellus semper interdum mauris ullamcorper purus sit amet nulla quisque arcu libero rutrum ac lobortis vel dapibus at",
    "email": "zsorriel@arizona.edu",
    "image": "http://dummyimage.com/300x300.png/ff4444/ffffff&text=Kohler",
    "related": null
},
{
    "id": 23,
    "name": "Cummerata, Trantow and Huels",
    "description": "potenti nullam porttitor lacus at turpis donec posuere metus vitae ipsum aliquam non mauris morbi non lectus aliquam sit amet diam in magna bibendum imperdiet nullam orci pede venenatis non",
    "email": "rshillingtonm@people.com.cn",
    "image": "http://dummyimage.com/300x300.jpg/dddddd/000000&text=Cummerata",
    "related": [
        5,
        4,
        13,
        23,
        27
    ]
},
{
    "id": 24,
    "name": "O'Reilly LLC",
    "description": "eu orci mauris lacinia sapien quis libero nullam sit amet turpis elementum ligula vehicula consequat morbi a ipsum integer a",
    "email": "tstaten@symantec.com",
    "image": "http://dummyimage.com/300x300.png/5fa2dd/ffffff&text=O'Reilly%20LLC",
    "related": [
        4,
        5,
        6,
        10
    ]
},
{
    "id": 25,
    "name": "Grant-Spencer",
    "description": "augue vel accumsan tellus nisi eu orci mauris lacinia sapien quis libero nullam sit amet turpis elementum ligula vehicula consequat morbi a ipsum integer a",
    "email": "bgrzegorczyko@vk.com",
    "image": "http://dummyimage.com/300x300.png/ff4444/ffffff&text=Grant-Spencer",
    "related": null
},
{
    "id": 26,
    "name": "Jacobi-Jaskolski",
    "description": "orci nullam molestie nibh in lectus pellentesque at nulla suspendisse potenti cras in purus eu magna vulputate luctus cum sociis natoque penatibus et magnis dis parturient montes",
    "email": "afranktonp@uol.com.br",
    "image": "http://dummyimage.com/300x300.bmp/5fa2dd/ffffff&text=Jacobi-Jaskolski",
    "related": null
},
{
    "id": 27,
    "name": "Heathcote LLC",
    "description": "curabitur in libero ut massa volutpat convallis morbi odio odio elementum eu interdum eu tincidunt in leo maecenas pulvinar lobortis est phasellus",
    "email": "sgeggusq@weather.com",
    "image": "http://dummyimage.com/300x300.bmp/5fa2dd/ffffff&text=Heathcote%20LLC",
    "related": [
        15,
        20,
        1,
        3
    ]
},
{
    "id": 28,
    "name": "Towne, Schaefer and Reichert",
    "description": "congue elementum in hac habitasse platea dictumst morbi vestibulum velit id pretium iaculis diam erat fermentum justo nec condimentum neque sapien placerat ante nulla justo aliquam quis",
    "email": "msnoadr@army.mil",
    "image": "http://dummyimage.com/300x300.jpg/ff4444/ffffff&text=Towne",
    "related": null
},
{
    "id": 29,
    "name": "Graham, Green and Roberts",
    "description": "vestibulum sagittis sapien cum sociis natoque penatibus et magnis dis parturient montes nascetur ridiculus mus etiam vel augue vestibulum rutrum rutrum neque aenean auctor gravida",
    "email": "aflecknoes@redcross.org",
    "image": "http://dummyimage.com/300x300.jpg/dddddd/000000&text=Graham",
    "related": null
},
{
    "id": 30,
    "name": "Commings Group",
    "description": "luctus tincidunt nulla mollis molestie lorem quisque ut erat curabitur gravida nisi at nibh in hac habitasse platea dictumst aliquam augue",
    "email": "gmationt@slideshare.net",
    "image": "http://dummyimage.com/300x300.jpg/cc0000/ffffff&text=Commings%20Group",
    "related": null
}

]

As you can see for every item has a related, but related are just ID's how can i find each related item object and show them heres what i tried

this is the item details screen

   import React from "react";
import { View, Image, StyleSheet, Text, FlatList } from "react-native";

import RelatedList from "../components/RelatedList";

import api from "../apis/stores.json";

function StoreDetails(props) {
  const { navigation } = props;
  const id = navigation.getParam("id");
  const name = navigation.getParam("name");
  const email = navigation.getParam("email");
  const description = navigation.getParam("description");
  const image = navigation.getParam("image");
  const data = [api[0]];

  data.filter(value => value.id == id)
  const related = [
    data
  ];
  return (
    <View>
      <Image style={styles.image} source={{ uri: image }} />
      <View style={styles.detailsContainer}>
        <Text style={styles.name}>{name}</Text>
        <Text>{email}</Text>
        <Text>{description}</Text>
        <FlatList
          data={related}
          keyExtractor={(related) => related.id.toString()}
          renderItem={({ item }) => (
            <RelatedList
              image={item.image}
              name={item.name}
              status={item.status}
            />
          )}
        />
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  image: {
    width: "100%",
    height: 300,
  },
  detailsContainer: {
    padding: 20,
  },
  name: {
    fontWeight: "bold",
    fontSize: 25,
  },
});

export default StoreDetails;

Body:
use this function in your code
I think, it's one of the fastest way to find related data

const findRelatedData = (data, id) => {
      const mainItem = data.find(item => item.id === id)
      if (!mainItem || !Array.isArray(mainItem.related)) {
        return []
      }
      const dataLength = data.length
      const relatedLength = mainItem.related.length
      let jInitVal = 0;
      const result = []
      for (let i = 0; i < dataLength && jInitVal < relatedLength; i++) {
        for (let j = jInitVal; j < relatedLength; j++) {
          if (data[i].id === mainItem.related[j]) {
            result.push(data[i])
            // if the related list isn't sort this condition would be true
            // it likes a buble sort
            if (j > jInitVal ) {
             let tmp = mainItem.related[j]
              mainItem.related[j] = mainItem.related[jInitVal]
              mainItem.related[jInitVal] = tmp
            }
            jInitVal++
            break;
          }
        }
      }
      return result;
    }

I call this function in your code

import React from "react";
import { View, Image, StyleSheet, Text, FlatList } from "react-native";

import RelatedList from "../components/RelatedList";

import api from "../apis/stores.json";

// here you can past 'findRelatedData' function

function StoreDetails(props) {
  const { navigation } = props;
  const id = navigation.getParam("id");
  const name = navigation.getParam("name");
  const email = navigation.getParam("email");
  const description = navigation.getParam("description");
  const image = navigation.getParam("image");
  const data = [api[0]];

  /*data.filter(value => value.id == id)
  const related = [
    data
  ];*/
  const related = findRelatedData(data , id)

  return (
    <View>
      <Image style={styles.image} source={{ uri: image }} />
      <View style={styles.detailsContainer}>
        <Text style={styles.name}>{name}</Text>
        <Text>{email}</Text>
        <Text>{description}</Text>
        <FlatList
          data={related}
          keyExtractor={(related) => related.id.toString()}
          renderItem={({ item }) => (
            <RelatedList
              image={item.image}
              name={item.name}
              status={item.status}
            />
          )}
        />
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  image: {
    width: "100%",
    height: 300,
  },
  detailsContainer: {
    padding: 20,
  },
  name: {
    fontWeight: "bold",
    fontSize: 25,
  },
});

export default StoreDetails;


问:
Cant Load Content When Not In Main Game Class
```<code>public class Dirt : Tile
{
    Vector2 position;
    Texture2D texture;

    public Dirt(Game game, Vector2 Position)
        : base(game)
    {
        type = "dirt";
        textureName = "Textures/Dirt";

        position = Position;
    }

    public override void Initialize()
    {

        base.Initialize();
    }

    protected override void LoadContent()
    {
        texture = Salvage.contentManager.Load<Texture2D>("Textures/Dirt"); // This doesnt work

        base.LoadContent();
    }

    public override void Update(GameTime gameTime)
    {
        if (InputHandler.KeyDown(Keys.W))
        {
            position.Y -= 1;
        }
        else if (InputHandler.KeyDown(Keys.S))
        {
            position.Y += 1;
        }

        if (InputHandler.KeyDown(Keys.D))
        {
            position.X += 1;
        }
        else if (InputHandler.KeyDown(Keys.A))
        {
            position.X -= 1;
        }

        Camera.DesiredPosition = position;

        base.Update(gameTime);
    }

    public override void Draw(GameTime gameTime)
    {
        Salvage.spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend, null, null, null, null, Camera.Transformation);
        Salvage.spriteBatch.Draw(texture, position, Color.White);
        Salvage.spriteBatch.End();

        base.Draw(gameTime);
    }
}
</code>```

The loading seems to work fine if i load it in the Salvage class(Main game class)

Edit:

The error im getting is:

Salvage.spriteBatch.Draw(texture, position, Color.White);
This method does not accept null for this parameter.
Parameter name: texture

Here is the code for Salvage class:

```<code>public class Salvage : Microsoft.Xna.Framework.Game
{

    public static GraphicsDeviceManager graphics;
    public static SpriteBatch spriteBatch;
    public static ContentManager contentManager;
    public static SpriteFont spriteFont;
    public GameStateManager stateManager;
    public Rectangle ScreenRectangle = new Rectangle(0, 0, 1024, 768);

    public Salvage()
    {
        graphics = new GraphicsDeviceManager(this);
        graphics.PreferredBackBufferHeight = ScreenRectangle.Height;
        graphics.PreferredBackBufferWidth = ScreenRectangle.Width;

        Content.RootDirectory = "Content";
        contentManager = Content;

    }

    protected override void Initialize()
    {

        base.Initialize();
    }

    protected override void LoadContent()
    {
        spriteBatch = new SpriteBatch(GraphicsDevice);
        spriteFont = Content.Load<SpriteFont>("Fonts/DefaultSpriteFont"); // This works fine

        stateManager = new GameStateManager(this);
        GameplayState gameplayState = new GameplayState(this, stateManager);

        Components.Add(new InputHandler(this));
        Components.Add(new Camera(this, ScreenRectangle));
        Components.Add(stateManager);

        stateManager.ChangeState(gameplayState);

    }

    protected override void UnloadContent()
    {

    }

    protected override void Update(GameTime gameTime)
    {
        if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || InputHandler.KeyReleased(Keys.Escape))
            this.Exit();

        base.Update(gameTime);
    }

    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.CornflowerBlue);

        base.Draw(gameTime);
    }
}
</code>```

And the code for Tile

```<code>public abstract class Tile : Microsoft.Xna.Framework.DrawableGameComponent
{
    public string textureName;
    public string type;

    public Tile(Game game)
        : base(game)
    {

    }

    public override void Initialize()
    {

        base.Initialize();
    }

    protected override void LoadContent()
    {

        base.LoadContent();
    }

    public override void Update(GameTime gameTime)
    {

        base.Update(gameTime);
    }

    public override void Draw(GameTime gameTime)
    {

        base.Draw(gameTime);
    }
}
</code>```

Edit:

Here is the GamePlayState class

```<code>public class GameplayState : GameState
{

    public GameplayState(Game game, GameStateManager manager)
        : base(game, manager)
    {
        childGameComponents.Add(new Dirt(game, new Vector2(0, 0)));
    }

    public override void Initialize()
    {

        base.Initialize();
    }

    protected override void LoadContent()
    {
        base.LoadContent();
    }

    public override void Update(GameTime gameTime)
    {

        base.Update(gameTime);
    }

    public override void Draw(GameTime gameTime)
    {

        base.Draw(gameTime);
    }
}
</code>```

答:
I have seen your problem.  You declare the contentManager variable, but you never assign it until the LoadContent method.  If you are loading Dirt before this, you won't have a valid ContentManager variable causing it to fail.

In your constructor of your Salvage class, add the following line:

contentManager = Content;

This should resolve your issue.

Body:
public class Dirt : Tile
{
    Vector2 position;
    Texture2D texture;

    public Dirt(Game game, Vector2 Position)
        : base(game)
    {
        type = "dirt";
        textureName = "Textures/Dirt";

        position = Position;
    }

    public override void Initialize()
    {

        base.Initialize();
    }

    protected override void LoadContent()
    {
        texture = Salvage.contentManager.Load<Texture2D>("Textures/Dirt"); // This doesnt work

        base.LoadContent();
    }

    public override void Update(GameTime gameTime)
    {
        if (InputHandler.KeyDown(Keys.W))
        {
            position.Y -= 1;
        }
        else if (InputHandler.KeyDown(Keys.S))
        {
            position.Y += 1;
        }

        if (InputHandler.KeyDown(Keys.D))
        {
            position.X += 1;
        }
        else if (InputHandler.KeyDown(Keys.A))
        {
            position.X -= 1;
        }

        Camera.DesiredPosition = position;

        base.Update(gameTime);
    }

    public override void Draw(GameTime gameTime)
    {
        Salvage.spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend, null, null, null, null, Camera.Transformation);
        Salvage.spriteBatch.Draw(texture, position, Color.White);
        Salvage.spriteBatch.End();

        base.Draw(gameTime);
    }
}

The loading seems to work fine if i load it in the Salvage class(Main game class)

Edit:

The error im getting is:

Salvage.spriteBatch.Draw(texture, position, Color.White);
This method does not accept null for this parameter.
Parameter name: texture

Here is the code for Salvage class:

public class Salvage : Microsoft.Xna.Framework.Game
{

    public static GraphicsDeviceManager graphics;
    public static SpriteBatch spriteBatch;
    public static ContentManager contentManager;
    public static SpriteFont spriteFont;
    public GameStateManager stateManager;
    public Rectangle ScreenRectangle = new Rectangle(0, 0, 1024, 768);

    public Salvage()
    {
        graphics = new GraphicsDeviceManager(this);
        graphics.PreferredBackBufferHeight = ScreenRectangle.Height;
        graphics.PreferredBackBufferWidth = ScreenRectangle.Width;

        Content.RootDirectory = "Content";
        contentManager = Content;

    }

    protected override void Initialize()
    {

        base.Initialize();
    }

    protected override void LoadContent()
    {
        spriteBatch = new SpriteBatch(GraphicsDevice);
        spriteFont = Content.Load<SpriteFont>("Fonts/DefaultSpriteFont"); // This works fine

        stateManager = new GameStateManager(this);
        GameplayState gameplayState = new GameplayState(this, stateManager);

        Components.Add(new InputHandler(this));
        Components.Add(new Camera(this, ScreenRectangle));
        Components.Add(stateManager);

        stateManager.ChangeState(gameplayState);

    }

    protected override void UnloadContent()
    {

    }

    protected override void Update(GameTime gameTime)
    {
        if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || InputHandler.KeyReleased(Keys.Escape))
            this.Exit();

        base.Update(gameTime);
    }

    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.CornflowerBlue);

        base.Draw(gameTime);
    }
}

And the code for Tile

public abstract class Tile : Microsoft.Xna.Framework.DrawableGameComponent
{
    public string textureName;
    public string type;

    public Tile(Game game)
        : base(game)
    {

    }

    public override void Initialize()
    {

        base.Initialize();
    }

    protected override void LoadContent()
    {

        base.LoadContent();
    }

    public override void Update(GameTime gameTime)
    {

        base.Update(gameTime);
    }

    public override void Draw(GameTime gameTime)
    {

        base.Draw(gameTime);
    }
}

Edit:

Here is the GamePlayState class

public class GameplayState : GameState
{

    public GameplayState(Game game, GameStateManager manager)
        : base(game, manager)
    {
        childGameComponents.Add(new Dirt(game, new Vector2(0, 0)));
    }

    public override void Initialize()
    {

        base.Initialize();
    }

    protected override void LoadContent()
    {
        base.LoadContent();
    }

    public override void Update(GameTime gameTime)
    {

        base.Update(gameTime);
    }

    public override void Draw(GameTime gameTime)
    {

        base.Draw(gameTime);
    }
}