edsmAround/edsmAround.py

194 lines
7.8 KiB
Python

import requests as r
import re
import json
from datetime import datetime as dt
from math import floor
import sys
#IMPORTANT BITS
###This is the name of the sector you want to search into (Do not use caps!)
sectorName = "Phoi Auwsy"
### "weights" to query, beware of big results when searching for lighter systems in more dense area
weightsToQuery = ["f","g","h"]
### postFix List, modify as needed
postFixList =["AA-A","BA-A","CL-Y","DL-Y","EG-Y","FG-Y","YE-A","ZE-A"]
#postFixList =["WP-X"]
###Call to EDSM API, don't run this script too much in a short timeframe.
def apiCall(systemName):
systems = r.get("https://www.edsm.net/api-v1/systems", params={'systemName' : systemName})
return systems
# takes a sector name, a postfix and a weight, returns list of known systems in EDSM matching that
def fetchEdsmSystems(sectorName, postFix, weight):
hasMultipleHyphens = False
systemList = []
pattern = re.compile(f".*{postFix} {weight}.*")
for system in json.loads(apiCall(sectorName +" "+postFix).content):
if pattern.match(system['name']):
systemList.append(system['name'])
hasMultipleHyphens = system['name'].count("-") > 1 # if at least one of those has multiple hyphens, we consider all of them do
return systemList, hasMultipleHyphens
#given a list of systems (assumed to be all the same weight and postfix) returns the maximum value of the integer value in the system name for that list
def maxSystemValue(systemList):
currentMax = 0
patternWithoutHyphen = re.compile(f".*[A-Z][A-Z]-[A-Z] [A-Za-z]([0-9]+)")
patternWithHyphen = re.compile(f".*[A-Z][A-Z]-[A-Z] [A-Za-z][0-9]*-([0-9]+)")
for system in systemList:
val = 0
if system.count("-") > 1:
match = patternWithHyphen.match(system)
else:
match = patternWithoutHyphen.match(system)
val = int(match.group(1))
if val > currentMax:
currentMax = val
return currentMax
###interactive part
if (len(sys.argv) > 1):
for arg in sys.argv:
if arg == "-i":
print("Starting interactive mode.")
print("Please input a sector name with only the first letter capitalized (ex : Byoomiae) ")
sectorNamePattern = re.compile("^[A-Z][a-z]+ *[A-Z]*[a-z]*$")
possibleSectorName = input()
while not sectorNamePattern.match(possibleSectorName):
print("The sector name you have entered is incorrect. Please try again")
possibleSectorName = input()
sectorName = possibleSectorName
print(f"Entered Sector name is {sectorName}")
print("Please enter the postFix you want to use. PostFix are the letters after the sector name (AA-A, RD-A). Write one per line, in all caps, with the hyphen. Send an empty line to finish")
possiblePostFix = input()
postFixList = []
while possiblePostFix != "":
postFixPattern = re.compile("^[A-Z][A-Z]-[A-Z]$")
if postFixPattern.match(possiblePostFix):
if possiblePostFix not in postFixList:
postFixList.append(possiblePostFix)
print(f"added {possiblePostFix} to the list of patterns. Current list is {postFixList}")
else:
print(f"PostFix already in list! Current list is {postFixList}")
possiblePostFix = input()
else:
print("This postFix doesn't look right. Try again")
possiblePostFix = input()
if postFixList == []:
print("postFix list empty. Exiting!")
exit()
print("Please enter the weights you want to use. One letter per line, in lowercase, send an empty line to finish.")
possibleWeights = input()
weightsToQuery = []
while possibleWeights != "":
weightPattern = re.compile("^[a-h]$")
if weightPattern.match(possibleWeights):
if possibleWeights not in weightsToQuery:
weightsToQuery.append(possibleWeights)
print(f"added {possibleWeights} to the list of weights. Current list is {weightsToQuery}")
else:
print(f"Weight already in list! Current list is {weightsToQuery}")
possibleWeights = input()
else:
print("This weight doesn't look right. Try again")
possibleWeights = input()
if weightsToQuery == []:
print("weight list empty. Exiting!")
exit()
print("Starting search!")
#dict of dict of systems keyed by postfix, keyed by weight ( dict["AA-A"]["g"] gives back all the AA-A GXXX systems)
sysWeightDict = {}
#dict of dict of systems maximum value by postfix, keyed by weight ( dict["AA-A"]["g"] gives back the maximum recorded value for X where X is the integer in a system name : AA-A GX)
sysMaxDict = {}
#This is used to register how much systems are in EDSM to compute an "explored" percentage further
sysDiscovered = {}
postFixWithMultipleHyphens = {} # deals with system names like "Sector AA-A e5-8"
#dict of dict of all the systems in a sector keyed by postfix, keyed by weight, used later for substracting EDSM values from ALL systems
sysCandidates = {}
base = ""
reference = ""
#for each weight class, we initialize our dicts with our postfix list
for weight in weightsToQuery:
sysWeightDict[weight] = {}
sysMaxDict[weight] = {}
sysCandidates[weight] = {}
sysDiscovered[weight] = {}
postFixWithMultipleHyphens[weight] = {}
#then we populate our dicts with the provided postfix
for postfix in postFixList:
sysWeightDict[weight][postfix], postFixWithMultipleHyphens[weight][postfix] = fetchEdsmSystems(sectorName, postfix, weight) # this is reversed from IG "AA-A G"
sysMaxDict[weight][postfix] = maxSystemValue(sysWeightDict[weight][postfix])
sysDiscovered[weight][postfix] = 0
#now we generate the inverse of the known system list
# for all systems indexes to the max known index
sysCandidates[weight][postfix] = []
if len(sysWeightDict[weight][postfix]) > 0:
if postFixWithMultipleHyphens[weight][postfix]: #if we have multiple hyphens we take the first system to see what's in front of the hyphen
reference = sysWeightDict[weight][postfix][0]
base = reference[:reference.rfind("-")+1]
print(f"Warning, sector {sectorName} {postfix} with size {weight} has multiple hyphens, predictions may be wrong!")
else:
base =f"{sectorName} {postfix} {weight}"
for i in range(sysMaxDict[weight][postfix]):
candidate = f"{base}{i}"
if candidate not in sysWeightDict[weight][postfix]:
sysCandidates[weight][postfix].append(candidate)
else:
sysDiscovered[weight][postfix] += 1
#this computes the percentage of systems that are already discovered on EDSM
sysDiscovered[weight][postfix] = round(sysDiscovered[weight][postfix] / sysMaxDict[weight][postfix] * 100,2)
print("These are the systems known to EDSM")
print(sysMaxDict)
print("These are the exploration stats in percent of systems known to EDSM versus all the possible systems")
print(sysDiscovered)
#Finally writes the results to a JSON file.
with open(f"{floor(dt.now().timestamp())}-{sectorName}-RESULTS-v2.json",'w') as f:
f.write(json.dumps(sysCandidates, indent=4))