diff --git a/README.md b/README.md
index db79e05..3e0d0cc 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@
Visual intel chat analysis, planning and notification application for [EVE Online](http://www.eveonline.com). Gathers status through in-game intelligence channels on all known hostiles and presents all the data on a [dotlan](http://evemaps.dotlan.net/map/Cache#npc24) generated regional map. The map is annotated in real-time as players report intel in monitored chat channels.
-Vintel is written with Python 2.7, using PyQt4 for the application presentation layer, BeautifulSoup4 for SVG parsing, and Pyglet for audio playback.
+Vintel is written with Python 2.7, using PyQt5 for the application presentation layer, BeautifulSoup4 for SVG parsing, and Pyglet for audio playback.
### News
_The current release version of Vintel [can be found here](https://github.com/Xanthos-Eve/vintel/releases). Both Mac and Windows distributions are now available for download with this release._
@@ -74,6 +74,22 @@ pyglet is used to play the sound – If it is not available the sound option wil
https://pypi.python.org/pypi/requests
- Six for python 3 compatibility https://pypi.python.org/pypi/six
+## Note for windows users
+
+The anaconda python package will come with most of what you need [download](https://www.continuum.io/downloads#windows).
+vintel compilation has been tested with 64 bit anaconda2 v4.2.0 for python 2.7 on windows 10.
+
+You will need to run this command to install the pyglet package. If you installed anaconda for all
+users, you may need to run them in an *admin* anaconda prompt.
+
+```
+pip install pyglet
+```
+
+## Note for cygwin users
+
+pyglet doesn't currently work under cygwin. Skip installing it or pip uninstall if it causes problems.
+
## Building the Vintel Standalone Package
- The standalone is created using pyinstaller. All media files and the .spec-file with the configuration for pyinstaller are included in the source repo. Pyinstaller can be found here: https://github.com/pyinstaller/pyinstaller/wiki.
diff --git a/SETUP.md b/SETUP.md
new file mode 100644
index 0000000..d798e21
--- /dev/null
+++ b/SETUP.md
@@ -0,0 +1,127 @@
+# Vintel Setup
+
+This document describes the settings available in the Vintel application.
+
+## Settings Dialog
+
+The settings dialog has three panes: *Quick Setup*, *Jumpbridges*, and *Chat Channels*.
+
+The *Jumpbridges* pane allows you to specify a source for jumpbridges to be
+rendered on the maps. You may specify either a DOTLAN jumpbridge list id or an URL to
+a file containing your own jumpbridge list. More details on the format of the file
+can be seen in the application pane or in *Quick Setup* below.
+
+The *Chat Channels* pane allows you to specify EVE chat channels to monitor for
+intelligence reports. You must keep this chat channel open in a tab in game
+and have *Log Chat to File* selected in EVE Settings > Chat. Vintel monitors and
+processes these log files on your local disk.
+
+## Quick Setup
+
+The first pane of the settings allows you to paste a quick configuration JSON
+blob that may be provided by your alliance.
+
+1. **dotlan_jb_id** The id of a jumpbridge list from DOTLAN. Include just the id,
+ i.e. from http://evemaps.dotlan.net/bridges/**XXXXxxxx** use the XXXXxxxx
+2. **jumpbridge_url** A url to a file containing your bridge list. Each line
+ in the file should contain two systems separated by a `<->`. i.e.
+ `HED-GP <-> 36N-HZ`
+3. **channels** A JSON list of the channels to be monitored.
+4. **kos_url** A URL to your alliances KOS server.
+5. **region_name** The default region to load on launch. Later, the application will
+ remember the last region viewed and load that when you restart.
+6. **quick_regions** The regions listed here are automatically added to the
+ application's *Region* menu. Any name starting with a dash will be interpreted
+ as a separator and will draw a horizontal line between entries. Each entry
+ should have a **label** field which is how it will appear in the menu. Each
+ may also have a **region** field which can be used to override the region name
+ used when looking up this system on DOTLAN if the label is not an exact match
+ (spaces will be automatically converted to underscores).
+
+ The **region** should match a DOTLAN url - i.e. http://evemaps.dotlan.net/map/**Catch**.
+ The **region** can also be one of the special or combined maps listed at the
+ bottom of the DOTLAN universe page. Vintel also recognizes the custom region
+ providencecatch.
+
+This is what the Vintel defaults would look like as a quick configuration entry:
+
+```
+{
+ "dotlan_jb_id": "",
+ "jumpbridge_url": "",
+ "channels": [
+ "TheCitadel",
+ "North Provi Intel",
+ "North Catch Intel",
+ "North Querious Intel"
+ ],
+ "kos_url": "http://kos.cva-eve.org/api/",
+ "region_name": "Catch",
+ "quick_regions": [
+ {"label": "Catch"},
+ {"label": "Providence"},
+ {"label": "Querious"},
+ {"label": "---"},
+ {"label": "Provi / Catch", "region": "providencecatch"},
+ {"label": "Provi / Catch (compact)", "region": "Providence-catch"}
+ ]
+}
+```
+
+## Other Menu Settings
+
+### File > Clear Cache
+
+If you notice any weirdness with maps or avatars, you may try flushing the Vintel
+cache. Avatars and maps will be redownloaded.
+
+### Chat > Show Chat
+
+Hide the chat history on the right side of the screen
+
+### Chat > Show Chat Avatars
+
+Do not show character portraits in the chat history. Unfortunately selecting this
+doesn't yet make the chat window more compact.
+
+### Sound > Activate Sound
+
+This should be checked to enable sound in Vintel.
+
+### Sound > Sound Setup ...
+
+Test the sound configuration.
+
+### Sound > Spoken Notifications
+
+Doesn't work on Windows 10, what does it do?
+
+### Region
+
+Select a region from the quick region shortcuts configured in *Quick Settings*
+
+### Region > Other Region
+
+Select from a list of all known EVE regions.
+
+### Region > Custom Region ...
+
+Displays a freeform text box to enter a standard or custom region by name.
+
+### K.O.S.
+
+Activate some of the Kill On Sight processing and warnings.
+
+### Window > Always On Top
+
+Keep this window above all other windows.
+
+### Window > Frameless Main Window
+
+Remove OS decorations from the window: titlebar, menubar, ... Once activated a *Restore Frame* button will
+be available in the upper left corner of the screen. Click that to restore the window decorations.
+
+### Window > Transparency
+
+Set the window opacity.
+
diff --git a/TODO.md b/TODO.md
new file mode 100644
index 0000000..a49ad8c
--- /dev/null
+++ b/TODO.md
@@ -0,0 +1,19 @@
+ROLLED THIS BACK FROM MainWindowUi, seems QWebEngineWidgets is not available in most PyQt5 builds
+
+```
+
+
+
+ QWebView
+ QWebEngineView
+ QWidget
+
+ PyQt5/QtWebEngineWidgets/QWebEngineView
+
+
+ PanningWebView
+ QWebView
+ QWebEngineView
+
+
+```
diff --git a/quick_config_cva.json b/quick_config_cva.json
new file mode 100644
index 0000000..e37c46f
--- /dev/null
+++ b/quick_config_cva.json
@@ -0,0 +1,20 @@
+{
+ "dotlan_jb_id": "",
+ "jumpbridge_url": "",
+ "channels": [
+ "TheCitadel",
+ "North Provi Intel",
+ "North Catch Intel",
+ "North Querious Intel"
+ ],
+ "kos_url": "http://kos.cva-eve.org/api/",
+ "region_name": "Catch",
+ "quick_regions": [
+ {"label": "Catch"},
+ {"label": "Providence"},
+ {"label": "Querious"},
+ {"label": "---"},
+ {"label": "Provi / Catch", "region": "providencecatch"},
+ {"label": "Provi / Catch (compact)", "region": "Providence-catch"}
+ ]
+}
diff --git a/src/vi/PanningWebView.py b/src/vi/PanningWebView.py
index 6fbd4b1..cddfb5c 100644
--- a/src/vi/PanningWebView.py
+++ b/src/vi/PanningWebView.py
@@ -137,7 +137,7 @@ def __init__(self, parent=None):
def acceptNavigationRequest(self, url, type, isMainFrame):
if MainWindow.oldStyleWebKit:
- return super(PanningWebView, self).acceptNavigationRequest(url, type, isMainFrame)
+ return super(VintelSvgPage, self).acceptNavigationRequest(url, type, isMainFrame)
else:
if type == QWebEnginePage.NavigationTypeLinkClicked:
self.view().mapLinkClicked.emit(url)
diff --git a/src/vi/cache/cache.py b/src/vi/cache/cache.py
index c11b892..658d740 100644
--- a/src/vi/cache/cache.py
+++ b/src/vi/cache/cache.py
@@ -21,6 +21,7 @@
import threading
import time
import six
+import sys
if six.PY2:
def to_blob(x):
return buffer(str(x))
@@ -30,7 +31,7 @@ def from_blob(x):
def to_blob(x):
return x
def from_blob(x):
- return x
+ return x[0][0]
from vi.cache.dbstructure import updateDatabase
@@ -73,7 +74,7 @@ def checkVersion(self):
updateDatabase(version, self.con)
def putIntoCache(self, key, value, maxAge=60 * 60 * 24 * 3):
- """ Putting something in the cache maxAge is maximum age in seconds
+ """ Putting something in the cache maxAge is maximum age in seconds, default is 3 days
"""
with Cache.SQLITE_WRITE_LOCK:
query = "DELETE FROM cache WHERE key = ?"
@@ -96,6 +97,32 @@ def getFromCache(self, key, outdated=False):
else:
return founds[0][1]
+ def getConfigValue(self, key):
+ """ Retrieve a config value from cache that never expires
+ """
+ return self.getFromCache(key, True)
+
+ def saveConfigValue(self, key, value):
+ """ Save a config value to cache that never expires
+ """
+ return self.putIntoCache(key, value, sys.maxsize)
+
+ def deleteFromCache(self, key):
+ """ Deleteing from cache
+ """
+ with Cache.SQLITE_WRITE_LOCK:
+ query = "DELETE FROM cache WHERE key = ?"
+ self.con.execute(query, (key,))
+ self.con.commit()
+
+ def flush(self):
+ """ Flush non config items from cache
+ """
+ with Cache.SQLITE_WRITE_LOCK:
+ query = "DELETE FROM cache WHERE maxAge < ?"
+ self.con.execute(query, (sys.maxsize,))
+ self.con.commit()
+
def putPlayerName(self, name, status):
""" Putting a playername into the cache
"""
@@ -136,8 +163,8 @@ def getAvatar(self, name):
if len(founds) == 0:
return None
else:
- # dats is buffer, we convert it back to str
- data = from_blob(founds[0][0])
+ # data is buffer, we convert it back to str
+ data = from_blob(founds)
return data
def removeAvatar(self, name):
diff --git a/src/vi/chatparser/chatparser.py b/src/vi/chatparser/chatparser.py
index 270573d..35c2e14 100644
--- a/src/vi/chatparser/chatparser.py
+++ b/src/vi/chatparser/chatparser.py
@@ -20,13 +20,15 @@
import datetime
import os
import time
+import logging
import six
from PyQt5.QtWidgets import QMessageBox
if six.PY2:
from io import open
from bs4 import BeautifulSoup
-from vi import states
+from vi import states, evegate
+
from .parser_functions import parseStatus
@@ -40,12 +42,16 @@ class ChatParser(object):
""" ChatParser will analyze every new line that was found inside the Chatlogs.
"""
- def __init__(self, path, rooms, systems):
+ def HEADER_SIZE(self): return 13
+ def REPLAY_SIZE(self): return 500 # retreive up to 500 lines from a logfile when starting up
+
+ def __init__(self, path, rooms, allSystems, messageExpirySecs):
""" path = the path with the logs
rooms = the rooms to parse"""
+ self.messageExpirySecs = messageExpirySecs
self.path = path # the path with the chatlog
self.rooms = rooms # the rooms to watch (excl. local)
- self.systems = systems # the known systems as dict name: system
+ self.allSystems = allSystems # the known systems as dict name: system
self.fileData = {} # informations about the files in the directory
self.knownMessages = [] # message we allready analyzed
self.locations = {} # informations about the location of a char
@@ -103,6 +109,9 @@ def _lineToMessage(self, line, roomname):
timestamp = datetime.datetime.strptime(timeStr, "%Y.%m.%d %H:%M:%S")
except ValueError:
return None
+ if (evegate.currentEveTime() - timestamp).total_seconds() > self.messageExpirySecs:
+ # logging.debug('ignoring message from ' + timeStr + " || " + str((evegate.currentEveTime() - timestamp).total_seconds()) )
+ return None
# finding the username of the poster
userEnds = line.find(">")
username = line[timeEnds + 1:userEnds].strip()
@@ -136,7 +145,7 @@ def _lineToMessage(self, line, roomname):
continue
while parseUrls(rtext):
continue
- while parseSystems(self.systems, rtext, systems):
+ while parseSystems(self.allSystems, rtext, systems):
continue
parsedStatus = parseStatus(rtext)
status = parsedStatus if parsedStatus is not None else states.ALARM
@@ -154,9 +163,6 @@ def _lineToMessage(self, line, roomname):
message.message = six.text_type(rtext)
message.status = status
self.knownMessages.append(message)
- if systems:
- for system in systems:
- system.messages.append(message)
return message
def _parseLocal(self, path, line):
@@ -205,7 +211,7 @@ def fileModified(self, path):
roomname = filename[:-20]
if path not in self.fileData:
# seems eve created a new file. New Files have 12 lines header
- self.fileData[path] = {"lines": 13}
+ self.fileData[path] = {"lines": self.HEADER_SIZE()}
oldLength = self.fileData[path]["lines"]
lines = self.addFile(path)
if path in self.ignoredPaths:
@@ -222,6 +228,22 @@ def fileModified(self, path):
messages.append(message)
return messages
+ def rewind(self):
+ """On region change or startup, rewind files to replay info from logfiles"""
+ for path in self.fileData:
+ newsize = self.fileData[path]["lines"] - self.REPLAY_SIZE()
+ if newsize < self.HEADER_SIZE():
+ newsize = self.HEADER_SIZE()
+ logging.info("Rewinding %d lines from %s" % (self.fileData[path]["lines"]-newsize, path))
+ self.fileData[path]["lines"] = newsize
+ return self.fileData
+
+ def expire(self):
+ for m in self.knownMessages:
+ if (evegate.currentEveTime() - m.timestamp).total_seconds() > self.messageExpirySecs:
+ self.knownMessages.pop(0)
+ else:
+ break
class Message(object):
def __init__(self, room, message, timestamp, user, systems, upperText, plainText="", status=states.ALARM):
@@ -235,6 +257,7 @@ def __init__(self, room, message, timestamp, user, systems, upperText, plainText
self.plainText = plainText # plain text of the message, as posted
# if you add the message to a widget, please add it to widgets
self.widgets = []
+ self.isOld = False
def __key(self):
return (self.room, self.plainText, self.timestamp, self.user)
diff --git a/src/vi/chatparser/parser_functions.py b/src/vi/chatparser/parser_functions.py
index 92fcb59..d9d38f9 100644
--- a/src/vi/chatparser/parser_functions.py
+++ b/src/vi/chatparser/parser_functions.py
@@ -36,13 +36,20 @@
"""
import six
+import logging
+import re
+import vi.evegate as evegate
from bs4 import BeautifulSoup
from bs4.element import NavigableString
from vi import states
-import vi.evegate as evegate
+from vi.systems import SYSTEMS
+
+# Do not ignore <>/" which keep html from word matching on replacement
+# Do not ignore ? which triggers status change to request
+CHARS_TO_IGNORE_REGEX = '[*,!.()]'
-CHARS_TO_IGNORE = ("*", "?", ",", "!", ".")
+REPLACE_WORD_REGEX = r'(^|(?<=[^0-9a-zA-Z])){0}((?=[^0-9a-zA-Z_])|$)'
def textReplace(element, newText):
@@ -58,39 +65,41 @@ def textReplace(element, newText):
def parseStatus(rtext):
texts = [t for t in rtext.contents if isinstance(t, NavigableString)]
for text in texts:
+ upperText = re.sub(CHARS_TO_IGNORE_REGEX, ' ', text.strip().upper()) # KEEP QUESTION MARK?
upperText = text.strip().upper()
- originalText = upperText
- for char in CHARS_TO_IGNORE:
- upperText = upperText.replace(char, "")
upperWords = upperText.split()
- if (("CLEAR" in upperWords or "CLR" in upperWords) and not originalText.endswith("?")):
+ if ("?" in upperText):
+ return states.REQUEST
+ elif ("CLEAR" in upperWords or "CLR" in upperWords):
return states.CLEAR
elif ("STAT" in upperWords or "STATUS" in upperWords):
return states.REQUEST
- elif ("?" in originalText):
- return states.REQUEST
elif (text.strip().upper() in ("BLUE", "BLUES ONLY", "ONLY BLUE" "STILL BLUE", "ALL BLUES")):
return states.CLEAR
def parseShips(rtext):
def formatShipName(text, word):
- newText = u""" {0}"""
- text = text.replace(word, newText.format(word))
+ newText = u"""{0}"""
+ # Only do replacements at word boundaries
+ text = re.sub(REPLACE_WORD_REGEX.format(word), newText.format(word), text)
return text
texts = [t for t in rtext.contents if isinstance(t, NavigableString)]
for text in texts:
+ upperText = re.sub(CHARS_TO_IGNORE_REGEX, ' ', text.upper())
upperText = text.upper()
for shipName in evegate.SHIPNAMES:
if shipName in upperText:
hit = True
start = upperText.find(shipName)
end = start + len(shipName)
- if ((start > 0 and upperText[start - 1] not in (" ", "X")) or (
- end < len(upperText) - 1 and upperText[end] not in ("S", " "))):
+ if ( (start > 0 and re.match('[A-Z0-9]', upperText[start - 1]))
+ or (end < len(upperText) and re.match('[A-RT-Z0-9]', upperText[end])) ):
hit = False
if hit:
+ if (end < len(upperText) and 'S' == upperText[end]):
+ end += 1
shipInText = text[start:end]
formatted = formatShipName(text, shipInText)
textReplace(text, formatted)
@@ -102,18 +111,19 @@ def parseSystems(systems, rtext, foundSystems):
systemNames = systems.keys()
# words to ignore on the system parser. use UPPER CASE
- WORDS_TO_IGNORE = ("IN", "IS", "AS")
+ WORDS_TO_IGNORE = ("IN", "IS", "AS", "OR", "NV", "TO", "ME", "HE", "SHE", "YOU", "ARE",
+ "ON", "HAS", "OF", "IT", "GET", "IF", "THE", "HOT", "OH", "OK", "GJ", "AND", "MY",
+ "SAY", "ANY", "NO", "FOR", "OUT", "WH", "MAN", "PART", "AT", "AN" )
def formatSystem(text, word, system):
newText = u"""{1}"""
- text = text.replace(word, newText.format(system, word))
+ # Only do replacements at word boundaries: "no cyno onboard" would replace both "no"s in the first pass and then find a "cy"
+ text = re.sub(REPLACE_WORD_REGEX.format(word), newText.format(system, word), text)
return text
texts = [t for t in rtext.contents if isinstance(t, NavigableString) and len(t)]
- for wtIdx, text in enumerate(texts):
- worktext = text
- for char in CHARS_TO_IGNORE:
- worktext = worktext.replace(char, "")
+ for text in texts:
+ worktext = re.sub(CHARS_TO_IGNORE_REGEX, ' ', text)
# Drop redundant whitespace so as to not throw off word index
worktext = ' '.join(worktext.split())
@@ -121,6 +131,8 @@ def formatSystem(text, word, system):
for idx, word in enumerate(words):
+ matchKey = None
+
# Is this about another a system's gate?
if len(words) > idx + 1:
if words[idx+1].upper() == 'GATE':
@@ -137,37 +149,17 @@ def formatSystem(text, word, system):
upperWord = word.upper()
if upperWord != word and upperWord in WORDS_TO_IGNORE: continue
if upperWord in systemNames: # - direct hit on name
- foundSystems.add(systems[upperWord]) # of the system?
- formattedText = formatSystem(text, word, upperWord)
- textReplace(text, formattedText)
- return True
- elif 1 < len(upperWord) < 5: # - upperWord < 4 chars.
+ matchKey = systems[upperWord]['name']
+ elif 1 < len(upperWord) < 5: # - upperWord 2-4 chars.
for system in systemNames: # system begins with?
if system.startswith(upperWord):
- foundSystems.add(systems[system])
- formattedText = formatSystem(text, word, system)
- textReplace(text, formattedText)
- return True
- elif "-" in upperWord and len(upperWord) > 2: # - short with - (minus)
- upperWordParts = upperWord.split("-") # (I-I will match I43-IF3)
- for system in systemNames:
- systemParts = system.split("-")
- if (len(upperWordParts) == 2 and len(systemParts) == 2 and len(upperWordParts[0]) > 1 and len(
- upperWordParts[1]) > 1 and len(systemParts[0]) > 1 and len(systemParts[1]) > 1 and len(
- upperWordParts) == len(systemParts) and upperWordParts[0][0] == systemParts[0][0] and
- upperWordParts[1][0] == systemParts[1][0]):
- foundSystems.add(systems[system])
- formattedText = formatSystem(text, word, system)
- textReplace(text, formattedText)
- return True
- elif len(upperWord) > 1: # what if F-YH58 is named FY?
- for system in systemNames:
- clearedSystem = system.replace("-", "")
- if clearedSystem.startswith(upperWord):
- foundSystems.add(systems[system])
- formattedText = formatSystem(text, word, system)
- textReplace(text, formattedText)
- return True
+ matchKey = systems[system]['name']
+ break
+ if matchKey:
+ foundSystems.add(matchKey)
+ formattedText = formatSystem(text, word, matchKey)
+ textReplace(text, formattedText)
+ return True
return False
diff --git a/src/vi/dotlan.py b/src/vi/dotlan.py
index 182b7bd..1d41038 100644
--- a/src/vi/dotlan.py
+++ b/src/vi/dotlan.py
@@ -23,6 +23,7 @@
import math
import time
+import datetime
import six
import requests
import logging
@@ -37,7 +38,6 @@
"88aa00" "FFE4E1", "008080", "00BFFF", "4682B4", "00FF7F", "7FFF00", "ff6600",
"CD5C5C", "FFD700", "66CDAA", "AFEEEE", "5F9EA0", "FFDEAD", "696969", "2F4F4F")
-
class DotlanException(Exception):
def __init__(self, *args, **kwargs):
Exception.__init__(self, *args, **kwargs)
@@ -48,8 +48,6 @@ class Map(object):
The map including all information from dotlan
"""
- DOTLAN_BASIC_URL = u"http://evemaps.dotlan.net/svg/{0}.svg"
-
@property
def svg(self):
# Re-render all systems
@@ -90,17 +88,40 @@ def __init__(self, region, svgFile=None):
"without the map.\n\nRemember the site for possible " \
"updates: https://github.com/Xanthos-Eve/vintel".format(type(e), six.text_type(e))
raise DotlanException(t)
+
# Create soup from the svg
- self.soup = BeautifulSoup(svg, 'html.parser')
- self.systems = self._extractSystemsFromSoup(self.soup)
- self.systemsById = {}
- for system in self.systems.values():
- self.systemsById[system.systemId] = system
- self._prepareSvg(self.soup, self.systems)
- self._connectNeighbours()
- self._jumpMapsVisible = False
- self._statisticsVisible = False
- self.marker = self.soup.select("#select_marker")[0]
+ try:
+ self.soup = BeautifulSoup(svg, 'html.parser')
+ self.systems = self._extractSystemsFromSoup(self.soup)
+ self._cleanSoup(self.soup)
+ self.setJumpbridgesVisibility(False)
+ self.systemsById = {}
+ for system in self.systems.values():
+ self.systemsById[system.systemId] = system
+ self._prepareSvg(self.soup, self.systems)
+ self._connectNeighbours()
+ self._jumpMapsVisible = False
+ self._statisticsVisible = False
+ self.marker = self.soup.select("#select_marker")[0]
+ except Exception as e:
+ # Could get hung up on a bad retreival forever
+ cache.deleteFromCache("map_" + self.region)
+ raise
+
+ def _cleanSoup(self, soup):
+ try:
+ legend = soup.find('g', id='legend')
+ copyright = legend.find('text', class_='lc')
+ copyright.string = '(C) by Wollari & CCP'
+ for t in legend.select("text"):
+ if t.text == '= Alliance':
+ t.string = '= Intel Time'
+ elif t.text == '= Sov. Lvl' or t.text == 'Z':
+ t.string = ''
+ elif t.text == 'YYYYY (Z)':
+ t.string = 'YYYYY'
+ except:
+ pass
def _extractSystemsFromSoup(self, soup):
systems = {}
@@ -118,16 +139,21 @@ def _extractSystemsFromSoup(self, soup):
continue
for element in symbol.select(".sys"):
name = element.select("text")[0].text.strip().upper()
+ # could be region name or sov. info
+ secondaryInfo = element.select("text")[1].text.strip().upper()
mapCoordinates = {}
for keyname in ("x", "y", "width", "height"):
mapCoordinates[keyname] = float(uses[symbolId][keyname])
mapCoordinates["center_x"] = (mapCoordinates["x"] + (mapCoordinates["width"] / 2))
mapCoordinates["center_y"] = (mapCoordinates["y"] + (mapCoordinates["height"] / 2))
+ # Modify href to just be system name to deal better with out of region systems drawn on map
+ # leaving slash for now, not sure about effects on provi/catch combined maps
+ symbol.a['xlink:href'] = "/" + name
try:
transform = uses[symbolId]["transform"]
except KeyError:
transform = "translate(0,0)"
- systems[name] = System(name, element, self.soup, mapCoordinates, transform, systemId)
+ systems[name] = System(name, secondaryInfo, element, self.soup, mapCoordinates, transform, systemId)
return systems
def _prepareSvg(self, soup, systems):
@@ -191,7 +217,7 @@ def _connectNeighbours(self):
startSystem.addNeighbour(stopSystem)
def _getSvgFromDotlan(self, region):
- url = self.DOTLAN_BASIC_URL.format(region)
+ url = dotlan_url(region)
content = requests.get(url).text
return content
@@ -263,7 +289,15 @@ def changeStatisticsVisibility(self):
def changeJumpbridgesVisibility(self):
newStatus = False if self._jumpMapsVisible else True
+ return self.setJumpbridgesVisibility(newStatus)
+
+ def setJumpbridgesVisibility(self, newStatus):
value = "visible" if newStatus else "hidden"
+ try:
+ for jb in self.soup.select('path.jb'):
+ jb['visibility'] = value
+ except:
+ pass
for line in self.soup.select(".jumpbridge"):
line["visibility"] = value
self._jumpMapsVisible = newStatus
@@ -285,25 +319,32 @@ class System(object):
A System on the Map
"""
- ALARM_COLORS = [(60 * 4, "#FF0000", "#FFFFFF"), (60 * 10, "#FF9B0F", "#FFFFFF"), (60 * 15, "#FFFA0F", "#000000"),
- (60 * 25, "#FFFDA2", "#000000"), (60 * 60 * 24, "#FFFFFF", "#000000")]
- ALARM_COLOR = ALARM_COLORS[0][1]
UNKNOWN_COLOR = "#FFFFFF"
CLEAR_COLOR = "#59FF6C"
-
- def __init__(self, name, svgElement, mapSoup, mapCoordinates, transform, systemId):
+ ALARM_COLORS = [
+ # Alarmed systems change colors based on how long ago the alarm was received
+ # maxDiff (seconds), system background color, timer text color
+ (60 * 4, "#FF0000", "#FFFFFF"),
+ (60 * 10, "#FF9B0F", "#FFFFFF"),
+ (60 * 15, "#FFFA0F", "#000000"),
+ (60 * 25, "#FFFDA2", "#000000"),
+ (60 * 60 * 24, "#FFFFFF", "#000000")
+ ]
+
+ def __init__(self, name, secondaryInfo, svgElement, mapSoup, mapCoordinates, transform, systemId):
self.status = states.UNKNOWN
self.name = name
+ self.secondaryInfo = secondaryInfo
self.svgElement = svgElement
self.mapSoup = mapSoup
self.origSvgElement = svgElement
self.rect = svgElement.select("rect")[0]
self.secondLine = svgElement.select("text")[1]
- self.lastAlarmTime = 0
+ self.lastAlarmTime = datetime.datetime.min
self.messages = []
self.setStatus(states.UNKNOWN)
self.__locatedCharacters = []
- self.backgroundColor = "#FFFFFF"
+ self.backgroundColor = self.UNKNOWN_COLOR
self.mapCoordinates = mapCoordinates
self.systemId = systemId
self.transform = transform
@@ -418,16 +459,22 @@ def removeNeighbour(self, system):
if self in system._neighbours:
system._neigbours.remove(self)
- def setStatus(self, newStatus):
+ def setStatus(self, newStatus, statusTime = None):
+ if None == statusTime:
+ statusTime = evegate.currentEveTime()
if newStatus == states.ALARM:
- self.lastAlarmTime = time.time()
+ self.lastAlarmTime = statusTime
if "stopwatch" not in self.secondLine["class"]:
self.secondLine["class"].append("stopwatch")
self.secondLine["alarmtime"] = self.lastAlarmTime
self.secondLine["style"] = "fill: #FFFFFF;"
- self.setBackgroundColor(self.ALARM_COLOR)
+ delta = (evegate.currentEveTime() - self.lastAlarmTime).total_seconds()
+ for maxDiff, alarmColor, secondLineColor in self.ALARM_COLORS:
+ if delta < maxDiff:
+ self.setBackgroundColor(alarmColor)
+ break
elif newStatus == states.CLEAR:
- self.lastAlarmTime = time.time()
+ self.lastAlarmTime = statusTime
self.setBackgroundColor(self.CLEAR_COLOR)
self.secondLine["alarmtime"] = 0
if "stopwatch" not in self.secondLine["class"]:
@@ -457,7 +504,7 @@ def setStatistics(self, statistics):
def update(self):
# state changed?
if (self.status == states.ALARM):
- alarmTime = time.time() - self.lastAlarmTime
+ alarmTime = (evegate.currentEveTime() - self.lastAlarmTime).total_seconds()
for maxDiff, alarmColor, secondLineColor in self.ALARM_COLORS:
if alarmTime < maxDiff:
if self.backgroundColor != alarmColor:
@@ -468,7 +515,7 @@ def update(self):
self.secondLine["style"] = "fill: {0};".format(secondLineColor)
break
if self.status in (states.ALARM, states.WAS_ALARMED, states.CLEAR): # timer
- diff = math.floor(time.time() - self.lastAlarmTime)
+ diff = (evegate.currentEveTime() - self.lastAlarmTime).total_seconds()
minutes = int(math.floor(diff / 60))
seconds = int(diff - minutes * 60)
string = "{m:02d}:{s:02d}".format(m=minutes, s=seconds)
@@ -483,9 +530,18 @@ def update(self):
self.secondLine.string = string
+def dotlan_url(region):
+ """ Generate a DOTLAN url from the specified region name (which will be normalized to a DOTLAN region name)
+ """
+ url = u"http://evemaps.dotlan.net/svg/{0}.svg".format(convertRegionName(region))
+ jb_id = Cache().getConfigValue("dotlan_jb_id")
+ if jb_id:
+ url = url + u"?path=B:{0}".format(jb_id)
+ return url
+
def convertRegionName(name):
"""
- Converts a (system)name to the format that dotland uses
+ Converts a (system)name to the format that dotlan uses
"""
converted = []
nextUpper = False
diff --git a/src/vi/evegate.py b/src/vi/evegate.py
index 4ccabd9..2efd7b0 100644
--- a/src/vi/evegate.py
+++ b/src/vi/evegate.py
@@ -24,7 +24,6 @@
import requests
import logging
-from requests import utils
from bs4 import BeautifulSoup
from six.moves.urllib.error import HTTPError
from six.moves.urllib.request import urlopen
@@ -159,7 +158,7 @@ def checkPlayername(charname):
"""
baseUrl = "https://gate.eveonline.com/Profile/"
- queryCharname = utils.quote(charname)
+ queryCharname = requests.utils.quote(charname)
url = baseUrl + queryCharname
result = -1
@@ -313,7 +312,7 @@ def secondsTillDowntime():
u'CERBERUS', u'CHARON', u'CHEETAH', u'CHIMERA', u'CLAW', u'CLAYMORE', u'COERCER', u'CONDOR', u'CORMORANT',
u'COVETOR', u'CRANE', u'CROW', u'CRUCIFIER', u'CRUOR', u'CRUSADER', u'CURSE', u'CYCLONE', u'CYNABAL',
u'DAMNATION', u'DAREDEVIL', u'DEIMOS', u'DEVOTER', u'DOMINIX', u'DRAKE', u'DRAMIEL', u'EAGLE', u'EIDOLON',
- u'ENIGMA', u'ENYO', u'EOS', u'EREBUS', u'ERIS', u'EXECUTIONER', u'EXEQUROR', u'EXEQUROR NAVY ISSUE',
+ u'ENDURANCE', u'ENIGMA', u'ENYO', u'EOS', u'EREBUS', u'ERIS', u'EXECUTIONER', u'EXEQUROR', u'EXEQUROR NAVY ISSUE',
u'FALCON', u'FEDERATION NAVY COMET', u'FENRIR', u'FEROX', u'FLYCATCHER', u'GALLENTE SHUTTLE', u'GILA',
u'GOLD MAGNATE', u'GOLEM', u'GRIFFIN', u'GUARDIAN', u'HARBINGER', u'HARPY', u'HAWK', u'HEL', u'HELIOS',
u'HERETIC', u'HERON', u'HOARDER', u'HOUND', u'HUGINN', u'HULK', u'HURRICANE', u'HYENA', u'HYPERION',
@@ -326,7 +325,8 @@ def secondsTillDowntime():
u'NOMAD', u'NYX', u'OBELISK', u'OCCATOR', u'OMEN', u'OMEN NAVY ISSUE', u'ONEIROS', u'ONYX',
u'OPUX DRAGOON YACHT', u'OPUX LUXURY YACHT', u'ORACLE', u'ORCA', u'OSPREY', u'OSPREY NAVY ISSUE',
u'PALADIN', u'PANTHER', u'PHANTASM', u'PHANTOM', u'PHOBOS', u'PHOENIX', u'PILGRIM', u'POLARIS CENTURION',
- u'POLARIS INSPECTOR', u'POLARIS LEGATUS', u'PROBE', u'PROCURER', u'PROPHECY', u'PRORATOR', u'PROVIDENCE',
+ u'POLARIS INSPECTOR', u'POLARIS LEGATUS', u'PORPOISE', u'PROBE', u'PROCURER', u'PROPHECY', u'PRORATOR',
+ u'PROSPECT', u'PROVIDENCE',
u'PROWLER', u'PUNISHER', u'PURIFIER', u'RAGNAROK', u'RAPIER', u'RAPTOR', u'RATTLESNAKE', u'RAVEN',
u'RAVEN NAVY ISSUE', u'RAVEN STATE ISSUE', u'REAPER', u'REDEEMER', u'REPUBLIC FLEET FIRETAIL',
u'RETRIBUTION', u'RETRIEVER', u'REVELATION', u'RHEA', u'RIFTER', u'ROKH', u'ROOK', u'RORQUAL', u'RUPTURE',
@@ -336,7 +336,11 @@ def secondsTillDowntime():
u'TEMPEST TRIBAL ISSUE', u'THANATOS', u'THORAX', u'THRASHER', u'TORMENTOR', u'TRISTAN', u'TYPHOON',
u'VAGABOND', u'VARGUR', u'VELATOR', u'VENGEANCE', u'VEXOR', u'VEXOR NAVY ISSUE', u'VIATOR', u'VIGIL',
u'VIGILANT', u'VINDICATOR', u'VISITANT', u'VULTURE', u'WIDOW', u'WOLF', u'WORM', u'WRAITH', u'WREATHE',
- u'WYVERN', u'ZEALOT', u'CAPSULE',)
+ u'WYVERN', u'ZEALOT', u'CAPSULE',
+ u'BOMBER', u'LOGI',
+ u'T3D', u'JACKDAW', u'SVIPUL', u'CONFESSOR', u'HECTATE',
+ u'T3C', u'TENGU', u'LOKI', u'LEGION', u'PROTEUS',
+ u'STORK', u'BIFROST', u'PONTIFEX', u'MAGUS')
SHIPNAMES = sorted(SHIPNAMES, key=lambda x: len(x), reverse=True)
NPC_CORPS = (u'Republic Justice Department', u'House of Records', u'24th Imperial Crusade', u'Template:NPC corporation',
diff --git a/src/vi/filewatcher.py b/src/vi/filewatcher.py
index 3a958b3..849b1e1 100644
--- a/src/vi/filewatcher.py
+++ b/src/vi/filewatcher.py
@@ -1,97 +1,97 @@
-###########################################################################
-# Vintel - Visual Intel Chat Analyzer #
-# Copyright (C) 2014-15 Sebastian Meyer (sparrow.242.de+eve@gmail.com ) #
-# #
-# This program is free software: you can redistribute it and/or modify #
-# it under the terms of the GNU General Public License as published by #
-# the Free Software Foundation, either version 3 of the License, or #
-# (at your option) any later version. #
-# #
-# This program is distributed in the hope that it will be useful, #
-# but WITHOUT ANY WARRANTY; without even the implied warranty of #
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
-# GNU General Public License for more details. #
-# #
-# #
-# You should have received a copy of the GNU General Public License #
-# along with this program. If not, see . #
-###########################################################################
-
-import os
-import stat
-import time
-
-from PyQt5 import QtCore
-from PyQt5.QtCore import pyqtSignal
-
-"""
-There is a problem with the QFIleWatcher on Windows and the log
-files from EVE.
-The first implementation (now FileWatcher_orig) works fine on Linux, but
-on Windows it seems ther is something buffered. Only a file-operation on
-the watched directory another event there, which tirggers the OS to
-reread the files informations, trigger the QFileWatcher.
-So here is a workaround implementation.
-We use here also a QFileWatcher, only to the directory. It will notify it
-if a new file was created. We watch only the newest (last 24h), not all!
-"""
-
-DEFAULT_MAX_AGE = 60 * 60 * 24
-
-class FileWatcher(QtCore.QThread):
-
- fileChanged = pyqtSignal(str)
-
- def __init__(self, path, maxAge=DEFAULT_MAX_AGE):
- QtCore.QThread.__init__(self)
- self.path = path
- self.maxAge = maxAge
- self.files = {}
- self.updateWatchedFiles()
- self.qtfw = QtCore.QFileSystemWatcher()
- self.qtfw.directoryChanged.connect(self.directoryChanged)
- self.qtfw.addPath(path)
- self.paused = True
- self.active = True
-
-
- def directoryChanged(self):
- self.updateWatchedFiles()
-
-
- def run(self):
- while True:
- time.sleep(0.5)
- if not self.active:
- return
- if self.paused:
- continue
- for path, modified in self.files.items():
- pathStat = os.stat(path)
- if not stat.S_ISREG(pathStat.st_mode):
- continue
- if modified < pathStat.st_size:
- self.fileChanged.emit(path)
- self.files[path] = pathStat.st_size
-
-
- def quit(self):
- self.active = False
- QtCore.QThread.quit(self)
-
-
- def updateWatchedFiles(self):
- # Reading all files from the directory
- fullPath = None
- now = time.time()
- path = self.path
- filesInDir = {}
- for f in os.listdir(path):
- fullPath = os.path.join(path, f)
- pathStat = os.stat(fullPath)
- if not stat.S_ISREG(pathStat.st_mode):
- continue
- if self.maxAge and ((now - pathStat.st_mtime) > self.maxAge):
- continue
- filesInDir[fullPath] = self.files.get(fullPath, 0)
- self.files = filesInDir
+###########################################################################
+# Vintel - Visual Intel Chat Analyzer #
+# Copyright (C) 2014-15 Sebastian Meyer (sparrow.242.de+eve@gmail.com ) #
+# #
+# This program is free software: you can redistribute it and/or modify #
+# it under the terms of the GNU General Public License as published by #
+# the Free Software Foundation, either version 3 of the License, or #
+# (at your option) any later version. #
+# #
+# This program is distributed in the hope that it will be useful, #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+# GNU General Public License for more details. #
+# #
+# #
+# You should have received a copy of the GNU General Public License #
+# along with this program. If not, see . #
+###########################################################################
+
+import os
+import stat
+import time
+
+from PyQt5 import QtCore
+from PyQt5.QtCore import pyqtSignal
+
+"""
+There is a problem with the QFIleWatcher on Windows and the log
+files from EVE.
+The first implementation (now FileWatcher_orig) works fine on Linux, but
+on Windows it seems ther is something buffered. Only a file-operation on
+the watched directory another event there, which tirggers the OS to
+reread the files informations, trigger the QFileWatcher.
+So here is a workaround implementation.
+We use here also a QFileWatcher, only to the directory. It will notify it
+if a new file was created. We watch only the newest (last 24h), not all!
+"""
+
+DEFAULT_MAX_AGE = 60 * 60 * 24
+
+class FileWatcher(QtCore.QThread):
+
+ fileChanged = pyqtSignal(str)
+
+ def __init__(self, path, maxAge=DEFAULT_MAX_AGE):
+ QtCore.QThread.__init__(self)
+ self.path = path
+ self.maxAge = maxAge
+ self.files = {}
+ self.updateWatchedFiles()
+ self.qtfw = QtCore.QFileSystemWatcher()
+ self.qtfw.directoryChanged.connect(self.directoryChanged)
+ self.qtfw.addPath(path)
+ self.paused = True
+ self.active = True
+
+
+ def directoryChanged(self):
+ self.updateWatchedFiles()
+
+
+ def run(self):
+ while True:
+ time.sleep(0.5)
+ if not self.active:
+ return
+ if self.paused:
+ continue
+ for path, modified in self.files.items():
+ pathStat = os.stat(path)
+ if not stat.S_ISREG(pathStat.st_mode):
+ continue
+ if modified < pathStat.st_size:
+ self.fileChanged.emit(path)
+ self.files[path] = pathStat.st_size
+
+
+ def quit(self):
+ self.active = False
+ QtCore.QThread.quit(self)
+
+
+ def updateWatchedFiles(self):
+ # Reading all files from the directory
+ fullPath = None
+ now = time.time()
+ path = self.path
+ filesInDir = {}
+ for f in os.listdir(path):
+ fullPath = os.path.join(path, f)
+ pathStat = os.stat(fullPath)
+ if not stat.S_ISREG(pathStat.st_mode):
+ continue
+ if self.maxAge and ((now - pathStat.st_mtime) > self.maxAge):
+ continue
+ filesInDir[fullPath] = self.files.get(fullPath, 0)
+ self.files = filesInDir
diff --git a/src/vi/regions.py b/src/vi/regions.py
new file mode 100644
index 0000000..9c4fd1b
--- /dev/null
+++ b/src/vi/regions.py
@@ -0,0 +1,66 @@
+REGIONS = [
+ "Aridia",
+ "Black Rise",
+ "Branch",
+ "Cache",
+ "Catch",
+ "Cloud Ring",
+ "Cobalt Edge",
+ "Curse",
+ "Deklein",
+ "Delve",
+ "Derelik",
+ "Detorid",
+ "Devoid",
+ "Domain",
+ "Esoteria",
+ "Essence",
+ "Etherium Reach",
+ "Everyshore",
+ "Fade",
+ "Feythabolis",
+ "Fountain",
+ "Geminate",
+ "Genesis",
+ "Great Wildlands",
+ "Heimatar",
+ "Immensea",
+ "Impass",
+ "Insmother",
+ "Kador",
+ "Khanid",
+ "Kor-Azor",
+ "Lonetrek",
+ "Malpais",
+ "Metropolis",
+ "Molden Heath",
+ "Oasa",
+ "Omist",
+ "Outer Passage",
+ "Outer Ring",
+ "Paragon Soul",
+ "Period Basis",
+ "Perrigen Falls",
+ "Placid",
+ "Providence",
+ "Pure Blind",
+ "Querious",
+ "Scalding Pass",
+ "Sinq Laison",
+ "Solitude",
+ "Stain",
+ "Syndicate",
+ "Tash-Murkon",
+ "Tenal",
+ "Tenerifis",
+ "The Bleak Lands",
+ "The Citadel",
+ "The Forge",
+ "The Kalevala Expanse",
+ "The Spire",
+ "Tribute",
+ "Vale of the Silent",
+ "Venal",
+ "Verge Vendor",
+ "Wicked Creek"
+]
diff --git a/src/vi/states.py b/src/vi/states.py
index 202ea0c..ac3c3c5 100644
--- a/src/vi/states.py
+++ b/src/vi/states.py
@@ -26,7 +26,7 @@
NOT_CHANGE = 'no change'
CLEAR = 'clear'
ALARM = 'alarm'
-WAS_ALARMED = 'was alarmed'
+WAS_ALARMED = 'was alarmed' # UNUSED
REQUEST = 'request'
LOCATION = 'location'
KOS_STATUS_REQUEST = 'kos request'
diff --git a/src/vi/systems.py b/src/vi/systems.py
new file mode 100644
index 0000000..df6adcc
--- /dev/null
+++ b/src/vi/systems.py
@@ -0,0 +1,5465 @@
+SYSTEMS = {
+ "Tanoo": "Derelik",
+ "Lashesih": "Derelik",
+ "Akpivem": "Derelik",
+ "Jark": "Derelik",
+ "Sasta": "Derelik",
+ "Zaid": "Derelik",
+ "Yuzier": "Derelik",
+ "Nirbhi": "Derelik",
+ "Sooma": "Derelik",
+ "Chidah": "Derelik",
+ "Shenela": "Derelik",
+ "Asabona": "Derelik",
+ "Onsooh": "Derelik",
+ "Shamahi": "Derelik",
+ "Sendaya": "Derelik",
+ "Nazhgete": "Derelik",
+ "Futzchag": "Derelik",
+ "Kazna": "Derelik",
+ "Podion": "Derelik",
+ "Lilmad": "Derelik",
+ "Kuharah": "Derelik",
+ "Jayneleb": "Derelik",
+ "Fovihi": "Derelik",
+ "Kiereend": "Derelik",
+ "Rashy": "Derelik",
+ "Ordize": "Derelik",
+ "Psasa": "Derelik",
+ "Eshtah": "Derelik",
+ "Lachailes": "Derelik",
+ "Kasrasi": "Derelik",
+ "Mohas": "Derelik",
+ "Hasiari": "Derelik",
+ "Radima": "Derelik",
+ "Alkez": "Derelik",
+ "Nimambal": "Derelik",
+ "Yishinoon": "Derelik",
+ "Uplingur": "Derelik",
+ "Dooz": "Derelik",
+ "Bayuka": "Derelik",
+ "Uzistoon": "Derelik",
+ "Bairshir": "Derelik",
+ "Moh": "Derelik",
+ "Sari": "Derelik",
+ "Faspera": "Derelik",
+ "Jaymass": "Derelik",
+ "Mifrata": "Derelik",
+ "Majamar": "Derelik",
+ "Ihal": "Derelik",
+ "Camal": "Derelik",
+ "Fera": "Derelik",
+ "Juddi": "Derelik",
+ "Maspah": "Derelik",
+ "Ibaria": "Derelik",
+ "Shala": "Derelik",
+ "Zemalu": "Derelik",
+ "Khankenirdia": "Derelik",
+ "Nikh": "Derelik",
+ "Amphar": "Derelik",
+ "Salashayama": "Derelik",
+ "Janus": "Derelik",
+ "Agha": "Derelik",
+ "Iosantin": "Derelik",
+ "Orva": "Derelik",
+ "Zet": "Derelik",
+ "Akhrad": "Derelik",
+ "Pirohdim": "Derelik",
+ "Sharir": "Derelik",
+ "Usroh": "Derelik",
+ "Thiarer": "Derelik",
+ "Gomati": "Derelik",
+ "Jangar": "Derelik",
+ "Nakah": "Derelik",
+ "Irshah": "Derelik",
+ "Hasateem": "Derelik",
+ "Assah": "Derelik",
+ "Tidacha": "Derelik",
+ "Odlib": "Derelik",
+ "Jofan": "Derelik",
+ "Milu": "Derelik",
+ "Yadi": "Derelik",
+ "Buftiar": "Derelik",
+ "Jarizza": "Derelik",
+ "Ejahi": "Derelik",
+ "Asghatil": "Derelik",
+ "Bar": "Derelik",
+ "Sucha": "Derelik",
+ "Gelhan": "Derelik",
+ "Akeva": "Derelik",
+ "Sosa": "Derelik",
+ "Ilahed": "Derelik",
+ "Eshwil": "Derelik",
+ "Aranir": "Derelik",
+ "Ishkad": "Derelik",
+ "Hahyil": "Derelik",
+ "Asilem": "Derelik",
+ "Mahnagh": "Derelik",
+ "Shach": "Derelik",
+ "Kehrara": "Derelik",
+ "Arena": "Derelik",
+ "Timeor": "Derelik",
+ "Uhtafal": "Derelik",
+ "Dysa": "Derelik",
+ "Serad": "Derelik",
+ "Mahti": "Derelik",
+ "Abha": "Derelik",
+ "Shedoo": "Derelik",
+ "Gamis": "Derelik",
+ "Nieril": "Derelik",
+ "Berta": "Derelik",
+ "Bekirdod": "Derelik",
+ "Hothomouh": "Derelik",
+ "Arnola": "Derelik",
+ "Astabih": "Derelik",
+ "Ubtes": "Derelik",
+ "Bimener": "Derelik",
+ "Kenobanala": "Derelik",
+ "Khabi": "Derelik",
+ "Uanzin": "Derelik",
+ "Itamo": "The Forge",
+ "Mitsolen": "The Forge",
+ "Jatate": "The Forge",
+ "Mahtista": "The Forge",
+ "Vaankalen": "The Forge",
+ "Kylmabe": "The Forge",
+ "Ahtulaima": "The Forge",
+ "Geras": "The Forge",
+ "Sirseshin": "The Forge",
+ "Tuuriainas": "The Forge",
+ "Unpas": "The Forge",
+ "Shihuken": "The Forge",
+ "Nomaa": "The Forge",
+ "Ansila": "The Forge",
+ "Hirtamon": "The Forge",
+ "Hykkota": "The Forge",
+ "Outuni": "The Forge",
+ "Ohmahailen": "The Forge",
+ "Eskunen": "The Forge",
+ "Ikuchi": "The Forge",
+ "Urlen": "The Forge",
+ "Maurasi": "The Forge",
+ "Kisogo": "The Forge",
+ "Jita": "The Forge",
+ "Niyabainen": "The Forge",
+ "Perimeter": "The Forge",
+ "New Caldari": "The Forge",
+ "Saisio": "The Forge",
+ "Abagawa": "The Forge",
+ "Jakanerva": "The Forge",
+ "Gekutami": "The Forge",
+ "Hurtoken": "The Forge",
+ "Uoyonen": "The Forge",
+ "Hampinen": "The Forge",
+ "Poinen": "The Forge",
+ "Liekuri": "The Forge",
+ "Obanen": "The Forge",
+ "Josameto": "The Forge",
+ "Otela": "The Forge",
+ "Olo": "The Forge",
+ "Ikami": "The Forge",
+ "Reisen": "The Forge",
+ "Purjola": "The Forge",
+ "Maila": "The Forge",
+ "Akora": "The Forge",
+ "Messoya": "The Forge",
+ "Ishisomo": "The Forge",
+ "Airmia": "The Forge",
+ "Sakkikainen": "The Forge",
+ "Friggi": "The Forge",
+ "Ihakana": "The Forge",
+ "Vahunomi": "The Forge",
+ "Otitoh": "The Forge",
+ "Otomainen": "The Forge",
+ "Vattuolen": "The Forge",
+ "Onuse": "The Forge",
+ "Soshin": "The Forge",
+ "Keikaken": "The Forge",
+ "Ukkalen": "The Forge",
+ "Akkilen": "The Forge",
+ "Silen": "The Forge",
+ "Osmon": "The Forge",
+ "Korsiki": "The Forge",
+ "Inaya": "The Forge",
+ "Nuken": "The Forge",
+ "Uminas": "The Forge",
+ "Airaken": "The Forge",
+ "Oijanen": "The Forge",
+ "Wuos": "The Forge",
+ "Hentogaira": "The Forge",
+ "Kiainti": "The Forge",
+ "Vasala": "The Forge",
+ "Walvalin": "The Forge",
+ "Otanuomi": "The Forge",
+ "Vouskiaho": "The Forge",
+ "Otsela": "The Forge",
+ "Tasti": "The Forge",
+ "Otosela": "The Forge",
+ "Uemon": "The Forge",
+ "Paala": "The Forge",
+ "Fuskunen": "The Forge",
+ "Akkio": "The Forge",
+ "Uchoshi": "The Forge",
+ "Mastakomon": "The Forge",
+ "Eruka": "The Forge",
+ "Ohkunen": "The Forge",
+ "Obe": "The Forge",
+ "Wirashoda": "The Forge",
+ "Osaa": "The Forge",
+ "Sakenta": "The Forge",
+ "Senda": "The Forge",
+ "Aokannitoh": "The Forge",
+ "Uitra": "The Forge",
+ "LZ-6SU": "Vale of the Silent",
+ "MC6O-F": "Vale of the Silent",
+ "U54-1L": "Vale of the Silent",
+ "B-588R": "Vale of the Silent",
+ "NCGR-Q": "Vale of the Silent",
+ "G-LOIT": "Vale of the Silent",
+ "HE-V4V": "Vale of the Silent",
+ "N-HSK0": "Vale of the Silent",
+ "05R-7A": "Vale of the Silent",
+ "7-UH4Z": "Vale of the Silent",
+ "5ZO-NZ": "Vale of the Silent",
+ "FS-RFL": "Vale of the Silent",
+ "Y0-BVN": "Vale of the Silent",
+ "X97D-W": "Vale of the Silent",
+ "0-R5TS": "Vale of the Silent",
+ "H-UCD1": "Vale of the Silent",
+ "7-K5EL": "Vale of the Silent",
+ "H-5GUI": "Vale of the Silent",
+ "FH-TTC": "Vale of the Silent",
+ "FMBR-8": "Vale of the Silent",
+ "3HX-DL": "Vale of the Silent",
+ "UH-9ZG": "Vale of the Silent",
+ "NFM-0V": "Vale of the Silent",
+ "YXIB-I": "Vale of the Silent",
+ "MY-T2P": "Vale of the Silent",
+ "FA-DMO": "Vale of the Silent",
+ "GEKJ-9": "Vale of the Silent",
+ "Q-R3GP": "Vale of the Silent",
+ "N-5QPW": "Vale of the Silent",
+ "XV-8JQ": "Vale of the Silent",
+ "WBR5-R": "Vale of the Silent",
+ "4GYV-Q": "Vale of the Silent",
+ "4-HWWF": "Vale of the Silent",
+ "YMJG-4": "Vale of the Silent",
+ "8TPX-N": "Vale of the Silent",
+ "PM-DWE": "Vale of the Silent",
+ "K8X-6B": "Vale of the Silent",
+ "X445-5": "Vale of the Silent",
+ "KRUN-N": "Vale of the Silent",
+ "9OO-LH": "Vale of the Silent",
+ "V-OJEN": "Vale of the Silent",
+ "EIDI-N": "Vale of the Silent",
+ "P3EN-E": "Vale of the Silent",
+ "49-0LI": "Vale of the Silent",
+ "IPAY-2": "Vale of the Silent",
+ "DAYP-G": "Vale of the Silent",
+ "IFJ-EL": "Vale of the Silent",
+ "47L-J4": "Vale of the Silent",
+ "Q-L07F": "Vale of the Silent",
+ "E-D0VZ": "Vale of the Silent",
+ "6WW-28": "Vale of the Silent",
+ "A8A-JN": "Vale of the Silent",
+ "S-NJBB": "Vale of the Silent",
+ "T-GCGL": "Vale of the Silent",
+ "0MV-4W": "Vale of the Silent",
+ "TVN-FM": "Vale of the Silent",
+ "V-NL3K": "Vale of the Silent",
+ "AZBR-2": "Vale of the Silent",
+ "Z-8Q65": "Vale of the Silent",
+ "0J3L-V": "Vale of the Silent",
+ "H-NOU5": "Vale of the Silent",
+ "KX-2UI": "Vale of the Silent",
+ "MO-FIF": "Vale of the Silent",
+ "97-M96": "Vale of the Silent",
+ "MA-XAP": "Vale of the Silent",
+ "C-J7CR": "Vale of the Silent",
+ "Q-EHMJ": "Vale of the Silent",
+ "XSQ-TF": "Vale of the Silent",
+ "H-1EOH": "Vale of the Silent",
+ "IR-DYY": "Vale of the Silent",
+ "C-DHON": "Vale of the Silent",
+ "F-D49D": "Vale of the Silent",
+ "MQ-O27": "Vale of the Silent",
+ "H-EY0P": "Vale of the Silent",
+ "UNAG-6": "Vale of the Silent",
+ "E-SCTX": "Vale of the Silent",
+ "S6QX-N": "Vale of the Silent",
+ "IT-YAU": "Vale of the Silent",
+ "1VK-6B": "Vale of the Silent",
+ "7-PO3P": "Vale of the Silent",
+ "1W-0KS": "Vale of the Silent",
+ "669-IX": "Vale of the Silent",
+ "0R-F2F": "Vale of the Silent",
+ "R-P7KL": "Vale of the Silent",
+ "2DWM-2": "Vale of the Silent",
+ "XF-PWO": "Vale of the Silent",
+ "1N-FJ8": "Vale of the Silent",
+ "VI2K-J": "Vale of the Silent",
+ "ZLZ-1Z": "Vale of the Silent",
+ "6Y-WRK": "Vale of the Silent",
+ "RVCZ-C": "Vale of the Silent",
+ "5T-KM3": "Vale of the Silent",
+ "LS9B-9": "Vale of the Silent",
+ "1-GBBP": "Vale of the Silent",
+ "C-FP70": "Vale of the Silent",
+ "T-ZWA1": "Vale of the Silent",
+ "ZA0L-U": "Vale of the Silent",
+ "G96R-F": "Vale of the Silent",
+ "Y-ZXIO": "Vale of the Silent",
+ "B-E3KQ": "Vale of the Silent",
+ "Y5J-EU": "Vale of the Silent",
+ "O-LR1H": "Vale of the Silent",
+ "G5ED-Y": "Vale of the Silent",
+ "BR-6XP": "Vale of the Silent",
+ "8-TFDX": "Vale of the Silent",
+ "UL-4ZW": "Vale of the Silent",
+ "A-QRQT": "Vale of the Silent",
+ "WMBZ-U": "Vale of the Silent",
+ "PX5-LR": "Vale of the Silent",
+ "A3-RQ3": "Vale of the Silent",
+ "9-GBPD": "Vale of the Silent",
+ "LS-JEP": "Vale of the Silent",
+ "R-RSZZ": "Vale of the Silent",
+ "MGAM-4": "Vale of the Silent",
+ "VORM-W": "Vale of the Silent",
+ "7G-H7D": "Vale of the Silent",
+ "Q3-BAY": "Vale of the Silent",
+ "JZV-F4": "Vale of the Silent",
+ "WF-1LM": "UUA-F4",
+ "D95-FQ": "UUA-F4",
+ "ZSPJ-K": "UUA-F4",
+ "U1F-86": "UUA-F4",
+ "T-P7A6": "UUA-F4",
+ "Y-T3JJ": "UUA-F4",
+ "F3R-IA": "UUA-F4",
+ "74-YTJ": "UUA-F4",
+ "8-RS3U": "UUA-F4",
+ "OVFN-N": "UUA-F4",
+ "1Q-BBM": "UUA-F4",
+ "WXNC-N": "UUA-F4",
+ "G-EA07": "UUA-F4",
+ "X-L6BO": "UUA-F4",
+ "D-PHUA": "UUA-F4",
+ "3-HXHQ": "UUA-F4",
+ "18A-NB": "UUA-F4",
+ "3-J5OQ": "UUA-F4",
+ "GYF-GD": "UUA-F4",
+ "W-6TS9": "UUA-F4",
+ "VIG-VR": "UUA-F4",
+ "KX-P5C": "UUA-F4",
+ "N-FJBK": "UUA-F4",
+ "2-4ZT5": "UUA-F4",
+ "NVN-6F": "UUA-F4",
+ "09-8TH": "UUA-F4",
+ "TI0-AX": "UUA-F4",
+ "7O-POM": "UUA-F4",
+ "L6Q-SX": "UUA-F4",
+ "BFJ-TB": "UUA-F4",
+ "ZZ7-L6": "UUA-F4",
+ "L-CHVW": "UUA-F4",
+ "X0LN-U": "UUA-F4",
+ "RQAE-M": "UUA-F4",
+ "7CO-SA": "UUA-F4",
+ "4G-E5A": "UUA-F4",
+ "A-VWK9": "UUA-F4",
+ "JQHP-4": "UUA-F4",
+ "6Q5K-5": "UUA-F4",
+ "P-MVFP": "UUA-F4",
+ "J-Z1UW": "UUA-F4",
+ "W477-P": "UUA-F4",
+ "NQ1-BL": "UUA-F4",
+ "K7A-G8": "UUA-F4",
+ "HP-PMX": "UUA-F4",
+ "6BN-K9": "UUA-F4",
+ "WLE-PY": "UUA-F4",
+ "EH-HXW": "UUA-F4",
+ "OS-RR3": "UUA-F4",
+ "V4-GZL": "UUA-F4",
+ "4C-Z91": "UUA-F4",
+ "RU-97T": "UUA-F4",
+ "1S-1V7": "UUA-F4",
+ "PE1-R1": "UUA-F4",
+ "Polaris": "UUA-F4",
+ "JB-007": "UUA-F4",
+ "USJ2-M": "UUA-F4",
+ "7M-RAL": "UUA-F4",
+ "LPBU-U": "UUA-F4",
+ "RF-342": "UUA-F4",
+ "J2V-XY": "UUA-F4",
+ "Z-JBTR": "UUA-F4",
+ "S-QNXH": "UUA-F4",
+ "S94-X8": "UUA-F4",
+ "J-YQEC": "UUA-F4",
+ "8MX-OR": "UUA-F4",
+ "97YC-C": "UUA-F4",
+ "V-AMD5": "UUA-F4",
+ "U-JC8X": "UUA-F4",
+ "1HH3-E": "UUA-F4",
+ "DUIU-Q": "UUA-F4",
+ "LQH0-H": "UUA-F4",
+ "FRW3-2": "UUA-F4",
+ "9MX-1C": "UUA-F4",
+ "IED-4U": "UUA-F4",
+ "N-9EOQ": "UUA-F4",
+ "6F3-TK": "UUA-F4",
+ "2E0P-2": "UUA-F4",
+ "U-ITH5": "UUA-F4",
+ "N-4G5L": "UUA-F4",
+ "RB-2EA": "UUA-F4",
+ "ZK5-42": "UUA-F4",
+ "YRZ-E4": "UUA-F4",
+ "A3-PAT": "UUA-F4",
+ "H55-2R": "UUA-F4",
+ "P6-DBM": "UUA-F4",
+ "9XI-0X": "UUA-F4",
+ "Q8T-MC": "UUA-F4",
+ "Z-YOJ9": "UUA-F4",
+ "4T4B-L": "UUA-F4",
+ "F-JB3H": "UUA-F4",
+ "XBO7-F": "UUA-F4",
+ "FI-449": "UUA-F4",
+ "UA7-U4": "UUA-F4",
+ "VM-QFU": "UUA-F4",
+ "PU-1Z8": "UUA-F4",
+ "IEZW-V": "UUA-F4",
+ "B-DXO9": "UUA-F4",
+ "1TS-WN": "UUA-F4",
+ "16-31U": "UUA-F4",
+ "H472-N": "UUA-F4",
+ "U8MM-3": "UUA-F4",
+ "3C-26I": "UUA-F4",
+ "9K-VDI": "UUA-F4",
+ "L-SDU7": "UUA-F4",
+ "4-IPWK": "UUA-F4",
+ "Q-KCK3": "UUA-F4",
+ "WU-FHQ": "Detorid",
+ "V-4DBR": "Detorid",
+ "B-5UFY": "Detorid",
+ "SK42-F": "Detorid",
+ "EU9-J3": "Detorid",
+ "PQRE-W": "Detorid",
+ "OEG-K9": "Detorid",
+ "0-W778": "Detorid",
+ "DG-8VJ": "Detorid",
+ "5J4K-9": "Detorid",
+ "MD-0AW": "Detorid",
+ "H-FGJO": "Detorid",
+ "1KAW-T": "Detorid",
+ "C5-SUU": "Detorid",
+ "XSUD-1": "Detorid",
+ "3-LJW3": "Detorid",
+ "ZLO3-V": "Detorid",
+ "P7MI-T": "Detorid",
+ "JFV-ID": "Detorid",
+ "3-3EZB": "Detorid",
+ "52CW-6": "Detorid",
+ "9-OUGJ": "Detorid",
+ "4NDT-W": "Detorid",
+ "GR-X26": "Detorid",
+ "6OU9-U": "Detorid",
+ "9N-0HF": "Detorid",
+ "U-OVFR": "Detorid",
+ "G3D-ZT": "Detorid",
+ "D-0UI0": "Detorid",
+ "L8-WNE": "Detorid",
+ "1-GBVE": "Detorid",
+ "GC-LTF": "Detorid",
+ "NB-ALM": "Detorid",
+ "LT-XI4": "Detorid",
+ "L-QQ6P": "Detorid",
+ "5OJ-G2": "Detorid",
+ "9-02G0": "Detorid",
+ "XA5-TY": "Detorid",
+ "M-XUZZ": "Detorid",
+ "OFVH-Y": "Detorid",
+ "2-X0PF": "Detorid",
+ "1-PGSG": "Detorid",
+ "QLPX-J": "Detorid",
+ "A-C5TC": "Detorid",
+ "RZ-PIY": "Detorid",
+ "FR46-E": "Detorid",
+ "SLVP-D": "Detorid",
+ "0-G8NO": "Detorid",
+ "QRFJ-Q": "Detorid",
+ "HZFJ-M": "Detorid",
+ "77S8-E": "Detorid",
+ "FMH-OV": "Detorid",
+ "TYB-69": "Detorid",
+ "EDQG-L": "Detorid",
+ "7-P1JO": "Detorid",
+ "T-0JWP": "Detorid",
+ "J-L9MA": "Detorid",
+ "DX-TAR": "Detorid",
+ "A-7XFN": "Detorid",
+ "O3-4MN": "Detorid",
+ "U-MFTL": "Detorid",
+ "8FN-GP": "Detorid",
+ "FIDY-8": "Detorid",
+ "X40H-9": "Detorid",
+ "F2W-C6": "Detorid",
+ "KZ9T-C": "Detorid",
+ "XW2H-V": "Detorid",
+ "F9O-U9": "Detorid",
+ "S-51XG": "Detorid",
+ "E-1XVP": "Detorid",
+ "E-ACV6": "Detorid",
+ "BOZ1-O": "Detorid",
+ "QIMO-2": "Detorid",
+ "Z-2Y2Y": "Detorid",
+ "Q0J-RH": "Detorid",
+ "SAI-T9": "Detorid",
+ "IAS-I5": "Detorid",
+ "K7S-FF": "Detorid",
+ "RT-9WL": "Detorid",
+ "O5Q7-U": "Detorid",
+ "62O-UE": "Detorid",
+ "U0W-DR": "Detorid",
+ "SY-UWN": "Detorid",
+ "DX-DFJ": "Detorid",
+ "X-31TE": "Detorid",
+ "DVWV-3": "Detorid",
+ "KE-0FB": "Detorid",
+ "I-9GI1": "Detorid",
+ "W6P-7U": "Detorid",
+ "0IF-26": "Detorid",
+ "H-93YV": "Detorid",
+ "E51-JE": "Detorid",
+ "7-A6XV": "Detorid",
+ "QXE-1N": "Detorid",
+ "U69-YC": "Detorid",
+ "L-L7PE": "Detorid",
+ "MKIG-5": "Wicked Creek",
+ "YHEN-G": "Wicked Creek",
+ "E-JCUS": "Wicked Creek",
+ "W-QN5X": "Wicked Creek",
+ "LP1M-Q": "Wicked Creek",
+ "30-YOU": "Wicked Creek",
+ "384-IN": "Wicked Creek",
+ "4F89-U": "Wicked Creek",
+ "G063-U": "Wicked Creek",
+ "J7-BDX": "Wicked Creek",
+ "MLQ-O9": "Wicked Creek",
+ "L-FM3P": "Wicked Creek",
+ "X-ARMF": "Wicked Creek",
+ "8-OZU1": "Wicked Creek",
+ "0TYR-T": "Wicked Creek",
+ "GM-50Y": "Wicked Creek",
+ "G9L-LP": "Wicked Creek",
+ "MWA-5Q": "Wicked Creek",
+ "H-HHTH": "Wicked Creek",
+ "JQU-KY": "Wicked Creek",
+ "UY5A-D": "Wicked Creek",
+ "C-62I5": "Wicked Creek",
+ "ZH-GKG": "Wicked Creek",
+ "GPLB-C": "Wicked Creek",
+ "GGE-5Q": "Wicked Creek",
+ "5E-CMA": "Wicked Creek",
+ "U104-3": "Wicked Creek",
+ "M3-KAQ": "Wicked Creek",
+ "6-L4YC": "Wicked Creek",
+ "UM-SCG": "Wicked Creek",
+ "F-3FOY": "Wicked Creek",
+ "OAIG-0": "Wicked Creek",
+ "UZ-QXW": "Wicked Creek",
+ "5DE-QS": "Wicked Creek",
+ "R0-DMM": "Wicked Creek",
+ "5Q65-4": "Wicked Creek",
+ "SR-4EK": "Wicked Creek",
+ "0RI-OV": "Wicked Creek",
+ "C-LTXS": "Wicked Creek",
+ "C0O6-K": "Wicked Creek",
+ "HD-AJ7": "Wicked Creek",
+ "G9NE-B": "Wicked Creek",
+ "SJJ-4F": "Wicked Creek",
+ "F-QQ5N": "Wicked Creek",
+ "1-7B6D": "Wicked Creek",
+ "H6-EYX": "Wicked Creek",
+ "U-HVIX": "Wicked Creek",
+ "4-EFLU": "Wicked Creek",
+ "EIH-IU": "Wicked Creek",
+ "F-EM4Q": "Wicked Creek",
+ "1L-OEK": "Wicked Creek",
+ "MN-Q26": "Wicked Creek",
+ "5H-SM2": "Wicked Creek",
+ "4-OS2A": "Wicked Creek",
+ "YI-GV6": "Wicked Creek",
+ "SO-X5L": "Wicked Creek",
+ "XQS-GZ": "Wicked Creek",
+ "Q-GQHN": "Wicked Creek",
+ "A-4JOO": "Wicked Creek",
+ "TP7-KE": "Wicked Creek",
+ "R4N-LD": "Wicked Creek",
+ "3Q-VZA": "Wicked Creek",
+ "M-MBRT": "Wicked Creek",
+ "HPBE-D": "Wicked Creek",
+ "GRHS-B": "Wicked Creek",
+ "J-RXYN": "Wicked Creek",
+ "DUO-51": "Wicked Creek",
+ "07-SLO": "Wicked Creek",
+ "Z-A8FS": "Wicked Creek",
+ "GPD5-0": "Wicked Creek",
+ "LKZ-CY": "Wicked Creek",
+ "F5M-CC": "Wicked Creek",
+ "TZE-UB": "Wicked Creek",
+ "WRL4-2": "Wicked Creek",
+ "V7G-RL": "Wicked Creek",
+ "XEN7-0": "Wicked Creek",
+ "L-Z9KJ": "Wicked Creek",
+ "7K-NSE": "Wicked Creek",
+ "OR-7N5": "Wicked Creek",
+ "JEQG-7": "Wicked Creek",
+ "5NQI-E": "Wicked Creek",
+ "B-WQDP": "Wicked Creek",
+ "2-2EWC": "Cache",
+ "E1W-TB": "Cache",
+ "D-6H64": "Cache",
+ "8-BIE3": "Cache",
+ "LMM7-L": "Cache",
+ "995-3G": "Cache",
+ "W2T-TR": "Cache",
+ "Q-UEN6": "Cache",
+ "BLMX-B": "Cache",
+ "M-CNUD": "Cache",
+ "YE1-9S": "Cache",
+ "IVP-KA": "Cache",
+ "04EI-U": "Cache",
+ "B-T6BT": "Cache",
+ "VK-A5G": "Cache",
+ "I6-SYN": "Cache",
+ "O-5TN1": "Cache",
+ "8-SPNN": "Cache",
+ "U-QMOA": "Cache",
+ "4S0-NP": "Cache",
+ "K-RMI5": "Cache",
+ "C-6YHJ": "Cache",
+ "M53-1V": "Cache",
+ "E5T-CS": "Cache",
+ "W4C8-Q": "Cache",
+ "I-2705": "Cache",
+ "5F-MG1": "Cache",
+ "P7-45V": "Cache",
+ "M-MCP8": "Cache",
+ "JZ-B5Y": "Cache",
+ "TPG-DD": "Cache",
+ "NIF-JE": "Cache",
+ "BTLH-I": "Cache",
+ "U93O-A": "Cache",
+ "0LY-W1": "Cache",
+ "4YO-QK": "Cache",
+ "LJ-RJK": "Cache",
+ "8-VC6H": "Cache",
+ "LQ-01M": "Cache",
+ "NG-M8K": "Cache",
+ "RV5-TT": "Cache",
+ "8OYE-Z": "Cache",
+ "K85Y-6": "Cache",
+ "PKN-NJ": "Cache",
+ "EIN-QG": "Scalding Pass",
+ "ARG-3R": "Scalding Pass",
+ "S-E6ES": "Scalding Pass",
+ "R-3FBU": "Scalding Pass",
+ "K7-LDX": "Scalding Pass",
+ "U-IVGH": "Scalding Pass",
+ "P-N5N9": "Scalding Pass",
+ "JMH-PT": "Scalding Pass",
+ "DE-A7P": "Scalding Pass",
+ "X9V-15": "Scalding Pass",
+ "K212-A": "Scalding Pass",
+ "F-5FDA": "Scalding Pass",
+ "S1-XTL": "Scalding Pass",
+ "9PX2-F": "Scalding Pass",
+ "N3-JBX": "Scalding Pass",
+ "SG-75T": "Scalding Pass",
+ "GN-PDU": "Scalding Pass",
+ "AZ3F-N": "Scalding Pass",
+ "RNM-Y6": "Scalding Pass",
+ "V-KDY2": "Scalding Pass",
+ "FYD-TO": "Scalding Pass",
+ "ER2O-Y": "Scalding Pass",
+ "J2-PZ6": "Scalding Pass",
+ "XV-MWG": "Scalding Pass",
+ "OAQY-M": "Scalding Pass",
+ "1V-LI2": "Scalding Pass",
+ "M9-MLR": "Scalding Pass",
+ "Q-K2T7": "Scalding Pass",
+ "LBC-AW": "Scalding Pass",
+ "2-KPW6": "Scalding Pass",
+ "H5N-V7": "Scalding Pass",
+ "HQ-Q1Q": "Scalding Pass",
+ "WHI-61": "Scalding Pass",
+ "ZFJH-T": "Scalding Pass",
+ "I-1B7X": "Scalding Pass",
+ "G15Z-W": "Scalding Pass",
+ "AH8-Q7": "Scalding Pass",
+ "SD4A-2": "Scalding Pass",
+ "U6K-RG": "Scalding Pass",
+ "V-S9YY": "Scalding Pass",
+ "F2-NXA": "Scalding Pass",
+ "NSBE-L": "Scalding Pass",
+ "8Q-T7B": "Scalding Pass",
+ "WV0D-1": "Scalding Pass",
+ "ZNF-OK": "Scalding Pass",
+ "C8-7AS": "Scalding Pass",
+ "4E-EZS": "Scalding Pass",
+ "A-80UA": "Scalding Pass",
+ "U2-28D": "Scalding Pass",
+ "LQ-OAI": "Scalding Pass",
+ "5-MQQ7": "Scalding Pass",
+ "6-EQYE": "Scalding Pass",
+ "03-OR2": "Scalding Pass",
+ "JLO-Z3": "Scalding Pass",
+ "IAK-JW": "Scalding Pass",
+ "KZFV-4": "Scalding Pass",
+ "WO-GC0": "Scalding Pass",
+ "RYC-19": "Scalding Pass",
+ "X2-ZA5": "Scalding Pass",
+ "28Y9-P": "Scalding Pass",
+ "Q4C-S5": "Scalding Pass",
+ "B-1UJC": "Scalding Pass",
+ "Q-NA5H": "Scalding Pass",
+ "4-CM8I": "Scalding Pass",
+ "ZDB-HT": "Scalding Pass",
+ "1QZ-Y9": "Scalding Pass",
+ "HJ-BCH": "Scalding Pass",
+ "QPTT-F": "Scalding Pass",
+ "9M-M0P": "Scalding Pass",
+ "9BC-EB": "Scalding Pass",
+ "WFFE-4": "Scalding Pass",
+ "71-UTX": "Scalding Pass",
+ "PU-UMM": "Scalding Pass",
+ "6-KPAB": "Scalding Pass",
+ "Y5-E1U": "Scalding Pass",
+ "4-43BW": "Scalding Pass",
+ "8CN-CH": "Scalding Pass",
+ "V-F6DQ": "Scalding Pass",
+ "3S-6VU": "Scalding Pass",
+ "1-7HVI": "Scalding Pass",
+ "OX-S7P": "Scalding Pass",
+ "KDG-TA": "Insmother",
+ "KD-KPR": "Insmother",
+ "PT-21C": "Insmother",
+ "Z182-R": "Insmother",
+ "EKPB-3": "Insmother",
+ "5M2-KP": "Insmother",
+ "TK-DLH": "Insmother",
+ "C8H5-X": "Insmother",
+ "O-7LAI": "Insmother",
+ "7L3-JS": "Insmother",
+ "WF4C-8": "Insmother",
+ "TZN-2V": "Insmother",
+ "8EF-58": "Insmother",
+ "4DS-OI": "Insmother",
+ "XQP-9C": "Insmother",
+ "W-6GBI": "Insmother",
+ "XKH-6O": "Insmother",
+ "S0U-MO": "Insmother",
+ "F39H-1": "Insmother",
+ "V-QXXK": "Insmother",
+ "2-Q4YG": "Insmother",
+ "2JT-3Q": "Insmother",
+ "I3CR-F": "Insmother",
+ "7-JT09": "Insmother",
+ "AGCP-I": "Insmother",
+ "M4-GJ6": "Insmother",
+ "5-2PQU": "Insmother",
+ "SN9-3Z": "Insmother",
+ "6BJH-3": "Insmother",
+ "U-UTU9": "Insmother",
+ "1TG7-W": "Insmother",
+ "QYD-WK": "Insmother",
+ "R959-U": "Insmother",
+ "A-TJ0G": "Insmother",
+ "88A-RA": "Insmother",
+ "8G-2FP": "Insmother",
+ "C-J6MT": "Insmother",
+ "78-0R6": "Insmother",
+ "MSG-BZ": "Insmother",
+ "8-WYQZ": "Insmother",
+ "4M-QXK": "Insmother",
+ "X5-0EM": "Insmother",
+ "G-EURJ": "Insmother",
+ "SHBF-V": "Insmother",
+ "RERZ-L": "Insmother",
+ "0UBC-R": "Insmother",
+ "3U-48K": "Insmother",
+ "EFM-C4": "Insmother",
+ "YPW-M4": "Insmother",
+ "Q7-FZ8": "Insmother",
+ "L5-UWT": "Insmother",
+ "74-VZA": "Insmother",
+ "I-1QKL": "Insmother",
+ "GK5Z-T": "Insmother",
+ "RQN-OO": "Insmother",
+ "67Y-NR": "Insmother",
+ "GDHN-K": "Insmother",
+ "QTME-D": "Insmother",
+ "A24L-V": "Insmother",
+ "4CJ-AC": "Insmother",
+ "EUU-4N": "Insmother",
+ "Q-3HS5": "Insmother",
+ "3AE-CP": "Insmother",
+ "0-VG7A": "Insmother",
+ "9OLQ-6": "Insmother",
+ "MOCW-2": "Insmother",
+ "ZO-4AR": "Insmother",
+ "MJ-LGH": "Insmother",
+ "F2A-GX": "Insmother",
+ "RD-FWY": "Insmother",
+ "VBPT-T": "Insmother",
+ "KS-1TS": "Insmother",
+ "X0-6LH": "Insmother",
+ "FN0-QS": "Insmother",
+ "F3-8X2": "Insmother",
+ "N7-BIY": "Insmother",
+ "TTP-2B": "Insmother",
+ "LVL-GZ": "Insmother",
+ "EJ48-O": "Insmother",
+ "ROJ-B0": "Insmother",
+ "DFH-V5": "Insmother",
+ "B-II34": "Insmother",
+ "4LB-EL": "Insmother",
+ "UDE-FX": "Insmother",
+ "5IH-GL": "Insmother",
+ "C1G-XC": "Insmother",
+ "04-EHC": "Insmother",
+ "3-0FYP": "Insmother",
+ "N-O53U": "Insmother",
+ "HZ-O18": "Insmother",
+ "D-P1EH": "Insmother",
+ "74L2-U": "Insmother",
+ "HL-VZX": "Insmother",
+ "38NZ-1": "Insmother",
+ "W-MF6J": "Insmother",
+ "O-9G5Y": "Insmother",
+ "27-HP0": "Insmother",
+ "X1-IZ0": "Insmother",
+ "RZ-TI6": "Insmother",
+ "FX4L-2": "Insmother",
+ "1ZF-PJ": "Insmother",
+ "HFC-AQ": "Insmother",
+ "0-6VZ5": "Insmother",
+ "GB-6X5": "Insmother",
+ "7EX-14": "Insmother",
+ "N7-KGJ": "Insmother",
+ "VD-8QY": "Insmother",
+ "J-ZYSZ": "Insmother",
+ "5C-RPA": "Insmother",
+ "CR2-PQ": "Insmother",
+ "E-OGL4": "Tribute",
+ "J-GAMP": "Tribute",
+ "M-OEE8": "Tribute",
+ "V0DF-2": "Tribute",
+ "FY0W-N": "Tribute",
+ "MJI3-8": "Tribute",
+ "A-DDGY": "Tribute",
+ "F-RT6Q": "Tribute",
+ "B-S42H": "Tribute",
+ "NL6V-7": "Tribute",
+ "F-749O": "Tribute",
+ "0-YMBJ": "Tribute",
+ "UMI-KK": "Tribute",
+ "GKP-YT": "Tribute",
+ "AW1-2I": "Tribute",
+ "15W-GC": "Tribute",
+ "N-FK87": "Tribute",
+ "C2X-M5": "Tribute",
+ "MSHD-4": "Tribute",
+ "H-W9TY": "Tribute",
+ "PNDN-V": "Tribute",
+ "D7-ZAC": "Tribute",
+ "SH1-6P": "Tribute",
+ "TRKN-L": "Tribute",
+ "O-0ERG": "Tribute",
+ "WH-JCA": "Tribute",
+ "Q-CAB2": "Tribute",
+ "PBD-0G": "Tribute",
+ "L-1HKR": "Tribute",
+ "9GI-FB": "Tribute",
+ "3G-LHB": "Tribute",
+ "DBT-GB": "Tribute",
+ "U-W3WS": "Tribute",
+ "DL1C-E": "Tribute",
+ "YLS8-J": "Tribute",
+ "2ISU-Y": "Tribute",
+ "X-CFN6": "Tribute",
+ "9SL-K9": "Tribute",
+ "Y-PZHM": "Tribute",
+ "OY-UZ1": "Tribute",
+ "S8-NSQ": "Tribute",
+ "GIH-ZG": "Tribute",
+ "V7-FB4": "Tribute",
+ "XD-TOV": "Tribute",
+ "K-6SNI": "Tribute",
+ "L-VXTK": "Tribute",
+ "C8VC-S": "Tribute",
+ "W-UQA5": "Tribute",
+ "W6VP-Y": "Tribute",
+ "IMK-K1": "Tribute",
+ "NJ4X-S": "Tribute",
+ "F-G7BO": "Tribute",
+ "2CG-5V": "Tribute",
+ "QFF-O6": "Tribute",
+ "NIH-02": "Great Wildlands",
+ "JPL-RA": "Great Wildlands",
+ "NK-7XO": "Great Wildlands",
+ "E02-IK": "Great Wildlands",
+ "N-DQ0D": "Great Wildlands",
+ "M-MD3B": "Great Wildlands",
+ "FVXK-D": "Great Wildlands",
+ "6EG7-R": "Great Wildlands",
+ "56D-TC": "Great Wildlands",
+ "2X7Z-L": "Great Wildlands",
+ "8DL-CP": "Great Wildlands",
+ "UMDQ-6": "Great Wildlands",
+ "504Z-V": "Great Wildlands",
+ "F8K-WQ": "Great Wildlands",
+ "AB-FZE": "Great Wildlands",
+ "N-6Z8B": "Great Wildlands",
+ "YUY-LM": "Great Wildlands",
+ "NE-3GR": "Great Wildlands",
+ "Y4-GQV": "Great Wildlands",
+ "7-IDWY": "Great Wildlands",
+ "AZF-GH": "Great Wildlands",
+ "UT-UZB": "Great Wildlands",
+ "M-EKDF": "Great Wildlands",
+ "CRXA-Y": "Great Wildlands",
+ "VXO-OM": "Great Wildlands",
+ "BY5-V8": "Great Wildlands",
+ "TET3-B": "Great Wildlands",
+ "VKU-BG": "Great Wildlands",
+ "WPR-EI": "Great Wildlands",
+ "0NV-YU": "Great Wildlands",
+ "V-2GYS": "Great Wildlands",
+ "168-6H": "Great Wildlands",
+ "W-RFUO": "Great Wildlands",
+ "AI-EVH": "Great Wildlands",
+ "F-MKH3": "Great Wildlands",
+ "ZM-DNR": "Great Wildlands",
+ "GF-3FL": "Great Wildlands",
+ "ZJ-GOU": "Great Wildlands",
+ "QQ3-YI": "Great Wildlands",
+ "9-34L5": "Great Wildlands",
+ "0R-GZQ": "Great Wildlands",
+ "QM-20X": "Great Wildlands",
+ "8YC-AN": "Great Wildlands",
+ "7Q-8Z2": "Great Wildlands",
+ "SUR-F7": "Great Wildlands",
+ "OK-6XN": "Great Wildlands",
+ "Q2FL-T": "Great Wildlands",
+ "Y7-XFD": "Great Wildlands",
+ "U3K-4A": "Great Wildlands",
+ "P1T-LP": "Great Wildlands",
+ "R-ESG0": "Great Wildlands",
+ "CI4M-T": "Great Wildlands",
+ "I-QRJA": "Great Wildlands",
+ "M-YWAL": "Great Wildlands",
+ "DE71-9": "Great Wildlands",
+ "7JF-0Z": "Great Wildlands",
+ "IX8-JB": "Great Wildlands",
+ "WTIE-6": "Great Wildlands",
+ "Y-DSSK": "Great Wildlands",
+ "F5-CGW": "Great Wildlands",
+ "H9S-WC": "Great Wildlands",
+ "B-ROFP": "Great Wildlands",
+ "1L-AED": "Great Wildlands",
+ "1C-953": "Great Wildlands",
+ "SL-YBS": "Great Wildlands",
+ "UNJ-GX": "Great Wildlands",
+ "0PI4-E": "Great Wildlands",
+ "6WT-BE": "Great Wildlands",
+ "L1S-G1": "Great Wildlands",
+ "9SNK-O": "Great Wildlands",
+ "B-VIP9": "Great Wildlands",
+ "LXTC-S": "Great Wildlands",
+ "WE3-BX": "Great Wildlands",
+ "H7O-JZ": "Great Wildlands",
+ "H-8F5Q": "Great Wildlands",
+ "O-RXCZ": "Great Wildlands",
+ "4M-P1I": "Great Wildlands",
+ "P7UZ-T": "Great Wildlands",
+ "PUZ-IO": "Great Wildlands",
+ "HB-1NJ": "Great Wildlands",
+ "EOE3-N": "Great Wildlands",
+ "F7A-MR": "Great Wildlands",
+ "O-8SOC": "Great Wildlands",
+ "OJOS-T": "Great Wildlands",
+ "V89M-R": "Great Wildlands",
+ "66U-1P": "Great Wildlands",
+ "BRT-OP": "Great Wildlands",
+ "JUK0-1": "Great Wildlands",
+ "V-IH6B": "Great Wildlands",
+ "52V6-B": "Great Wildlands",
+ "PUC-JZ": "Great Wildlands",
+ "SB-23C": "Great Wildlands",
+ "5FCV-A": "Great Wildlands",
+ "O-OVOQ": "Great Wildlands",
+ "92-B0X": "Great Wildlands",
+ "0-3VW8": "Great Wildlands",
+ "28-QWU": "Great Wildlands",
+ "UD-AOK": "Great Wildlands",
+ "M9U-75": "Great Wildlands",
+ "N-RAEL": "Great Wildlands",
+ "K-IYNW": "Great Wildlands",
+ "H-ADOC": "Curse",
+ "G-G78S": "Curse",
+ "UW9B-F": "Curse",
+ "ZZ-ZWC": "Curse",
+ "OSY-UD": "Curse",
+ "K-MGJ7": "Curse",
+ "JWJ-P1": "Curse",
+ "V-IUEL": "Curse",
+ "0SHT-A": "Curse",
+ "D87E-A": "Curse",
+ "K-B2D3": "Curse",
+ "PO4F-3": "Curse",
+ "J7A-UR": "Curse",
+ "5E-VR8": "Curse",
+ "V7D-JD": "Curse",
+ "HLW-HP": "Curse",
+ "8G-MQV": "Curse",
+ "RA-NXN": "Curse",
+ "VOL-MI": "Curse",
+ "KLMT-W": "Curse",
+ "XX9-WV": "Curse",
+ "AAM-1A": "Curse",
+ "EW-JR5": "Curse",
+ "YKE4-3": "Curse",
+ "CL-85V": "Curse",
+ "K-QWHE": "Curse",
+ "MDD-79": "Curse",
+ "RMOC-W": "Curse",
+ "ES-UWY": "Curse",
+ "S1DP-Y": "Curse",
+ "Y-DW5K": "Curse",
+ "M-N7WD": "Curse",
+ "QFEW-K": "Curse",
+ "CVY-UC": "Curse",
+ "EQX-AE": "Curse",
+ "G-R4W1": "Curse",
+ "BPK-XK": "Curse",
+ "LJ-YSW": "Curse",
+ "Y-K50G": "Curse",
+ "K88X-J": "Curse",
+ "G-0Q86": "Curse",
+ "CL-1JE": "Curse",
+ "J4UD-J": "Curse",
+ "Hemin": "Curse",
+ "Utopia": "Curse",
+ "Jorund": "Curse",
+ "Doril": "Curse",
+ "Litom": "Curse",
+ "Farit": "Curse",
+ "Jamunda": "Curse",
+ "TD-4XL": "Malpais",
+ "IBOX-2": "Malpais",
+ "8AB-Q4": "Malpais",
+ "VW-PXL": "Malpais",
+ "JA-G0T": "Malpais",
+ "IF-KD1": "Malpais",
+ "7-YHRX": "Malpais",
+ "Y6-9LF": "Malpais",
+ "X-PQEX": "Malpais",
+ "N-H95C": "Malpais",
+ "NSI-MW": "Malpais",
+ "N-YLOE": "Malpais",
+ "NBO-O0": "Malpais",
+ "F-TQWO": "Malpais",
+ "0-TRV1": "Malpais",
+ "13-49W": "Malpais",
+ "6UT-1K": "Malpais",
+ "O8W-5O": "Malpais",
+ "LH-PLU": "Malpais",
+ "AZA-QE": "Malpais",
+ "8-2JZA": "Malpais",
+ "ZT-L3S": "Malpais",
+ "VVB-QH": "Malpais",
+ "Z-DDVJ": "Malpais",
+ "7-2Z93": "Malpais",
+ "B-VFDD": "Malpais",
+ "A0M-R8": "Malpais",
+ "LY-WRW": "Malpais",
+ "9F-ERQ": "Malpais",
+ "QCGG-Q": "Malpais",
+ "1NZV-7": "Malpais",
+ "NIM-FY": "Malpais",
+ "DAI-SH": "Malpais",
+ "V3P-AZ": "Malpais",
+ "C-KW6X": "Malpais",
+ "X1W-AL": "Malpais",
+ "F-WZYG": "Malpais",
+ "S-R9J2": "Malpais",
+ "XU-BF8": "Malpais",
+ "RIU-GC": "Malpais",
+ "Z0H2-4": "Malpais",
+ "63-7Q6": "Malpais",
+ "XCZ5-Y": "Malpais",
+ "NRD-5Q": "Malpais",
+ "W5-205": "Malpais",
+ "T-4H0B": "Malpais",
+ "Z-EKCY": "Malpais",
+ "SH-YZY": "Malpais",
+ "O7-RFZ": "Malpais",
+ "CLW-SI": "Malpais",
+ "5-A0PX": "Malpais",
+ "R-RMDH": "Malpais",
+ "2XI8-Y": "Malpais",
+ "5B-YDD": "Malpais",
+ "W-XY4J": "Malpais",
+ "PWPY-4": "Malpais",
+ "QZ1-OH": "Malpais",
+ "Y-XZA7": "Malpais",
+ "1-EVAX": "Malpais",
+ "I8-AJY": "Malpais",
+ "6-WMKE": "Malpais",
+ "J-Z8C2": "Malpais",
+ "XTVZ-E": "Malpais",
+ "APES-G": "Malpais",
+ "B2J-5N": "Malpais",
+ "2Z-HPQ": "Malpais",
+ "NBW-GD": "Malpais",
+ "YM-SRU": "Malpais",
+ "LO5-LN": "Malpais",
+ "06-70G": "Malpais",
+ "UYG-YX": "Malpais",
+ "GL6S-2": "Malpais",
+ "RUF3-O": "Malpais",
+ "C-NMG9": "Malpais",
+ "P3X-TN": "Malpais",
+ "N6NK-J": "Malpais",
+ "TP-APY": "Malpais",
+ "9NI-FW": "Malpais",
+ "H-EBQG": "Malpais",
+ "DOA-YU": "Malpais",
+ "ZOPZ-6": "Malpais",
+ "863P-X": "Malpais",
+ "ZO-YJZ": "Malpais",
+ "6A-FUY": "Malpais",
+ "HG-YEQ": "Malpais",
+ "2FL-5W": "Malpais",
+ "QSCO-D": "Malpais",
+ "RXTY-4": "Malpais",
+ "RSE-PT": "Malpais",
+ "WVJU-4": "Malpais",
+ "7T-0QS": "Malpais",
+ "RWML-A": "Malpais",
+ "V-JCJS": "Malpais",
+ "8C-VE3": "Malpais",
+ "S5W-1Z": "Malpais",
+ "IL-OL1": "Malpais",
+ "POQP-K": "Malpais",
+ "FO9-FZ": "Malpais",
+ "4QY-NT": "Malpais",
+ "0-N1BJ": "Malpais",
+ "T-8GWA": "Malpais",
+ "UW-6MW": "Malpais",
+ "F9E-KX": "Catch",
+ "9KOE-A": "Catch",
+ "U-QVWD": "Catch",
+ "B-3QPD": "Catch",
+ "36N-HZ": "Catch",
+ "SV5-8N": "Catch",
+ "HY-RWO": "Catch",
+ "WD-VTV": "Catch",
+ "HED-GP": "Catch",
+ "V-3YG7": "Catch",
+ "QSM-LM": "Catch",
+ "KDF-GY": "Catch",
+ "QBQ-RF": "Catch",
+ "9-8GBA": "Catch",
+ "6-K738": "Catch",
+ "ZXIC-7": "Catch",
+ "2J-WJY": "Catch",
+ "1P-WGB": "Catch",
+ "F4R2-Q": "Catch",
+ "K0CN-3": "Catch",
+ "WLAR-J": "Catch",
+ "L7XS-5": "Catch",
+ "VA6-DR": "Catch",
+ "S-U2VD": "Catch",
+ "GE-94X": "Catch",
+ "GMLH-K": "Catch",
+ "W9-DID": "Catch",
+ "KW-I6T": "Catch",
+ "EX-0LQ": "Catch",
+ "MB-NKE": "Catch",
+ "G-7WUF": "Catch",
+ "6-MM99": "Catch",
+ "JBY6-F": "Catch",
+ "FZ-6A5": "Catch",
+ "RNF-YH": "Catch",
+ "I-8D0G": "Catch",
+ "R-K4QY": "Catch",
+ "JWZ2-V": "Catch",
+ "OGL8-Q": "Catch",
+ "GJ0-OJ": "Catch",
+ "A-803L": "Catch",
+ "WQH-4K": "Catch",
+ "J-ODE7": "Catch",
+ "Q-S7ZD": "Catch",
+ "6X7-JO": "Catch",
+ "GE-8JV": "Catch",
+ "3-OKDA": "Catch",
+ "3GD6-8": "Catch",
+ "4M-HGL": "Catch",
+ "MY-W1V": "Catch",
+ "AX-DOT": "Catch",
+ "YHN-3K": "Catch",
+ "CB4-Q2": "Catch",
+ "CBL-XP": "Catch",
+ "WJ-9YO": "Catch",
+ "UQ-PWD": "Catch",
+ "N-8BZ6": "Catch",
+ "A-VILQ": "Catch",
+ "X3FQ-W": "Catch",
+ "3-SFWG": "Catch",
+ "MUXX-4": "Catch",
+ "E1-4YH": "Catch",
+ "B-XJX4": "Catch",
+ "AOK-WQ": "Catch",
+ "E3-SDZ": "Catch",
+ "7LHB-Z": "Catch",
+ "8B-2YA": "Catch",
+ "SNFV-I": "Catch",
+ "HP-64T": "Catch",
+ "V2-VC2": "Catch",
+ "L-B55M": "Catch",
+ "CX65-5": "Catch",
+ "JA-O6J": "Catch",
+ "ZQ-Z3Y": "Catch",
+ "G-AOTH": "Catch",
+ "TA3T-3": "Catch",
+ "E-YJ8G": "Catch",
+ "J6QB-P": "Catch",
+ "KA6D-K": "Catch",
+ "7MD-S1": "Catch",
+ "ERVK-P": "Catch",
+ "UL-7I8": "Catch",
+ "BR-N97": "Catch",
+ "IS-R7P": "Catch",
+ "S25C-K": "Catch",
+ "K717-8": "Catch",
+ "NH-1X6": "Catch",
+ "KH0Z-0": "Catch",
+ "5-N2EY": "Catch",
+ "KB-U56": "Catch",
+ "JGW-OT": "Catch",
+ "UCG4-B": "Catch",
+ "BUZ-DB": "Catch",
+ "QETZ-W": "Catch",
+ "WFC-MY": "Catch",
+ "Q-U96U": "Catch",
+ "X4-WL0": "Catch",
+ "W-MPTH": "Catch",
+ "4NBN-9": "Catch",
+ "EX6-AO": "Catch",
+ "CZK-ZQ": "Catch",
+ "CNC-4V": "Catch",
+ "Y-PNRL": "Catch",
+ "FAT-6P": "Catch",
+ "6BPS-T": "Catch",
+ "25S-6P": "Catch",
+ "RR-D05": "Catch",
+ "4-07MU": "Catch",
+ "Y-W1Q3": "Venal",
+ "Y6-HPG": "Venal",
+ "Z-GY5S": "Venal",
+ "KK-L97": "Venal",
+ "R-KZK7": "Venal",
+ "9-R6GU": "Venal",
+ "N-Q5PW": "Venal",
+ "P-FSQE": "Venal",
+ "H-PA29": "Venal",
+ "1-Y6KI": "Venal",
+ "YP-J33": "Venal",
+ "D-8SI1": "Venal",
+ "9-266Q": "Venal",
+ "K3JR-J": "Venal",
+ "CSOA-B": "Venal",
+ "6W-HRH": "Venal",
+ "N5Y-4N": "Venal",
+ "MQFX-Q": "Venal",
+ "9-8BL8": "Venal",
+ "N6G-H3": "Venal",
+ "3A1P-N": "Venal",
+ "OZ-VAE": "Venal",
+ "A-AFGR": "Venal",
+ "92K-H2": "Venal",
+ "AA-YRK": "Venal",
+ "BV-1JG": "Venal",
+ "0-BFTQ": "Venal",
+ "SS-GED": "Venal",
+ "AJCJ-1": "Venal",
+ "6NJ8-V": "Venal",
+ "Y-4CFK": "Venal",
+ "HBD-CC": "Venal",
+ "P-GKF5": "Venal",
+ "E-7U8U": "Venal",
+ "0-XIDJ": "Venal",
+ "SBL5-R": "Venal",
+ "O-TVTD": "Venal",
+ "8CIX-S": "Venal",
+ "D-SKWC": "Venal",
+ "4RX-EE": "Venal",
+ "V3X-L8": "Venal",
+ "N0C-UN": "Venal",
+ "VG-6CH": "Venal",
+ "Z0-TJW": "Venal",
+ "QHJ-FW": "Venal",
+ "9IPC-E": "Venal",
+ "EIV-1W": "Venal",
+ "S-1ZXZ": "Venal",
+ "N-5476": "Venal",
+ "PZOZ-K": "Venal",
+ "W3KK-R": "Venal",
+ "92D-OI": "Venal",
+ "EK2-ET": "Venal",
+ "SE-SHZ": "Venal",
+ "JURU-T": "Venal",
+ "MC6-5J": "Venal",
+ "65V-RH": "Venal",
+ "4-7IL9": "Venal",
+ "2PLH-3": "Venal",
+ "RQ9-OZ": "Venal",
+ "B-CZXG": "Venal",
+ "0-O2UT": "Venal",
+ "Q61Y-F": "Venal",
+ "PF-QHK": "Venal",
+ "XW-6TC": "Venal",
+ "Q-7SUI": "Venal",
+ "VVD-O6": "Venal",
+ "6ZJ-SC": "Venal",
+ "P-VYVL": "Venal",
+ "HD-JVQ": "Venal",
+ "H-AJ27": "Venal",
+ "M2-2V1": "Venal",
+ "2TH-3F": "Venal",
+ "E1F-E5": "Venal",
+ "4S-PVC": "Venal",
+ "WLF-D3": "Venal",
+ "LHJ-2G": "Venal",
+ "SHJO-J": "Venal",
+ "6UQ-4U": "Venal",
+ "430-BE": "Venal",
+ "OJ-CT4": "Venal",
+ "AZ-UWB": "Venal",
+ "H-S5BM": "Venal",
+ "FHB-QA": "Venal",
+ "Z3U-GI": "Venal",
+ "B3QP-K": "Venal",
+ "GVZ-1W": "Venal",
+ "G9D-XW": "Venal",
+ "42XJ-N": "Venal",
+ "L-IE41": "Venal",
+ "VG-QW1": "Venal",
+ "2IBE-N": "Venal",
+ "YJ3-UT": "Venal",
+ "ZD4-G9": "Venal",
+ "C2-DDA": "Venal",
+ "Dantumi": "Lonetrek",
+ "Antiainen": "Lonetrek",
+ "Ossa": "Lonetrek",
+ "Semiki": "Lonetrek",
+ "Kiskoken": "Lonetrek",
+ "Aurohunen": "Lonetrek",
+ "Veisto": "Lonetrek",
+ "Sobaseki": "Lonetrek",
+ "Funtanainen": "Lonetrek",
+ "Isikemi": "Lonetrek",
+ "Uosusuokko": "Lonetrek",
+ "Hageken": "Lonetrek",
+ "Uemisaisen": "Lonetrek",
+ "Sotrentaira": "Lonetrek",
+ "Ouranienen": "Lonetrek",
+ "Erenta": "Lonetrek",
+ "Kino": "Lonetrek",
+ "Raussinen": "Lonetrek",
+ "Iidoken": "Lonetrek",
+ "Tsuguwa": "Lonetrek",
+ "Nourvukaiken": "Lonetrek",
+ "Sarekuwa": "Lonetrek",
+ "Ekura": "Lonetrek",
+ "Tunttaras": "Lonetrek",
+ "Vellaine": "Lonetrek",
+ "Arvasaras": "Lonetrek",
+ "Akonoinen": "Lonetrek",
+ "Vaajaita": "Lonetrek",
+ "Autaris": "Lonetrek",
+ "Jan": "Lonetrek",
+ "Saatuban": "Lonetrek",
+ "Isikano": "Lonetrek",
+ "Mara": "Lonetrek",
+ "Isanamo": "Lonetrek",
+ "Pakkonen": "Lonetrek",
+ "Piekura": "Lonetrek",
+ "Amsen": "Lonetrek",
+ "Malkalen": "Lonetrek",
+ "Korama": "Lonetrek",
+ "Ylandoki": "Lonetrek",
+ "Aakari": "Lonetrek",
+ "Isseras": "Lonetrek",
+ "Aunenen": "Lonetrek",
+ "Elonaya": "Lonetrek",
+ "Litiura": "Lonetrek",
+ "Nonni": "Lonetrek",
+ "Passari": "Lonetrek",
+ "Piak": "Lonetrek",
+ "Airkio": "Lonetrek",
+ "Kakakela": "Lonetrek",
+ "Kamokor": "Lonetrek",
+ "Todaki": "Lonetrek",
+ "Ruvas": "Lonetrek",
+ "Umokka": "Lonetrek",
+ "Kirras": "Lonetrek",
+ "Autama": "Lonetrek",
+ "Tsukuras": "Lonetrek",
+ "Nani": "Lonetrek",
+ "Ajanen": "Lonetrek",
+ "Kuoka": "Lonetrek",
+ "Liukikka": "Lonetrek",
+ "Rauntaka": "Lonetrek",
+ "Aikantoh": "Lonetrek",
+ "Atai": "Lonetrek",
+ "Daras": "Lonetrek",
+ "Otalieto": "Lonetrek",
+ "Iitanmadan": "Lonetrek",
+ "Jotenen": "Lonetrek",
+ "Haajinen": "Lonetrek",
+ "Oipo": "Lonetrek",
+ "Isinokka": "Lonetrek",
+ "Yoma": "Lonetrek",
+ "Ibura": "Lonetrek",
+ "Torrinos": "Lonetrek",
+ "Endatoh": "Lonetrek",
+ "Aivoli": "Lonetrek",
+ "Uesuro": "Lonetrek",
+ "Oishami": "Lonetrek",
+ "Elanoda": "Lonetrek",
+ "Ohbochi": "Lonetrek",
+ "Isie": "Lonetrek",
+ "Tamo": "Lonetrek",
+ "Nannaras": "Lonetrek",
+ "Anin": "Lonetrek",
+ "Karjataimon": "Lonetrek",
+ "Tartoken": "Lonetrek",
+ "Saranen": "Lonetrek",
+ "Vuorrassi": "Lonetrek",
+ "Oimmo": "Lonetrek",
+ "Nalvula": "Lonetrek",
+ "Otsasai": "Lonetrek",
+ "Taisy": "Lonetrek",
+ "Hakonen": "Lonetrek",
+ "Jouvulen": "Lonetrek",
+ "Akiainavas": "Lonetrek",
+ "Kappas": "Lonetrek",
+ "Hitanishio": "Lonetrek",
+ "Ichinumi": "Lonetrek",
+ "PZP1-D": "J7HZ-F",
+ "R1KE-A": "J7HZ-F",
+ "JGDF-B": "J7HZ-F",
+ "1SR-HT": "J7HZ-F",
+ "SQ-2XA": "J7HZ-F",
+ "Z-FYJR": "J7HZ-F",
+ "ZA6-9N": "J7HZ-F",
+ "J1-6CJ": "J7HZ-F",
+ "7H-Z5R": "J7HZ-F",
+ "0RZ5-2": "J7HZ-F",
+ "A9-NB6": "J7HZ-F",
+ "LG1-TA": "J7HZ-F",
+ "TNK-BQ": "J7HZ-F",
+ "E2AX-5": "J7HZ-F",
+ "HPE-KP": "J7HZ-F",
+ "THS-MN": "J7HZ-F",
+ "UBES-K": "J7HZ-F",
+ "I-R8B0": "J7HZ-F",
+ "QIW-TQ": "J7HZ-F",
+ "WLL-QX": "J7HZ-F",
+ "BJC4-8": "J7HZ-F",
+ "PQA-9K": "J7HZ-F",
+ "S5-U0R": "J7HZ-F",
+ "CW-R71": "J7HZ-F",
+ "QO-3LC": "J7HZ-F",
+ "3E-ER7": "J7HZ-F",
+ "REZ-YZ": "J7HZ-F",
+ "OU-AIT": "J7HZ-F",
+ "VYX2-I": "J7HZ-F",
+ "5-P3CQ": "J7HZ-F",
+ "M-FDTD": "J7HZ-F",
+ "54-VNO": "J7HZ-F",
+ "IAMZ-5": "J7HZ-F",
+ "HD3-JK": "J7HZ-F",
+ "PBXG-A": "J7HZ-F",
+ "9-ERCP": "J7HZ-F",
+ "KN7M-N": "J7HZ-F",
+ "Z-D1DW": "J7HZ-F",
+ "FO-3PJ": "J7HZ-F",
+ "6-QXE6": "J7HZ-F",
+ "N-FKXV": "J7HZ-F",
+ "X7-8IG": "J7HZ-F",
+ "R-G1SF": "J7HZ-F",
+ "6-NCE7": "J7HZ-F",
+ "WDJQ-G": "J7HZ-F",
+ "JS3-RS": "J7HZ-F",
+ "JX-T1W": "J7HZ-F",
+ "CZ-CED": "J7HZ-F",
+ "BKK4-H": "J7HZ-F",
+ "Y-4V7U": "J7HZ-F",
+ "L-TPN0": "J7HZ-F",
+ "3-XORH": "J7HZ-F",
+ "G1VU-H": "J7HZ-F",
+ "W6H6-K": "J7HZ-F",
+ "6-23NU": "J7HZ-F",
+ "DVAR-P": "J7HZ-F",
+ "J-JS0D": "J7HZ-F",
+ "VR3-PS": "J7HZ-F",
+ "LH-J8H": "J7HZ-F",
+ "I9D-0D": "J7HZ-F",
+ "HGB-C6": "J7HZ-F",
+ "2L5-FI": "J7HZ-F",
+ "RS08-B": "J7HZ-F",
+ "4U-14I": "J7HZ-F",
+ "H-EDXD": "J7HZ-F",
+ "8-ULAA": "J7HZ-F",
+ "KF1-DU": "J7HZ-F",
+ "W-WQM5": "J7HZ-F",
+ "G5J-LH": "J7HZ-F",
+ "H7OL-I": "J7HZ-F",
+ "TO21-U": "J7HZ-F",
+ "RN-5K9": "J7HZ-F",
+ "0M-M64": "J7HZ-F",
+ "W5-SGC": "J7HZ-F",
+ "8RV-1L": "J7HZ-F",
+ "1C-TD6": "J7HZ-F",
+ "YBYX-1": "J7HZ-F",
+ "L-WG68": "The Spire",
+ "E4-E8W": "The Spire",
+ "HIK-MC": "The Spire",
+ "B9EA-G": "The Spire",
+ "E-BFLT": "The Spire",
+ "GZM-KB": "The Spire",
+ "5LAJ-8": "The Spire",
+ "C6C-K9": "The Spire",
+ "AL-JSG": "The Spire",
+ "ETO-OT": "The Spire",
+ "KPI-OW": "The Spire",
+ "A-J6SN": "The Spire",
+ "OTJ-4W": "The Spire",
+ "AG-SYG": "The Spire",
+ "1I5-0V": "The Spire",
+ "VX1-HV": "The Spire",
+ "JNG7-K": "The Spire",
+ "K-XJJT": "The Spire",
+ "FO1U-K": "The Spire",
+ "6U-1RX": "The Spire",
+ "Y4OK-W": "The Spire",
+ "P-NI4K": "The Spire",
+ "T6T-BQ": "The Spire",
+ "N-PS2Y": "The Spire",
+ "K-BBYU": "The Spire",
+ "0J-MQW": "The Spire",
+ "XT-1E0": "The Spire",
+ "3ET-G8": "The Spire",
+ "MOSA-I": "The Spire",
+ "B6-XE8": "The Spire",
+ "JLH-FN": "The Spire",
+ "DFTK-D": "The Spire",
+ "4HF-4R": "The Spire",
+ "Y8K-5B": "The Spire",
+ "L7-BLT": "The Spire",
+ "8P-LKL": "The Spire",
+ "Q-UVY6": "The Spire",
+ "RXA-W1": "The Spire",
+ "QFU-4S": "The Spire",
+ "QQGH-G": "The Spire",
+ "VK6-EZ": "The Spire",
+ "JVA-FE": "The Spire",
+ "P65-TA": "The Spire",
+ "G-VFVB": "The Spire",
+ "Y4B-BQ": "The Spire",
+ "EU-WFW": "The Spire",
+ "K-YL9T": "The Spire",
+ "GTB-O4": "The Spire",
+ "6W-6O9": "The Spire",
+ "H4X-0I": "The Spire",
+ "C-BHDN": "The Spire",
+ "R-RE2B": "The Spire",
+ "4DH-ST": "The Spire",
+ "OSW-0P": "The Spire",
+ "GF-GR7": "The Spire",
+ "DVN6-0": "The Spire",
+ "Z19-B8": "The Spire",
+ "HPMN-V": "The Spire",
+ "XR-ZL7": "The Spire",
+ "U1-VHY": "The Spire",
+ "OTJ9-E": "The Spire",
+ "LH-LY1": "The Spire",
+ "7-QOYS": "The Spire",
+ "KS8G-M": "The Spire",
+ "ZWM-BB": "The Spire",
+ "S-CUEA": "The Spire",
+ "L-EUY2": "The Spire",
+ "JL-ZUQ": "The Spire",
+ "X-KHRZ": "The Spire",
+ "WIW-X8": "The Spire",
+ "QRH-BF": "The Spire",
+ "M-NP5O": "The Spire",
+ "2-NF2Z": "A821-A",
+ "0Z-VHC": "A821-A",
+ "9-BUSQ": "A821-A",
+ "LQB-TC": "A821-A",
+ "II-1B3": "A821-A",
+ "6-HFD6": "A821-A",
+ "P3UD-M": "A821-A",
+ "LCN-0V": "A821-A",
+ "FX-XMW": "A821-A",
+ "G-N6MC": "A821-A",
+ "7-8XK0": "A821-A",
+ "90G-OA": "A821-A",
+ "DT-7EO": "A821-A",
+ "B-Y06L": "A821-A",
+ "HHQ-8L": "A821-A",
+ "Z-KPAR": "A821-A",
+ "8U-RZH": "A821-A",
+ "2RV-06": "A821-A",
+ "CLDT-L": "A821-A",
+ "QU7-EE": "A821-A",
+ "UC-X28": "A821-A",
+ "R79-I7": "A821-A",
+ "E-RPGP": "A821-A",
+ "ZV-KZO": "A821-A",
+ "NSE-U1": "A821-A",
+ "KER-EU": "A821-A",
+ "69A-54": "A821-A",
+ "M9-OS2": "A821-A",
+ "5V-YL6": "A821-A",
+ "8-UWFS": "A821-A",
+ "PQWA-L": "A821-A",
+ "BWO-UU": "A821-A",
+ "SQVI-U": "A821-A",
+ "T-YWDD": "A821-A",
+ "DLY-RG": "A821-A",
+ "T-C5A0": "A821-A",
+ "UP-L3Y": "A821-A",
+ "F-KBNV": "A821-A",
+ "JL-P9P": "A821-A",
+ "FR-RCH": "A821-A",
+ "FNS3-F": "A821-A",
+ "7BA-TK": "A821-A",
+ "IAWJ-X": "A821-A",
+ "50-TJY": "A821-A",
+ "3-CE1R": "A821-A",
+ "0IRK-R": "A821-A",
+ "Tividu": "Tash-Murkon",
+ "Tendhyes": "Tash-Murkon",
+ "Goram": "Tash-Murkon",
+ "Anjedin": "Tash-Murkon",
+ "Adahum": "Tash-Murkon",
+ "Ahrosseas": "Tash-Murkon",
+ "Riramia": "Tash-Murkon",
+ "Nafomeh": "Tash-Murkon",
+ "Pimsu": "Tash-Murkon",
+ "Jarzalad": "Tash-Murkon",
+ "Matyas": "Tash-Murkon",
+ "Imeshasa": "Tash-Murkon",
+ "Ivih": "Tash-Murkon",
+ "Seil": "Tash-Murkon",
+ "Mani": "Tash-Murkon",
+ "Sehmosh": "Tash-Murkon",
+ "Dabrid": "Tash-Murkon",
+ "Gyerzen": "Tash-Murkon",
+ "Hibi": "Tash-Murkon",
+ "Gemodi": "Tash-Murkon",
+ "Chamume": "Tash-Murkon",
+ "Nuzair": "Tash-Murkon",
+ "Pera": "Tash-Murkon",
+ "Shousran": "Tash-Murkon",
+ "Yong": "Tash-Murkon",
+ "Pimebeka": "Tash-Murkon",
+ "Baviasi": "Tash-Murkon",
+ "Tash-Murkon Prime": "Tash-Murkon",
+ "Emrayur": "Tash-Murkon",
+ "Shesha": "Tash-Murkon",
+ "Hilaban": "Tash-Murkon",
+ "Sacalan": "Tash-Murkon",
+ "Mimen": "Tash-Murkon",
+ "Thashkarai": "Tash-Murkon",
+ "Atoosh": "Tash-Murkon",
+ "Unkah": "Tash-Murkon",
+ "Hoona": "Tash-Murkon",
+ "Teshkat": "Tash-Murkon",
+ "Keshirou": "Tash-Murkon",
+ "Nasesharafa": "Tash-Murkon",
+ "Tirbam": "Tash-Murkon",
+ "Ordat": "Tash-Murkon",
+ "Rethan": "Tash-Murkon",
+ "Lossa": "Tash-Murkon",
+ "Onazel": "Tash-Murkon",
+ "Asesamy": "Tash-Murkon",
+ "Hostni": "Tash-Murkon",
+ "Mimime": "Tash-Murkon",
+ "Kibursha": "Tash-Murkon",
+ "Perdan": "Tash-Murkon",
+ "Abai": "Tash-Murkon",
+ "Nehkiah": "Tash-Murkon",
+ "Iro": "Tash-Murkon",
+ "Ahkour": "Tash-Murkon",
+ "Gaknem": "Tash-Murkon",
+ "Siyi": "Tash-Murkon",
+ "Remoriu": "Tash-Murkon",
+ "Yanuel": "Tash-Murkon",
+ "Nafrivik": "Tash-Murkon",
+ "Taru": "Tash-Murkon",
+ "Arkoz": "Tash-Murkon",
+ "Azhgabid": "Tash-Murkon",
+ "Jinizu": "Tash-Murkon",
+ "Phoren": "Tash-Murkon",
+ "Asezai": "Tash-Murkon",
+ "Ferira": "Tash-Murkon",
+ "Yeder": "Tash-Murkon",
+ "Azerakish": "Tash-Murkon",
+ "Lari": "Tash-Murkon",
+ "Yasud": "Tash-Murkon",
+ "Ghishul": "Tash-Murkon",
+ "Moutid": "Tash-Murkon",
+ "Goni": "Tash-Murkon",
+ "Adar": "Tash-Murkon",
+ "Paye": "Tash-Murkon",
+ "Sagain": "Tash-Murkon",
+ "Modun": "Tash-Murkon",
+ "Saminer": "Tash-Murkon",
+ "Marthia": "Tash-Murkon",
+ "Assiad": "Tash-Murkon",
+ "Rumida": "Tash-Murkon",
+ "Nosodnis": "Tash-Murkon",
+ "Iswa": "Tash-Murkon",
+ "Rand": "Tash-Murkon",
+ "Sizamod": "Tash-Murkon",
+ "Sinid": "Tash-Murkon",
+ "Alra": "Tash-Murkon",
+ "Ilas": "Tash-Murkon",
+ "Zith": "Tash-Murkon",
+ "Tew": "Tash-Murkon",
+ "Zehru": "Tash-Murkon",
+ "Uhodoh": "Tash-Murkon",
+ "Esa": "Tash-Murkon",
+ "Hath": "Tash-Murkon",
+ "Judra": "Tash-Murkon",
+ "Sharios": "Tash-Murkon",
+ "Arakor": "Tash-Murkon",
+ "Ahteer": "Tash-Murkon",
+ "Kari": "Tash-Murkon",
+ "Kerepa": "Tash-Murkon",
+ "Pasha": "Tash-Murkon",
+ "Safilbab": "Tash-Murkon",
+ "Seitam": "Tash-Murkon",
+ "JUE-DX": "Outer Passage",
+ "HLR-GL": "Outer Passage",
+ "80G-H5": "Outer Passage",
+ "2EV-BA": "Outer Passage",
+ "M1-PX9": "Outer Passage",
+ "W9-TFD": "Outer Passage",
+ "QHH-13": "Outer Passage",
+ "J4AQ-O": "Outer Passage",
+ "O-O2GN": "Outer Passage",
+ "I-HRX3": "Outer Passage",
+ "XUPK-Z": "Outer Passage",
+ "M4U-EH": "Outer Passage",
+ "WK2F-Y": "Outer Passage",
+ "WIO-OL": "Outer Passage",
+ "1-10QG": "Outer Passage",
+ "YQM-P1": "Outer Passage",
+ "6-GRN7": "Outer Passage",
+ "TFPT-U": "Outer Passage",
+ "D-JVGJ": "Outer Passage",
+ "K4UV-G": "Outer Passage",
+ "Q7E-DU": "Outer Passage",
+ "9Z-XJN": "Outer Passage",
+ "ZEZ1-9": "Outer Passage",
+ "QFRV-2": "Outer Passage",
+ "HZID-J": "Outer Passage",
+ "8-AA98": "Outer Passage",
+ "EZWQ-X": "Outer Passage",
+ "2ULC-J": "Outer Passage",
+ "T0DT-T": "Outer Passage",
+ "QG3-Z0": "Outer Passage",
+ "RT64-C": "Outer Passage",
+ "2ID-87": "Outer Passage",
+ "FVQF-W": "Outer Passage",
+ "8K-QCZ": "Outer Passage",
+ "JBUH-H": "Outer Passage",
+ "XDTW-F": "Outer Passage",
+ "0-4VQL": "Outer Passage",
+ "SN-DZ6": "Outer Passage",
+ "DJ-GBH": "Outer Passage",
+ "I0N-BM": "Outer Passage",
+ "QOK-SX": "Outer Passage",
+ "24I-FE": "Outer Passage",
+ "4H-YJZ": "Outer Passage",
+ "2-84WC": "Outer Passage",
+ "V-SEE6": "Outer Passage",
+ "U-FQ21": "Outer Passage",
+ "NHKO-4": "Outer Passage",
+ "KGCF-5": "Outer Passage",
+ "Y-UO9U": "Outer Passage",
+ "XME-SW": "Outer Passage",
+ "JX-SOA": "Outer Passage",
+ "VH-9VO": "Outer Passage",
+ "P-T9VC": "Outer Passage",
+ "9S-GPT": "Outer Passage",
+ "UAJ5-K": "Outer Passage",
+ "XJ-AG7": "Outer Passage",
+ "2WU-XT": "Outer Passage",
+ "J7X-VN": "Outer Passage",
+ "F-WCLC": "Outer Passage",
+ "G-HE0N": "Outer Passage",
+ "YC-ANK": "Outer Passage",
+ "LTT-AP": "Outer Passage",
+ "8RL-OG": "Outer Passage",
+ "R3P0-Z": "Outer Passage",
+ "ZZK-VF": "Outer Passage",
+ "SN-Q1T": "Outer Passage",
+ "L1YK-V": "Outer Passage",
+ "ZJ-5IS": "Outer Passage",
+ "GA58-7": "Outer Passage",
+ "J-0KB3": "Outer Passage",
+ "UC-8XF": "Outer Passage",
+ "90-A1P": "Outer Passage",
+ "4AZV-W": "Outer Passage",
+ "UNV-3J": "Outer Passage",
+ "7F-2FB": "Outer Passage",
+ "MC4C-H": "Outer Passage",
+ "OW-QXW": "Outer Passage",
+ "3-QNM4": "Outer Passage",
+ "UEPO-D": "Outer Passage",
+ "NQ-M6W": "Outer Passage",
+ "P-8PDJ": "Outer Passage",
+ "VE-W7O": "Outer Passage",
+ "CNHV-M": "Outer Passage",
+ "NEU-UD": "Outer Passage",
+ "N-I024": "Outer Passage",
+ "4O-ZRI": "Outer Passage",
+ "Y-7XVJ": "Outer Passage",
+ "RQNF-9": "Outer Passage",
+ "DSS-EZ": "Stain",
+ "MB4D-4": "Stain",
+ "LGK-VP": "Stain",
+ "E-C0SR": "Stain",
+ "X1E-OQ": "Stain",
+ "VTGN-U": "Stain",
+ "0Y1-M7": "Stain",
+ "Q-Q2S6": "Stain",
+ "WHG2-7": "Stain",
+ "9RQ-L8": "Stain",
+ "32-GI9": "Stain",
+ "TG-Z23": "Stain",
+ "IP-MVJ": "Stain",
+ "4J-ZC9": "Stain",
+ "7R5-7R": "Stain",
+ "Y1-UQ2": "Stain",
+ "HM-UVD": "Stain",
+ "G-ME2K": "Stain",
+ "WNS-7J": "Stain",
+ "57M7-W": "Stain",
+ "JS-E8E": "Stain",
+ "FV-SE8": "Stain",
+ "FZSW-Y": "Stain",
+ "UF-KKH": "Stain",
+ "O5Y3-W": "Stain",
+ "0GN-VO": "Stain",
+ "9U6-SV": "Stain",
+ "4GQ-XQ": "Stain",
+ "R8-5XF": "Stain",
+ "2IGP-1": "Stain",
+ "Z2-QQP": "Stain",
+ "GDEW-0": "Stain",
+ "PSJ-10": "Stain",
+ "2-V0KY": "Stain",
+ "U-WLT9": "Stain",
+ "ZG8Q-N": "Stain",
+ "40GX-P": "Stain",
+ "37S-KO": "Stain",
+ "4J9-DK": "Stain",
+ "A-GPTM": "Stain",
+ "HQ-TDJ": "Stain",
+ "WBLF-0": "Stain",
+ "GDO-7H": "Stain",
+ "NZG-LF": "Stain",
+ "UJM-RD": "Stain",
+ "L0AD-B": "Stain",
+ "8ZO-CK": "Stain",
+ "WEQT-K": "Stain",
+ "8O-OSG": "Stain",
+ "1H-I12": "Stain",
+ "D9D-GD": "Stain",
+ "4A-XJ6": "Stain",
+ "GU-54G": "Stain",
+ "7-X3RN": "Stain",
+ "BF-FVB": "Stain",
+ "9O-ZTS": "Stain",
+ "8KQR-O": "Stain",
+ "F9SX-1": "Stain",
+ "0G-A25": "Stain",
+ "WJO0-G": "Stain",
+ "S91-TI": "Stain",
+ "V1V-6F": "Stain",
+ "S-DLKC": "Stain",
+ "42-UOW": "Stain",
+ "CBGG-0": "Stain",
+ "A4UG-O": "Stain",
+ "W-VXL9": "Stain",
+ "U2-BJ2": "Stain",
+ "UKYS-5": "Stain",
+ "RV5-DW": "Stain",
+ "KP-FQ1": "Stain",
+ "RLDS-R": "Stain",
+ "QM-O7J": "Stain",
+ "0-7XA8": "Stain",
+ "X5O1-L": "Stain",
+ "F-TVAP": "Stain",
+ "6Y-0TW": "Stain",
+ "TL-T9Z": "Stain",
+ "E7-WSY": "Stain",
+ "B-G1LG": "Stain",
+ "T-8UOF": "Stain",
+ "DP-2WP": "Stain",
+ "MMR-LZ": "Stain",
+ "I-ME3L": "Stain",
+ "YE17-R": "Stain",
+ "T7-JNB": "Stain",
+ "LB0-A1": "Stain",
+ "S-BWWQ": "Stain",
+ "Z-R96X": "Stain",
+ "J-AYLV": "Stain",
+ "DABV-N": "Stain",
+ "ZH-KEV": "Stain",
+ "LC-1ED": "Stain",
+ "RPS-0K": "Stain",
+ "VNPF-7": "Stain",
+ "CJF-1P": "Stain",
+ "U6-FCE": "Stain",
+ "L6B-0N": "Stain",
+ "Z-XMUC": "Stain",
+ "6QBH-S": "Stain",
+ "RRWI-5": "Stain",
+ "Y-4U62": "Stain",
+ "EAWE-2": "Stain",
+ "I-3FET": "Stain",
+ "QCKK-T": "Stain",
+ "RP-H66": "Stain",
+ "JU-UYK": "Stain",
+ "O-FTHE": "Stain",
+ "W-Q233": "Stain",
+ "4XW2-D": "Stain",
+ "J5NU-K": "Stain",
+ "EOT-XL": "Stain",
+ "RVRE-Z": "Stain",
+ "B-2UL0": "Stain",
+ "L-A9FS": "Stain",
+ "OOO-FS": "Stain",
+ "373Z-7": "Stain",
+ "JVJ2-N": "Stain",
+ "2B-3M4": "Stain",
+ "A-XASO": "Stain",
+ "5J-UEX": "Stain",
+ "1H4V-O": "Stain",
+ "LGL-SD": "Stain",
+ "A-DZA8": "Stain",
+ "O-CT8N": "Stain",
+ "Z-6YQC": "Stain",
+ "F7-ICZ": "Stain",
+ "XFBE-T": "Stain",
+ "T-NNJZ": "Stain",
+ "DK6W-I": "Stain",
+ "0T-LIB": "Stain",
+ "NRT4-U": "Stain",
+ "KQK1-2": "Pure Blind",
+ "O-BY0Y": "Pure Blind",
+ "2D-0SO": "Pure Blind",
+ "UR-E6D": "Pure Blind",
+ "X47L-Q": "Pure Blind",
+ "D7T-C0": "Pure Blind",
+ "KI-TL0": "Pure Blind",
+ "EL8-4Q": "Pure Blind",
+ "JC-YX8": "Pure Blind",
+ "5-9WNU": "Pure Blind",
+ "XI-VUF": "Pure Blind",
+ "N-H32Y": "Pure Blind",
+ "12YA-2": "Pure Blind",
+ "BDV3-T": "Pure Blind",
+ "J-CIJV": "Pure Blind",
+ "X-7OMU": "Pure Blind",
+ "CXN1-Z": "Pure Blind",
+ "KLY-C0": "Pure Blind",
+ "CL6-ZG": "Pure Blind",
+ "G95-VZ": "Pure Blind",
+ "ROIR-Y": "Pure Blind",
+ "EC-P8R": "Pure Blind",
+ "EWOK-K": "Pure Blind",
+ "O-N8XZ": "Pure Blind",
+ "G-M4I8": "Pure Blind",
+ "MI6O-6": "Pure Blind",
+ "L-TS8S": "Pure Blind",
+ "93PI-4": "Pure Blind",
+ "ION-FG": "Pure Blind",
+ "C-H9X7": "Pure Blind",
+ "A8I-C5": "Pure Blind",
+ "DK-FXK": "Pure Blind",
+ "M-76XI": "Pure Blind",
+ "ZJET-E": "Pure Blind",
+ "U-INPD": "Pure Blind",
+ "WW-KGD": "Pure Blind",
+ "XQ-PXU": "Pure Blind",
+ "M-YCD4": "Pure Blind",
+ "Q-5211": "Pure Blind",
+ "R-2R0G": "Pure Blind",
+ "CR-AQH": "Pure Blind",
+ "8S-0E1": "Pure Blind",
+ "5ZXX-K": "Pure Blind",
+ "JE-D5U": "Pure Blind",
+ "2-6TGQ": "Pure Blind",
+ "OE-9UF": "Pure Blind",
+ "PFU-LH": "Pure Blind",
+ "R6XN-9": "Pure Blind",
+ "3V8-LJ": "Pure Blind",
+ "B8EN-S": "Pure Blind",
+ "R-LW2I": "Pure Blind",
+ "DP-1YE": "Pure Blind",
+ "4-ABS8": "Pure Blind",
+ "7RM-N0": "Pure Blind",
+ "S-MDYI": "Pure Blind",
+ "ZKYV-W": "Pure Blind",
+ "F-NMX6": "Pure Blind",
+ "GA-P6C": "Pure Blind",
+ "FWA-4V": "Pure Blind",
+ "RZC-16": "Pure Blind",
+ "RD-G2R": "Pure Blind",
+ "UC3H-Y": "Pure Blind",
+ "6GWE-A": "Pure Blind",
+ "J-OK0C": "Pure Blind",
+ "KDV-DE": "Pure Blind",
+ "MT9Q-S": "Pure Blind",
+ "B-9C24": "Pure Blind",
+ "P-2TTL": "Pure Blind",
+ "7X-VKB": "Pure Blind",
+ "E-Z2ZX": "Pure Blind",
+ "RORZ-H": "Pure Blind",
+ "O-A6YN": "Pure Blind",
+ "MQ-NPY": "Pure Blind",
+ "D2-HOS": "Pure Blind",
+ "Y2-6EA": "Pure Blind",
+ "TFA0-U": "Pure Blind",
+ "RQH-MY": "Pure Blind",
+ "HPS5-C": "Pure Blind",
+ "DT-TCD": "Pure Blind",
+ "KU5R-W": "Pure Blind",
+ "H1-J33": "Pure Blind",
+ "Y-C3EQ": "Pure Blind",
+ "OGV-AS": "Pure Blind",
+ "7D-0SQ": "Pure Blind",
+ "UI-8ZE": "Pure Blind",
+ "NS2L-4": "Immensea",
+ "QI-S9W": "Immensea",
+ "B-S347": "Immensea",
+ "PPFB-U": "Immensea",
+ "AF0-V5": "Immensea",
+ "B-A587": "Immensea",
+ "Y19P-1": "Immensea",
+ "B9E-H6": "Immensea",
+ "SPBS-6": "Immensea",
+ "JDAS-0": "Immensea",
+ "A4B-V5": "Immensea",
+ "LN-56V": "Immensea",
+ "Y2-QUV": "Immensea",
+ "O7-7UX": "Immensea",
+ "Z8-81T": "Immensea",
+ "XD-JW7": "Immensea",
+ "DY-P7Q": "Immensea",
+ "H-RXNZ": "Immensea",
+ "ZBP-TP": "Immensea",
+ "XVV-21": "Immensea",
+ "GXK-7F": "Immensea",
+ "EA-HSA": "Immensea",
+ "78TS-Q": "Immensea",
+ "WYF8-8": "Immensea",
+ "CJNF-J": "Immensea",
+ "FYI-49": "Immensea",
+ "RF6T-8": "Immensea",
+ "ZJA-6U": "Immensea",
+ "94FR-S": "Immensea",
+ "Q-HJ97": "Immensea",
+ "GM-0K7": "Immensea",
+ "I-NGI8": "Immensea",
+ "R-ZUOL": "Immensea",
+ "E1F-LK": "Immensea",
+ "Z4-QLD": "Immensea",
+ "QE-E1D": "Immensea",
+ "LK1K-5": "Immensea",
+ "REB-KR": "Immensea",
+ "Z-H2MA": "Immensea",
+ "L-5JCJ": "Immensea",
+ "B-KDOZ": "Immensea",
+ "4-GB14": "Immensea",
+ "PH-NFR": "Immensea",
+ "DW-N2S": "Immensea",
+ "W-FHWJ": "Immensea",
+ "X-6WC7": "Immensea",
+ "D-BAMJ": "Immensea",
+ "JKWP-U": "Immensea",
+ "RHE7-W": "Immensea",
+ "F76-8Q": "Immensea",
+ "O3Z5-G": "Immensea",
+ "4DV-1T": "Immensea",
+ "XS-K1O": "Immensea",
+ "FN-DSR": "Immensea",
+ "B-R5RB": "Immensea",
+ "7-ZT1Y": "Immensea",
+ "9-XN3F": "Immensea",
+ "AC-7LZ": "Immensea",
+ "LBA-SO": "Immensea",
+ "Y-FZ5N": "Immensea",
+ "E8-YS9": "Immensea",
+ "U79-JF": "Immensea",
+ "B2-UQW": "Immensea",
+ "U9U-TQ": "Immensea",
+ "6-I162": "Immensea",
+ "08-N7Q": "Immensea",
+ "Y-C4AL": "Immensea",
+ "CKX-RW": "Immensea",
+ "8X6T-8": "Immensea",
+ "W4E-IT": "Immensea",
+ "OP9L-F": "Immensea",
+ "J-QA7I": "Immensea",
+ "2O-EEW": "Immensea",
+ "Y-N4EF": "Immensea",
+ "7YSF-E": "Immensea",
+ "KCDX-7": "Immensea",
+ "O7-VJ5": "Immensea",
+ "FRTC-5": "Immensea",
+ "M-ZJWJ": "Immensea",
+ "R-ORB7": "Immensea",
+ "RU-PT9": "Immensea",
+ "DR-427": "Immensea",
+ "NI-J0B": "Immensea",
+ "QN-6J2": "Immensea",
+ "2G-VDP": "Etherium Reach",
+ "9F-3CR": "Etherium Reach",
+ "J7M-3W": "Etherium Reach",
+ "KRPF-A": "Etherium Reach",
+ "9P-870": "Etherium Reach",
+ "QNXJ-M": "Etherium Reach",
+ "AID-9T": "Etherium Reach",
+ "PXE-RG": "Etherium Reach",
+ "5J-62N": "Etherium Reach",
+ "Z-DRIY": "Etherium Reach",
+ "8-MXHA": "Etherium Reach",
+ "LPVL-5": "Etherium Reach",
+ "D3S-EA": "Etherium Reach",
+ "KGT3-6": "Etherium Reach",
+ "4LJ6-Q": "Etherium Reach",
+ "SAH-AD": "Etherium Reach",
+ "MF-PGF": "Etherium Reach",
+ "L-ZJLN": "Etherium Reach",
+ "G-QTSD": "Etherium Reach",
+ "3G-LFX": "Etherium Reach",
+ "NK-VTL": "Etherium Reach",
+ "D-CR6W": "Etherium Reach",
+ "BY-7PY": "Etherium Reach",
+ "GN-TNT": "Etherium Reach",
+ "QKCU-4": "Etherium Reach",
+ "0M-24X": "Etherium Reach",
+ "N06Z-Q": "Etherium Reach",
+ "YX-0KH": "Etherium Reach",
+ "KMH-J1": "Etherium Reach",
+ "CYB-BZ": "Etherium Reach",
+ "5U-3PW": "Etherium Reach",
+ "89JS-J": "Etherium Reach",
+ "C9R-NO": "Etherium Reach",
+ "FKR-SR": "Etherium Reach",
+ "1ACJ-6": "Etherium Reach",
+ "BNX-AS": "Etherium Reach",
+ "XB-9U2": "Etherium Reach",
+ "F9-FUV": "Etherium Reach",
+ "FB-MPY": "Etherium Reach",
+ "RO-0PZ": "Etherium Reach",
+ "JTA2-2": "Etherium Reach",
+ "R-6KYM": "Etherium Reach",
+ "3H58-R": "Etherium Reach",
+ "RV-GA8": "Etherium Reach",
+ "TP-RTO": "Etherium Reach",
+ "GTY-FW": "Etherium Reach",
+ "1H5-3W": "Etherium Reach",
+ "QZV-X3": "Etherium Reach",
+ "IS-OBW": "Etherium Reach",
+ "1GH-48": "Etherium Reach",
+ "IRD-HU": "Etherium Reach",
+ "B-2VXB": "Etherium Reach",
+ "FIZU-X": "Etherium Reach",
+ "JAWX-R": "Etherium Reach",
+ "Z0G-XG": "Etherium Reach",
+ "ALC-JM": "Etherium Reach",
+ "9QS5-C": "Etherium Reach",
+ "NWX-LI": "Etherium Reach",
+ "N-SFZK": "Etherium Reach",
+ "2B-UUQ": "Etherium Reach",
+ "I64-XB": "Etherium Reach",
+ "4-QDIX": "Etherium Reach",
+ "FGJP-J": "Etherium Reach",
+ "89-JPE": "Etherium Reach",
+ "D-IZT9": "Etherium Reach",
+ "WU9-ZR": "Etherium Reach",
+ "E8-432": "Etherium Reach",
+ "43-1TL": "Etherium Reach",
+ "O-LJOO": "Etherium Reach",
+ "ZS-PNI": "Etherium Reach",
+ "TZ-74M": "Etherium Reach",
+ "8KE-YS": "Etherium Reach",
+ "LXQ2-T": "Etherium Reach",
+ "HV-EAP": "Etherium Reach",
+ "3IK-7O": "Etherium Reach",
+ "O-EUHA": "Etherium Reach",
+ "MO-I1W": "Etherium Reach",
+ "ZZ5X-M": "Etherium Reach",
+ "UAV-1E": "Etherium Reach",
+ "CL-IRS": "Etherium Reach",
+ "QBZO-R": "Etherium Reach",
+ "QHJR-E": "Etherium Reach",
+ "1PF-BC": "Etherium Reach",
+ "D-OJEZ": "Etherium Reach",
+ "C-V6DQ": "Etherium Reach",
+ "Z-FET0": "Etherium Reach",
+ "EX-GBT": "Etherium Reach",
+ "PX-IHN": "Etherium Reach",
+ "WPV-JN": "Etherium Reach",
+ "IL-H0A": "Etherium Reach",
+ "CT8K-0": "Etherium Reach",
+ "M9-LAN": "Etherium Reach",
+ "C-4D0W": "Etherium Reach",
+ "L4X-1V": "Etherium Reach",
+ "M-V0PQ": "Etherium Reach",
+ "DYPL-6": "Etherium Reach",
+ "V-OL61": "Etherium Reach",
+ "RK-Q51": "Etherium Reach",
+ "F69O-M": "Etherium Reach",
+ "T-IDGH": "Etherium Reach",
+ "Aeddin": "Molden Heath",
+ "Gulfonodi": "Molden Heath",
+ "Teonusude": "Molden Heath",
+ "Gelfiven": "Molden Heath",
+ "Bosena": "Molden Heath",
+ "Oddelulf": "Molden Heath",
+ "Atlar": "Molden Heath",
+ "Heild": "Molden Heath",
+ "Hrokkur": "Molden Heath",
+ "Hrober": "Molden Heath",
+ "Aedald": "Molden Heath",
+ "Muttokon": "Molden Heath",
+ "Audesder": "Molden Heath",
+ "Illamur": "Molden Heath",
+ "Horaka": "Molden Heath",
+ "Eldulf": "Molden Heath",
+ "Orien": "Molden Heath",
+ "Varigne": "Molden Heath",
+ "Meildolf": "Molden Heath",
+ "Istodard": "Molden Heath",
+ "Gonheim": "Molden Heath",
+ "Half": "Molden Heath",
+ "Sakulda": "Molden Heath",
+ "Hedaleolfarber": "Molden Heath",
+ "Altbrard": "Molden Heath",
+ "Fegomenko": "Molden Heath",
+ "Osvetur": "Molden Heath",
+ "Mimiror": "Molden Heath",
+ "Skarkon": "Molden Heath",
+ "Ennur": "Molden Heath",
+ "Unertek": "Molden Heath",
+ "Klingt": "Molden Heath",
+ "Weld": "Molden Heath",
+ "Kattegaud": "Molden Heath",
+ "Kadlina": "Molden Heath",
+ "Hegfunden": "Molden Heath",
+ "Aeditide": "Molden Heath",
+ "Egbinger": "Molden Heath",
+ "MR4-MY": "Geminate",
+ "SR-KBB": "Geminate",
+ "FDZ4-A": "Geminate",
+ "2E-ZR5": "Geminate",
+ "O1-FTD": "Geminate",
+ "Roua": "Geminate",
+ "OEY-OR": "Geminate",
+ "M-MD31": "Geminate",
+ "WH-2EZ": "Geminate",
+ "D0-F4W": "Geminate",
+ "QKTR-L": "Geminate",
+ "YN3-E3": "Geminate",
+ "NBPH-N": "Geminate",
+ "L-HV5C": "Geminate",
+ "L4X-FH": "Geminate",
+ "B6-52M": "Geminate",
+ "V-MZW0": "Geminate",
+ "BND-16": "Geminate",
+ "IOO-7O": "Geminate",
+ "BWF-ZZ": "Geminate",
+ "4-CUM5": "Geminate",
+ "8MG-J6": "Geminate",
+ "RLSI-V": "Geminate",
+ "39-DGG": "Geminate",
+ "SV-K8J": "Geminate",
+ "6RQ9-A": "Geminate",
+ "K42-IE": "Geminate",
+ "VSJ-PP": "Geminate",
+ "3USX-F": "Geminate",
+ "9-KWXC": "Geminate",
+ "NQ-9IH": "Geminate",
+ "KR-V6G": "Geminate",
+ "AP9-LV": "Geminate",
+ "0-GZX9": "Geminate",
+ "2H-TSE": "Geminate",
+ "4NGK-F": "Geminate",
+ "O-VWPB": "Geminate",
+ "LX-ZOJ": "Geminate",
+ "6L78-1": "Geminate",
+ "04-LQM": "Geminate",
+ "4VY-Y1": "Geminate",
+ "LU-HQS": "Geminate",
+ "U-L4KS": "Geminate",
+ "K25-XD": "Geminate",
+ "6YC-TU": "Geminate",
+ "Y8R-XZ": "Geminate",
+ "P-E9GN": "Geminate",
+ "HJO-84": "Geminate",
+ "4D9-66": "Geminate",
+ "L-TOFR": "Geminate",
+ "Q-TBHW": "Geminate",
+ "9P4O-F": "Geminate",
+ "UBX-CC": "Geminate",
+ "TJM-JJ": "Geminate",
+ "EOA-ZC": "Geminate",
+ "G-73MR": "Geminate",
+ "E-91FV": "Geminate",
+ "AD-5B8": "Geminate",
+ "QP0K-B": "Geminate",
+ "54-MF6": "Geminate",
+ "D-I9HJ": "Geminate",
+ "P-6I0B": "Geminate",
+ "CFYY-J": "Geminate",
+ "8-KZXQ": "Geminate",
+ "HKYW-T": "Geminate",
+ "3SFU-S": "Geminate",
+ "VJ-NQP": "Geminate",
+ "U6D-9A": "Geminate",
+ "Atioth": "Geminate",
+ "PYY3-5": "Geminate",
+ "RFGW-V": "Geminate",
+ "N-HK93": "Geminate",
+ "LR-2XT": "Geminate",
+ "TZL-WT": "Geminate",
+ "4K0N-J": "Geminate",
+ "B-F1MI": "Geminate",
+ "W-3BSU": "Geminate",
+ "BE-UUN": "Geminate",
+ "O2O-2X": "Geminate",
+ "JE1-36": "Geminate",
+ "5F-YRA": "Geminate",
+ "TDE4-H": "Geminate",
+ "UER-TH": "Geminate",
+ "UG-UWZ": "Geminate",
+ "Hulm": "Heimatar",
+ "Osoggur": "Heimatar",
+ "Abudban": "Heimatar",
+ "Trytedald": "Heimatar",
+ "Odatrik": "Heimatar",
+ "Rens": "Heimatar",
+ "Ameinaka": "Heimatar",
+ "Alakgur": "Heimatar",
+ "Dammalin": "Heimatar",
+ "Bosboger": "Heimatar",
+ "Olfeim": "Heimatar",
+ "Lulm": "Heimatar",
+ "Gulmorogod": "Heimatar",
+ "Edmalbrurdus": "Heimatar",
+ "Kronsur": "Heimatar",
+ "Dumkirinur": "Heimatar",
+ "Sist": "Heimatar",
+ "Obrolber": "Heimatar",
+ "Austraka": "Heimatar",
+ "Ivar": "Heimatar",
+ "Meirakulf": "Heimatar",
+ "Frarn": "Heimatar",
+ "Illinfrik": "Heimatar",
+ "Balginia": "Heimatar",
+ "Gyng": "Heimatar",
+ "Avesber": "Heimatar",
+ "Gerek": "Heimatar",
+ "Tongofur": "Heimatar",
+ "Gerbold": "Heimatar",
+ "Rokofur": "Heimatar",
+ "Ebasgerdur": "Heimatar",
+ "Ebodold": "Heimatar",
+ "Amamake": "Heimatar",
+ "Vard": "Heimatar",
+ "Siseide": "Heimatar",
+ "Lantorn": "Heimatar",
+ "Dal": "Heimatar",
+ "Auga": "Heimatar",
+ "Eystur": "Heimatar",
+ "Pator": "Heimatar",
+ "Lustrevik": "Heimatar",
+ "Isendeldik": "Heimatar",
+ "Ammold": "Heimatar",
+ "Emolgranlan": "Heimatar",
+ "Offugen": "Heimatar",
+ "Roniko": "Heimatar",
+ "Aralgrund": "Heimatar",
+ "Eddar": "Heimatar",
+ "Bogelek": "Heimatar",
+ "Wiskeber": "Heimatar",
+ "Eifer": "Heimatar",
+ "Gusandall": "Heimatar",
+ "Atgur": "Heimatar",
+ "Endrulf": "Heimatar",
+ "Ingunn": "Heimatar",
+ "Gultratren": "Heimatar",
+ "Auren": "Heimatar",
+ "Trer": "Heimatar",
+ "Egmur": "Heimatar",
+ "Javrendei": "Heimatar",
+ "Appen": "Heimatar",
+ "Klir": "Heimatar",
+ "Jorus": "Heimatar",
+ "Onga": "Heimatar",
+ "Osaumuni": "Heimatar",
+ "Magiko": "Heimatar",
+ "Oremmulf": "Heimatar",
+ "Hurjafren": "Heimatar",
+ "Vullat": "Heimatar",
+ "Hrondedir": "Heimatar",
+ "Sotrenzur": "Heimatar",
+ "Hrondmund": "Heimatar",
+ "Bundindus": "Heimatar",
+ "Otraren": "Heimatar",
+ "Hedgiviter": "Heimatar",
+ "Katugumur": "Heimatar",
+ "Malukker": "Heimatar",
+ "Hadaugago": "Heimatar",
+ "Krilmokenur": "Heimatar",
+ "Todeko": "Heimatar",
+ "Larkugei": "Heimatar",
+ "Usteli": "Heimatar",
+ "Loguttur": "Heimatar",
+ "1-7KWU": "Impass",
+ "3-UCBF": "Impass",
+ "N-CREL": "Impass",
+ "TM-0P2": "Impass",
+ "4OIV-X": "Impass",
+ "Y-JKJ8": "Impass",
+ "AFJ-NB": "Impass",
+ "H-64KI": "Impass",
+ "9I-SRF": "Impass",
+ "9-IIBL": "Impass",
+ "5GQ-S9": "Impass",
+ "YALR-F": "Impass",
+ "68FT-6": "Impass",
+ "IV-UNR": "Impass",
+ "IRE-98": "Impass",
+ "HOHF-B": "Impass",
+ "Y-6B0E": "Impass",
+ "F-3H2P": "Impass",
+ "DY-40Z": "Impass",
+ "XWY-YM": "Impass",
+ "M-9V5D": "Impass",
+ "O2-39S": "Impass",
+ "M-VEJZ": "Impass",
+ "LJK-T0": "Impass",
+ "E7VE-V": "Impass",
+ "NUG-OF": "Impass",
+ "L6BY-P": "Impass",
+ "U3SQ-X": "Impass",
+ "01TG-J": "Impass",
+ "UK-SHL": "Impass",
+ "A1BK-A": "Impass",
+ "N-7ECY": "Impass",
+ "4-MPSJ": "Impass",
+ "TWJ-AW": "Impass",
+ "PZMA-E": "Impass",
+ "442-CS": "Impass",
+ "Z-N9IP": "Impass",
+ "9ZFH-Z": "Impass",
+ "6E-MOW": "Impass",
+ "GBT4-J": "Impass",
+ "GZ1-A1": "Impass",
+ "X-0CKQ": "Impass",
+ "6B-GKA": "Impass",
+ "LHGA-W": "Impass",
+ "4RS-L1": "Impass",
+ "D-L4H0": "Impass",
+ "GU-9F4": "Impass",
+ "FG-1GH": "Impass",
+ "WFYM-0": "Impass",
+ "FR-B1H": "Impass",
+ "DDI-B7": "Impass",
+ "Pettinck": "Sinq Laison",
+ "Du Annes": "Sinq Laison",
+ "Balle": "Sinq Laison",
+ "Decon": "Sinq Laison",
+ "Grinacanne": "Sinq Laison",
+ "Metserel": "Sinq Laison",
+ "Sharuveil": "Sinq Laison",
+ "Adreland": "Sinq Laison",
+ "Erme": "Sinq Laison",
+ "Aufay": "Sinq Laison",
+ "Iyen-Oursta": "Sinq Laison",
+ "Faurent": "Sinq Laison",
+ "Ambeke": "Sinq Laison",
+ "Carrou": "Sinq Laison",
+ "Direrie": "Sinq Laison",
+ "Ignoitton": "Sinq Laison",
+ "Ardene": "Sinq Laison",
+ "Boillair": "Sinq Laison",
+ "Ney": "Sinq Laison",
+ "Fasse": "Sinq Laison",
+ "Ala": "Sinq Laison",
+ "Gratesier": "Sinq Laison",
+ "Schoorasana": "Sinq Laison",
+ "Vylade": "Sinq Laison",
+ "Auvergne": "Sinq Laison",
+ "Aunia": "Sinq Laison",
+ "Agrallarier": "Sinq Laison",
+ "Dodixie": "Sinq Laison",
+ "Eglennaert": "Sinq Laison",
+ "Botane": "Sinq Laison",
+ "Pulin": "Sinq Laison",
+ "Foves": "Sinq Laison",
+ "Alles": "Sinq Laison",
+ "Misneden": "Sinq Laison",
+ "Basgerin": "Sinq Laison",
+ "Chelien": "Sinq Laison",
+ "Trosquesere": "Sinq Laison",
+ "Ansone": "Sinq Laison",
+ "Dunraelare": "Sinq Laison",
+ "Nausschie": "Sinq Laison",
+ "Inghenges": "Sinq Laison",
+ "Estene": "Sinq Laison",
+ "Gallareue": "Sinq Laison",
+ "Stayme": "Sinq Laison",
+ "Parchanier": "Sinq Laison",
+ "Fluekele": "Sinq Laison",
+ "Alsottobier": "Sinq Laison",
+ "Jolia": "Sinq Laison",
+ "Augnais": "Sinq Laison",
+ "Deltole": "Sinq Laison",
+ "Colelie": "Sinq Laison",
+ "Barmalie": "Sinq Laison",
+ "Audaerne": "Sinq Laison",
+ "Dodenvale": "Sinq Laison",
+ "Olettiers": "Sinq Laison",
+ "Artisine": "Sinq Laison",
+ "Chainelant": "Sinq Laison",
+ "Sileperer": "Sinq Laison",
+ "Bamiette": "Sinq Laison",
+ "Crielere": "Sinq Laison",
+ "Jel": "Sinq Laison",
+ "Egghelende": "Sinq Laison",
+ "Odette": "Sinq Laison",
+ "Ation": "Sinq Laison",
+ "Stegette": "Sinq Laison",
+ "Ravarin": "Sinq Laison",
+ "Aliette": "Sinq Laison",
+ "Brapelille": "Sinq Laison",
+ "Bawilan": "Sinq Laison",
+ "Atier": "Sinq Laison",
+ "Archee": "Sinq Laison",
+ "Brybier": "Sinq Laison",
+ "Adrallezoen": "Sinq Laison",
+ "Croleur": "Sinq Laison",
+ "Doussivitte": "Sinq Laison",
+ "Unel": "Sinq Laison",
+ "Claysson": "Sinq Laison",
+ "Auberulle": "Sinq Laison",
+ "Adiere": "Sinq Laison",
+ "Stetille": "Sinq Laison",
+ "Alillere": "Sinq Laison",
+ "Abenync": "Sinq Laison",
+ "Pozirblant": "Sinq Laison",
+ "Bourynes": "Sinq Laison",
+ "Aurcel": "Sinq Laison",
+ "Aymaerne": "Sinq Laison",
+ "Rancer": "Sinq Laison",
+ "Miroitem": "Sinq Laison",
+ "Thelan": "Sinq Laison",
+ "Rorsins": "Sinq Laison",
+ "Lamadent": "Sinq Laison",
+ "Otou": "Sinq Laison",
+ "Assiettes": "Sinq Laison",
+ "Goinard": "Sinq Laison",
+ "Raeghoscon": "Sinq Laison",
+ "Allipes": "Sinq Laison",
+ "Lermireve": "Sinq Laison",
+ "Aetree": "Sinq Laison",
+ "Esmes": "Sinq Laison",
+ "Vittenyn": "Sinq Laison",
+ "Mirilene": "Sinq Laison",
+ "Pucherie": "Sinq Laison",
+ "Fricoure": "Sinq Laison",
+ "Caretyn": "Sinq Laison",
+ "Ainaille": "Sinq Laison",
+ "Odotte": "Sinq Laison",
+ "Oirtlair": "Sinq Laison",
+ "Olelon": "Sinq Laison",
+ "Trossere": "Sinq Laison",
+ "Konola": "The Citadel",
+ "Inoue": "The Citadel",
+ "Isaziwa": "The Citadel",
+ "Eitu": "The Citadel",
+ "Horkkisen": "The Citadel",
+ "Erila": "The Citadel",
+ "Ohvosamon": "The Citadel",
+ "Auviken": "The Citadel",
+ "Saikanen": "The Citadel",
+ "Oijamon": "The Citadel",
+ "Kakki": "The Citadel",
+ "Jeras": "The Citadel",
+ "Kausaaja": "The Citadel",
+ "Oiniken": "The Citadel",
+ "Kaimon": "The Citadel",
+ "Ahynada": "The Citadel",
+ "Aikoro": "The Citadel",
+ "Alikara": "The Citadel",
+ "Usi": "The Citadel",
+ "Ishomilken": "The Citadel",
+ "Nikkishina": "The Citadel",
+ "Hasama": "The Citadel",
+ "Uuna": "The Citadel",
+ "Manjonakko": "The Citadel",
+ "Kassigainen": "The Citadel",
+ "Yashunen": "The Citadel",
+ "Tennen": "The Citadel",
+ "Hatakani": "The Citadel",
+ "Sivala": "The Citadel",
+ "Iivinen": "The Citadel",
+ "Kubinen": "The Citadel",
+ "Uedama": "The Citadel",
+ "Enderailen": "The Citadel",
+ "Tunudan": "The Citadel",
+ "Kulelen": "The Citadel",
+ "Rairomon": "The Citadel",
+ "Hogimo": "The Citadel",
+ "Huttaken": "The Citadel",
+ "Paara": "The Citadel",
+ "Annaro": "The Citadel",
+ "Isutaka": "The Citadel",
+ "Tasabeshi": "The Citadel",
+ "Ono": "The Citadel",
+ "Muvolailen": "The Citadel",
+ "Halaima": "The Citadel",
+ "Kamio": "The Citadel",
+ "Sankkasen": "The Citadel",
+ "Tintoh": "The Citadel",
+ "Santola": "The Citadel",
+ "Ikao": "The Citadel",
+ "Waira": "The Citadel",
+ "Inaro": "The Citadel",
+ "Kaaputenen": "The Citadel",
+ "Waskisen": "The Citadel",
+ "Sirppala": "The Citadel",
+ "Irjunen": "The Citadel",
+ "Inari": "The Citadel",
+ "Yria": "The Citadel",
+ "Oshaima": "The Citadel",
+ "Hysera": "The Citadel",
+ "Kaunokka": "The Citadel",
+ "Venilen": "The Citadel",
+ "Oisio": "The Citadel",
+ "Haatomo": "The Citadel",
+ "Suroken": "The Citadel",
+ "Kusomonmon": "The Citadel",
+ "Juunigaishi": "The Citadel",
+ "Isikesu": "The Citadel",
+ "Anttiri": "The Citadel",
+ "Hasmijaala": "The Citadel",
+ "Nagamanen": "The Citadel",
+ "Oto": "The Citadel",
+ "Sujarento": "The Citadel",
+ "Eranakko": "The Citadel",
+ "Onatoh": "The Citadel",
+ "Tannolen": "The Citadel",
+ "Tama": "The Citadel",
+ "Uotila": "The Citadel",
+ "Isenairos": "The Citadel",
+ "Saila": "The Citadel",
+ "Aramachi": "The Citadel",
+ "Oichiya": "The Citadel",
+ "Motsu": "The Citadel",
+ "Komo": "The Citadel",
+ "Urhinichi": "The Citadel",
+ "Laah": "The Citadel",
+ "N-JK02": "The Kalevala Expanse",
+ "JT2I-7": "The Kalevala Expanse",
+ "XTJ-5Q": "The Kalevala Expanse",
+ "1-KCSA": "The Kalevala Expanse",
+ "UJXC-B": "The Kalevala Expanse",
+ "UDVW-O": "The Kalevala Expanse",
+ "F48K-D": "The Kalevala Expanse",
+ "FBH-JN": "The Kalevala Expanse",
+ "BVRQ-O": "The Kalevala Expanse",
+ "QX-4HO": "The Kalevala Expanse",
+ "LS3-HP": "The Kalevala Expanse",
+ "SH6X-F": "The Kalevala Expanse",
+ "6V-D0E": "The Kalevala Expanse",
+ "SG-3HY": "The Kalevala Expanse",
+ "AU2V-J": "The Kalevala Expanse",
+ "SY-0AM": "The Kalevala Expanse",
+ "A-YB15": "The Kalevala Expanse",
+ "QZX-L9": "The Kalevala Expanse",
+ "D-6PKO": "The Kalevala Expanse",
+ "RAI-0E": "The Kalevala Expanse",
+ "MN9P-A": "The Kalevala Expanse",
+ "TA9T-P": "The Kalevala Expanse",
+ "L-TLFU": "The Kalevala Expanse",
+ "BM-VYZ": "The Kalevala Expanse",
+ "Q-GICU": "The Kalevala Expanse",
+ "EPCD-D": "The Kalevala Expanse",
+ "0S1-GI": "The Kalevala Expanse",
+ "L-GY1B": "The Kalevala Expanse",
+ "74-DRC": "The Kalevala Expanse",
+ "LE-67X": "The Kalevala Expanse",
+ "B1UE-J": "The Kalevala Expanse",
+ "O31W-6": "The Kalevala Expanse",
+ "M3-H2Y": "The Kalevala Expanse",
+ "G-KCFT": "The Kalevala Expanse",
+ "WNM-V0": "The Kalevala Expanse",
+ "6FS-CZ": "The Kalevala Expanse",
+ "HPV-RJ": "The Kalevala Expanse",
+ "H7S-5I": "The Kalevala Expanse",
+ "C3J0-O": "The Kalevala Expanse",
+ "GSO-SR": "The Kalevala Expanse",
+ "B3ZU-H": "The Kalevala Expanse",
+ "G4-QU6": "The Kalevala Expanse",
+ "V2-GZS": "The Kalevala Expanse",
+ "HD-HOZ": "The Kalevala Expanse",
+ "42G-OB": "The Kalevala Expanse",
+ "LEM-I1": "The Kalevala Expanse",
+ "1S-SU1": "The Kalevala Expanse",
+ "ND-GL4": "The Kalevala Expanse",
+ "9-0QB7": "The Kalevala Expanse",
+ "M-75WN": "The Kalevala Expanse",
+ "PNFW-O": "The Kalevala Expanse",
+ "HVGR-R": "The Kalevala Expanse",
+ "K76A-3": "The Kalevala Expanse",
+ "K95-9I": "The Kalevala Expanse",
+ "R1O-GN": "The Kalevala Expanse",
+ "GQ-7SP": "The Kalevala Expanse",
+ "BGMZ-0": "The Kalevala Expanse",
+ "I2D3-5": "The Kalevala Expanse",
+ "FZX-PU": "The Kalevala Expanse",
+ "O9K-FT": "The Kalevala Expanse",
+ "RQOO-U": "The Kalevala Expanse",
+ "FB5U-I": "The Kalevala Expanse",
+ "BZ-BCK": "The Kalevala Expanse",
+ "5-VFC6": "The Kalevala Expanse",
+ "O5-YNW": "The Kalevala Expanse",
+ "86L-9F": "The Kalevala Expanse",
+ "IUU3-L": "The Kalevala Expanse",
+ "J-OAH2": "The Kalevala Expanse",
+ "S-LHPJ": "The Kalevala Expanse",
+ "4U90-Z": "Deklein",
+ "T-945F": "Deklein",
+ "FO8M-2": "Deklein",
+ "AD-CBT": "Deklein",
+ "QPO-WI": "Deklein",
+ "R8S-1K": "Deklein",
+ "94-H3F": "Deklein",
+ "CU9-T0": "Deklein",
+ "XCF-8N": "Deklein",
+ "FMB-JP": "Deklein",
+ "0P-F3K": "Deklein",
+ "K5F-Z2": "Deklein",
+ "TXME-A": "Deklein",
+ "YA0-XJ": "Deklein",
+ "2-KF56": "Deklein",
+ "VFK-IV": "Deklein",
+ "2R-CRW": "Deklein",
+ "CCP-US": "Deklein",
+ "II-5O9": "Deklein",
+ "I30-3A": "Deklein",
+ "2O9G-D": "Deklein",
+ "NC-N3F": "Deklein",
+ "JU-OWQ": "Deklein",
+ "S-DN5M": "Deklein",
+ "MXX5-9": "Deklein",
+ "ZZZR-5": "Deklein",
+ "C7Y-7Z": "Deklein",
+ "X-Z4DA": "Deklein",
+ "3OAT-Q": "Deklein",
+ "N-TFXK": "Deklein",
+ "33RB-O": "Deklein",
+ "DKUK-G": "Deklein",
+ "3QE-9Q": "Deklein",
+ "E-FIC0": "Deklein",
+ "ZOYW-O": "Deklein",
+ "85-B52": "Deklein",
+ "YZ-UKA": "Deklein",
+ "RO0-AF": "Deklein",
+ "5W3-DG": "Deklein",
+ "LT-DRO": "Deklein",
+ "7T6P-C": "Deklein",
+ "8S28-3": "Deklein",
+ "E3UY-6": "Deklein",
+ "LEK-N5": "Deklein",
+ "AGG-NR": "Deklein",
+ "0V0R-R": "Deklein",
+ "O-2RNZ": "Deklein",
+ "OWXT-5": "Deklein",
+ "3JN9-Q": "Deklein",
+ "3T7-M8": "Deklein",
+ "WUZ-WM": "Deklein",
+ "MZ1E-P": "Deklein",
+ "43B-O1": "Deklein",
+ "J1AU-9": "Deklein",
+ "X3-PBC": "Deklein",
+ "4N-BUI": "Deklein",
+ "N2IS-B": "Deklein",
+ "XCBK-X": "Deklein",
+ "GY5-26": "Deklein",
+ "VPLL-N": "Deklein",
+ "9CK-KZ": "Deklein",
+ "5S-KXA": "Deklein",
+ "U-TJ7Y": "Deklein",
+ "A4L-A2": "Deklein",
+ "CZDJ-1": "Deklein",
+ "RG9-7U": "Deklein",
+ "UJY-HE": "Deklein",
+ "UEJX-G": "Deklein",
+ "Tzvi": "Devoid",
+ "Raa": "Devoid",
+ "Sifilar": "Devoid",
+ "Arzad": "Devoid",
+ "Oyeman": "Devoid",
+ "Ezzara": "Devoid",
+ "Odin": "Devoid",
+ "Esescama": "Devoid",
+ "Choonka": "Devoid",
+ "Thasinaz": "Devoid",
+ "Dihra": "Devoid",
+ "Dital": "Devoid",
+ "Eredan": "Devoid",
+ "Ohide": "Devoid",
+ "Sasoutikh": "Devoid",
+ "Gheth": "Devoid",
+ "Lisudeh": "Devoid",
+ "Mehatoor": "Devoid",
+ "Roushzar": "Devoid",
+ "Labapi": "Devoid",
+ "Arayar": "Devoid",
+ "Asghed": "Devoid",
+ "Tararan": "Devoid",
+ "Sosan": "Devoid",
+ "Halmah": "Devoid",
+ "Rahadalon": "Devoid",
+ "Soosat": "Devoid",
+ "Ibash": "Devoid",
+ "Itsyamil": "Devoid",
+ "Mendori": "Devoid",
+ "Ussad": "Devoid",
+ "Nakatre": "Devoid",
+ "Laddiaha": "Devoid",
+ "Hakshma": "Devoid",
+ "Uadelah": "Devoid",
+ "Akes": "Devoid",
+ "Riavayed": "Devoid",
+ "Hati": "Devoid",
+ "Naeel": "Devoid",
+ "Lower Debyl": "Devoid",
+ "Ehnoum": "Devoid",
+ "Upper Debyl": "Devoid",
+ "Shastal": "Devoid",
+ "Thakala": "Devoid",
+ "Mili": "Devoid",
+ "Faktun": "Devoid",
+ "Halenan": "Devoid",
+ "Ulerah": "Devoid",
+ "Uktiad": "Devoid",
+ "Nidebora": "Devoid",
+ "Arveyil": "Devoid",
+ "Palpis": "Devoid",
+ "Arnatele": "Everyshore",
+ "Halle": "Everyshore",
+ "Mormoen": "Everyshore",
+ "Amattens": "Everyshore",
+ "Jurlesel": "Everyshore",
+ "Bereye": "Everyshore",
+ "Aice": "Everyshore",
+ "Junsoraert": "Everyshore",
+ "Harerget": "Everyshore",
+ "Azer": "Everyshore",
+ "Cherore": "Everyshore",
+ "Torvi": "Everyshore",
+ "Mosson": "Everyshore",
+ "Mya": "Everyshore",
+ "Gerper": "Everyshore",
+ "Marosier": "Everyshore",
+ "Lirsautton": "Everyshore",
+ "Blameston": "Everyshore",
+ "Vaurent": "Everyshore",
+ "Aclan": "Everyshore",
+ "Jaschercis": "Everyshore",
+ "Ardallabier": "Everyshore",
+ "Athinard": "Everyshore",
+ "Meves": "Everyshore",
+ "Ethernity": "Everyshore",
+ "Mattere": "Everyshore",
+ "Gicodel": "Everyshore",
+ "Frarolle": "Everyshore",
+ "Quier": "Everyshore",
+ "Atlanins": "Everyshore",
+ "Leremblompes": "Everyshore",
+ "Bille": "Everyshore",
+ "Colcer": "Everyshore",
+ "Alachene": "Everyshore",
+ "Uphene": "Everyshore",
+ "Elarel": "Everyshore",
+ "Enedore": "Everyshore",
+ "Angymonne": "Everyshore",
+ "Averon": "Everyshore",
+ "Carirgnottin": "Everyshore",
+ "Laic": "Everyshore",
+ "Odixie": "Everyshore",
+ "Antollare": "Everyshore",
+ "Tolle": "Everyshore",
+ "Avele": "Everyshore",
+ "Scuelazyns": "Everyshore",
+ "Aydoteaux": "Everyshore",
+ "Muer": "Everyshore",
+ "Groothese": "Everyshore",
+ "Olide": "Everyshore",
+ "Adeel": "Everyshore",
+ "Mannar": "Everyshore",
+ "Mormelot": "Everyshore",
+ "Angatalie": "Everyshore",
+ "Lamaa": "The Bleak Lands",
+ "Tuomuta": "The Bleak Lands",
+ "Otelen": "The Bleak Lands",
+ "Kuomi": "The Bleak Lands",
+ "Huola": "The Bleak Lands",
+ "Kourmonen": "The Bleak Lands",
+ "Kamela": "The Bleak Lands",
+ "Sosala": "The Bleak Lands",
+ "Anka": "The Bleak Lands",
+ "Iesa": "The Bleak Lands",
+ "Netsalakka": "The Bleak Lands",
+ "Sasiekko": "The Bleak Lands",
+ "Myyhera": "The Bleak Lands",
+ "Gammel": "The Bleak Lands",
+ "Uusanen": "The Bleak Lands",
+ "Erkinen": "The Bleak Lands",
+ "Saikamon": "The Bleak Lands",
+ "Jarkkolen": "The Bleak Lands",
+ "Ronne": "The Bleak Lands",
+ "Hatori": "The Bleak Lands",
+ "Junsen": "The Bleak Lands",
+ "Malpara": "The Bleak Lands",
+ "Hakodan": "The Bleak Lands",
+ "Sahtogas": "The Bleak Lands",
+ "Haras": "The Bleak Lands",
+ "Oyonata": "The Bleak Lands",
+ "Kurniainen": "The Bleak Lands",
+ "Saidusairos": "The Bleak Lands",
+ "Tannakan": "The Bleak Lands",
+ "Komaa": "The Bleak Lands",
+ "Ayeroilen": "The Bleak Lands",
+ "Imata": "The Bleak Lands",
+ "Furskeshin": "The Bleak Lands",
+ "Kurmaru": "The Bleak Lands",
+ "Satalama": "The Bleak Lands",
+ "VYJ-DA": "Esoteria",
+ "HHQ-M1": "Esoteria",
+ "A-CJGE": "Esoteria",
+ "G2-INZ": "Esoteria",
+ "WAC-HW": "Esoteria",
+ "HT4K-M": "Esoteria",
+ "RBW-8G": "Esoteria",
+ "4-OUKF": "Esoteria",
+ "HAJ-DQ": "Esoteria",
+ "JAUD-V": "Esoteria",
+ "DTX8-M": "Esoteria",
+ "C9N-CC": "Esoteria",
+ "X-7BIX": "Esoteria",
+ "5-9UXZ": "Esoteria",
+ "Q0OH-V": "Esoteria",
+ "C-VZAK": "Esoteria",
+ "0-O6XF": "Esoteria",
+ "D-FVI7": "Esoteria",
+ "VL7-60": "Esoteria",
+ "NH-R5B": "Esoteria",
+ "FN-GFQ": "Esoteria",
+ "XKZ8-H": "Esoteria",
+ "WX-6UX": "Esoteria",
+ "BZ-0GW": "Esoteria",
+ "16P-PX": "Esoteria",
+ "CR-0E5": "Esoteria",
+ "Z-Y9C3": "Esoteria",
+ "A1-AUH": "Esoteria",
+ "F-UVBV": "Esoteria",
+ "R-FM0G": "Esoteria",
+ "TEIZ-C": "Esoteria",
+ "VUAC-Y": "Esoteria",
+ "V-XANH": "Esoteria",
+ "450I-W": "Esoteria",
+ "OIOM-Y": "Esoteria",
+ "G-YZUX": "Esoteria",
+ "CZ6U-1": "Esoteria",
+ "D-PNP9": "Esoteria",
+ "E1UU-3": "Esoteria",
+ "P-3XVV": "Esoteria",
+ "BY-MSY": "Esoteria",
+ "6EK-BV": "Esoteria",
+ "IR-FDV": "Esoteria",
+ "NIZJ-0": "Esoteria",
+ "J-RVGD": "Esoteria",
+ "V1ZC-S": "Esoteria",
+ "H-T40Z": "Esoteria",
+ "6-TYRX": "Esoteria",
+ "Q1-R7K": "Esoteria",
+ "111-F1": "Esoteria",
+ "JD-TYH": "Esoteria",
+ "02V-BK": "Esoteria",
+ "A5MT-B": "Esoteria",
+ "R-ARKN": "Esoteria",
+ "SN9S-N": "Esoteria",
+ "MS2-V8": "Esoteria",
+ "Z-MO29": "Esoteria",
+ "G-JC9R": "Esoteria",
+ "DIBH-Q": "Esoteria",
+ "DNEP-Y": "Esoteria",
+ "YAP-TN": "Esoteria",
+ "PE-H02": "Esoteria",
+ "H-YHYM": "Esoteria",
+ "G-4H4C": "Esoteria",
+ "HHE5-L": "Esoteria",
+ "P9F-ZG": "Esoteria",
+ "QFGB-E": "Esoteria",
+ "7P-J38": "Esoteria",
+ "WT-2J9": "Esoteria",
+ "PK-PHZ": "Esoteria",
+ "L-M6JK": "Esoteria",
+ "C-PEWN": "Esoteria",
+ "DL-CDY": "Esoteria",
+ "29YH-V": "Esoteria",
+ "LG-RO2": "Esoteria",
+ "X-HISR": "Esoteria",
+ "QS-530": "Esoteria",
+ "VR-YRV": "Esoteria",
+ "IPX-H5": "Esoteria",
+ "KSM-1T": "Esoteria",
+ "YRV-MZ": "Esoteria",
+ "6SB-BN": "Esoteria",
+ "B1D-KU": "Esoteria",
+ "QFIU-K": "Esoteria",
+ "2R-KLH": "Esoteria",
+ "QB-AE6": "Oasa",
+ "G-W1ND": "Oasa",
+ "MZLW-9": "Oasa",
+ "ND-X7X": "Oasa",
+ "DGDT-3": "Oasa",
+ "2-WNTD": "Oasa",
+ "83-YGI": "Oasa",
+ "KH-EWC": "Oasa",
+ "3VL6-I": "Oasa",
+ "F-816R": "Oasa",
+ "DS3-6A": "Oasa",
+ "V0-H4L": "Oasa",
+ "T-HMWP": "Oasa",
+ "DYS-CG": "Oasa",
+ "MTGF-2": "Oasa",
+ "0-QP56": "Oasa",
+ "GTQ-C9": "Oasa",
+ "M-NWLB": "Oasa",
+ "ORB4-J": "Oasa",
+ "GGMF-J": "Oasa",
+ "IG-4OF": "Oasa",
+ "LQQH-J": "Oasa",
+ "W5-VBR": "Oasa",
+ "J-D5U7": "Oasa",
+ "Y-770C": "Oasa",
+ "X-Z4JW": "Oasa",
+ "R8WV-7": "Oasa",
+ "6U-MFQ": "Oasa",
+ "1EO-OE": "Oasa",
+ "YQTK-R": "Oasa",
+ "FZCR-3": "Oasa",
+ "5-9L3H": "Oasa",
+ "1-HDQ4": "Oasa",
+ "WVMS-X": "Oasa",
+ "7-UVMT": "Oasa",
+ "R-ZESX": "Oasa",
+ "IO-R2S": "Oasa",
+ "HF-K3O": "Oasa",
+ "QE2-FS": "Oasa",
+ "Q-ITV5": "Oasa",
+ "5JEZ-I": "Oasa",
+ "XEF6-Z": "Oasa",
+ "SON-TW": "Oasa",
+ "V-X0KM": "Oasa",
+ "U9SE-N": "Oasa",
+ "XXZ-3W": "Oasa",
+ "RF-X7V": "Oasa",
+ "BQ0-UU": "Oasa",
+ "3-JG3X": "Oasa",
+ "GK3-RX": "Oasa",
+ "1P-QWR": "Oasa",
+ "FJ-GUR": "Oasa",
+ "UGR-J2": "Oasa",
+ "QZ-DIZ": "Oasa",
+ "Y-0HVF": "Oasa",
+ "21M1-B": "Oasa",
+ "KED-2O": "Oasa",
+ "U-RELP": "Oasa",
+ "IAMJ-Q": "Oasa",
+ "E6Q-LE": "Oasa",
+ "HO4E-Q": "Oasa",
+ "QY2Y-N": "Oasa",
+ "X-9ZZR": "Oasa",
+ "RO-AIQ": "Oasa",
+ "VZEG-B": "Oasa",
+ "P-ZWKH": "Oasa",
+ "9G5J-1": "Oasa",
+ "B-ETDW": "Oasa",
+ "0PU2-R": "Oasa",
+ "XM-RMD": "Oasa",
+ "91-KD8": "Oasa",
+ "OZ-DS5": "Oasa",
+ "LA2-KV": "Oasa",
+ "WW-OVQ": "Oasa",
+ "S7WI-F": "Oasa",
+ "1-BK1Q": "Oasa",
+ "X-CYNC": "Oasa",
+ "RJBC-I": "Oasa",
+ "H-MHWF": "Oasa",
+ "PND-SI": "Oasa",
+ "XKM-DE": "Oasa",
+ "JXQJ-B": "Oasa",
+ "Y-BIPM": "Oasa",
+ "QYT-X8": "Oasa",
+ "5-IH57": "Oasa",
+ "MHC-R3": "Syndicate",
+ "F67E-Q": "Syndicate",
+ "6E-578": "Syndicate",
+ "Poitot": "Syndicate",
+ "ZVN5-H": "Syndicate",
+ "ATY-2U": "Syndicate",
+ "X-BV98": "Syndicate",
+ "2X-PQG": "Syndicate",
+ "FD-MLJ": "Syndicate",
+ "PF-346": "Syndicate",
+ "X-M2LR": "Syndicate",
+ "K5-JRD": "Syndicate",
+ "6-CZ49": "Syndicate",
+ "EZA-FM": "Syndicate",
+ "8-JYPM": "Syndicate",
+ "PVH8-0": "Syndicate",
+ "M2-CF1": "Syndicate",
+ "JH-M2W": "Syndicate",
+ "PC9-AY": "Syndicate",
+ "T22-QI": "Syndicate",
+ "X-PYH5": "Syndicate",
+ "ZN0-SR": "Syndicate",
+ "5-DSFH": "Syndicate",
+ "AK-QBU": "Syndicate",
+ "QWF-6P": "Syndicate",
+ "AAS-8R": "Syndicate",
+ "V4-L0X": "Syndicate",
+ "PFP-GU": "Syndicate",
+ "0EK-NJ": "Syndicate",
+ "1-NKVT": "Syndicate",
+ "UM-Q7F": "Syndicate",
+ "T-LIWS": "Syndicate",
+ "KTHT-O": "Syndicate",
+ "97X-CH": "Syndicate",
+ "5-T0PZ": "Syndicate",
+ "6R-PWU": "Syndicate",
+ "2Q-I6Q": "Syndicate",
+ "A-ZLHX": "Syndicate",
+ "UTKS-5": "Syndicate",
+ "Y9G-KS": "Syndicate",
+ "I-YGGI": "Syndicate",
+ "VV-VCR": "Syndicate",
+ "5-75MB": "Syndicate",
+ "IIRH-G": "Syndicate",
+ "35-RK9": "Syndicate",
+ "XS-XAY": "Syndicate",
+ "DP34-U": "Syndicate",
+ "617I-I": "Syndicate",
+ "6-U2M8": "Syndicate",
+ "I0AB-R": "Syndicate",
+ "MXYS-8": "Syndicate",
+ "A-3ES3": "Syndicate",
+ "8V-SJJ": "Syndicate",
+ "5-FGQI": "Syndicate",
+ "3KNK-A": "Syndicate",
+ "TXW-EI": "Syndicate",
+ "3MOG-V": "Syndicate",
+ "NG-C6Y": "Syndicate",
+ "XYY-IA": "Syndicate",
+ "BMNV-P": "Syndicate",
+ "BY-S36": "Syndicate",
+ "31-MLU": "Syndicate",
+ "0LTQ-C": "Syndicate",
+ "A9D-R0": "Syndicate",
+ "2P-4LS": "Syndicate",
+ "RF-GGF": "Syndicate",
+ "LSC4-P": "Syndicate",
+ "A-SJ8X": "Syndicate",
+ "10UZ-P": "Syndicate",
+ "EN-VOD": "Syndicate",
+ "9GYL-O": "Syndicate",
+ "VLGD-R": "Syndicate",
+ "S-GKKR": "Syndicate",
+ "9U-TTJ": "Syndicate",
+ "Y-W6GF": "Syndicate",
+ "KFR-ZE": "Syndicate",
+ "KLYN-8": "Syndicate",
+ "D85-VD": "Syndicate",
+ "5-VKCN": "Syndicate",
+ "U0V6-T": "Syndicate",
+ "5KS-AB": "Syndicate",
+ "0T-AMZ": "Syndicate",
+ "57-YRU": "Syndicate",
+ "4L-E5P": "Syndicate",
+ "UFXF-C": "Syndicate",
+ "RLL-9R": "Syndicate",
+ "51-5XG": "Syndicate",
+ "EF-F36": "Syndicate",
+ "3-IN0V": "Syndicate",
+ "Z-QENW": "Syndicate",
+ "D-B7YK": "Syndicate",
+ "DUV-5Y": "Syndicate",
+ "GRNJ-3": "Syndicate",
+ "VSIG-K": "Syndicate",
+ "RSS-KA": "Syndicate",
+ "CIS-7X": "Syndicate",
+ "DCHR-L": "Syndicate",
+ "EU0I-T": "Syndicate",
+ "4-JWWQ": "Syndicate",
+ "G-6SXJ": "Syndicate",
+ "S-U8A4": "Syndicate",
+ "ZV-72W": "Syndicate",
+ "2G38-I": "Syndicate",
+ "CY-ZLP": "Syndicate",
+ "U4-Q2V": "Syndicate",
+ "98Q-8O": "Syndicate",
+ "Bei": "Metropolis",
+ "Uttindar": "Metropolis",
+ "Hagilur": "Metropolis",
+ "Anher": "Metropolis",
+ "Ragnarg": "Metropolis",
+ "Hek": "Metropolis",
+ "Hror": "Metropolis",
+ "Amo": "Metropolis",
+ "Resbroko": "Metropolis",
+ "Hadozeko": "Metropolis",
+ "Ardar": "Metropolis",
+ "Auner": "Metropolis",
+ "Evati": "Metropolis",
+ "Ofstold": "Metropolis",
+ "Todifrauan": "Metropolis",
+ "Helgatild": "Metropolis",
+ "Arnstur": "Metropolis",
+ "Lasleinur": "Metropolis",
+ "Arnher": "Metropolis",
+ "Brin": "Metropolis",
+ "Nakugard": "Metropolis",
+ "Traun": "Metropolis",
+ "Uriok": "Metropolis",
+ "Barkrik": "Metropolis",
+ "Inder": "Metropolis",
+ "Tvink": "Metropolis",
+ "Lanngisi": "Metropolis",
+ "Hjoramold": "Metropolis",
+ "Dudreda": "Metropolis",
+ "Hakisalki": "Metropolis",
+ "Arwa": "Metropolis",
+ "Krirald": "Metropolis",
+ "Arifsdald": "Metropolis",
+ "Ansen": "Metropolis",
+ "Floseswin": "Metropolis",
+ "Uisper": "Metropolis",
+ "Aset": "Metropolis",
+ "Eytjangard": "Metropolis",
+ "Turnur": "Metropolis",
+ "Isbrabata": "Metropolis",
+ "Vimeini": "Metropolis",
+ "Avenod": "Metropolis",
+ "Frerstorn": "Metropolis",
+ "Ontorn": "Metropolis",
+ "Sirekur": "Metropolis",
+ "Gebuladi": "Metropolis",
+ "Ebolfer": "Metropolis",
+ "Eszur": "Metropolis",
+ "Hofjaldgund": "Metropolis",
+ "Klogori": "Metropolis",
+ "Orfrold": "Metropolis",
+ "Egmar": "Metropolis",
+ "Taff": "Metropolis",
+ "Ualkin": "Metropolis",
+ "Gukarla": "Metropolis",
+ "Arlulf": "Metropolis",
+ "Brundakur": "Metropolis",
+ "Stirht": "Metropolis",
+ "Illuin": "Metropolis",
+ "Nedegulf": "Metropolis",
+ "Aldilur": "Metropolis",
+ "Alf": "Metropolis",
+ "Eust": "Metropolis",
+ "Flost": "Metropolis",
+ "Todrir": "Metropolis",
+ "Asgeir": "Metropolis",
+ "Evuldgenzo": "Metropolis",
+ "Ongund": "Metropolis",
+ "Jondik": "Metropolis",
+ "Olbra": "Metropolis",
+ "Altrinur": "Metropolis",
+ "Vilur": "Metropolis",
+ "Reset": "Metropolis",
+ "Eygfe": "Metropolis",
+ "Eiluvodi": "Metropolis",
+ "Freatlidur": "Metropolis",
+ "Roleinn": "Metropolis",
+ "Maturat": "Metropolis",
+ "Bongveber": "Metropolis",
+ "Anbald": "Metropolis",
+ "Vorsk": "Metropolis",
+ "Hjortur": "Metropolis",
+ "Egbonbet": "Metropolis",
+ "Totkubad": "Metropolis",
+ "Meimungen": "Metropolis",
+ "Agtver": "Metropolis",
+ "Datulen": "Metropolis",
+ "Situner": "Metropolis",
+ "Tamekamur": "Metropolis",
+ "Evettullur": "Metropolis",
+ "Leurtmar": "Metropolis",
+ "Ryddinjorn": "Metropolis",
+ "Arlek": "Metropolis",
+ "Elgoi": "Metropolis",
+ "Eram": "Metropolis",
+ "Yrmori": "Metropolis",
+ "Aldagolf": "Metropolis",
+ "Aldrat": "Metropolis",
+ "Urnhard": "Metropolis",
+ "Hardbako": "Metropolis",
+ "Erstur": "Metropolis",
+ "Fredagod": "Metropolis",
+ "Libold": "Metropolis",
+ "Wirdalen": "Metropolis",
+ "Nein": "Metropolis",
+ "Enden": "Metropolis",
+ "Erstet": "Metropolis",
+ "Anstard": "Metropolis",
+ "Osvestmunnur": "Metropolis",
+ "Hilfhurmur": "Metropolis",
+ "Geffur": "Metropolis",
+ "Oppold": "Metropolis",
+ "Tratokard": "Metropolis",
+ "Lumegen": "Metropolis",
+ "Gedugaud": "Metropolis",
+ "Polstodur": "Metropolis",
+ "Hebisa": "Metropolis",
+ "Tollus": "Metropolis",
+ "Ogoten": "Metropolis",
+ "Earled": "Metropolis",
+ "Aderkan": "Metropolis",
+ "Ansher": "Metropolis",
+ "Earwik": "Metropolis",
+ "Finanar": "Metropolis",
+ "Moselgi": "Metropolis",
+ "Mateber": "Metropolis",
+ "Iluin": "Metropolis",
+ "Ofage": "Metropolis",
+ "Josekorn": "Metropolis",
+ "Nifflung": "Metropolis",
+ "Hakeri": "Metropolis",
+ "Oraekja": "Metropolis",
+ "Dantbeinn": "Metropolis",
+ "Irgrus": "Metropolis",
+ "Orduin": "Metropolis",
+ "Engosi": "Metropolis",
+ "Atonder": "Metropolis",
+ "Hotrardik": "Metropolis",
+ "Ridoner": "Metropolis",
+ "Klaevik": "Metropolis",
+ "Lirerim": "Metropolis",
+ "Offikatlin": "Metropolis",
+ "Diromitur": "Metropolis",
+ "Eldjaerin": "Metropolis",
+ "Erlendur": "Metropolis",
+ "Aldik": "Metropolis",
+ "Tabbetzur": "Metropolis",
+ "Eurgrana": "Metropolis",
+ "Frulegur": "Metropolis",
+ "Hroduko": "Metropolis",
+ "Hodrold": "Metropolis",
+ "Odebeinn": "Metropolis",
+ "Konora": "Metropolis",
+ "Erindur": "Metropolis",
+ "Abrat": "Metropolis",
+ "Orgron": "Metropolis",
+ "Embod": "Metropolis",
+ "Erego": "Metropolis",
+ "Fildar": "Metropolis",
+ "Amarr": "Domain",
+ "Boranai": "Domain",
+ "Hedion": "Domain",
+ "Mabnen": "Domain",
+ "Toshabia": "Domain",
+ "Irnin": "Domain",
+ "Kehour": "Domain",
+ "Martha": "Domain",
+ "Simbeloud": "Domain",
+ "Ebidan": "Domain",
+ "Akhragan": "Domain",
+ "Mikhir": "Domain",
+ "Bashakru": "Domain",
+ "Sukirah": "Domain",
+ "Shuria": "Domain",
+ "Narai": "Domain",
+ "Ziona": "Domain",
+ "Gaha": "Domain",
+ "Armala": "Domain",
+ "Murema": "Domain",
+ "Cailanar": "Domain",
+ "Ilonarav": "Domain",
+ "Uchat": "Domain",
+ "Joppaya": "Domain",
+ "Pelkia": "Domain",
+ "Raren": "Domain",
+ "Mazitah": "Domain",
+ "Hiramu": "Domain",
+ "Sakhti": "Domain",
+ "Aldali": "Domain",
+ "Hutian": "Domain",
+ "Noli": "Domain",
+ "Nomash": "Domain",
+ "Aghesi": "Domain",
+ "Fabin": "Domain",
+ "Airshaz": "Domain",
+ "Patzcha": "Domain",
+ "Charra": "Domain",
+ "Harva": "Domain",
+ "Thebeka": "Domain",
+ "Rasile": "Domain",
+ "Nererut": "Domain",
+ "Sitanan": "Domain",
+ "Vashkah": "Domain",
+ "Ardishapur Prime": "Domain",
+ "Gid": "Domain",
+ "Dakba": "Domain",
+ "Nifshed": "Domain",
+ "Shumam": "Domain",
+ "Milal": "Domain",
+ "Sobenah": "Domain",
+ "Bourar": "Domain",
+ "Rammi": "Domain",
+ "Arodan": "Domain",
+ "Rimbah": "Domain",
+ "Mamenkhanar": "Domain",
+ "Seiradih": "Domain",
+ "Arera": "Domain",
+ "Hizhara": "Domain",
+ "Neziel": "Domain",
+ "Ahala": "Domain",
+ "Knophtikoo": "Domain",
+ "Ruchy": "Domain",
+ "Hai": "Domain",
+ "Sadye": "Domain",
+ "Bika": "Domain",
+ "Arshat": "Domain",
+ "Jerma": "Domain",
+ "Miyeli": "Domain",
+ "Reyi": "Domain",
+ "Moussou": "Domain",
+ "Nadohman": "Domain",
+ "Sahdil": "Domain",
+ "Esteban": "Domain",
+ "Luromooh": "Domain",
+ "Nalu": "Domain",
+ "Jarshitsan": "Domain",
+ "Hadonoo": "Domain",
+ "Azizora": "Domain",
+ "Ahmak": "Domain",
+ "Shabura": "Domain",
+ "Adia": "Domain",
+ "Ebo": "Domain",
+ "Avair": "Domain",
+ "Rayl": "Domain",
+ "Asoutar": "Domain",
+ "Porsharrah": "Domain",
+ "Tastela": "Domain",
+ "Clarelam": "Domain",
+ "Isamm": "Domain",
+ "Ebtesham": "Domain",
+ "Artoun": "Domain",
+ "Safizon": "Domain",
+ "Zatsyaki": "Domain",
+ "Eba": "Domain",
+ "Bhizheba": "Domain",
+ "Fahruni": "Domain",
+ "Sahda": "Domain",
+ "Naguton": "Domain",
+ "Ealur": "Domain",
+ "Shajarleg": "Domain",
+ "Basan": "Domain",
+ "Akila": "Domain",
+ "Amod": "Domain",
+ "Unefsih": "Domain",
+ "Mista": "Domain",
+ "Valmu": "Domain",
+ "Sibot": "Domain",
+ "Andabiar": "Domain",
+ "Kheram": "Domain",
+ "Arbaz": "Domain",
+ "Penirgman": "Domain",
+ "Chaven": "Domain",
+ "Khopa": "Domain",
+ "Ashab": "Domain",
+ "Orkashu": "Domain",
+ "Youl": "Domain",
+ "Ekid": "Domain",
+ "Raravoss": "Domain",
+ "Nakri": "Domain",
+ "Zaimeth": "Domain",
+ "Sharhelund": "Domain",
+ "Mai": "Domain",
+ "Sharji": "Domain",
+ "Kudi": "Domain",
+ "Bahromab": "Domain",
+ "Madirmilire": "Domain",
+ "Niarja": "Domain",
+ "Fabum": "Domain",
+ "Saana": "Domain",
+ "Teshi": "Domain",
+ "Sayartchen": "Domain",
+ "Gosalav": "Domain",
+ "Sorzielang": "Domain",
+ "Somouh": "Domain",
+ "Abaim": "Domain",
+ "Ides": "Domain",
+ "Yeeramoun": "Domain",
+ "Anila": "Domain",
+ "Pedel": "Domain",
+ "Etav": "Domain",
+ "Saheri": "Domain",
+ "Lahnina": "Domain",
+ "Mahrokht": "Domain",
+ "Alkabsi": "Domain",
+ "Sarum Prime": "Domain",
+ "Hama": "Domain",
+ "Irnal": "Domain",
+ "Bagodan": "Domain",
+ "Murzi": "Domain",
+ "Chesoh": "Domain",
+ "Herila": "Domain",
+ "Chemilip": "Domain",
+ "Raravath": "Domain",
+ "Hisoufad": "Domain",
+ "Jesoyeh": "Domain",
+ "Hahda": "Domain",
+ "Namaili": "Domain",
+ "Afivad": "Domain",
+ "Uzigh": "Domain",
+ "Erzoh": "Domain",
+ "Merz": "Domain",
+ "Miakie": "Domain",
+ "Sirkahri": "Domain",
+ "Faswiba": "Domain",
+ "Hayumtom": "Domain",
+ "Zanka": "Domain",
+ "Galeh": "Domain",
+ "Yuhelia": "Domain",
+ "Maiah": "Domain",
+ "Hamse": "Domain",
+ "Barira": "Domain",
+ "Lashkai": "Domain",
+ "Zhilshinou": "Domain",
+ "Jaswelu": "Domain",
+ "Ana": "Domain",
+ "Warouh": "Domain",
+ "Jambu": "Domain",
+ "Bittanshal": "Domain",
+ "Arton": "Domain",
+ "Sieh": "Domain",
+ "Madimal": "Domain",
+ "Mamet": "Domain",
+ "Hoshoun": "Domain",
+ "Biphi": "Domain",
+ "Ziriert": "Domain",
+ "Misaba": "Domain",
+ "Rephirib": "Domain",
+ "Deepari": "Domain",
+ "Fora": "Domain",
+ "Hanan": "Domain",
+ "Horir": "Domain",
+ "Conomette": "Solitude",
+ "Aimoguier": "Solitude",
+ "Yveve": "Solitude",
+ "Meunvon": "Solitude",
+ "Cadelanne": "Solitude",
+ "Elore": "Solitude",
+ "Anckee": "Solitude",
+ "Vevelonel": "Solitude",
+ "Pertnineere": "Solitude",
+ "Boystin": "Solitude",
+ "Lour": "Solitude",
+ "Maire": "Solitude",
+ "Oerse": "Solitude",
+ "Octanneve": "Solitude",
+ "Larryn": "Solitude",
+ "Niballe": "Solitude",
+ "Postouvin": "Solitude",
+ "Odinesyn": "Solitude",
+ "Weraroix": "Solitude",
+ "Sarline": "Solitude",
+ "Aeter": "Solitude",
+ "Gererique": "Solitude",
+ "Harner": "Solitude",
+ "Yvaeroure": "Solitude",
+ "Vecodie": "Solitude",
+ "Arasare": "Solitude",
+ "Yvelet": "Solitude",
+ "Lazer": "Solitude",
+ "Stoure": "Solitude",
+ "Heluene": "Solitude",
+ "Arittant": "Solitude",
+ "Oruse": "Solitude",
+ "Hare": "Solitude",
+ "Ogaria": "Solitude",
+ "Faurulle": "Solitude",
+ "Agaullores": "Solitude",
+ "Babirmoult": "Solitude",
+ "Ratillose": "Solitude",
+ "Ondree": "Solitude",
+ "Pochelympe": "Solitude",
+ "Eggheron": "Solitude",
+ "Toustain": "Solitude",
+ "Straloin": "Solitude",
+ "H1-ESN": "Tenal",
+ "3DR-CR": "Tenal",
+ "RLTG-3": "Tenal",
+ "S-EVIQ": "Tenal",
+ "EOY-BG": "Tenal",
+ "PNS7-J": "Tenal",
+ "IG-ZAM": "Tenal",
+ "0-UVHJ": "Tenal",
+ "NCG-PW": "Tenal",
+ "1QH-0K": "Tenal",
+ "ZH3-BS": "Tenal",
+ "ZJ-QOO": "Tenal",
+ "ZXA-V6": "Tenal",
+ "I1-BE8": "Tenal",
+ "W8O-19": "Tenal",
+ "U1TX-A": "Tenal",
+ "1BWK-S": "Tenal",
+ "KMV-CQ": "Tenal",
+ "RKE-CP": "Tenal",
+ "NV-3KA": "Tenal",
+ "S-1LIO": "Tenal",
+ "S-KSWL": "Tenal",
+ "5-O8B1": "Tenal",
+ "R-YWID": "Tenal",
+ "30-D5G": "Tenal",
+ "HB-FSO": "Tenal",
+ "J1-KJP": "Tenal",
+ "KW-1MV": "Tenal",
+ "G06-8Y": "Tenal",
+ "U-O2DA": "Tenal",
+ "WV-0R2": "Tenal",
+ "SZ6-TA": "Tenal",
+ "6-AOLS": "Tenal",
+ "IKTD-P": "Tenal",
+ "33CE-7": "Tenal",
+ "L-P3XM": "Tenal",
+ "DCJ-ZT": "Tenal",
+ "O36A-P": "Tenal",
+ "Z-LO6I": "Tenal",
+ "0M-103": "Tenal",
+ "6OYQ-Z": "Tenal",
+ "HE5T-A": "Tenal",
+ "A-1IJ9": "Tenal",
+ "Y-YHZQ": "Tenal",
+ "Z-SR1I": "Tenal",
+ "GW7P-8": "Tenal",
+ "SF-XJS": "Tenal",
+ "A1RR-M": "Tenal",
+ "AR-5SY": "Tenal",
+ "OE-4HB": "Tenal",
+ "ZK-YQ3": "Tenal",
+ "MZPH-W": "Tenal",
+ "W0X-MG": "Tenal",
+ "JI-1UQ": "Tenal",
+ "EN-GTB": "Tenal",
+ "U5-XW7": "Tenal",
+ "JSI-LL": "Tenal",
+ "M-UC0S": "Tenal",
+ "V7-MID": "Tenal",
+ "SY0W-2": "Tenal",
+ "2-3Q2G": "Tenal",
+ "Q1U-IU": "Tenal",
+ "C-XNUA": "Tenal",
+ "7D-PAT": "Tenal",
+ "V-LDEJ": "Tenal",
+ "T-K10W": "Tenal",
+ "P-UCRP": "Tenal",
+ "3-QYVE": "Tenal",
+ "C8-CHY": "Fade",
+ "E-9ORY": "Fade",
+ "CR-IFM": "Fade",
+ "HHK-VL": "Fade",
+ "P-33KR": "Fade",
+ "DO6H-Q": "Fade",
+ "DW-T2I": "Fade",
+ "O-CNPR": "Fade",
+ "L-SCBU": "Fade",
+ "VRH-H7": "Fade",
+ "O1Y-ED": "Fade",
+ "K4YZ-Y": "Fade",
+ "X36Y-G": "Fade",
+ "L-C3O7": "Fade",
+ "YKSC-A": "Fade",
+ "FIO1-8": "Fade",
+ "C-OK0R": "Fade",
+ "0-ARFO": "Fade",
+ "E9KD-N": "Fade",
+ "8W-OSE": "Fade",
+ "WQY-IQ": "Fade",
+ "C4C-Z4": "Fade",
+ "GME-PQ": "Fade",
+ "MPPA-A": "Fade",
+ "X5-UME": "Fade",
+ "I-UUI5": "Fade",
+ "8QMO-E": "Fade",
+ "G-5EN2": "Providence",
+ "9-F0B2": "Providence",
+ "YWS0-Z": "Providence",
+ "4B-NQN": "Providence",
+ "9UY4-H": "Providence",
+ "49GC-R": "Providence",
+ "D-GTMI": "Providence",
+ "FSW-3C": "Providence",
+ "FX-7EM": "Providence",
+ "MH9C-S": "Providence",
+ "G7AQ-7": "Providence",
+ "QBL-BV": "Providence",
+ "T-RPFU": "Providence",
+ "I7S-1S": "Providence",
+ "U-HYMT": "Providence",
+ "FC-3YI": "Providence",
+ "QR-K85": "Providence",
+ "5IO8-U": "Providence",
+ "DP-JD4": "Providence",
+ "OXIY-V": "Providence",
+ "H6-CX8": "Providence",
+ "D61A-G": "Providence",
+ "Shintaht": "Providence",
+ "Y-MPWL": "Providence",
+ "D-6WS1": "Providence",
+ "SI-I89": "Providence",
+ "KBP7-G": "Providence",
+ "B-WPLZ": "Providence",
+ "XHQ-7V": "Providence",
+ "E-YCML": "Providence",
+ "TU-O0T": "Providence",
+ "Y9-MDG": "Providence",
+ "PI5-39": "Providence",
+ "GN7-XY": "Providence",
+ "F-DTOO": "Providence",
+ "5KG-PY": "Providence",
+ "QO-SRI": "Providence",
+ "INQ-WR": "Providence",
+ "S9X-AX": "Providence",
+ "TU-RI6": "Providence",
+ "08Z-JJ": "Providence",
+ "X-4WZD": "Providence",
+ "6-OQJV": "Providence",
+ "AY-YCU": "Providence",
+ "ZT-LPU": "Providence",
+ "3GXF-U": "Providence",
+ "VKI-T7": "Providence",
+ "8P9-BM": "Providence",
+ "F-YH5B": "Providence",
+ "H-GKI6": "Providence",
+ "YQB-22": "Providence",
+ "2-TEGJ": "Providence",
+ "MVCJ-E": "Providence",
+ "AY-24I": "Providence",
+ "BK4-YC": "Providence",
+ "K1I1-J": "Providence",
+ "LF-2KP": "Providence",
+ "JEIV-E": "Providence",
+ "O-Y5JQ": "Providence",
+ "DNR-7M": "Providence",
+ "N-RMSH": "Providence",
+ "K1Y-5H": "Providence",
+ "IWZ3-C": "Providence",
+ "1-1I53": "Providence",
+ "N8XA-L": "Providence",
+ "18-GZM": "Providence",
+ "R3-K7K": "Providence",
+ "X-R3NM": "Providence",
+ "8B-VLX": "Providence",
+ "G-B22J": "Providence",
+ "X6AB-Y": "Providence",
+ "2V-CS5": "Providence",
+ "H9-J8N": "Providence",
+ "HP-6Z6": "Providence",
+ "GA9P-0": "Providence",
+ "7YWV-S": "Providence",
+ "TXJ-II": "Providence",
+ "C1-HAB": "Providence",
+ "3KB-J0": "Providence",
+ "0B-HLZ": "Providence",
+ "Z-RFE3": "Providence",
+ "I-MGAB": "Providence",
+ "18XA-C": "Providence",
+ "3D-CQU": "Providence",
+ "Agoze": "Placid",
+ "Intaki": "Placid",
+ "Brarel": "Placid",
+ "Vey": "Placid",
+ "Annancale": "Placid",
+ "Ostingele": "Placid",
+ "Harroule": "Placid",
+ "Stacmon": "Placid",
+ "Covryn": "Placid",
+ "Iges": "Placid",
+ "Dastryns": "Placid",
+ "Slays": "Placid",
+ "Uphallant": "Placid",
+ "Alperaute": "Placid",
+ "Aunsou": "Placid",
+ "Cumemare": "Placid",
+ "Reynire": "Placid",
+ "Pain": "Placid",
+ "Gare": "Placid",
+ "Pelille": "Placid",
+ "Dour": "Placid",
+ "Grispire": "Placid",
+ "Brellystier": "Placid",
+ "Vivanier": "Placid",
+ "Algasienan": "Placid",
+ "Osmallanais": "Placid",
+ "Ivorider": "Placid",
+ "Mollin": "Placid",
+ "Iffrue": "Placid",
+ "Vilinnon": "Placid",
+ "Ommaerrer": "Placid",
+ "Aulbres": "Placid",
+ "Barleguet": "Placid",
+ "Vestouve": "Placid",
+ "Ausmaert": "Placid",
+ "Espigoure": "Placid",
+ "Kenninck": "Placid",
+ "Archavoinet": "Placid",
+ "Eugales": "Placid",
+ "Frarie": "Placid",
+ "Aubenall": "Placid",
+ "Moclinamaud": "Placid",
+ "Renarelle": "Placid",
+ "Orvolle": "Placid",
+ "Osmeden": "Placid",
+ "Adacyne": "Placid",
+ "Oulley": "Placid",
+ "Chardalane": "Placid",
+ "Maut": "Placid",
+ "Vlillirier": "Placid",
+ "Aldranette": "Placid",
+ "Oicx": "Placid",
+ "Evaulon": "Placid",
+ "Anchauttes": "Placid",
+ "Alsavoinon": "Placid",
+ "Esesier": "Placid",
+ "Avaux": "Placid",
+ "Gallusiene": "Placid",
+ "Ruerrotta": "Placid",
+ "Hedoubel": "Placid",
+ "Amoen": "Placid",
+ "Amasiree": "Placid",
+ "Aubonnie": "Placid",
+ "Alparena": "Placid",
+ "Reschard": "Placid",
+ "Arderonne": "Placid",
+ "Mercomesier": "Placid",
+ "Alamel": "Placid",
+ "Mantenault": "Placid",
+ "Athounon": "Placid",
+ "Odamia": "Placid",
+ "Gousoviba": "Khanid",
+ "Neyi": "Khanid",
+ "Kihtaled": "Khanid",
+ "Ipref": "Khanid",
+ "Agil": "Khanid",
+ "Khanid Prime": "Khanid",
+ "Jachanu": "Khanid",
+ "Sazre": "Khanid",
+ "Bukah": "Khanid",
+ "Ervekam": "Khanid",
+ "Mashtarmem": "Khanid",
+ "Sehsasez": "Khanid",
+ "Osis": "Khanid",
+ "Geztic": "Khanid",
+ "Yezara": "Khanid",
+ "Kahah": "Khanid",
+ "Saloti": "Khanid",
+ "Hishai": "Khanid",
+ "Molea": "Khanid",
+ "Gidali": "Khanid",
+ "Palas": "Khanid",
+ "Safshela": "Khanid",
+ "Reteka": "Khanid",
+ "Moniyyuku": "Khanid",
+ "Lansez": "Khanid",
+ "Keberz": "Khanid",
+ "Nourbal": "Khanid",
+ "Arzanni": "Khanid",
+ "Ashmarir": "Khanid",
+ "Kaira": "Khanid",
+ "Badivefi": "Khanid",
+ "Talidal": "Khanid",
+ "Ashi": "Khanid",
+ "Tzashrah": "Khanid",
+ "Efa": "Khanid",
+ "Moro": "Khanid",
+ "Sabusi": "Khanid",
+ "Ainsan": "Khanid",
+ "Claini": "Khanid",
+ "Gehi": "Khanid",
+ "Seshala": "Khanid",
+ "Vezila": "Khanid",
+ "Ham": "Khanid",
+ "Upt": "Khanid",
+ "Hemouner": "Khanid",
+ "Afnakat": "Khanid",
+ "Col": "Khanid",
+ "Chamemi": "Khanid",
+ "Firbha": "Khanid",
+ "Tegheon": "Khanid",
+ "Bashyam": "Khanid",
+ "Parses": "Khanid",
+ "Balanaz": "Khanid",
+ "Edani": "Khanid",
+ "Danera": "Khanid",
+ "Bomana": "Khanid",
+ "Rahabeda": "Khanid",
+ "Aurejet": "Khanid",
+ "Rilera": "Khanid",
+ "Amafi": "Khanid",
+ "Hakana": "Khanid",
+ "Ashkoo": "Khanid",
+ "Baratar": "Khanid",
+ "Arzieh": "Khanid",
+ "Nahrneder": "Khanid",
+ "Nandeza": "Khanid",
+ "Dimoohan": "Khanid",
+ "Chitiamem": "Khanid",
+ "Kuhri": "Khanid",
+ "Zahefeus": "Khanid",
+ "Zephan": "Khanid",
+ "Neda": "Khanid",
+ "Goudiyah": "Khanid",
+ "Sassecho": "Khanid",
+ "Timudan": "Khanid",
+ "Ibani": "Khanid",
+ "Cabeki": "Khanid",
+ "Irmalin": "Khanid",
+ "Nakis": "Khanid",
+ "Hezere": "Khanid",
+ "Fanathor": "Khanid",
+ "Zirsem": "Khanid",
+ "Pout": "Khanid",
+ "Rafeme": "Khanid",
+ "A2-V27": "Querious",
+ "T8H-66": "Querious",
+ "A3-LOG": "Querious",
+ "7V-KHW": "Querious",
+ "O3L-95": "Querious",
+ "0-WT2D": "Querious",
+ "7GCD-P": "Querious",
+ "G-3BOG": "Querious",
+ "K7D-II": "Querious",
+ "L-6BE1": "Querious",
+ "1M4-FK": "Querious",
+ "V-LEKM": "Querious",
+ "9ES-SI": "Querious",
+ "UQY-IK": "Querious",
+ "60M-TG": "Querious",
+ "0TKF-6": "Querious",
+ "TV8-HS": "Querious",
+ "VT-G2P": "Querious",
+ "YOP-0T": "Querious",
+ "9-HM04": "Querious",
+ "MKD-O8": "Querious",
+ "GOP-GE": "Querious",
+ "SKR-SP": "Querious",
+ "V-3U8T": "Querious",
+ "T8T-RA": "Querious",
+ "A-BO4V": "Querious",
+ "W-IX39": "Querious",
+ "K-B8DK": "Querious",
+ "L-6W1J": "Querious",
+ "P4-3TJ": "Querious",
+ "K-Z0V4": "Querious",
+ "LNVW-K": "Querious",
+ "8B-SAJ": "Querious",
+ "Q2-N6W": "Querious",
+ "C-9RRR": "Querious",
+ "A-5F4A": "Querious",
+ "P-ZMZV": "Querious",
+ "9CG6-H": "Querious",
+ "NDII-Q": "Querious",
+ "UYU-VV": "Querious",
+ "K-L690": "Querious",
+ "W6V-VM": "Querious",
+ "OGY-6D": "Querious",
+ "8-SNUD": "Querious",
+ "H-4R6Z": "Querious",
+ "IGE-NE": "Querious",
+ "UVHO-F": "Querious",
+ "Z-XX2J": "Querious",
+ "YW-SYT": "Querious",
+ "Z-UZZN": "Querious",
+ "DS-LO3": "Querious",
+ "BX2-ZX": "Querious",
+ "RF-CN3": "Querious",
+ "C-7SBM": "Querious",
+ "ZAU-JW": "Querious",
+ "YF-6L1": "Querious",
+ "K-YI1L": "Querious",
+ "KEJY-U": "Querious",
+ "3BK-O7": "Querious",
+ "8-GE2P": "Querious",
+ "QXQ-I6": "Querious",
+ "L3-I3K": "Querious",
+ "3-JCJT": "Querious",
+ "W-IIYI": "Querious",
+ "AO-N1P": "Querious",
+ "4-GJT1": "Querious",
+ "5V-BJI": "Querious",
+ "49-U6U": "Querious",
+ "M1BZ-2": "Querious",
+ "N-M1A3": "Querious",
+ "8QT-H4": "Querious",
+ "F2OY-X": "Querious",
+ "4-2UXV": "Querious",
+ "RKM-GE": "Querious",
+ "DG-L7S": "Querious",
+ "K4-RFZ": "Querious",
+ "L-FVHR": "Querious",
+ "3-FKCZ": "Querious",
+ "ED-L9T": "Querious",
+ "LS-V29": "Querious",
+ "9SBB-9": "Querious",
+ "I1Y-IU": "Querious",
+ "U-HYZN": "Querious",
+ "8-YNBE": "Querious",
+ "YQX-7U": "Querious",
+ "QY1E-N": "Querious",
+ "E-VKJV": "Querious",
+ "BX-VEX": "Querious",
+ "B-7DFU": "Querious",
+ "ZXJ-71": "Querious",
+ "F-NXLQ": "Querious",
+ "ES-Q0W": "Querious",
+ "H74-B0": "Querious",
+ "NU4-2G": "Querious",
+ "3D5K-R": "Querious",
+ "1-3HWZ": "Cloud Ring",
+ "XT-R36": "Cloud Ring",
+ "5-MLDT": "Cloud Ring",
+ "B-DBYQ": "Cloud Ring",
+ "QXW-PV": "Cloud Ring",
+ "DY-F70": "Cloud Ring",
+ "FD53-H": "Cloud Ring",
+ "O-ZXUV": "Cloud Ring",
+ "77-KDQ": "Cloud Ring",
+ "F7C-H0": "Cloud Ring",
+ "TN-T7T": "Cloud Ring",
+ "1-NW2G": "Cloud Ring",
+ "O-IVNH": "Cloud Ring",
+ "O-0HW8": "Cloud Ring",
+ "YI-8ZM": "Cloud Ring",
+ "OU-X3P": "Cloud Ring",
+ "6-4V20": "Cloud Ring",
+ "Q-UA3C": "Cloud Ring",
+ "W-4NUU": "Cloud Ring",
+ "8R-RTB": "Cloud Ring",
+ "6Z9-0M": "Cloud Ring",
+ "FQ9W-C": "Cloud Ring",
+ "9-4RP2": "Cloud Ring",
+ "O-BDXB": "Cloud Ring",
+ "G8AD-C": "Cloud Ring",
+ "XZH-4X": "Cloud Ring",
+ "Z-Y7R7": "Cloud Ring",
+ "MJYW-3": "Cloud Ring",
+ "PPG-XC": "Cloud Ring",
+ "QA1-BT": "Cloud Ring",
+ "5S-KNL": "Cloud Ring",
+ "00TY-J": "Cloud Ring",
+ "XG-D1L": "Cloud Ring",
+ "6RCQ-V": "Cloud Ring",
+ "28O-JY": "Cloud Ring",
+ "CX7-70": "Cloud Ring",
+ "6ON-RW": "Cloud Ring",
+ "U65-CN": "Cloud Ring",
+ "X-M9ON": "Cloud Ring",
+ "P5-KCC": "Cloud Ring",
+ "Hiroudeh": "Kador",
+ "Dresi": "Kador",
+ "Aphend": "Kador",
+ "Romi": "Kador",
+ "Zororzih": "Kador",
+ "Aharalel": "Kador",
+ "Gensela": "Kador",
+ "Ghesis": "Kador",
+ "Gamdis": "Kador",
+ "Joamma": "Kador",
+ "Gonan": "Kador",
+ "Joramok": "Kador",
+ "Neburab": "Kador",
+ "Aband": "Kador",
+ "Uanim": "Kador",
+ "Murini": "Kador",
+ "Askonak": "Kador",
+ "Nordar": "Kador",
+ "Kador Prime": "Kador",
+ "Khafis": "Kador",
+ "Dantan": "Kador",
+ "Turba": "Kador",
+ "Sonama": "Kador",
+ "Halibai": "Kador",
+ "Suner": "Kador",
+ "Inis-Ilix": "Kador",
+ "Kothe": "Kador",
+ "Ansasos": "Kador",
+ "Dehrokh": "Kador",
+ "Bordan": "Kador",
+ "Zimmem": "Kador",
+ "Chaneya": "Kador",
+ "Oberen": "Kador",
+ "Finid": "Kador",
+ "Yarebap": "Kador",
+ "Mandoo": "Kador",
+ "Miah": "Kador",
+ "Peyiri": "Kador",
+ "Kamda": "Kador",
+ "Rayeret": "Kador",
+ "Bushemal": "Kador",
+ "Ardhis": "Kador",
+ "Gasavak": "Kador",
+ "Iaokit": "Kador",
+ "Menri": "Kador",
+ "Chanoun": "Kador",
+ "Garisas": "Kador",
+ "Aphi": "Kador",
+ "Jakri": "Kador",
+ "Nidupad": "Kador",
+ "Zimse": "Kador",
+ "Koona": "Kador",
+ "Munory": "Kador",
+ "Hostakoh": "Kador",
+ "Yooh": "Kador",
+ "Jeshideh": "Kador",
+ "Hilmar": "Kador",
+ "Kasi": "Kador",
+ "Shura": "Kador",
+ "Mod": "Kador",
+ "Omam": "Kador",
+ "Bersyrim": "Kador",
+ "Sechmaren": "Kador",
+ "Zinoo": "Kador",
+ "Hiremir": "Kador",
+ "Hikansog": "Kador",
+ "Syrikos": "Kador",
+ "Yebouz": "Kador",
+ "Hapala": "Kador",
+ "Salah": "Kador",
+ "Akhmoh": "Kador",
+ "Jennim": "Kador",
+ "Elmed": "Kador",
+ "Shaggoth": "Kador",
+ "Ustnia": "Kador",
+ "Kooreng": "Kador",
+ "Minin": "Kador",
+ "Yehnifi": "Kador",
+ "Shemah": "Kador",
+ "Asrios": "Kador",
+ "Ithar": "Kador",
+ "Telang": "Kador",
+ "Lazara": "Kador",
+ "Zorrabed": "Kador",
+ "Akhwa": "Kador",
+ "FV-YEA": "Cobalt Edge",
+ "J-A5QD": "Cobalt Edge",
+ "BI0Y-X": "Cobalt Edge",
+ "SK7-G6": "Cobalt Edge",
+ "4-PCHD": "Cobalt Edge",
+ "5-3722": "Cobalt Edge",
+ "GQLB-V": "Cobalt Edge",
+ "5E-EZC": "Cobalt Edge",
+ "9KE-IT": "Cobalt Edge",
+ "P-NRD3": "Cobalt Edge",
+ "Y-RAW3": "Cobalt Edge",
+ "S-W8CF": "Cobalt Edge",
+ "X-41DA": "Cobalt Edge",
+ "YVSL-2": "Cobalt Edge",
+ "5E6I-W": "Cobalt Edge",
+ "KIG9-K": "Cobalt Edge",
+ "I-CMZA": "Cobalt Edge",
+ "H23-B5": "Cobalt Edge",
+ "A-0IIQ": "Cobalt Edge",
+ "CBY8-J": "Cobalt Edge",
+ "E-BYOS": "Cobalt Edge",
+ "ETXT-F": "Cobalt Edge",
+ "MK-YNM": "Cobalt Edge",
+ "2-9Z6V": "Cobalt Edge",
+ "5HN-D6": "Cobalt Edge",
+ "E-B957": "Cobalt Edge",
+ "P-H5IY": "Cobalt Edge",
+ "4A-6NI": "Cobalt Edge",
+ "1M7-RK": "Cobalt Edge",
+ "87-1PM": "Cobalt Edge",
+ "C2-1B5": "Cobalt Edge",
+ "JE-VLG": "Cobalt Edge",
+ "5ED-4E": "Cobalt Edge",
+ "B-U299": "Cobalt Edge",
+ "DN58-U": "Cobalt Edge",
+ "VAF1-P": "Cobalt Edge",
+ "FV1-RQ": "Cobalt Edge",
+ "QT-EBC": "Cobalt Edge",
+ "O-F4SN": "Cobalt Edge",
+ "CUT-0V": "Cobalt Edge",
+ "9-WEMC": "Cobalt Edge",
+ "U6R-F9": "Cobalt Edge",
+ "L-Z9NB": "Cobalt Edge",
+ "EJ-5X2": "Cobalt Edge",
+ "HXK-J6": "Cobalt Edge",
+ "4LNE-M": "Cobalt Edge",
+ "DK0-N8": "Cobalt Edge",
+ "E0DR-G": "Cobalt Edge",
+ "KI2-S3": "Cobalt Edge",
+ "CHP-76": "Cobalt Edge",
+ "T-67F8": "Cobalt Edge",
+ "58Z-IH": "Cobalt Edge",
+ "M-VACR": "Cobalt Edge",
+ "0B-VOJ": "Cobalt Edge",
+ "J-QOKQ": "Cobalt Edge",
+ "4GSZ-1": "Cobalt Edge",
+ "E-EFAM": "Cobalt Edge",
+ "SBEN-Q": "Cobalt Edge",
+ "9-7SRQ": "Cobalt Edge",
+ "VEQ-3V": "Cobalt Edge",
+ "4T-VDE": "Cobalt Edge",
+ "D9Z-VY": "Cobalt Edge",
+ "MO-YDG": "Cobalt Edge",
+ "42SU-L": "Cobalt Edge",
+ "RGU1-T": "Cobalt Edge",
+ "1GT-MA": "Cobalt Edge",
+ "VY-866": "Cobalt Edge",
+ "HB-5L3": "Cobalt Edge",
+ "Q-VTWJ": "Cobalt Edge",
+ "Van": "Aridia",
+ "Shakasi": "Aridia",
+ "Zayi": "Aridia",
+ "Shirshocin": "Aridia",
+ "Maalna": "Aridia",
+ "Maseera": "Aridia",
+ "Yehaba": "Aridia",
+ "Kenahehab": "Aridia",
+ "Gens": "Aridia",
+ "Kamih": "Aridia",
+ "Hier": "Aridia",
+ "Jasson": "Aridia",
+ "Sadana": "Aridia",
+ "Isid": "Aridia",
+ "Onanam": "Aridia",
+ "Udianoor": "Aridia",
+ "Vehan": "Aridia",
+ "Marmeha": "Aridia",
+ "Haimeh": "Aridia",
+ "Avada": "Aridia",
+ "Chibi": "Aridia",
+ "Mishi": "Aridia",
+ "Bazadod": "Aridia",
+ "Pahineh": "Aridia",
+ "Fihrneh": "Aridia",
+ "Parouz": "Aridia",
+ "Edilkam": "Aridia",
+ "Hakatiz": "Aridia",
+ "Khnar": "Aridia",
+ "Ertoo": "Aridia",
+ "Yiratal": "Aridia",
+ "Balas": "Aridia",
+ "Pemsah": "Aridia",
+ "Feshur": "Aridia",
+ "Hoseen": "Aridia",
+ "Yekh": "Aridia",
+ "Gesh": "Aridia",
+ "Nema": "Aridia",
+ "Shenda": "Aridia",
+ "Rashagh": "Aridia",
+ "Sazilid": "Aridia",
+ "Afrah": "Aridia",
+ "Sota": "Aridia",
+ "Soliara": "Aridia",
+ "Nielez": "Aridia",
+ "Tukanas": "Aridia",
+ "Fageras": "Aridia",
+ "Ajna": "Aridia",
+ "Sheri": "Aridia",
+ "Ahraghen": "Aridia",
+ "Nalnifan": "Aridia",
+ "Jerhesh": "Aridia",
+ "Getrenjesa": "Aridia",
+ "Shafrak": "Aridia",
+ "Defsunun": "Aridia",
+ "Zazamye": "Aridia",
+ "Yahyerer": "Aridia",
+ "Esubara": "Aridia",
+ "Ghekon": "Aridia",
+ "Vaini": "Aridia",
+ "Zaveral": "Aridia",
+ "Anohel": "Aridia",
+ "Soza": "Aridia",
+ "Pserz": "Aridia",
+ "Illi": "Aridia",
+ "Keba": "Aridia",
+ "Bapraya": "Aridia",
+ "Efu": "Aridia",
+ "Tisot": "Aridia",
+ "Sakht": "Aridia",
+ "Naga": "Aridia",
+ "Anath": "Aridia",
+ "Omigiav": "Aridia",
+ "Fobiner": "Aridia",
+ "Huna": "Aridia",
+ "Esaeel": "Aridia",
+ "Karan": "Aridia",
+ "Nouta": "Aridia",
+ "Ned": "Aridia",
+ "Hophib": "Aridia",
+ "UQ9-3C": "Branch",
+ "DCI7-7": "Branch",
+ "J7YR-1": "Branch",
+ "PKG4-7": "Branch",
+ "EWN-2U": "Branch",
+ "VL3I-M": "Branch",
+ "KMC-WI": "Branch",
+ "4-48K1": "Branch",
+ "NTV0-1": "Branch",
+ "C-HCGU": "Branch",
+ "XW-2XP": "Branch",
+ "Q-FEEJ": "Branch",
+ "0P9Z-I": "Branch",
+ "AH-B84": "Branch",
+ "JTAU-5": "Branch",
+ "HB7R-F": "Branch",
+ "O-JPKH": "Branch",
+ "F-9F6Q": "Branch",
+ "B-GC1T": "Branch",
+ "V8W-QS": "Branch",
+ "JRZ-B9": "Branch",
+ "X4UV-Z": "Branch",
+ "S-B7IT": "Branch",
+ "BKG-Q2": "Branch",
+ "OJ-A8M": "Branch",
+ "CX-1XF": "Branch",
+ "3-TD6L": "Branch",
+ "Q-NJZ4": "Branch",
+ "NLPB-0": "Branch",
+ "R4O-I6": "Branch",
+ "KL3O-J": "Branch",
+ "Z-K495": "Branch",
+ "XM-4L0": "Branch",
+ "QCWA-Z": "Branch",
+ "52G-NZ": "Branch",
+ "5LJ-MD": "Branch",
+ "B8O-KJ": "Branch",
+ "6-O5GY": "Branch",
+ "KV-8SN": "Branch",
+ "UB-UQZ": "Branch",
+ "YG-82V": "Branch",
+ "8-4GQM": "Branch",
+ "T-Q2DD": "Branch",
+ "LRWD-B": "Branch",
+ "QXQ-BA": "Branch",
+ "X7R-JW": "Branch",
+ "M-HU4V": "Branch",
+ "CS-ZGD": "Branch",
+ "3-N3OO": "Branch",
+ "A-G1FM": "Branch",
+ "4-BE0M": "Branch",
+ "I-7RIS": "Branch",
+ "P7Z-R3": "Branch",
+ "ZIU-EP": "Branch",
+ "LXWN-W": "Branch",
+ "C-LP3N": "Branch",
+ "9F-7PZ": "Branch",
+ "1G-MJE": "Branch",
+ "WO-AIJ": "Branch",
+ "MA-VDX": "Branch",
+ "RO90-H": "Branch",
+ "BWI1-9": "Branch",
+ "C-LBQS": "Branch",
+ "J52-BH": "Branch",
+ "5-P1Y2": "Branch",
+ "KMQ4-V": "Branch",
+ "KJ-QWL": "Branch",
+ "SVB-RE": "Branch",
+ "C-4ZOS": "Branch",
+ "K-8SQS": "Branch",
+ "C-VGYO": "Branch",
+ "O94U-A": "Branch",
+ "XW-JHT": "Branch",
+ "NEH-CS": "Branch",
+ "4DTQ-K": "Branch",
+ "J9-5MQ": "Branch",
+ "D4R-H7": "Branch",
+ "313I-B": "Branch",
+ "EQI2-2": "Branch",
+ "Q-4DEC": "Branch",
+ "3F-JZF": "Branch",
+ "5-0WB9": "Branch",
+ "W-4FA9": "Branch",
+ "1IX-C0": "Branch",
+ "2B7A-3": "Branch",
+ "PUWL-4": "Branch",
+ "Y-1918": "Branch",
+ "9-B1DS": "Branch",
+ "ME-4IU": "Branch",
+ "BU-IU4": "Branch",
+ "I-7JR4": "Branch",
+ "CH9L-K": "Branch",
+ "QYZM-W": "Branch",
+ "3KNA-N": "Branch",
+ "UD-VZW": "Feythabolis",
+ "3-YX2D": "Feythabolis",
+ "V-TN6Q": "Feythabolis",
+ "CFLF-P": "Feythabolis",
+ "QBH5-F": "Feythabolis",
+ "9-ZFCG": "Feythabolis",
+ "J-TPTA": "Feythabolis",
+ "PMV-G6": "Feythabolis",
+ "5-IZGE": "Feythabolis",
+ "OXC-UL": "Feythabolis",
+ "F-8Y13": "Feythabolis",
+ "4AZ-J8": "Feythabolis",
+ "X6-J6R": "Feythabolis",
+ "BGN1-O": "Feythabolis",
+ "DUU1-K": "Feythabolis",
+ "3L-Y9M": "Feythabolis",
+ "BLC-X0": "Feythabolis",
+ "K-X5AX": "Feythabolis",
+ "BJD4-E": "Feythabolis",
+ "TSG-NO": "Feythabolis",
+ "O9V-R7": "Feythabolis",
+ "Z-PNIA": "Feythabolis",
+ "OCU4-R": "Feythabolis",
+ "BG-W90": "Feythabolis",
+ "Y-YGMW": "Feythabolis",
+ "75C-WN": "Feythabolis",
+ "I5Q2-S": "Feythabolis",
+ "PO-3QW": "Feythabolis",
+ "5XR-KZ": "Feythabolis",
+ "VF-FN6": "Feythabolis",
+ "C-0ND2": "Feythabolis",
+ "JI-LGM": "Feythabolis",
+ "U-BXU9": "Feythabolis",
+ "ZXOG-O": "Feythabolis",
+ "NW2S-A": "Feythabolis",
+ "U-JJEW": "Feythabolis",
+ "NX5W-U": "Feythabolis",
+ "U1-C18": "Feythabolis",
+ "6O-XIO": "Feythabolis",
+ "H65-HE": "Feythabolis",
+ "BJ-ZFD": "Feythabolis",
+ "5ELE-A": "Feythabolis",
+ "H-P4LB": "Feythabolis",
+ "2UK4-N": "Feythabolis",
+ "QK-CDG": "Feythabolis",
+ "M-CMLV": "Feythabolis",
+ "AZN-D2": "Feythabolis",
+ "E-PR0S": "Feythabolis",
+ "TR07-S": "Feythabolis",
+ "VNGJ-U": "Feythabolis",
+ "2-F3OE": "Feythabolis",
+ "5-LCI7": "Feythabolis",
+ "Y2-I3W": "Feythabolis",
+ "VVO-R6": "Feythabolis",
+ "CL-J9W": "Feythabolis",
+ "YHP2-D": "Feythabolis",
+ "J94-MU": "Feythabolis",
+ "M2GJ-X": "Feythabolis",
+ "JO-32L": "Feythabolis",
+ "UB5Z-3": "Feythabolis",
+ "MSKR-1": "Feythabolis",
+ "GPUS-A": "Feythabolis",
+ "3-BADZ": "Feythabolis",
+ "23M-PX": "Feythabolis",
+ "UTDH-N": "Feythabolis",
+ "ZS-2LT": "Feythabolis",
+ "DB1R-4": "Feythabolis",
+ "P8-BKO": "Feythabolis",
+ "RIT-A7": "Feythabolis",
+ "R4K-8L": "Feythabolis",
+ "GHZ-SJ": "Feythabolis",
+ "K-J50B": "Feythabolis",
+ "NLO-3Z": "Feythabolis",
+ "5P-AIP": "Feythabolis",
+ "M-PGT0": "Feythabolis",
+ "NPD9-A": "Feythabolis",
+ "D6SK-L": "Feythabolis",
+ "HYPL-V": "Feythabolis",
+ "I9-ZQZ": "Feythabolis",
+ "0OYZ-G": "Feythabolis",
+ "SWBV-2": "Feythabolis",
+ "R97-CI": "Feythabolis",
+ "6-ELQP": "Feythabolis",
+ "OBK-K8": "Feythabolis",
+ "KJ-V0P": "Feythabolis",
+ "ZID-LE": "Feythabolis",
+ "K-9UG4": "Feythabolis",
+ "D4-2XN": "Feythabolis",
+ "2-RSC7": "Feythabolis",
+ "C0T-77": "Outer Ring",
+ "RL-KT0": "Outer Ring",
+ "UO9-YG": "Outer Ring",
+ "ZQP-QV": "Outer Ring",
+ "P-NUWP": "Outer Ring",
+ "ZJQH-S": "Outer Ring",
+ "E9G-MT": "Outer Ring",
+ "TQ-RR8": "Outer Ring",
+ "1L-BHT": "Outer Ring",
+ "D5IW-F": "Outer Ring",
+ "F-XWIN": "Outer Ring",
+ "4C-B7X": "Outer Ring",
+ "LGUZ-1": "Outer Ring",
+ "BF-SDP": "Outer Ring",
+ "F5FO-U": "Outer Ring",
+ "5WAE-M": "Outer Ring",
+ "0-WVQS": "Outer Ring",
+ "0-9UHT": "Outer Ring",
+ "M-NKZM": "Outer Ring",
+ "H-M1BY": "Outer Ring",
+ "J1H-R4": "Outer Ring",
+ "J9SH-A": "Outer Ring",
+ "JKJ-VJ": "Outer Ring",
+ "RTX0-S": "Outer Ring",
+ "33FN-P": "Outer Ring",
+ "NM-OEA": "Outer Ring",
+ "MT-2VJ": "Outer Ring",
+ "3HQC-6": "Outer Ring",
+ "OX-RGN": "Outer Ring",
+ "R-OCBA": "Outer Ring",
+ "GA-2V7": "Outer Ring",
+ "DB-6W4": "Outer Ring",
+ "7-692B": "Outer Ring",
+ "L3-XYO": "Outer Ring",
+ "AN-G54": "Outer Ring",
+ "ZXI-K2": "Outer Ring",
+ "T-Z6J2": "Outer Ring",
+ "CT7-5V": "Outer Ring",
+ "2JJ-0E": "Outer Ring",
+ "B0C-LD": "Outer Ring",
+ "NP6-38": "Outer Ring",
+ "G-YT55": "Outer Ring",
+ "IZ-AOB": "Outer Ring",
+ "G5-EN3": "Outer Ring",
+ "W-Z3HW": "Outer Ring",
+ "W2F-ZH": "Outer Ring",
+ "BMU-V1": "Outer Ring",
+ "ZXC8-1": "Outer Ring",
+ "LBV-Q1": "Outer Ring",
+ "Z-40CG": "Outer Ring",
+ "O-RIDF": "Outer Ring",
+ "A-5M31": "Outer Ring",
+ "BOE7-P": "Outer Ring",
+ "E-GCX0": "Outer Ring",
+ "VBFC-8": "Outer Ring",
+ "YVA-F0": "Outer Ring",
+ "0D-CHA": "Outer Ring",
+ "A2V6-6": "Outer Ring",
+ "VJ0-81": "Outer Ring",
+ "XF-TQL": "Fountain",
+ "4-EP12": "Fountain",
+ "YZS5-4": "Fountain",
+ "3WE-KY": "Fountain",
+ "IR-WT1": "Fountain",
+ "9-VO0Q": "Fountain",
+ "A8-XBW": "Fountain",
+ "PNQY-Y": "Fountain",
+ "RP2-OQ": "Fountain",
+ "YVBE-E": "Fountain",
+ "BYXF-Q": "Fountain",
+ "AC2E-3": "Fountain",
+ "C-C99Z": "Fountain",
+ "CL-BWB": "Fountain",
+ "R3W-XU": "Fountain",
+ "E-BWUU": "Fountain",
+ "Y-1W01": "Fountain",
+ "9R4-EJ": "Fountain",
+ "SPLE-Y": "Fountain",
+ "Q-XEB3": "Fountain",
+ "K8L-X7": "Fountain",
+ "5-D82P": "Fountain",
+ "8ESL-G": "Fountain",
+ "JGOW-Y": "Fountain",
+ "APM-6K": "Fountain",
+ "RE-C26": "Fountain",
+ "AL8-V4": "Fountain",
+ "KCT-0A": "Fountain",
+ "N2-OQG": "Fountain",
+ "OW-TPO": "Fountain",
+ "9O-ORX": "Fountain",
+ "IGE-RI": "Fountain",
+ "Z9PP-H": "Fountain",
+ "7-8S5X": "Fountain",
+ "EI-O0O": "Fountain",
+ "7X-02R": "Fountain",
+ "D2AH-Z": "Fountain",
+ "J5A-IX": "Fountain",
+ "B17O-R": "Fountain",
+ "6F-H3W": "Fountain",
+ "H-NPXW": "Fountain",
+ "L-1SW8": "Fountain",
+ "U-SOH2": "Fountain",
+ "DBRN-Z": "Fountain",
+ "00GD-D": "Fountain",
+ "C1XD-X": "Fountain",
+ "G95F-H": "Fountain",
+ "B32-14": "Fountain",
+ "C-N4OD": "Fountain",
+ "CHA2-Q": "Fountain",
+ "UAYL-F": "Fountain",
+ "ESC-RI": "Fountain",
+ "671-ST": "Fountain",
+ "A-HZYL": "Fountain",
+ "H-S80W": "Fountain",
+ "Z30S-A": "Fountain",
+ "6VDT-H": "Fountain",
+ "NDH-NV": "Fountain",
+ "QV28-G": "Fountain",
+ "15U-JY": "Fountain",
+ "NY6-FH": "Fountain",
+ "XJP-Y7": "Fountain",
+ "AV-VB6": "Fountain",
+ "HMF-9D": "Fountain",
+ "7BX-6F": "Fountain",
+ "YZ-LQL": "Fountain",
+ "MN5N-X": "Fountain",
+ "A-1CON": "Fountain",
+ "75FA-Z": "Fountain",
+ "WY-9LL": "Fountain",
+ "D-Q04X": "Fountain",
+ "Serpentis Prime": "Fountain",
+ "P5-EFH": "Fountain",
+ "L-A5XP": "Fountain",
+ "D4KU-5": "Fountain",
+ "YRNJ-8": "Fountain",
+ "3ZTV-V": "Fountain",
+ "9D6O-M": "Fountain",
+ "LIWW-P": "Fountain",
+ "G-UTHL": "Fountain",
+ "38IA-E": "Fountain",
+ "M-KXEH": "Fountain",
+ "TU-Y2A": "Fountain",
+ "7BIX-A": "Fountain",
+ "I-CUVX": "Fountain",
+ "J-RQMF": "Fountain",
+ "TEG-SD": "Fountain",
+ "14YI-D": "Fountain",
+ "87XQ-0": "Fountain",
+ "LJ-TZW": "Fountain",
+ "KVN-36": "Fountain",
+ "57-KJB": "Fountain",
+ "V6-NY1": "Fountain",
+ "OL3-78": "Fountain",
+ "9DQW-W": "Fountain",
+ "PXF-RF": "Fountain",
+ "R-BGSU": "Fountain",
+ "O-PNSN": "Fountain",
+ "1-5GBW": "Fountain",
+ "C-FER9": "Fountain",
+ "F2-2C3": "Fountain",
+ "F-88PJ": "Fountain",
+ "ATQ-QS": "Fountain",
+ "XUW-3X": "Fountain",
+ "006-L3": "Fountain",
+ "PB-0C1": "Fountain",
+ "ZUE-NS": "Fountain",
+ "L7-APB": "Fountain",
+ "ZTS-4D": "Fountain",
+ "4HS-CR": "Fountain",
+ "WMH-SO": "Fountain",
+ "LBGI-2": "Fountain",
+ "G1CA-Y": "Fountain",
+ "Y-2ANO": "Fountain",
+ "Z-YN5Y": "Fountain",
+ "JI-K5H": "Paragon Soul",
+ "33-JRO": "Paragon Soul",
+ "ARBX-9": "Paragon Soul",
+ "5-CSE3": "Paragon Soul",
+ "O-MCZR": "Paragon Soul",
+ "9T-APQ": "Paragon Soul",
+ "4Y-OBL": "Paragon Soul",
+ "0-MX34": "Paragon Soul",
+ "5AQ-5H": "Paragon Soul",
+ "T-ZFID": "Paragon Soul",
+ "0ZN7-G": "Paragon Soul",
+ "H8-ZTO": "Paragon Soul",
+ "YV-FDG": "Paragon Soul",
+ "LUL-WX": "Paragon Soul",
+ "8Q-UYU": "Paragon Soul",
+ "3PPT-9": "Paragon Soul",
+ "S-KU8B": "Paragon Soul",
+ "JK-GLL": "Paragon Soul",
+ "UAAU-C": "Paragon Soul",
+ "HHJD-5": "Paragon Soul",
+ "ZWV-GD": "Paragon Soul",
+ "1DDR-X": "Paragon Soul",
+ "LG-WA9": "Paragon Soul",
+ "AA-GWF": "Paragon Soul",
+ "O4T-Z5": "Paragon Soul",
+ "O-97ZG": "Paragon Soul",
+ "2I-520": "Paragon Soul",
+ "GQ2S-8": "Paragon Soul",
+ "0SUF-3": "Paragon Soul",
+ "G-M4GK": "Paragon Soul",
+ "G1D0-G": "Paragon Soul",
+ "KU3-BB": "Paragon Soul",
+ "O1Q-P1": "Paragon Soul",
+ "LD-2VL": "Paragon Soul",
+ "ZBY-0I": "Paragon Soul",
+ "MP5-KR": "Paragon Soul",
+ "O-N589": "Paragon Soul",
+ "ZDYA-G": "Paragon Soul",
+ "LX5K-W": "Paragon Soul",
+ "UHKL-N": "Delve",
+ "Z3V-1W": "Delve",
+ "A-ELE2": "Delve",
+ "KFIE-Z": "Delve",
+ "1DH-SX": "Delve",
+ "PR-8CA": "Delve",
+ "NOL-M9": "Delve",
+ "O-IOAI": "Delve",
+ "QX-LIJ": "Delve",
+ "HM-XR2": "Delve",
+ "4K-TRB": "Delve",
+ "AJI-MA": "Delve",
+ "FWST-8": "Delve",
+ "YZ9-F6": "Delve",
+ "0N-3RO": "Delve",
+ "G-TT5V": "Delve",
+ "319-3D": "Delve",
+ "I3Q-II": "Delve",
+ "RF-K9W": "Delve",
+ "E3OI-U": "Delve",
+ "IP6V-X": "Delve",
+ "R5-MM8": "Delve",
+ "1B-VKF": "Delve",
+ "T-J6HT": "Delve",
+ "D-W7F0": "Delve",
+ "JP4-AA": "Delve",
+ "FM-JK5": "Delve",
+ "PDE-U3": "Delve",
+ "23G-XC": "Delve",
+ "T5ZI-S": "Delve",
+ "4X0-8B": "Delve",
+ "Q-HESZ": "Delve",
+ "1-SMEB": "Delve",
+ "M5-CGW": "Delve",
+ "6Q-R50": "Delve",
+ "ZA9-PY": "Delve",
+ "RCI-VL": "Delve",
+ "MJXW-P": "Delve",
+ "QC-YX6": "Delve",
+ "T-M0FA": "Delve",
+ "4O-239": "Delve",
+ "LUA5-L": "Delve",
+ "T-IPZB": "Delve",
+ "Q-JQSG": "Delve",
+ "D-3GIQ": "Delve",
+ "K-6K16": "Delve",
+ "QY6-RK": "Delve",
+ "W-KQPI": "Delve",
+ "PUIG-F": "Delve",
+ "J-LPX7": "Delve",
+ "0-HDC8": "Delve",
+ "F-TE1T": "Delve",
+ "SVM-3K": "Delve",
+ "1DQ1-A": "Delve",
+ "8WA-Z6": "Delve",
+ "5BTK-M": "Delve",
+ "N-8YET": "Delve",
+ "Y-OMTZ": "Delve",
+ "3-DMQT": "Delve",
+ "MO-GZ5": "Delve",
+ "39P-1J": "Delve",
+ "HZAQ-W": "Delve",
+ "7G-QIG": "Delve",
+ "NIDJ-K": "Delve",
+ "PS-94K": "Delve",
+ "8RQJ-2": "Delve",
+ "KEE-N6": "Delve",
+ "M2-XFE": "Delve",
+ "5-CQDA": "Delve",
+ "I-E3TG": "Delve",
+ "S-6HHN": "Delve",
+ "ZXB-VC": "Delve",
+ "GY6A-L": "Delve",
+ "UEXO-Z": "Delve",
+ "9O-8W1": "Delve",
+ "8F-TK3": "Delve",
+ "PF-KUQ": "Delve",
+ "N8D9-Z": "Delve",
+ "F-9PXR": "Delve",
+ "Y5C-YD": "Delve",
+ "31X-RE": "Delve",
+ "Q-02UL": "Delve",
+ "7UTB-F": "Delve",
+ "5-6QW7": "Delve",
+ "7-K6UE": "Delve",
+ "C6Y-ZF": "Delve",
+ "6Z-CKS": "Delve",
+ "G-M5L3": "Delve",
+ "KBAK-I": "Delve",
+ "M-SRKS": "Delve",
+ "9GNS-2": "Delve",
+ "YAW-7M": "Delve",
+ "C3N-3S": "Delve",
+ "CX8-6K": "Delve",
+ "LWX-93": "Delve",
+ "1-2J4P": "Delve",
+ "M0O-JG": "Delve",
+ "WB-AYY": "Tenerifis",
+ "BW-WJ2": "Tenerifis",
+ "S4-9DN": "Tenerifis",
+ "DT-PXH": "Tenerifis",
+ "UALX-3": "Tenerifis",
+ "3L3N-X": "Tenerifis",
+ "Y-ORBJ": "Tenerifis",
+ "6-IAFR": "Tenerifis",
+ "4-P4FE": "Tenerifis",
+ "RH0-EG": "Tenerifis",
+ "D-9UEV": "Tenerifis",
+ "H-HWQR": "Tenerifis",
+ "QRBN-M": "Tenerifis",
+ "78R-PI": "Tenerifis",
+ "ZD1-Z2": "Tenerifis",
+ "C-FD0D": "Tenerifis",
+ "S-9RCJ": "Tenerifis",
+ "ZMV9-A": "Tenerifis",
+ "FE-6YQ": "Tenerifis",
+ "W-16DY": "Tenerifis",
+ "M-4KDB": "Tenerifis",
+ "C3-0YD": "Tenerifis",
+ "PDF-3Z": "Tenerifis",
+ "9-MJVQ": "Tenerifis",
+ "L2GN-K": "Tenerifis",
+ "4-IT9G": "Tenerifis",
+ "PEK-8Z": "Tenerifis",
+ "2PG-KN": "Tenerifis",
+ "ABE-M2": "Tenerifis",
+ "IL-YTR": "Tenerifis",
+ "KW-OAM": "Tenerifis",
+ "U2U5-A": "Tenerifis",
+ "EQWO-Y": "Tenerifis",
+ "JK-Q77": "Tenerifis",
+ "QI9-42": "Tenerifis",
+ "YF-P4X": "Tenerifis",
+ "JI1-SY": "Tenerifis",
+ "X-1QGA": "Tenerifis",
+ "CCE-0J": "Tenerifis",
+ "T2-V8F": "Tenerifis",
+ "0VK-43": "Tenerifis",
+ "TY2X-C": "Tenerifis",
+ "Q0G-L8": "Tenerifis",
+ "Q5KZ-W": "Tenerifis",
+ "WE-KK2": "Tenerifis",
+ "B8HU-Z": "Tenerifis",
+ "16AM-3": "Tenerifis",
+ "A-REKV": "Tenerifis",
+ "BB-EKF": "Tenerifis",
+ "DZ6-I5": "Tenerifis",
+ "R-XDKM": "Tenerifis",
+ "G1-0UI": "Tenerifis",
+ "QCDG-H": "Tenerifis",
+ "XUDX-A": "Tenerifis",
+ "QLU-P0": "Tenerifis",
+ "OQTY-Z": "Tenerifis",
+ "Y-EQ0C": "Tenerifis",
+ "7M4C-F": "Tenerifis",
+ "MS1-KJ": "Tenerifis",
+ "8-BEW8": "Tenerifis",
+ "NZW-ZO": "Tenerifis",
+ "WSK-1A": "Tenerifis",
+ "5-NZNW": "Tenerifis",
+ "NR8S-Y": "Tenerifis",
+ "F-ZBO0": "Tenerifis",
+ "3Q1T-O": "Tenerifis",
+ "8-4KME": "Tenerifis",
+ "T6GY-Y": "Tenerifis",
+ "R1-IMO": "Tenerifis",
+ "7KIK-H": "Tenerifis",
+ "B-6STA": "Tenerifis",
+ "0P-U0Q": "Tenerifis",
+ "XGH-SH": "Tenerifis",
+ "G-D0N3": "Tenerifis",
+ "T-AKQZ": "Tenerifis",
+ "46DP-O": "Tenerifis",
+ "9-980U": "Tenerifis",
+ "EMIG-F": "Tenerifis",
+ "M-RPN3": "Tenerifis",
+ "ZO-P5K": "Tenerifis",
+ "JV1V-O": "Tenerifis",
+ "9MWZ-B": "Omist",
+ "LS-QLX": "Omist",
+ "S-XZHU": "Omist",
+ "CO-7BI": "Omist",
+ "ZJG-7D": "Omist",
+ "C-WPWH": "Omist",
+ "VULA-I": "Omist",
+ "R2TJ-1": "Omist",
+ "G-B3PR": "Omist",
+ "73-JQO": "Omist",
+ "XPUM-L": "Omist",
+ "KR8-27": "Omist",
+ "LQ-AHE": "Omist",
+ "LOI-L1": "Omist",
+ "Y-MSJN": "Omist",
+ "MJ-X5V": "Omist",
+ "3FKU-H": "Omist",
+ "M9-FIB": "Omist",
+ "D2EZ-X": "Omist",
+ "DJK-67": "Omist",
+ "AXDX-F": "Omist",
+ "J-4FNO": "Omist",
+ "PEM-LC": "Omist",
+ "X-EHHD": "Omist",
+ "6T3I-L": "Omist",
+ "QSF-EJ": "Omist",
+ "L-AS00": "Omist",
+ "NZPK-G": "Omist",
+ "K-1OY3": "Omist",
+ "MMUF-8": "Omist",
+ "99-0GS": "Omist",
+ "X-3AUU": "Omist",
+ "H90-C9": "Omist",
+ "0DD-MH": "Omist",
+ "RI-JB1": "Omist",
+ "NQH-MR": "Omist",
+ "1I6F-9": "Omist",
+ "Z-7OK1": "Omist",
+ "UEP0-A": "Omist",
+ "66-PMM": "Omist",
+ "OKEO-X": "Omist",
+ "7-8EOE": "Omist",
+ "7L9-ZC": "Omist",
+ "L-YMYU": "Period Basis",
+ "35-JWD": "Period Basis",
+ "F-M1FU": "Period Basis",
+ "0-NTIS": "Period Basis",
+ "VR-YIQ": "Period Basis",
+ "XZ-SKZ": "Period Basis",
+ "I6M-9U": "Period Basis",
+ "MG0-RD": "Period Basis",
+ "TPAR-G": "Period Basis",
+ "VYO-68": "Period Basis",
+ "TCAG-3": "Period Basis",
+ "UR-E46": "Period Basis",
+ "CW9-1Y": "Period Basis",
+ "1-NJLK": "Period Basis",
+ "Y-CWQY": "Period Basis",
+ "8KR9-5": "Period Basis",
+ "VQE-CN": "Period Basis",
+ "L5D-ZL": "Period Basis",
+ "G-C8QO": "Period Basis",
+ "EIMJ-M": "Period Basis",
+ "0A-KZ0": "Period Basis",
+ "E-DOF2": "Period Basis",
+ "48I1-X": "Period Basis",
+ "0OTX-J": "Period Basis",
+ "3OP-3E": "Period Basis",
+ "JZL-VB": "Period Basis",
+ "RJ3H-0": "Period Basis",
+ "08S-39": "Period Basis",
+ "ZU-MS3": "Period Basis",
+ "HIX4-H": "Period Basis",
+ "GR-J8B": "Period Basis",
+ "OY0-2T": "Period Basis",
+ "E2-RDQ": "Period Basis",
+ "TN25-J": "Period Basis",
+ "PA-VE3": "Period Basis",
+ "G-Q5JU": "Period Basis",
+ "RYQC-I": "Period Basis",
+ "1E-W5I": "Period Basis",
+ "Z-M5A1": "Period Basis",
+ "MVUO-F": "Period Basis",
+ "Luminaire": "Essence",
+ "Mies": "Essence",
+ "Oursulaert": "Essence",
+ "Renyn": "Essence",
+ "Duripant": "Essence",
+ "Algogille": "Essence",
+ "Caslemon": "Essence",
+ "Jolevier": "Essence",
+ "Mesybier": "Essence",
+ "Charmerout": "Essence",
+ "Yvangier": "Essence",
+ "Pemene": "Essence",
+ "Heydieles": "Essence",
+ "Fliet": "Essence",
+ "Actee": "Essence",
+ "Indregulle": "Essence",
+ "Amane": "Essence",
+ "Abune": "Essence",
+ "Deven": "Essence",
+ "Estaunitte": "Essence",
+ "Deninard": "Essence",
+ "Hulmate": "Essence",
+ "Annages": "Essence",
+ "Onne": "Essence",
+ "Vitrauze": "Essence",
+ "Palmon": "Essence",
+ "Villore": "Essence",
+ "Arant": "Essence",
+ "Allamotte": "Essence",
+ "Obalyu": "Essence",
+ "Vifrevaert": "Essence",
+ "Parts": "Essence",
+ "Ladistier": "Essence",
+ "Old Man Star": "Essence",
+ "Arnon": "Essence",
+ "Laurvier": "Essence",
+ "Adirain": "Essence",
+ "Attyn": "Essence",
+ "Ignebaener": "Essence",
+ "Aere": "Essence",
+ "Lisbaetanne": "Essence",
+ "Aeschee": "Essence",
+ "Allebin": "Essence",
+ "Atlulle": "Essence",
+ "Droselory": "Essence",
+ "Haine": "Essence",
+ "Perckhevin": "Essence",
+ "Isenan": "Essence",
+ "Synchelle": "Essence",
+ "Wysalan": "Essence",
+ "Yona": "Essence",
+ "Noghere": "Essence",
+ "Aporulie": "Essence",
+ "Seyllin": "Essence",
+ "Adrel": "Essence",
+ "Ane": "Essence",
+ "Clorteler": "Essence",
+ "Atlangeins": "Essence",
+ "Derririntel": "Essence",
+ "Cat": "Essence",
+ "Ommare": "Essence",
+ "Andole": "Essence",
+ "Vale": "Essence",
+ "Couster": "Essence",
+ "Hecarrin": "Essence",
+ "Henebene": "Essence",
+ "Mesokel": "Essence",
+ "Fensi": "Kor-Azor",
+ "Nebian": "Kor-Azor",
+ "Khabara": "Kor-Azor",
+ "Jeni": "Kor-Azor",
+ "Bridi": "Kor-Azor",
+ "Ami": "Kor-Azor",
+ "Amdonen": "Kor-Azor",
+ "Mora": "Kor-Azor",
+ "Kor-Azor Prime": "Kor-Azor",
+ "Leva": "Kor-Azor",
+ "Nishah": "Kor-Azor",
+ "Masanuh": "Kor-Azor",
+ "Sehmy": "Kor-Azor",
+ "Nakregde": "Kor-Azor",
+ "Danyana": "Kor-Azor",
+ "Nahyeen": "Kor-Azor",
+ "Jinkah": "Kor-Azor",
+ "Nibainkier": "Kor-Azor",
+ "Polfaly": "Kor-Azor",
+ "Andrub": "Kor-Azor",
+ "Kulu": "Kor-Azor",
+ "Choga": "Kor-Azor",
+ "Soumi": "Kor-Azor",
+ "Imih": "Kor-Azor",
+ "Nare": "Kor-Azor",
+ "Zinkon": "Kor-Azor",
+ "Kizama": "Kor-Azor",
+ "Shaha": "Kor-Azor",
+ "Neesher": "Kor-Azor",
+ "Misha": "Kor-Azor",
+ "Ordion": "Kor-Azor",
+ "Perbhe": "Kor-Azor",
+ "Abath": "Kor-Azor",
+ "Schmaeel": "Kor-Azor",
+ "Mafra": "Kor-Azor",
+ "Arzi": "Kor-Azor",
+ "Kerying": "Kor-Azor",
+ "Zorenyen": "Kor-Azor",
+ "Oguser": "Kor-Azor",
+ "Nahol": "Kor-Azor",
+ "Tadadan": "Kor-Azor",
+ "Tralasa": "Kor-Azor",
+ "Gademam": "Kor-Azor",
+ "Pananan": "Kor-Azor",
+ "Daran": "Kor-Azor",
+ "Latari": "Kor-Azor",
+ "Shokal": "Kor-Azor",
+ "Atarli": "Kor-Azor",
+ "Keproh": "Kor-Azor",
+ "Zatamaka": "Kor-Azor",
+ "Rannoze": "Kor-Azor",
+ "Piri": "Kor-Azor",
+ "Enal": "Kor-Azor",
+ "Jedandan": "Kor-Azor",
+ "Miroona": "Kor-Azor",
+ "Ranni": "Kor-Azor",
+ "Arza": "Kor-Azor",
+ "Liparer": "Kor-Azor",
+ "Annad": "Kor-Azor",
+ "Chaktaren": "Kor-Azor",
+ "Conoban": "Kor-Azor",
+ "B-B0ME": "Perrigen Falls",
+ "TDP-T3": "Perrigen Falls",
+ "H-HGGJ": "Perrigen Falls",
+ "OJT-J3": "Perrigen Falls",
+ "A9-F18": "Perrigen Falls",
+ "DE-IHK": "Perrigen Falls",
+ "AY9X-Q": "Perrigen Falls",
+ "XU7-CH": "Perrigen Falls",
+ "2V-ZHM": "Perrigen Falls",
+ "V-3K7C": "Perrigen Falls",
+ "AK-L0Z": "Perrigen Falls",
+ "R-AG7W": "Perrigen Falls",
+ "E-WMT7": "Perrigen Falls",
+ "FLK-LJ": "Perrigen Falls",
+ "0FG-KS": "Perrigen Falls",
+ "F-5WYK": "Perrigen Falls",
+ "EF-QZK": "Perrigen Falls",
+ "RZ3O-K": "Perrigen Falls",
+ "LW-YEW": "Perrigen Falls",
+ "HB-KSF": "Perrigen Falls",
+ "EH2I-P": "Perrigen Falls",
+ "OP7-BP": "Perrigen Falls",
+ "5ZU-VG": "Perrigen Falls",
+ "6-1T6Z": "Perrigen Falls",
+ "R-AYGT": "Perrigen Falls",
+ "G-GRSZ": "Perrigen Falls",
+ "6-8QLA": "Perrigen Falls",
+ "5T-A3D": "Perrigen Falls",
+ "H-FOYG": "Perrigen Falls",
+ "1A8-6G": "Perrigen Falls",
+ "PE-SAM": "Perrigen Falls",
+ "RY-2FX": "Perrigen Falls",
+ "K-3PQW": "Perrigen Falls",
+ "4-M1TY": "Perrigen Falls",
+ "C6CG-W": "Perrigen Falls",
+ "H-29TM": "Perrigen Falls",
+ "KOI8-Z": "Perrigen Falls",
+ "D-QJR9": "Perrigen Falls",
+ "U4-V3J": "Perrigen Falls",
+ "B9N2-2": "Perrigen Falls",
+ "6Q4-X6": "Perrigen Falls",
+ "BEG-RL": "Perrigen Falls",
+ "972C-1": "Perrigen Falls",
+ "U-W436": "Perrigen Falls",
+ "Z-ENUD": "Perrigen Falls",
+ "MJ-5F9": "Perrigen Falls",
+ "M5NO-B": "Perrigen Falls",
+ "JZ-UQC": "Perrigen Falls",
+ "JPEZ-R": "Perrigen Falls",
+ "9WVY-F": "Perrigen Falls",
+ "7M4-4C": "Perrigen Falls",
+ "2-YO2K": "Perrigen Falls",
+ "M-SG47": "Perrigen Falls",
+ "SR-10Z": "Perrigen Falls",
+ "W-KXEX": "Perrigen Falls",
+ "TAL1-3": "Perrigen Falls",
+ "QHY-RU": "Perrigen Falls",
+ "7AH-SF": "Perrigen Falls",
+ "7MMJ-3": "Perrigen Falls",
+ "PVF-N9": "Perrigen Falls",
+ "9-EXU9": "Perrigen Falls",
+ "4-1ECP": "Perrigen Falls",
+ "UYOC-1": "Perrigen Falls",
+ "5-U12M": "Perrigen Falls",
+ "5V-Q1R": "Perrigen Falls",
+ "M4-KX5": "Perrigen Falls",
+ "4F9Y-3": "Perrigen Falls",
+ "MS-RXH": "Perrigen Falls",
+ "U-3FKL": "Perrigen Falls",
+ "0XN-SK": "Perrigen Falls",
+ "J9A-BH": "Perrigen Falls",
+ "4F6-VZ": "Perrigen Falls",
+ "B-7LYC": "Perrigen Falls",
+ "JM0A-4": "Perrigen Falls",
+ "PT-2KR": "Perrigen Falls",
+ "L-POLO": "Perrigen Falls",
+ "8B-A4E": "Perrigen Falls",
+ "49V-E4": "Perrigen Falls",
+ "3LL-O0": "Perrigen Falls",
+ "A1F-22": "Perrigen Falls",
+ "9-ZA4Z": "Perrigen Falls",
+ "IU-E9T": "Perrigen Falls",
+ "NGM-OK": "Perrigen Falls",
+ "O-QKSM": "Perrigen Falls",
+ "QKQ3-L": "Perrigen Falls",
+ "VWES-Y": "Perrigen Falls",
+ "SY-OLX": "Perrigen Falls",
+ "XY-ZCI": "Perrigen Falls",
+ "7JRA-G": "Perrigen Falls",
+ "W-CSFY": "Perrigen Falls",
+ "PFV-ZH": "Perrigen Falls",
+ "L5Y4-M": "Perrigen Falls",
+ "9IZ-HU": "Perrigen Falls",
+ "OBV-YC": "Perrigen Falls",
+ "2AUL-X": "Perrigen Falls",
+ "F-HQWV": "Perrigen Falls",
+ "F-A3TR": "Perrigen Falls",
+ "PA-ALN": "Perrigen Falls",
+ "01B-88": "Perrigen Falls",
+ "F18-AY": "Perrigen Falls",
+ "RZ8A-P": "Perrigen Falls",
+ "MTO2-2": "Perrigen Falls",
+ "C3I-D5": "Perrigen Falls",
+ "0-U2M4": "Perrigen Falls",
+ "Shera": "Genesis",
+ "Lor": "Genesis",
+ "Cleyd": "Genesis",
+ "Vecamia": "Genesis",
+ "Ahbazon": "Genesis",
+ "Atreen": "Genesis",
+ "Pakhshi": "Genesis",
+ "Tar": "Genesis",
+ "Tekaima": "Genesis",
+ "Manarq": "Genesis",
+ "Emsar": "Genesis",
+ "Ourapheh": "Genesis",
+ "Yulai": "Genesis",
+ "Tarta": "Genesis",
+ "Kemerk": "Genesis",
+ "Nardiarang": "Genesis",
+ "Ziasad": "Genesis",
+ "Sibe": "Genesis",
+ "Makhwasan": "Genesis",
+ "Zarer": "Genesis",
+ "Toon": "Genesis",
+ "Hesarid": "Genesis",
+ "Ashokon": "Genesis",
+ "Avyuh": "Genesis",
+ "Apanake": "Genesis",
+ "Sheroo": "Genesis",
+ "Sosh": "Genesis",
+ "Sigga": "Genesis",
+ "Keseya": "Genesis",
+ "Zoohen": "Genesis",
+ "Serren": "Genesis",
+ "Hadji": "Genesis",
+ "Assez": "Genesis",
+ "Alal": "Genesis",
+ "Dom-Aphis": "Genesis",
+ "Iderion": "Genesis",
+ "Chamja": "Genesis",
+ "Diaderi": "Genesis",
+ "Manatirid": "Genesis",
+ "Pashanai": "Genesis",
+ "Pamah": "Genesis",
+ "Leran": "Genesis",
+ "Beke": "Genesis",
+ "Malma": "Genesis",
+ "Noranim": "Genesis",
+ "Chej": "Genesis",
+ "Menai": "Genesis",
+ "Aring": "Genesis",
+ "Gayar": "Genesis",
+ "Petidu": "Genesis",
+ "Naka": "Genesis",
+ "Madomi": "Genesis",
+ "Gergish": "Genesis",
+ "Tahli": "Genesis",
+ "Imya": "Genesis",
+ "Kobam": "Genesis",
+ "Hirizan": "Genesis",
+ "Anyed": "Genesis",
+ "Habu": "Genesis",
+ "Asanot": "Genesis",
+ "Anzalaisio": "Genesis",
+ "Chiga": "Genesis",
+ "Abhan": "Genesis",
+ "Saphthar": "Genesis",
+ "Itrin": "Genesis",
+ "Bantish": "Genesis",
+ "Korridi": "Genesis",
+ "Lela": "Genesis",
+ "Keri": "Genesis",
+ "Antem": "Genesis",
+ "Djimame": "Genesis",
+ "Mozzidit": "Genesis",
+ "Angur": "Genesis",
+ "Hangond": "Genesis",
+ "Access": "Genesis",
+ "Bherdasopt": "Genesis",
+ "Gonditsa": "Genesis",
+ "Simela": "Genesis",
+ "Shalne": "Genesis",
+ "Shapisin": "Genesis",
+ "Olin": "Genesis",
+ "Galnafsad": "Genesis",
+ "Otakod": "Genesis",
+ "Azedi": "Genesis",
+ "Sharza": "Genesis",
+ "Pirna": "Genesis",
+ "Seshi": "Genesis",
+ "Anara": "Genesis",
+ "Partod": "Genesis",
+ "Exit": "Genesis",
+ "Gateway": "Genesis",
+ "Central Point": "Genesis",
+ "Promised Land": "Genesis",
+ "Dead End": "Genesis",
+ "New Eden": "Genesis",
+ "Canard": "Genesis",
+ "Girani-Fa": "Genesis",
+ "Nasreri": "Genesis",
+ "Heorah": "Genesis",
+ "Ebasez": "Genesis",
+ "Agal": "Genesis",
+ "Doza": "Genesis",
+ "Bania": "Genesis",
+ "Murethand": "Verge Vendor",
+ "Melmaniel": "Verge Vendor",
+ "Ouelletta": "Verge Vendor",
+ "Costolle": "Verge Vendor",
+ "Muetralle": "Verge Vendor",
+ "Loes": "Verge Vendor",
+ "Tourier": "Verge Vendor",
+ "Alenia": "Verge Vendor",
+ "Merolles": "Verge Vendor",
+ "Alentene": "Verge Vendor",
+ "Cistuvaert": "Verge Vendor",
+ "Vaere": "Verge Vendor",
+ "Aidart": "Verge Vendor",
+ "Jufvitte": "Verge Vendor",
+ "Ansalle": "Verge Vendor",
+ "Scheenins": "Verge Vendor",
+ "Amygnon": "Verge Vendor",
+ "Gisleres": "Verge Vendor",
+ "Ellmay": "Verge Vendor",
+ "Theruesse": "Verge Vendor",
+ "Eletta": "Verge Vendor",
+ "Luse": "Verge Vendor",
+ "Ekuenbiron": "Verge Vendor",
+ "Vay": "Verge Vendor",
+ "Raneilles": "Verge Vendor",
+ "Hevrice": "Verge Vendor",
+ "Jovainnon": "Verge Vendor",
+ "Scolluzer": "Verge Vendor",
+ "Sortet": "Verge Vendor",
+ "Claulenne": "Verge Vendor",
+ "Masalle": "Verge Vendor",
+ "Annelle": "Verge Vendor",
+ "Chesiette": "Verge Vendor",
+ "Reblier": "Verge Vendor",
+ "Amoderia": "Verge Vendor",
+ "Arraron": "Verge Vendor",
+ "Chantrousse": "Verge Vendor",
+ "Osmomonne": "Verge Vendor",
+ "Stou": "Verge Vendor",
+ "Tierijev": "Verge Vendor",
+ "Adallier": "Verge Vendor",
+ "Channace": "Verge Vendor",
+ "Clacille": "Verge Vendor",
+ "Clellinon": "Verge Vendor",
+ "Hykanima": "Black Rise",
+ "Okagaiken": "Black Rise",
+ "Kehjari": "Black Rise",
+ "Villasen": "Black Rise",
+ "Sarenemi": "Black Rise",
+ "Ashitsu": "Black Rise",
+ "Korasen": "Black Rise",
+ "Ienakkamon": "Black Rise",
+ "Kinakka": "Black Rise",
+ "Raihbaka": "Black Rise",
+ "Innia": "Black Rise",
+ "Iralaja": "Black Rise",
+ "Martoh": "Black Rise",
+ "Eha": "Black Rise",
+ "Pavanakka": "Black Rise",
+ "Uchomida": "Black Rise",
+ "Samanuni": "Black Rise",
+ "Astoh": "Black Rise",
+ "Onnamon": "Black Rise",
+ "Rohamaa": "Black Rise",
+ "Uuhulanen": "Black Rise",
+ "Tsuruma": "Black Rise",
+ "Ahtila": "Black Rise",
+ "Ichoriya": "Black Rise",
+ "Okkamon": "Black Rise",
+ "Vaaralen": "Black Rise",
+ "Asakai": "Black Rise",
+ "Prism": "Black Rise",
+ "Mushikegi": "Black Rise",
+ "Teskanen": "Black Rise",
+ "Elunala": "Black Rise",
+ "Ikoskio": "Black Rise",
+ "Hikkoken": "Black Rise",
+ "Enaluri": "Black Rise",
+ "Aivonen": "Black Rise",
+ "Hallanen": "Black Rise",
+ "Akidagi": "Black Rise",
+ "Immuri": "Black Rise",
+ "Nennamaila": "Black Rise",
+ "Hirri": "Black Rise",
+ "Kedama": "Black Rise",
+ "Oinasiken": "Black Rise",
+ "Notoras": "Black Rise",
+ "Rakapas": "Black Rise",
+ "Teimo": "Black Rise",
+ "Iwisoda": "Black Rise",
+ "Nisuwa": "Black Rise",
+ "Pynekastoh": "Black Rise",
+ "Reitsato": "Black Rise"
+}
+
+import logging
+
+def buildUpperKeyedAliases():
+ """Return a dictionary of systems keyed on their upper case name.
+ Each entry is a dictionary with name and region fields in standardized DOTLAN case
+ """
+ systems = dict()
+ for s in SYSTEMS:
+ value = { 'name': s, 'region': SYSTEMS[s] }
+ upper = s.upper()
+ systems[upper] = value
+
+ if '-' in upper:
+ # - short with - (minus), I-I will match I43-IF3
+ parts = upper.split("-")
+ if len(parts) != 2:
+ logging.critical("Unexpected number of dashes in system name [%s]", s)
+ systems[parts[0][0]+':'+parts[1][0]] = value
+ # also add systems removing dashes
+ nodash = upper.replace("-", "")
+ systems[nodash] = value
+
+ if '0' in upper:
+ ohs = upper.replace("0","O")
+ systems[ohs] = value
+
+ if 'O' in upper:
+ zeros = upper.replace("O","0")
+ systems[zeros] = value
+
+ return systems
diff --git a/src/vi/threads.py b/src/vi/threads.py
index 4a5322e..e0873ae 100755
--- a/src/vi/threads.py
+++ b/src/vi/threads.py
@@ -1,200 +1,200 @@
-###########################################################################
-# Vintel - Visual Intel Chat Analyzer #
-# Copyright (C) 2014-15 Sebastian Meyer (sparrow.242.de+eve@gmail.com ) #
-# #
-# This program is free software: you can redistribute it and/or modify #
-# it under the terms of the GNU General Public License as published by #
-# the Free Software Foundation, either version 3 of the License, or #
-# (at your option) any later version. #
-# #
-# This program is distributed in the hope that it will be useful, #
-# but WITHOUT ANY WARRANTY; without even the implied warranty of #
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
-# GNU General Public License for more details. #
-# #
-# #
-# You should have received a copy of the GNU General Public License #
-# along with this program. If not, see . #
-###########################################################################
-
-import time
-import logging
-import six
-
-#from six.moves import queue
-from six.moves.queue import Queue
-from PyQt5.QtCore import pyqtSignal, QThread, QTimer
-from vi import evegate
-from vi import koschecker
-from vi.cache.cache import Cache
-from vi.resources import resourcePath
-
-STATISTICS_UPDATE_INTERVAL_MSECS = 1 * 60 * 1000
-
-class AvatarFindThread(QThread):
-
- avatarUpdate = pyqtSignal(object, object)
-
- def __init__(self):
- QThread.__init__(self)
- self.queue = Queue()
- self.active = True
-
-
- def addChatEntry(self, chatEntry, clearCache=False):
- try:
- if clearCache:
- cache = Cache()
- cache.removeAvatar(chatEntry.message.user)
-
- # Enqeue the data to be picked up in run()
- self.queue.put(chatEntry)
- except Exception as e:
- logging.error("Error in AvatarFindThread: %s", e)
-
-
- def run(self):
- cache = Cache()
- lastCall = 0
- wait = 300 # time between 2 requests in ms
- while True:
- try:
- # Block waiting for addChatEntry() to enqueue something
- chatEntry = self.queue.get()
- if not self.active:
- return
- charname = chatEntry.message.user
- logging.debug("AvatarFindThread getting avatar for %s" % charname)
- avatar = None
- if charname == "VINTEL":
- with open(resourcePath("vi/ui/res/logo_small.png"), "rb") as f:
- avatar = f.read()
- if not avatar:
- avatar = cache.getAvatar(charname)
- if avatar:
- logging.debug("AvatarFindThread found cached avatar for %s" % charname)
- if not avatar:
- diffLastCall = time.time() - lastCall
- if diffLastCall < wait:
- time.sleep((wait - diffLastCall) / 1000.0)
- avatar = evegate.getAvatarForPlayer(charname)
- lastCall = time.time()
- if avatar:
- cache.putAvatar(charname, avatar)
- if avatar:
- logging.debug("AvatarFindThread emit avatar_update for %s" % charname)
- self.avatarUpdate.emit(chatEntry, avatar)
- except Exception as e:
- logging.error("Error in AvatarFindThread : %s", e)
-
-
- def quit(self):
- self.active = False
- self.queue.put(None)
- QThread.quit(self)
-
-
-class KOSCheckerThread(QThread):
-
- showKos = pyqtSignal(str, str, str, bool)
-
- def __init__(self):
- QThread.__init__(self)
- self.queue = Queue()
- self.recentRequestNamesAndTimes = {}
- self.active = True
-
-
- def addRequest(self, names, requestType, onlyKos=False):
- try:
- # Spam control for multi-client users
- now = time.time()
- if names in self.recentRequestNamesAndTimes:
- lastRequestTime = self.recentRequestNamesAndTimes[names]
- if now - lastRequestTime < 10:
- return
- self.recentRequestNamesAndTimes[names] = now
-
- # Enqeue the data to be picked up in run()
- self.queue.put((names, requestType, onlyKos))
- except Exception as e:
- logging.error("Error in KOSCheckerThread.addRequest: %s", e)
-
-
- def run(self):
- while True:
- # Block waiting for addRequest() to enqueue something
- names, requestType, onlyKos = self.queue.get()
- if not self.active:
- return
- try:
- #logging.info("KOSCheckerThread kos checking %s" % str(names))
- hasKos = False
- if not names:
- continue
- checkResult = koschecker.check(names)
- if not checkResult:
- continue
- text = koschecker.resultToText(checkResult, onlyKos)
- for name, data in checkResult.items():
- if data["kos"] in (koschecker.KOS, koschecker.RED_BY_LAST):
- hasKos = True
- break
- except Exception as e:
- logging.error("Error in KOSCheckerThread.run: %s", e)
- continue
-
- logging.info("KOSCheckerThread emitting kos_result for: state = {0}, text = {1}, requestType = {2}, hasKos = {3}".format(
- "ok", text, requestType, hasKos))
- self.showKos.emit("ok", text, requestType, hasKos)
-
- def quit(self):
- self.active = False
- self.queue.put((None, None, None))
- QThread.quit(self)
-
-
-class MapStatisticsThread(QThread):
-
- updateMap = pyqtSignal(dict)
-
- def __init__(self):
- QThread.__init__(self)
- self.queue = Queue(maxsize=1)
- self.lastStatisticsUpdate = time.time()
- self.pollRate = STATISTICS_UPDATE_INTERVAL_MSECS
- self.refreshTimer = None
- self.active = True
-
-
- def requestStatistics(self):
- self.queue.put(1)
-
-
- def run(self):
- self.refreshTimer = QTimer()
- self.refreshTimer.timeout.connect(self.requestStatistics)
- while True:
- # Block waiting for requestStatistics() to enqueue a token
- self.queue.get()
- if not self.active:
- return
- self.refreshTimer.stop()
- logging.debug("MapStatisticsThread requesting statistics")
- try:
- statistics = evegate.getSystemStatistics()
- #time.sleep(2) # sleeping to prevent a "need 2 arguments"-error
- requestData = {"result": "ok", "statistics": statistics}
- except Exception as e:
- logging.error("Error in MapStatisticsThread: %s", e)
- requestData = {"result": "error", "text": six.text_type(e)}
- self.lastStatisticsUpdate = time.time()
- self.refreshTimer.start(self.pollRate)
- self.updateMap.emit(requestData)
- logging.debug("MapStatisticsThread emitted statistic_data_update")
-
-
- def quit(self):
- self.active = False
- self.queue.put(None)
- QThread.quit(self)
+###########################################################################
+# Vintel - Visual Intel Chat Analyzer #
+# Copyright (C) 2014-15 Sebastian Meyer (sparrow.242.de+eve@gmail.com ) #
+# #
+# This program is free software: you can redistribute it and/or modify #
+# it under the terms of the GNU General Public License as published by #
+# the Free Software Foundation, either version 3 of the License, or #
+# (at your option) any later version. #
+# #
+# This program is distributed in the hope that it will be useful, #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+# GNU General Public License for more details. #
+# #
+# #
+# You should have received a copy of the GNU General Public License #
+# along with this program. If not, see . #
+###########################################################################
+
+import time
+import logging
+import six
+
+#from six.moves import queue
+from six.moves.queue import Queue
+from PyQt5.QtCore import pyqtSignal, QThread, QTimer
+from vi import evegate
+from vi import koschecker
+from vi.cache.cache import Cache
+from vi.resources import resourcePath
+
+STATISTICS_UPDATE_INTERVAL_MSECS = 1 * 60 * 1000
+
+class AvatarFindThread(QThread):
+
+ avatarUpdate = pyqtSignal(object, object)
+
+ def __init__(self):
+ QThread.__init__(self)
+ self.queue = Queue()
+ self.active = True
+
+
+ def addChatEntry(self, chatEntry, clearCache=False):
+ try:
+ if clearCache:
+ cache = Cache()
+ cache.removeAvatar(chatEntry.message.user)
+
+ # Enqeue the data to be picked up in run()
+ self.queue.put(chatEntry)
+ except Exception as e:
+ logging.error("Error in AvatarFindThread: %s", e)
+
+
+ def run(self):
+ cache = Cache()
+ lastCall = 0
+ wait = 300 # time between 2 requests in ms
+ while True:
+ try:
+ # Block waiting for addChatEntry() to enqueue something
+ chatEntry = self.queue.get()
+ if not self.active:
+ return
+ charname = chatEntry.message.user
+ logging.debug("AvatarFindThread getting avatar for %s" % charname)
+ avatar = None
+ if charname == "VINTEL":
+ with open(resourcePath("vi/ui/res/logo_small.png"), "rb") as f:
+ avatar = f.read()
+ if not avatar:
+ avatar = cache.getAvatar(charname)
+ if avatar:
+ logging.debug("AvatarFindThread found cached avatar for %s" % charname)
+ if not avatar:
+ diffLastCall = time.time() - lastCall
+ if diffLastCall < wait:
+ time.sleep((wait - diffLastCall) / 1000.0)
+ avatar = evegate.getAvatarForPlayer(charname)
+ lastCall = time.time()
+ if avatar:
+ cache.putAvatar(charname, avatar)
+ if avatar:
+ logging.debug("AvatarFindThread emit avatar_update for %s" % charname)
+ self.avatarUpdate.emit(chatEntry, avatar)
+ except Exception as e:
+ logging.error("Error in AvatarFindThread : %s", e)
+
+
+ def quit(self):
+ self.active = False
+ self.queue.put(None)
+ QThread.quit(self)
+
+
+class KOSCheckerThread(QThread):
+
+ showKos = pyqtSignal(str, str, str, bool)
+
+ def __init__(self):
+ QThread.__init__(self)
+ self.queue = Queue()
+ self.recentRequestNamesAndTimes = {}
+ self.active = True
+
+
+ def addRequest(self, names, requestType, onlyKos=False):
+ try:
+ # Spam control for multi-client users
+ now = time.time()
+ if names in self.recentRequestNamesAndTimes:
+ lastRequestTime = self.recentRequestNamesAndTimes[names]
+ if now - lastRequestTime < 10:
+ return
+ self.recentRequestNamesAndTimes[names] = now
+
+ # Enqeue the data to be picked up in run()
+ self.queue.put((names, requestType, onlyKos))
+ except Exception as e:
+ logging.error("Error in KOSCheckerThread.addRequest: %s", e)
+
+
+ def run(self):
+ while True:
+ # Block waiting for addRequest() to enqueue something
+ names, requestType, onlyKos = self.queue.get()
+ if not self.active:
+ return
+ try:
+ #logging.info("KOSCheckerThread kos checking %s" % str(names))
+ hasKos = False
+ if not names:
+ continue
+ checkResult = koschecker.check(names)
+ if not checkResult:
+ continue
+ text = koschecker.resultToText(checkResult, onlyKos)
+ for name, data in checkResult.items():
+ if data["kos"] in (koschecker.KOS, koschecker.RED_BY_LAST):
+ hasKos = True
+ break
+ except Exception as e:
+ logging.error("Error in KOSCheckerThread.run: %s", e)
+ continue
+
+ logging.info("KOSCheckerThread emitting kos_result for: state = {0}, text = {1}, requestType = {2}, hasKos = {3}".format(
+ "ok", text, requestType, hasKos))
+ self.showKos.emit("ok", text, requestType, hasKos)
+
+ def quit(self):
+ self.active = False
+ self.queue.put((None, None, None))
+ QThread.quit(self)
+
+
+class MapStatisticsThread(QThread):
+
+ updateMap = pyqtSignal(dict)
+
+ def __init__(self):
+ QThread.__init__(self)
+ self.queue = Queue(maxsize=1)
+ self.lastStatisticsUpdate = time.time()
+ self.pollRate = STATISTICS_UPDATE_INTERVAL_MSECS
+ self.refreshTimer = None
+ self.active = True
+
+
+ def requestStatistics(self):
+ self.queue.put(1)
+
+
+ def run(self):
+ self.refreshTimer = QTimer()
+ self.refreshTimer.timeout.connect(self.requestStatistics)
+ while True:
+ # Block waiting for requestStatistics() to enqueue a token
+ self.queue.get()
+ if not self.active:
+ return
+ self.refreshTimer.stop()
+ logging.debug("MapStatisticsThread requesting statistics")
+ try:
+ statistics = evegate.getSystemStatistics()
+ #time.sleep(2) # sleeping to prevent a "need 2 arguments"-error
+ requestData = {"result": "ok", "statistics": statistics}
+ except Exception as e:
+ logging.error("Error in MapStatisticsThread: %s", e)
+ requestData = {"result": "error", "text": six.text_type(e)}
+ self.lastStatisticsUpdate = time.time()
+ self.refreshTimer.start(self.pollRate)
+ self.updateMap.emit(requestData)
+ logging.debug("MapStatisticsThread emitted statistic_data_update")
+
+
+ def quit(self):
+ self.active = False
+ self.queue.put(None)
+ QThread.quit(self)
diff --git a/src/vi/ui/ChatroomsChooser.ui b/src/vi/ui/ChatroomsChooser.ui
deleted file mode 100644
index 4e4fb40..0000000
--- a/src/vi/ui/ChatroomsChooser.ui
+++ /dev/null
@@ -1,66 +0,0 @@
-
-
- Dialog
-
-
-
- 0
- 0
- 556
- 197
-
-
-
- Chatrooms
-
-
- -
-
-
-
-
-
- Enter the chatrooms to watch into the following field. Separate them by comma.
-
-
- Qt::PlainText
-
-
- true
-
-
-
- -
-
-
- -
-
-
-
-
-
- Restore Defaults
-
-
-
- -
-
-
- Cancel
-
-
-
- -
-
-
- Save
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/vi/ui/JumpbridgeChooser.ui b/src/vi/ui/JumpbridgeChooser.ui
deleted file mode 100644
index f6d233c..0000000
--- a/src/vi/ui/JumpbridgeChooser.ui
+++ /dev/null
@@ -1,106 +0,0 @@
-
-
- Dialog
-
-
-
- 0
- 0
- 696
- 394
-
-
-
- Jumpbridge Data
-
-
- -
-
-
-
-
-
-
-
-
-
- Path to the Data
-
-
-
-
-
-
- For example: http://example.org/jumpbridge_data.txt
-
-
-
- -
-
-
-
-
-
- Please enter the URL to the Jumpbridge data:
-
-
-
- -
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
- Format of the jumpbridge data:
-
-
-
-
-
-
- QPlainTextEdit::NoWrap
-
-
- true
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
- Cancel
-
-
-
- -
-
-
- Save
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/vi/ui/MainWindow.ui b/src/vi/ui/MainWindow.ui
index 3561e2f..39f1da9 100644
--- a/src/vi/ui/MainWindow.ui
+++ b/src/vi/ui/MainWindow.ui
@@ -37,16 +37,7 @@
-
- 0
-
-
- 0
-
-
- 0
-
-
+
0
@@ -72,16 +63,7 @@
-
- 0
-
-
- 0
-
-
- 0
-
-
+
0
-
@@ -255,19 +237,10 @@
All Intel (past 20 minutes)
-
- 5
-
-
- 5
-
-
- 5
-
-
+
5
-
+
5
-
@@ -341,15 +314,15 @@
0
0
936
- 22
+ 21
-
+
+
@@ -521,11 +501,8 @@
-
- true
-
- Other Region...
+ Custom Region...
@@ -533,9 +510,9 @@
Sound Setup...
-
+
- Jumpbridge Data...
+ Flush Cache
@@ -584,59 +561,9 @@
Transparency
-
-
- true
-
+
- Providence
-
-
- providence
-
-
-
-
- true
-
-
- Catch
-
-
- catch
-
-
-
-
- true
-
-
- Provi / Catch
-
-
- providencecatch
-
-
-
-
- true
-
-
- Provi / Catch (compact)
-
-
- Providence-catch
-
-
-
-
- true
-
-
- Querious
-
-
- querious
+ Settings
diff --git a/src/vi/ui/SettingsTabs.ui b/src/vi/ui/SettingsTabs.ui
new file mode 100644
index 0000000..7b4be63
--- /dev/null
+++ b/src/vi/ui/SettingsTabs.ui
@@ -0,0 +1,389 @@
+
+
+ Dialog
+
+
+
+ 0
+ 0
+ 640
+ 480
+
+
+
+ Settings
+
+
+
+
+ 0
+ 0
+ 640
+ 480
+
+
+
+
+ 0
+ 0
+
+
+
+ TabWidget
+
+
+ 1
+
+
+
+
+ 0
+ 0
+
+
+
+ Quick Setup
+
+
+
+
+ 10
+ 10
+ 611
+ 431
+
+
+
+ -
+
+
+ Paste the quick setup text here that was provided by your alliance, corporation, ...
+
+
+ Qt::PlainText
+
+
+ true
+
+
+
+ -
+
+
+ -
+
+
-
+
+
+ Undo
+
+
+
+ -
+
+
+ Apply
+
+
+
+
+
+
+
+
+
+
+ Jumpbridges
+
+
+
+
+ 10
+ 0
+ 611
+ 453
+
+
+
+
+ QLayout::SetMaximumSize
+
+ -
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ Setup jumpbridges to be displayed on the map. You can setup a url with your own data or include a DOTLAN jumpbridge id.
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ false
+
+
+ Please enter the URL to the Jumpbridge data (i.e. http://example.org/jumpbridge_data.txt):
+
+
+ false
+
+
+ false
+
+
+
+
+ 10
+ 24
+ 571
+ 221
+
+
+
+
-
+
+
+ -
+
+
+ true
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 100
+
+
+
+ Qt::ScrollBarAlwaysOn
+
+
+ Qt::ScrollBarAlwaysOff
+
+
+ QPlainTextEdit::WidgetWidth
+
+
+ true
+
+
+ How to format the data for the jumpbridges:
+
+Put all the jumpbridges in one single textfile, wher a line in the file represents a jumpbridge.
+
+The line contains the first system, the connection between the systems and the second system. Between the three parts hast to be a space.
+
+The connection is a line (minus) in the middle and possible arrows (sign for greater or lower) at the ends. If there is such a sign, an arrow will be drawn on the map.
+
+Examples:
+
+System1 <-> System2
+System3 <- System4
+System5 - System6
+
+The first line will draw a jumpbridge between System1 and System2 with an arrow on both sides.
+The second line will draw a jumpbridge between System3 and System4, but only the side to System3 will have an arrow pointing on the system (could be helpfull for "oneway"-jumpbridges).
+The last line draws a line between System5 and System 6 and no arrows at the endpoints.
+
+Write the systemnames as they are written in the maps.
+
+Don't forget the space between the System names and the jumpbridge!
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 48
+
+
+
+ Use Jumpbridge Info from Dotlan
+
+
+ false
+
+
+ false
+
+
+
-
+
+
+ QLayout::SetDefaultConstraint
+
+
+ 6
+
+
-
+
+
+
+ 0
+ 5
+
+
+
+ Dotlan Jumpbridge Id
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
-
+
+
+ Undo
+
+
+
+ -
+
+
+ Apply
+
+
+
+
+
+
+
+
+
+
+ Chat Channels
+
+
+
+
+ 10
+ 10
+ 611
+ 431
+
+
+
+ -
+
+
+ Enter the channels to watch below. Separate them by comma.
+
+
+ Qt::PlainText
+
+
+ true
+
+
+
+ -
+
+
+ -
+
+
-
+
+
+ Restore Defaults
+
+
+
+ -
+
+
+ Undo
+
+
+
+ -
+
+
+ Apply
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/vi/ui/viui.py b/src/vi/ui/viui.py
index cb49108..0b5e8a8 100644
--- a/src/vi/ui/viui.py
+++ b/src/vi/ui/viui.py
@@ -18,25 +18,29 @@
###########################################################################
import datetime
+import functools
import os
import sys
import time
import six
+import json
+import traceback
import requests
import webbrowser
import logging
import vi
from PyQt5 import QtWidgets, QtGui, uic, QtCore
-from PyQt5.QtCore import pyqtSignal, QSettings, QPoint, QByteArray
+from PyQt5.QtCore import pyqtSignal, pyqtSlot, QSettings, QPoint, QByteArray
from PyQt5.QtWidgets import QMessageBox, QAction, QActionGroup, QStyleOption, QStyle, QSystemTrayIcon, QDialog, QWidget
from PyQt5.QtGui import QImage, QPixmap, QPainter
-from vi import amazon_s3, evegate,dotlan, filewatcher, states, version
+from vi import amazon_s3, evegate, dotlan, filewatcher, states, systems, version
from vi.cache.cache import Cache
from vi.resources import resourcePath
from vi.soundmanager import SoundManager
from vi.threads import AvatarFindThread, KOSCheckerThread, MapStatisticsThread
from vi.ui.systemtray import TrayContextMenu
+from vi.regions import REGIONS
from vi.chatparser.chatparser import ChatParser, Message
OLD_STYLE_WEBKIT = "OLD_STYLE_WEBKIT" in os.environ
@@ -45,7 +49,7 @@
from PyQt5.QtWebKitWidgets import QWebPage
# Timer intervals
-MESSAGE_EXPIRY_SECS = 20 * 60
+MESSAGE_EXPIRY_SECS = 60 * 60 * 1
MAP_UPDATE_INTERVAL_MSECS = 4 * 1000
CLIPBOARD_CHECK_INTERVAL_MSECS = 4 * 1000
@@ -86,6 +90,10 @@ def __init__(self, pathToLogs, trayIcon, backGroundColor):
self.scanIntelForKosRequestsEnabled = True
self.initialMapPosition = None
self.mapPositionsDict = {}
+ self.chatparser = None
+ self.systemsWithRegions = systems.buildUpperKeyedAliases()
+
+ self.chatbox.setTitle("All Intel (past {0} minues)".format(str(MESSAGE_EXPIRY_SECS/60)))
# Load user's toon names
self.knownPlayerNames = self.cache.getFromCache("known_player_names")
@@ -97,12 +105,12 @@ def __init__(self, pathToLogs, trayIcon, backGroundColor):
QMessageBox.warning(None, "Known Characters not Found", diagText, QMessageBox.Ok)
# Set up user's intel rooms
- roomnames = self.cache.getFromCache("room_names")
+ roomnames = self.cache.getConfigValue("channel_names")
if roomnames:
roomnames = roomnames.split(",")
else:
roomnames = (u"TheCitadel", u"North Provi Intel", u"North Catch Intel", "North Querious Intel")
- self.cache.putIntoCache("room_names", u",".join(roomnames), 60 * 60 * 24 * 365 * 5)
+ self.cache.saveConfigValue("channel_names", u",".join(roomnames))
self.roomnames = roomnames
# Disable the sound UI if sound is not available
@@ -137,7 +145,10 @@ def __init__(self, pathToLogs, trayIcon, backGroundColor):
self.wireUpUIConnections()
self.readAndApplySettings()
self.setupThreads()
+ self.updateRegionMenu()
+ self.updateOtherRegionMenu()
self.setupMap(True)
+ self.replayLogs()
def paintEvent(self, event):
@@ -146,6 +157,66 @@ def paintEvent(self, event):
painter = QPainter(self)
self.style().drawPrimitive(QStyle.PE_Widget, opt, painter, self)
+ def wheelEvent(self,event):
+ if event.modifiers() & QtCore.Qt.ControlModifier:
+ steps = event.angleDelta().y() // 120
+ vector = steps and steps // abs(steps) # 0, 1, or -1
+ for step in range(1, abs(steps) + 1):
+ self.mapView.setZoomFactor(self.mapView.zoomFactor() + vector * 0.1)
+
+ def keyPressEvent(self, event):
+ key = event.key()
+ if key == QtCore.Qt.Key_0:
+ if event.modifiers() & QtCore.Qt.ControlModifier:
+ self.mapView.setZoomFactor(1.0)
+ elif key == QtCore.Qt.Key_Plus or key == QtCore.Qt.Key_Equal:
+ if event.modifiers() & QtCore.Qt.ControlModifier:
+ self.mapView.setZoomFactor(self.mapView.zoomFactor() + 0.1)
+ elif key == QtCore.Qt.Key_Minus or key == QtCore.Qt.Key_Underscore:
+ if event.modifiers() & QtCore.Qt.ControlModifier:
+ self.mapView.setZoomFactor(self.mapView.zoomFactor() - 0.1)
+ elif key == QtCore.Qt.Key_J:
+ self.changeJumpbridgesVisibility()
+
+
+ def updateOtherRegionMenu(self):
+ for region in REGIONS:
+ menuItem = self.otherRegionSubmenu.addAction(region)
+ menuItem.triggered.connect(functools.partial(self.onRegionSelect, region))
+ self.otherRegionSubmenu.addAction(menuItem)
+
+
+ def updateRegionMenu(self):
+ quick_regions = self.cache.getConfigValue("quick_regions")
+ if quick_regions:
+ j = json.loads(quick_regions)
+ for old_item in self.menuRegion.actions():
+ if "Other Region..." == old_item.text():
+ orm = self.menuRegion.insertSeparator(old_item)
+ break
+ self.menuRegion.removeAction(old_item)
+ for r in j:
+ if not 'label' in r:
+ self.trayIcon.showMessage("Quick regions error", "No label field in :\n {0}".format(str(r)), 1)
+ label = r['label']
+ if label.startswith('-'):
+ menuItem = self.menuRegion.insertSeparator(orm)
+ continue
+ if 'region' in r:
+ region = r['region']
+ else:
+ region = label
+ menuItem = self.menuRegion.addAction(label)
+ menuItem.triggered.connect(functools.partial(self.onRegionSelect, region))
+ self.menuRegion.insertAction(orm, menuItem)
+
+
+ @pyqtSlot(str)
+ def onRegionSelect(self, region):
+ logging.critical("NEW REGION: [%s]", region)
+ Cache().saveConfigValue("region_name", region)
+ self.handleRegionChosen()
+
def wireUpUIConnections(self):
# Wire up general UI connections
@@ -161,12 +232,6 @@ def wireUpUIConnections(self):
self.infoAction.triggered.connect(self.showInfo)
self.showChatAvatarsAction.triggered.connect(self.changeShowAvatars)
self.alwaysOnTopAction.triggered.connect(self.changeAlwaysOnTop)
- self.chooseChatRoomsAction.triggered.connect(self.showChatroomChooser)
- self.catchRegionAction.triggered.connect(lambda : self.handleRegionMenuItemSelected(self.catchRegionAction))
- self.providenceRegionAction.triggered.connect(lambda : self.handleRegionMenuItemSelected(self.providenceRegionAction))
- self.queriousRegionAction.triggered.connect(lambda : self.handleRegionMenuItemSelected(self.queriousRegionAction))
- self.providenceCatchRegionAction.triggered.connect(lambda : self.handleRegionMenuItemSelected(self.providenceCatchRegionAction))
- self.providenceCatchCompactRegionAction.triggered.connect(lambda : self.handleRegionMenuItemSelected(self.providenceCatchCompactRegionAction))
self.chooseRegionAction.triggered.connect(self.showRegionChooser)
self.showChatAction.triggered.connect(self.changeChatVisibility)
self.soundSetupAction.triggered.connect(self.showSoundSetup)
@@ -178,7 +243,8 @@ def wireUpUIConnections(self):
self.frameButton.clicked.connect(self.changeFrameless)
self.quitAction.triggered.connect(self.close)
self.trayIcon.quitSignal.connect(self.close)
- self.jumpbridgeDataAction.triggered.connect(self.showJumbridgeChooser)
+ self.settingsAction.triggered.connect(self.showSettings)
+ self.flushCacheAction.triggered.connect(self.flushCache)
if OLD_STYLE_WEBKIT:
self.mapView.page().scrollRequested.connect(self.mapPositionChanged)
else:
@@ -216,7 +282,7 @@ def setupMap(self, initialize=False):
self.filewatcherThread.paused = True
logging.info("Finding map file")
- regionName = self.cache.getFromCache("region_name")
+ regionName = self.cache.getConfigValue("region_name")
if not regionName:
regionName = "Providence"
svg = None
@@ -232,6 +298,11 @@ def setupMap(self, initialize=False):
logging.error(e)
QMessageBox.critical(None, "Error getting map", six.text_type(e), QMessageBox.Close)
sys.exit(1)
+ except Exception as e:
+ self.cache.deleteFromCache("region_name")
+ logging.error(e)
+ QMessageBox.critical(None, "Error setting up map", six.text_type(e), QMessageBox.Close)
+ sys.exit(1)
if self.dotlan.outdatedCacheError:
e = self.dotlan.outdatedCacheError
@@ -242,10 +313,19 @@ def setupMap(self, initialize=False):
# Load the jumpbridges
logging.critical("Load jump bridges")
- self.setJumpbridges(self.cache.getFromCache("jumpbridge_url"))
+ self.setJumpbridges(self.cache.getConfigValue("jumpbridge_url"))
+
self.systems = self.dotlan.systems
+
logging.critical("Creating chat parser")
- self.chatparser = ChatParser(self.pathToLogs, self.roomnames, self.systems)
+ oldParser = self.chatparser
+ self.chatparser = ChatParser(self.pathToLogs, self.roomnames, self.systemsWithRegions, MESSAGE_EXPIRY_SECS)
+ if oldParser:
+ scrollPosition = self.chatListWidget.verticalScrollBar().value()
+ self.chatListWidget.clear()
+ self.processLogMessages(oldParser.knownMessages)
+ self.chatListWidget.verticalScrollBar().setSliderPosition(scrollPosition)
+ self.chatparser.knownMessages = oldParser.knownMessages
# Menus - only once
if initialize:
@@ -263,19 +343,6 @@ def mapContextMenuEvent(event):
self.mapView.linkClicked.connect(self.mapLinkClicked)
self.mapView.page().setLinkDelegationPolicy(QWebPage.DelegateAllLinks)
- # Also set up our app menus
- if not regionName:
- self.providenceCatchRegionAction.setChecked(True)
- elif regionName.startswith("Providencecatch"):
- self.providenceCatchRegionAction.setChecked(True)
- elif regionName.startswith("Catch"):
- self.catchRegionAction.setChecked(True)
- elif regionName.startswith("Providence"):
- self.providenceRegionAction.setChecked(True)
- elif regionName.startswith("Querious"):
- self.queriousRegionAction.setChecked(True)
- else:
- self.chooseRegionAction.setChecked(True)
self.jumpbridgesButton.setChecked(False)
self.statisticsButton.setChecked(False)
@@ -284,6 +351,7 @@ def mapContextMenuEvent(event):
self.updateMapView()
self.setInitialMapPositionForRegion(regionName)
self.mapTimer.start(MAP_UPDATE_INTERVAL_MSECS)
+
# Allow the file watcher to run now that all else is set up
self.filewatcherThread.paused = False
logging.critical("Map setup complete")
@@ -315,7 +383,7 @@ def readAndApplySettings(self):
# Cached settings
try:
- settings = self.cache.getFromCache("settings-2")
+ settings = self.cache.getConfigValue("settings-2")
if settings:
try:
settings = eval(settings)
@@ -377,7 +445,8 @@ def writeSettings(self):
(None, "changeUseSpokenNotifications", self.useSpokenNotificationsAction.isChecked()),
(None, "changeKosCheckClipboard", self.kosClipboardActiveAction.isChecked()),
(None, "changeAutoScanIntel", self.scanIntelForKosRequestsEnabled))
- self.cache.putIntoCache("settings-2", str(settings), thirtyDaysInSeconds)
+
+ self.cache.saveConfigValue("settings-2", str(settings))
def startClipboardTimer(self):
@@ -584,8 +653,24 @@ def mapLinkClicked(self, url):
def markSystemOnMap(self, systemname):
- self.systems[six.text_type(systemname)].mark()
- self.updateMapView()
+ n = six.text_type(systemname)
+ if n in self.systems:
+ self.systems[n].mark()
+ self.updateMapView()
+ elif n.upper() in self.systemsWithRegions:
+ logging.warn('System [%s] is in another region [%s]',
+ self.systemsWithRegions[n]['name'], self.systemsWithRegions[n]['region'])
+ ans = QMessageBox.question(self,
+ u"System not on current map",
+ u"{0} is in {1}. Would you like to view the {1} map?".format(
+ six.text_type(self.systemsWithRegions[n]['name']),
+ six.text_type(self.systemsWithRegions[n]['region'])),
+ QMessageBox.Ok, QMessageBox.Cancel)
+ if QMessageBox.Ok == ans:
+ self.onRegionSelect(self.systemsWithRegions[n]['region'])
+ self.markSystemOnMap(systemname)
+ else:
+ logging.warn('System [%s] is unknown.', n)
def setLocation(self, char, newSystem):
@@ -593,7 +678,7 @@ def setLocation(self, char, newSystem):
system.removeLocatedCharacter(char)
if not newSystem == "?" and newSystem in self.systems:
self.systems[newSystem].addLocatedCharacter(char)
- self.setMapContent(self.dotlan.svg)
+ self.updateMapView()
def getMapScrollPosition(self):
if OLD_STYLE_WEBKIT:
@@ -647,7 +732,7 @@ def loadInitialMapPositions(self, newDictionary):
def setInitialMapPositionForRegion(self, regionName):
try:
if not regionName:
- regionName = self.cache.getFromCache("region_name")
+ regionName = self.cache.getConfigValue("region_name")
if regionName:
xy = self.mapPositionsDict[regionName]
self.initialMapPosition = QPoint(xy[0], xy[1])
@@ -656,12 +741,19 @@ def setInitialMapPositionForRegion(self, regionName):
def mapPositionChanged(self, dx, dy, rectToScroll):
- regionName = self.cache.getFromCache("region_name")
+ regionName = self.cache.getConfigValue("region_name")
if regionName:
scrollPosition = self.getMapScrollPosition()
self.mapPositionsDict[regionName] = (scrollPosition.x(), scrollPosition.y())
+ def showSettings(self):
+ chooser = Settings(self)
+ chooser.roomsChanged.connect(self.changedRoomnames)
+ chooser.setJumpbridgeUrl.connect(self.setJumpbridges)
+ chooser.show()
+
+
def mapPositionChangedToPoint(self, point):
regionName = self.cache.getFromCache("region_name")
if regionName:
@@ -675,17 +767,8 @@ def handleLoadFinished(self):
self.deferedScrollPosition = None
- def showChatroomChooser(self):
- chooser = ChatroomsChooser(self)
- chooser.roomsChanged.connect(self.changedRoomnames)
- chooser.show()
-
-
- def showJumbridgeChooser(self):
- url = self.cache.getFromCache("jumpbridge_url")
- chooser = JumpbridgeChooser(self, url)
- chooser.setJumpBridgeUrl.connect(self.setJumpbridges)
- chooser.show()
+ def flushCache(self):
+ self.cache.flush()
def setSoundVolume(self, value):
@@ -693,6 +776,7 @@ def setSoundVolume(self, value):
def setJumpbridges(self, url):
+
if url is None:
url = ""
try:
@@ -706,37 +790,36 @@ def setJumpbridges(self, url):
else:
data = amazon_s3.getJumpbridgeData(self.dotlan.region.lower())
self.dotlan.setJumpbridges(data)
- self.cache.putIntoCache("jumpbridge_url", url, 60 * 60 * 24 * 365 * 8)
+ self.cache.saveConfigValue("jumpbridge_url", url)
except Exception as e:
QMessageBox.warning(None, "Loading jumpbridges failed!", "Error: {0}".format(six.text_type(e)), QMessageBox.Ok)
def handleRegionMenuItemSelected(self, menuAction=None):
- self.catchRegionAction.setChecked(False)
- self.providenceRegionAction.setChecked(False)
- self.queriousRegionAction.setChecked(False)
- self.providenceCatchRegionAction.setChecked(False)
- self.providenceCatchCompactRegionAction.setChecked(False)
- self.chooseRegionAction.setChecked(False)
if menuAction:
- menuAction.setChecked(True)
regionName = six.text_type(str(menuAction.property("regionName")))
regionName = dotlan.convertRegionName(regionName)
- Cache().putIntoCache("region_name", regionName, 60 * 60 * 24 * 365)
+ Cache().saveConfigValue("region_name", regionName)
self.setupMap()
+ def handleRegionChosen(self):
+ self.setupMap()
def showRegionChooser(self):
- def handleRegionChosen():
- self.handleRegionMenuItemSelected(None)
- self.chooseRegionAction.setChecked(True)
- self.setupMap()
-
- self.chooseRegionAction.setChecked(False)
chooser = RegionChooser(self)
- chooser.newRegionChosen.connect(handleRegionChosen)
+ chooser.newRegionChosen.connect(self.handleRegionChosen)
chooser.show()
+ def replayLogs(self):
+ """On startup, replay info from logfiles"""
+ messages = []
+ for path in self.chatparser.rewind():
+ messages.extend(self.chatparser.fileModified(path))
+ messages.sort(key=lambda x: x.timestamp)
+ # we use these parsed messages to replay events on region switch, reset them to a time ordered list
+ self.chatparser.knownMessages = messages
+ self.processLogMessages(messages)
+ logging.critical("Done with replay")
def addMessageToIntelChat(self, message):
scrollToBottom = False
@@ -757,6 +840,7 @@ def addMessageToIntelChat(self, message):
def pruneMessages(self):
+ self.chatparser.expire()
try:
now = time.mktime(evegate.currentEveTime().timetuple())
for row in range(self.chatListWidget.count()):
@@ -799,7 +883,7 @@ def showKosResult(self, state, text, requestType, hasKos):
def changedRoomnames(self, newRoomnames):
- self.cache.putIntoCache("room_names", u",".join(newRoomnames), 60 * 60 * 24 * 365 * 5)
+ self.cache.saveConfigValue("channel_names", u",".join(newRoomnames))
self.chatparser.rooms = newRoomnames
@@ -837,7 +921,7 @@ def systemTrayActivated(self, reason):
def updateAvatarOnChatEntry(self, chatEntry, avatarData):
updated = chatEntry.updateAvatar(avatarData)
if not updated:
- self.avatarFindThread.addChatEntry(chatEntry, clearCache=True)
+ self.avatarFindThread.addChatEntry(chatEntry) # , clearCache=True)
else:
self.avatarLoaded.emit(chatEntry.message.user, avatarData)
@@ -869,7 +953,14 @@ def zoomMapOut(self):
def logFileChanged(self, path):
messages = self.chatparser.fileModified(path)
+ self.processLogMessages(messages)
+
+ def processLogMessages(self, messages):
for message in messages:
+
+ # This function is a resource pig, give others a chance to run while we process messages
+ time.sleep(0)
+
# If players location has changed
if message.status == states.LOCATION:
self.knownPlayerNames.add(message.user)
@@ -890,9 +981,12 @@ def logFileChanged(self, path):
# and alarm if within alarm distance.
systemList = self.dotlan.systems
if message.systems:
- for system in message.systems:
- systemname = system.name
- systemList[systemname].setStatus(message.status)
+ for systemname in message.systems:
+ if not systemname in self.systems:
+ logging.debug("No dotlan match for system [%s], maybe it's not shown right now:", systemname)
+ continue
+ system = self.systems[systemname]
+ system.setStatus(message.status, message.timestamp)
if message.status in (states.REQUEST, states.ALARM) and message.user not in self.knownPlayerNames:
alarmDistance = self.alarmDistance if message.status == states.ALARM else 0
for nSystem, data in system.getNeighbours(alarmDistance).items():
@@ -900,36 +994,10 @@ def logFileChanged(self, path):
chars = nSystem.getLocatedCharacters()
if len(chars) > 0 and message.user not in chars:
self.trayIcon.showNotification(message, system.name, ", ".join(chars), distance)
- self.setMapContent(self.dotlan.svg)
-
-
-class ChatroomsChooser(QDialog):
-
- roomsChanged = pyqtSignal(list);
-
- def __init__(self, parent):
- QDialog.__init__(self, parent)
- uic.loadUi(resourcePath("vi/ui/ChatroomsChooser.ui"), self)
- self.defaultButton.clicked.connect(self.setDefaults)
- self.cancelButton.clicked.connect(self.accept)
- self.saveButton.clicked.connect(self.saveClicked)
- cache = Cache()
- roomnames = cache.getFromCache("room_names")
- if not roomnames:
- roomnames = u"TheCitadel,North Provi Intel,North Catch Intel,North Querious Intel"
- self.roomnamesField.setPlainText(roomnames)
-
-
- def saveClicked(self):
- text = six.text_type(self.roomnamesField.toPlainText())
- rooms = [six.text_type(name.strip()) for name in text.split(",")]
- self.accept()
- self.roomsChanged.emit(rooms)
-
-
- def setDefaults(self):
- self.roomnamesField.setPlainText(u"TheCitadel,North Provi Intel,North Catch Intel,North Querious Intel")
+ system.messages.append(message)
+ # call once after all messages are processed
+ self.updateMapView()
class RegionChooser(QDialog):
@@ -941,7 +1009,7 @@ def __init__(self, parent):
self.cancelButton.clicked.connect(self.accept)
self.saveButton.clicked.connect(self.saveClicked)
cache = Cache()
- regionName = cache.getFromCache("region_name")
+ regionName = cache.getConfigValue("region_name")
if not regionName:
regionName = u"Providence"
self.regionNameField.setPlainText(regionName)
@@ -953,7 +1021,7 @@ def saveClicked(self):
self.regionNameField.setPlainText(text)
correct = False
try:
- url = dotlan.Map.DOTLAN_BASIC_URL.format(text)
+ url = dotlan.dotlan_url(text)
content = requests.get(url).text
if u"not found" in content:
correct = False
@@ -973,7 +1041,7 @@ def saveClicked(self):
logging.error(e)
correct = False
if correct:
- Cache().putIntoCache("region_name", text, 60 * 60 * 24 * 365)
+ Cache().saveConfigValue("region_name", text)
self.accept()
self.newRegionChosen.emit()
@@ -989,13 +1057,16 @@ def __init__(self, parent, chatType, selector, chatEntries, knownPlayerNames):
self.parent = parent
self.chatType = 0
self.selector = selector
- self.chatEntries = []
- for entry in chatEntries:
- self.addChatEntry(entry)
titleName = ""
+ self.chatEntries = []
if self.chatType == SystemChat.SYSTEM:
- titleName = self.selector.name
self.system = selector
+ systemDisplayName = self.system.name
+ if systemDisplayName in parent.systemsWithRegions:
+ systemDisplayName = parent.systemsWithRegions[systemDisplayName]['name']
+ titleName = "%s [%s]" % (systemDisplayName, self.selector.secondaryInfo)
+ for entry in chatEntries:
+ self.addChatEntry(entry)
for name in knownPlayerNames:
self.playerNamesBox.addItem(name)
self.setWindowTitle("Chat for {0}".format(titleName))
@@ -1024,10 +1095,12 @@ def _addMessageToChat(self, message, avatarPixmap):
def addChatEntry(self, entry):
if self.chatType == SystemChat.SYSTEM:
message = entry.message
- avatarPixmap = entry.avatarLabel.pixmap()
- if self.selector in message.systems:
- self._addMessageToChat(message, avatarPixmap)
-
+ try:
+ avatarPixmap = entry.avatarLabel.pixmap()
+ if self.system.name in message.systems:
+ self._addMessageToChat(message, avatarPixmap)
+ except:
+ pass
def locationSet(self):
char = six.text_type(self.playerNamesBox.currentText())
@@ -1101,7 +1174,10 @@ def updateAvatar(self, avatarData):
if pixmap.isNull():
return False
scaledAvatar = pixmap.scaled(32, 32)
- self.avatarLabel.setPixmap(scaledAvatar)
+ try:
+ self.avatarLabel.setPixmap(scaledAvatar)
+ except:
+ pass
return True
@@ -1111,27 +1187,105 @@ def changeFontSize(self, newSize):
self.textLabel.setFont(font)
-class JumpbridgeChooser(QDialog):
+class Settings(QDialog):
- setJumpBridgeUrl = pyqtSignal(str)
+ setJumpbridgeUrl = pyqtSignal(str)
+ roomsChanged = pyqtSignal(object)
- def __init__(self, parent, url):
+ def __init__(self, parent):
QDialog.__init__(self, parent)
- uic.loadUi(resourcePath("vi/ui/JumpbridgeChooser.ui"), self)
- self.saveButton.clicked.connect(self.savePath)
- self.cancelButton.clicked.connect(self.accept)
- self.urlField.setText(url)
+ uic.loadUi(resourcePath("vi/ui/SettingsTabs.ui"), self)
+ self.cache = Cache()
+ self.parent = parent
+ self.tabs.setCurrentIndex(0) # load displaying first tab, regardless of which page was last open in designer
+
+ # Chatrooms
+ self.chatDefaultButton.clicked.connect(self.setChatToDefaults)
+ self.chatCancelButton.clicked.connect(self.resetChatSettings)
+ self.chatSaveButton.clicked.connect(self.saveChatSettings)
+ self.resetChatSettings()
+
+ # JBS
+ self.jbSaveButton.clicked.connect(self.saveJbs)
+ self.jbCancelButton.clicked.connect(self.resetJbs)
+ self.resetJbs()
+
# loading format explanation from textfile
- with open(resourcePath("docs/jumpbridgeformat.txt")) as f:
- self.formatInfoField.setPlainText(f.read())
+ # with open(resourcePath("docs/jumpbridgeformat.txt")) as f:
+ # self.formatInfoField.setPlainText(f.read())
+
+ # Quick Setup
+ self.quickSettingsSaveButton.clicked.connect(self.saveQuickSettings)
+ self.quickSettingsCancelButton.clicked.connect(self.resetQuickSettings)
+ self.resetQuickSettings()
+ def resetJbs(self):
+ self.jbUrlField.setText(self.cache.getConfigValue("jumpbridge_url"))
+ self.jbIdField.setText(self.cache.getConfigValue("dotlan_jb_id"))
- def savePath(self):
+ def saveJbs(self):
try:
- url = six.text_type(self.urlField.text())
+ url = six.text_type(self.jbUrlField.text())
if url != "":
requests.get(url).text
- self.setJumpBridgeUrl.emit(url)
- self.accept()
+ self.cache.saveConfigValue("dotlan_jb_id", six.text_type(self.jbIdField.text()))
+ self.setJumpbridgeUrl.emit(url)
+ except Exception as e:
+ QMessageBox.critical(None, "Finding Jumpbridgedata failed", "Error: {0}".format(six.text_type(e)), "OK")
+
+ def resetChatSettings(self):
+ roomnames = self.cache.getConfigValue("channel_names")
+ if not roomnames:
+ self.setChatToDefaults()
+ else:
+ self.roomnamesField.setPlainText(roomnames)
+
+ def saveChatSettings(self):
+ text = six.text_type(self.roomnamesField.toPlainText())
+ rooms = [six.text_type(name.strip()) for name in text.split(",")]
+ self.roomsChanged.emit(rooms)
+
+ def setChatToDefaults(self):
+ roomnames = self.cache.getConfigValue("default_room_names")
+ if not roomnames:
+ self.roomnamesField.setPlainText(u"TheCitadel,North Provi Intel,North Catch Intel,North Querious Intel")
+ else:
+ self.roomnamesField.setPlainText(roomnames)
+
+ def resetQuickSettings(self):
+ self.quickSettingsField.setPlainText("")
+
+ def saveQuickSettings(self):
+ try:
+ d = json.loads(six.text_type(self.quickSettingsField.toPlainText()))
+ if not dict:
+ QMessageBox.critical(None, "Could not parse input field", "Error: {0}".format(six.text_type(d)), "OK")
+ return
+
+ if 'channels' in d:
+ self.cache.saveConfigValue('default_room_names', ",".join(d['channels']))
+ self.roomsChanged.emit(d['channels'])
+
+ if 'dotlan_jb_id' in d:
+ self.cache.saveConfigValue("dotlan_jb_id", d['dotlan_jb_id'])
+
+ if 'jumpbridge_url' in d:
+ self.setJumpbridgeUrl.emit(d['jumpbridge_url'])
+
+ if 'kos_url' in d:
+ self.cache.saveConfigValue("kos_url", d['kos_url'])
+
+ if 'region_name' in d:
+ self.cache.saveConfigValue("region_name", d['region_name'])
+ self.parent.handleRegionChosen()
+
+ if 'quick_regions' in d:
+ self.cache.saveConfigValue("quick_regions", json.dumps(d['quick_regions']))
+ self.parent.updateRegionMenu()
+
+ self.resetChatSettings()
+ self.resetJbs()
+
except Exception as e:
- QMessageBox.critical(None, "Finding Jumpbridgedata failed", "Error: {0}".format(six.text_type(e)), QMessageBox.Ok)
+ traceback.print_exc()
+ QMessageBox.critical(None, "Saving quick settings failed", "Error: {0}".format(six.text_type(e)), "OK")
diff --git a/src/vintel.py b/src/vintel.py
index f45f15a..514861a 100644
--- a/src/vintel.py
+++ b/src/vintel.py
@@ -57,13 +57,20 @@ class Application(QApplication):
def __init__(self, args):
super(Application, self).__init__(args)
+ self.setWindowIcon(QtGui.QIcon('icon.ico'))
+ # windows silliness to set taskbar icon
+ if sys.platform.startswith("win32"):
+ import ctypes
+ myappid = u'eve.vintel.' + version.VERSION
+ ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(myappid)
+
# Set up paths
chatLogDirectory = ""
if len(sys.argv) > 1:
chatLogDirectory = sys.argv[1]
if not os.path.exists(chatLogDirectory):
- if sys.platform.startswith("darwin"):
+ if sys.platform.startswith("darwin") or sys.platform.startswith("cygwin"):
chatLogDirectory = os.path.join(os.path.expanduser("~"), "Documents", "EVE", "logs", "Chatlogs")
if not os.path.exists(chatLogDirectory):
chatLogDirectory = os.path.join(os.path.expanduser("~"), "Library", "Application Support", "Eve Online",
@@ -73,12 +80,14 @@ def __init__(self, args):
if not os.path.exists(chatLogDirectory):
# Default path created by EveLauncher: https://forums.eveonline.com/default.aspx?g=posts&t=482663
chatLogDirectory = os.path.join(os.path.expanduser("~"), "Documents","EVE", "logs", "Chatlogs")
- elif sys.platform.startswith("win32") or sys.platform.startswith("cygwin"):
+ elif sys.platform.startswith("win32"):
import ctypes.wintypes
+ from win32com.shell import shellcon
buf = ctypes.create_unicode_buffer(ctypes.wintypes.MAX_PATH)
- ctypes.windll.shell32.SHGetFolderPathW(0, 5, 0, 0, buf)
- documentsPath = buf.value
- chatLogDirectory = os.path.join(documentsPath, "EVE", "logs", "Chatlogs")
+ hResult = ctypes.windll.shell32.SHGetFolderPathW(0, shellcon.CSIDL_PERSONAL, 0, 0, buf)
+ if hResult == 0:
+ documentsPath = buf.value
+ chatLogDirectory = os.path.join(documentsPath, "EVE", "logs", "Chatlogs")
if not os.path.exists(chatLogDirectory):
# None of the paths for logs exist, bailing out
QMessageBox.critical(None, "No path to Logs", "No logs found at: " + chatLogDirectory, "Quit")
@@ -97,10 +106,10 @@ def __init__(self, args):
splash = QtWidgets.QSplashScreen(QtGui.QPixmap(resourcePath("vi/ui/res/logo.png")))
vintelCache = Cache()
- logLevel = vintelCache.getFromCache("logging_level")
+ logLevel = vintelCache.getConfigValue("logging_level")
if not logLevel:
logLevel = logging.WARN
- backGroundColor = vintelCache.getFromCache("background_color")
+ backGroundColor = vintelCache.getConfigValue("background_color")
if backGroundColor:
self.setStyleSheet("QWidget { background-color: %s; }" % backGroundColor)
@@ -145,4 +154,3 @@ def __init__(self, args):
app = Application(sys.argv)
sys.exit(app.exec_())
-
diff --git a/src/vintel.spec b/src/vintel.spec
index 6bf561b..62fd559 100644
--- a/src/vintel.spec
+++ b/src/vintel.spec
@@ -19,11 +19,9 @@ a = Analysis(['vintel.py'],
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
a.datas += [('vi/ui/MainWindow.ui', 'vi/ui/MainWindow.ui', 'DATA'),
- ('vi/ui/SystemChat.ui', 'vi/ui/SystemChat.ui', 'DATA'),
+ ('vi/ui/SettingsTabs.ui', 'vi/ui/SettingsTabs.ui', 'DATA'),
('vi/ui/ChatEntry.ui', 'vi/ui/ChatEntry.ui', 'DATA'),
('vi/ui/Info.ui', 'vi/ui/Info.ui', 'DATA'),
- ('vi/ui/ChatroomsChooser.ui', 'vi/ui/ChatroomsChooser.ui', 'DATA'),
- ('vi/ui/RegionChooser.ui', 'vi/ui/RegionChooser.ui', 'DATA'),
('vi/ui/SoundSetup.ui', 'vi/ui/SoundSetup.ui', 'DATA'),
('vi/ui/JumpbridgeChooser.ui', 'vi/ui/JumpbridgeChooser.ui', 'DATA'),
('vi/ui/res/qmark.png', 'vi/ui/res/qmark.png', 'DATA'),