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 = "Byoomiae" ### "weights" to query, beware of big results when searching for lighter systems in more dense area weightsToQuery = ["a","b","c","d","e"] ### 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]+$") 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))