EDCD / EDDI

Companion application for Elite Dangerous
Other
453 stars 82 forks source link

'System materials report' (multiple problems) #2454

Closed Darkcyde13 closed 1 year ago

Darkcyde13 commented 1 year ago

What's Wrong (please be as specific as possible)

Expected

The 'System materials report' to run correctly.

Observed

The section for signal sources does not work. (Explained below)

Steps to reproduce

  1. Run the script.
  2. Observe the signal sources section does not work.

Configuration

My Investigation

Investigation Notes

I was going over all my scripts after the beta 3 bug, and came across 'System materials report'. I hadn't looked at this one before, so I checked it out.

Looking over it, I have found some things that don't appear to be correct, mainly in the signal sources section...

(In no particular order)

I apologise if I've missed anything as to why some of these are the way they are, in case there are specific reasons I've not noticed.

I'm sorry this is so long, and also if some of them should have their own issue raised, but because they all relate to the one script I thought I'd report it all in one go.

EDDI Logs

N/A

Player journals

N/A

Darkcyde13 commented 1 year ago

For the "and" point, I've changed the 'descriptions' to be two separate arrays, one for signals and one for bodies. Then at the end, just before the List() report, I've updated that IF check like this:

{if len(signalMaterials) > 0 && len(bodyMaterials) > 0: {set and to [" and"]}}
{set descriptions to cat(signalDescriptions, and, bodyDescriptions)}

This correctly adds "and" between the two sections if both are populated, but leaves it out if not. I guess you could also use the '...Descriptions' variables instead of '...Materials'. It should do the same job. :)

Tkael commented 1 year ago

Otherwise, I generally agree and will update the script accordingly.

Darkcyde13 commented 1 year ago

I did realise that my suggested code fix is slightly wrong in one situation. Using List() to report descriptions after I put the two arrays together, if there is only one body to report in addition to any signal sources, then it says 'and' twice (so, ", and, and"), once for the above code and once for the List(). If there is more than one body, then the List() 'and' goes between the bodies, and the speech is correct.

I fixed this by making the second check bodyMaterials > 1. So only the List() 'and' is used for a single body, and the additional 'and' is used correctly when there is more than one body.

That is, of course, if you decide to go with my suggestion. πŸ™‚

Darkcyde13 commented 1 year ago

Hi @Tkael,

I've just tried out beta 5 and found the faction.ActiveStates bug still appears to be present.

Also, as per my comment above, I screwed up a little with my intended fix for "and" between the two arrays. Sorry about that. πŸ™

The only other thing is the 'Proprietary Composites' also being available in Encoded Emissions. I have some ideas around this, but I'm not sure what will or won't work. I'm going to have to try some things out.

And thank you for the quick update, it is greatly appreciated! πŸ™‚

Darkcyde13 commented 1 year ago

Hi again @Tkael,

I'm not sure if I should open a new ticket as this one is closed? Well, I'll post here and if needed I can open a new one (or you can copy this to a new one, whichever is best).

So, after a some trial and error trying to get this to do what I wanted, I have finally succeeded. My new code allows any signal source type to easily be added, along with any associated materials assigned to the type. It's similar to your original script in that respect. It will now report the Proprietary Composites as being available in both signal source types, and separately list the others under HGE's, like this:

Proprietary Composites may be found in Encoded Emissions and High Grade Emissions signal sources, Core Dynamics Composites may be found in High Grade Emissions signal sources, and Carbon, Phosphorus, and Sulphur are found on body 3 d a in this system.

I also tested by adding a third source type, "Testing", between EncE and HGE, and added a copy of the "Proto ..." materials, plus the proprietary composites. This produced:

Proprietary Composites may be found in Encoded Emissions, High Grade Emissions, and Testing signal sources, Core Dynamics Composites may be found in High Grade Emissions signal sources, Proto Heat Radiators, Proto Light Alloys, and Proto Radiolic Alloys may be found in Testing signal sources, and Carbon, Phosphorus, and Sulphur are found on body 3 d a in this system.

So this now collates all materials by source type, and alphabetizes everything too.

The code is:

{_ Get information about signal sources _}
{set sigMaterials to []}
{set signalsType to ["Encoded Emissions", "High Grade Emissions"]}

{for sigType in signalsType:
    {if sigType = "Encoded Emissions":
        {if reportSystem.Faction.Allegiance.invariantName = "Federation":
            {set sigMaterials to cat(sigMaterials, ["Proprietary Composites"])}
        }
    |elif sigType = "High Grade Emissions":
        {if reportSystem.Faction.Allegiance.invariantName = "Federation":
            {set sigMaterials to cat(sigMaterials, ["Core Dynamics Composites"])}
            {set sigMaterials to cat(sigMaterials, ["Proprietary Composites"])}
        |elif reportSystem.Faction.Allegiance.invariantName = "Empire":
            {set sigMaterials to cat(sigMaterials, ["Imperial Shielding"])}
        }
        {for faction in reportSystem.factions:
            {for factionPresence in faction.presences:
                {if reportSystem.name = factionPresence.systemName && factionPresence.influence >= 25:
                    {for state in faction.ActiveStates:
                        {if state.invariantName = "Civil Unrest":
                            {set sigMaterials to cat(sigMaterials, ["Improvised Components"])}
                        |elif state.invariantName = "Civil War" || state.invariantName = "War":
                            {set sigMaterials to cat(sigMaterials, ["Military Grade Alloys", 
                                                                    "Military Supercapacitors"])}
                        |elif state.invariantName = "Outbreak":
                            {set sigMaterials to cat(sigMaterials, ["Pharmaceutical Isolators"])}
                        |elif state.invariantName = "Boom":
                            {set sigMaterials to cat(sigMaterials, ["Proto Heat Radiators",
                                                                    "Proto Light Alloys",
                                                                    "Proto Radiolic Alloys"])}
                        }
                    }
                }
            }
        }
    }

    {_ Add material if it is 'needed' and the signal type is not already added for it _}
    {for invariantMaterial in sigMaterials:
        {set details to MaterialDetails(invariantMaterial)}
        {if isNeeded(inventory(details.localizedName)):
            {if !has(signalMaterials[details.localizedName], sigType):
                {addSignalMaterial(details.localizedName, sigType)}
            }
        }
    }
    {_ Reset sigMaterials array _}
    {set sigMaterials to []}
}

{_ Reorganise signals array -> 'material':'sources' _}
{set signalsOrganised to []}
{for mat, sig in signalMaterials:
    {set sig to List(sig)}
    {set matList to []}
    {if has(signalsOrganised, sig):
        {set matList to cat(signalsOrganised[sig], [mat])}
        {set signalsOrganised to union(signalsOrganised, [sig:matList])}
    |else:
        {set signalsOrganised to union(signalsOrganised, [sig:[mat]])}
    }
}
{set signalMaterials to signalsOrganised}

{_ Sort materials into alphabetical order _}
{for signalType, mats in signalMaterials:
    {set sortMats to []}
    {for item in sort(mats, cmp(a, b)):
        {set sortMats to cat(sortMats, [item])}
    }
    {set signalDescriptions to cat(signalDescriptions, [cat(List(sortMats),
                                   " may be found in ", signalType, " signal sources")])}
}

While doing this, I also noticed I could make the 'add materials' subroutines more efficient, like this:

{set addBodyMaterial(details, bodyName) to:
    {set bodyName to:
        {if details.bodyname != details.bodyshortname: body} {details.bodyshortname}
    }
    {if has(bodyMaterials, bodyName):
        {if find(bodyMaterials[bodyName], details.localizedName) = -1:
            {set newMats to cat(bodyMaterials[bodyName], [details.localizedName])}
            {set bodyMaterials to union(bodyMaterialsExcept, [bodyName: newMats])}
        }
    |else:
        {set bodyMaterials to union(bodyMaterials, [bodyName: [details.localizedName]])}
    }
}

{set addSignalMaterial(materialName, signalSourceType) to:
    {if has(signalMaterials, materialName):
        {if find(signalMaterials[materialName], signalSourceType) = -1:
            {set locations to cat(signalMaterials[materialName], [signalSourceType])}
            {set signalMaterials to union(signalMaterials, [materialName:locations])}
        }
    |else:
        {set signalMaterials to union(signalMaterials, [materialName: [signalSourceType]])}
    }
}

With these there is less processing of the data to achieve the same result. Well, you can use them if you wish. πŸ™‚

Edit: Sorry, I forgot to say, the updated signals code needs the updated addSignalMaterial() function too, as I've swapped over the material and source to make it all work.

Tkael commented 1 year ago

Thanks. I was able to find the issue. Is: {for state in faction.ActiveStates: Should be: {for state in factionPresence.ActiveStates:

FYI, I've also found that your updated 'add materials' subroutines seem to have some issues with reporting surface materials from multiple bodies?

Darkcyde13 commented 1 year ago

Ah, OK, the faction presence makes sense. πŸ™‚

As for the addBodyMaterials() I found my error. I forgot to remove the word 'Except' from {set bodyMaterials to union(bodyMaterialsExcept, [bodyName: newMats])} After removing that, making it {set bodyMaterials to union(bodyMaterials, [bodyName: newMats])} it seems to work as intended. Thank you for pointing it out. πŸ™‚

I tested with the Sol system, and setting both script options to 2, and both the original and my version give the same data. However, it doesn't seem to order the bodies alphabetically, which I'll need to look into. The Othime system, with bodies named as numbers, are ordered correctly. So it seems the sorting works for numbers but not words. πŸ€”

Darkcyde13 commented 1 year ago

Ah, I figured it out. I needed to change the 'token' lines in the declare check(a, b). Using this, it now sorts correctly:

    {declare check(a, b) as:
        {set a to token(a, " on ", 1)}
        {set b to token(b, " on ", 1)}
        {return cmp(a, b)}
    }