Merge remote-tracking branch 'upstream/master' into geodata

This commit is contained in:
Tom Vogt 2019-09-14 22:52:58 +02:00
commit 0dc7d622ce
31 changed files with 1175 additions and 803 deletions

File diff suppressed because one or more lines are too long

338
index.css

File diff suppressed because one or more lines are too long

View file

@ -10,7 +10,7 @@
<meta name="google" content="notranslate"> <meta name="google" content="notranslate">
<meta property="og:url" content="https://azgaar.github.io/Fantasy-Map-Generator"> <meta property="og:url" content="https://azgaar.github.io/Fantasy-Map-Generator">
<meta property="og:title" content="Azgaar's Fantasy Map Generator"> <meta property="og:title" content="Azgaar's Fantasy Map Generator">
<meta property="og:description" content="Based on Voronoi diagram rendered to svg"> <meta property="og:description" content="Web application generating interactive and customizable maps">
<meta property="og:image" content="images/preview.png"> <meta property="og:image" content="images/preview.png">
<link rel="icon" type="image/png" href="images/favicon-32x32.png" sizes="32x32"/> <link rel="icon" type="image/png" href="images/favicon-32x32.png" sizes="32x32"/>
<link rel="icon" type="image/png" href="images/favicon-16x16.png" sizes="16x16"/> <link rel="icon" type="image/png" href="images/favicon-16x16.png" sizes="16x16"/>
@ -819,8 +819,8 @@
<g id="rose" stroke-width="1"> <g id="rose" stroke-width="1">
<g id="sL" stroke="#3f3f3f"> <g id="sL" stroke="#3f3f3f">
<line x1="0" y1="-10000000" x2="0" y2="10000000"/> <line id="sL1" x1="0" y1="-2000" x2="0" y2="2000"/>
<line x1="-10000000" y1="0" x2="10000000" y2="0"/> <line id="sL2" x1="-2000" y1="0" x2="2000" y2="0"/>
</g> </g>
<use xlink:href="#sL" transform="rotate(45)"/> <use xlink:href="#sL" transform="rotate(45)"/>
<use xlink:href="#sL" transform="rotate(22.5)"/> <use xlink:href="#sL" transform="rotate(22.5)"/>
@ -857,8 +857,8 @@
<use xlink:href="#s3" transform="scale(-1)"/> <use xlink:href="#s3" transform="scale(-1)"/>
</g> </g>
<marker id="arrow" viewBox="0 0 10 10" refX="5" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse"> <marker id="end-arrow" viewBox="0 -5 10 10" refX="6" markerWidth="7" markerHeight="7" orient="auto">
<path d="M 0 0 L 10 5 L 0 10 z" /> <path d="M0,-5L10,0L0,5" fill="#000"></path>
</marker> </marker>
</defs> </defs>
@ -881,8 +881,8 @@
<div id="optionsContainer" style="opacity:0"> <div id="optionsContainer" style="opacity:0">
<div id="collapsible"> <div id="collapsible">
<button id="optionsTrigger" data-tip="Click to show options pane. Shortcut: Tab" class="options glow" onclick="showOptions(event)" style="padding:7px 5px"></button> <button id="optionsTrigger" data-tip="Click to show options pane. Shortcut: Tab" class="options glow" onclick="showOptions(event)" style="padding:.6em .45em"></button>
<button id="regenerate" data-tip="Click to generate a new map. Shortcut: F2" onclick="regeneratePrompt()" class="options" style="display:none; padding:7px 8px">New Map!</button> <button id="regenerate" data-tip="Click to generate a new map. Shortcut: F2" onclick="regeneratePrompt()" class="options" style="display:none; padding:.6em 1em">New Map!</button>
</div> </div>
<div id="options" style="display:none"> <div id="options" style="display:none">
@ -909,8 +909,8 @@
<option value="landmass">Pure landmass</option> <option value="landmass">Pure landmass</option>
<option hidden value="custom">Custom (not saved)</option> <option hidden value="custom">Custom (not saved)</option>
</select> </select>
<button id="savePresetButton" data-tip="Click to save displayed layers as a new preset" class="icon-plus styleButton" style="display:none" onclick="savePreset()"></button> <button id="savePresetButton" data-tip="Click to save displayed layers as a new preset" class="icon-plus presetButton" style="display:none" onclick="savePreset()"></button>
<button id="removePresetButton" data-tip="Click to remove current custom preset" class="icon-minus styleButton" style="display:none" onclick="removePreset()"></button> <button id="removePresetButton" data-tip="Click to remove current custom preset" class="icon-minus presetButton" style="display:none" onclick="removePreset()"></button>
<p data-tip="Click to toggle a layer, drag to raise or lower a layer">Displayed layers:</p> <p data-tip="Click to toggle a layer, drag to raise or lower a layer">Displayed layers:</p>
<ul data-tip="Click to toggle a layer, drag to raise or lower a layer" id="mapLayers"> <ul data-tip="Click to toggle a layer, drag to raise or lower a layer" id="mapLayers">
@ -1163,8 +1163,7 @@
<tr data-tip="Set grid cells spacing (size)"> <tr data-tip="Set grid cells spacing (size)">
<td>Size</td> <td>Size</td>
<td> <td>
<input id="styleGridSize" type="range" min=2 max=50 step=.1 value=10 style="width:42%"> <input id="styleGridSize" type="number" min=2 max=50 step=.001 value=10 >
<output id="styleGridSizeOutput" data-tip="Grid cells spacing in pixels">10</output>
<output id="styleGridSizeFriendly" data-tip="Distance between two adjacent cells in map scale">(52 mi)</output> <output id="styleGridSizeFriendly" data-tip="Distance between two adjacent cells in map scale">(52 mi)</output>
</td> </td>
</tr> </tr>
@ -1512,6 +1511,19 @@
</td> </td>
</tr> </tr>
<tr data-tip="Click to set up map name to be used for downloaded files">
<td>
<i data-locked=0 id="lock_mapName" class="icon-lock-open"></i>
</td>
<td>Map name</td>
<td>
<input id="mapName" data-stored="mapName" class="long" autocorrect="off" spellcheck="false" type="text">
</td>
<td>
<i data-tip="Regenerate map name" onclick="Names.getMapName(true)" class="icon-arrows-cw"></i>
</td>
</tr>
<tr data-tip="Select template to be used for a Heightmap generation"> <tr data-tip="Select template to be used for a Heightmap generation">
<td> <td>
<i data-locked=0 id="lock_template" class="icon-lock-open"></i> <i data-locked=0 id="lock_template" class="icon-lock-open"></i>
@ -1529,6 +1541,7 @@
<option value="Peninsula">Peninsula</option> <option value="Peninsula">Peninsula</option>
<option value="Pangea">Pangea</option> <option value="Pangea">Pangea</option>
<option value="Isthmus">Isthmus</option> <option value="Isthmus">Isthmus</option>
<option value="Shattered">Shattered</option>
</select> </select>
</td> </td>
<td></td> <td></td>
@ -1599,7 +1612,7 @@
</td> </td>
</tr> </tr>
<tr data-tip="Define a number of towns to be placed (if suitable area is enougth)"> <tr data-tip="Define a number of towns to be placed (if enough suitable land exists)">
<td> <td>
<i data-locked=0 id="lock_manors" class="icon-lock-open"></i> <i data-locked=0 id="lock_manors" class="icon-lock-open"></i>
</td> </td>
@ -1644,21 +1657,21 @@
<td></td> <td></td>
<td>Interface size</td> <td>Interface size</td>
<td> <td>
<input id="uiSizeInput" data-stored="uiSize" type="range" min=.8 max=2 step=.1 value=1> <input id="uiSizeInput" data-stored="uiSize" type="range" min=.6 max=3 step=.1 value=1>
</td> </td>
<td> <td>
<input id="uiSizeOutput" data-stored="uiSize" type="number" min=.6 max=2 step=.1 value=1> <input id="uiSizeOutput" data-stored="uiSize" type="number" min=.6 max=3 step=.1 value=1>
</td> </td>
</tr> </tr>
<tr data-tip="Set tooltips size"> <tr data-tip="Set tooltip size">
<td></td> <td></td>
<td>Tooltips size</td> <td>Tooltip size</td>
<td> <td>
<input id="tooltipSizeInput" data-stored="tooltipSize" type="range" min=4 max=24 value=14> <input id="tooltipSizeInput" data-stored="tooltipSize" type="range" min=4 max=32 value=14>
</td> </td>
<td> <td>
<input id="tooltipSizeOutput" data-stored="tooltipSize" type="number" min=4 max=24 value=14> <input id="tooltipSizeOutput" data-stored="tooltipSize" type="number" min=4 max=32 value=14>
</td> </td>
</tr> </tr>
@ -1734,6 +1747,7 @@
<button id="regenerateStates" data-tip="Click to select new capitals and regenerate states. Burgs will remain as they are">States</button> <button id="regenerateStates" data-tip="Click to select new capitals and regenerate states. Burgs will remain as they are">States</button>
<button id="regenerateProvinces" data-tip="Click to regenerate provinces. States will remain as they are">Provinces</button> <button id="regenerateProvinces" data-tip="Click to regenerate provinces. States will remain as they are">Provinces</button>
<button id="regenerateReligions" data-tip="Click to regenerate religions">Religions</button> <button id="regenerateReligions" data-tip="Click to regenerate religions">Religions</button>
<button id="regenerateMarkers" data-tip="Click to regenerate markers">Markers</button>
</div> </div>
<div id="addFeature"> <div id="addFeature">
@ -1777,7 +1791,6 @@
<button data-tip="Open template editor" id="applyTemplate" style="display: none">Template Editor</button> <button data-tip="Open template editor" id="applyTemplate" style="display: none">Template Editor</button>
<button data-tip="Open Image Converter" id="convertImage" style="display: none">Image Converter</button> <button data-tip="Open Image Converter" id="convertImage" style="display: none">Image Converter</button>
<button data-tip="Render heightmap data as a small monochrome image" id="heightmapPreview">Heightmap Preview</button> <button data-tip="Render heightmap data as a small monochrome image" id="heightmapPreview">Heightmap Preview</button>
<button data-tip="Render heightmap in perspective" id="perspectiveView">Perspective View</button>
</div> </div>
<div id="customizeOptions"> <div id="customizeOptions">
@ -1796,7 +1809,7 @@
<div> <div>
<p>Statistics:</p> <p>Statistics:</p>
<span>Land cells: </span><span id="landmassCounter">0</span> <span>Land cells: </span><span id="landmassCounter">0</span>
<span style="margin-left:8px">Mean height: </span><span id="landmassAverage">0</span> <span style="margin-left:.9em">Mean height: </span><span id="landmassAverage">0</span>
</div> </div>
<div> <div>
@ -1916,7 +1929,7 @@
<div data-tip="Map coordinates on globe"><i>Coords:</i> <span id="mapCoordinates"></span></div> <div data-tip="Map coordinates on globe"><i>Coords:</i> <span id="mapCoordinates"></span></div>
</div> </div>
<svg id="globe" width="240" height="240" viewBox="-20 -25 240 240"> <svg id="globe" width="22em" height="22em" viewBox="-20 -25 240 240">
<defs> <defs>
<linearGradient id="temperatureGradient" x1="0" x2="0" y1="0" y2="1"> <linearGradient id="temperatureGradient" x1="0" x2="0" y1="0" y2="1">
<stop class="tempGradient90" offset="0%" stop-color="blue"/> <stop class="tempGradient90" offset="0%" stop-color="blue"/>
@ -1975,8 +1988,8 @@
<button id="labelGroupShow" data-tip="Show the group selection" class="icon-tags"></button> <button id="labelGroupShow" data-tip="Show the group selection" class="icon-tags"></button>
<div id="labelGroupSection" style="display: none"> <div id="labelGroupSection" style="display: none">
<button id="labelGroupHide" data-tip="Hide the group selection" class="icon-tags"></button> <button id="labelGroupHide" data-tip="Hide the group selection" class="icon-tags"></button>
<select id="labelGroupSelect" data-tip="Select a group for this label" style="width:113px"></select> <select id="labelGroupSelect" data-tip="Select a group for this label" style="width:10em"></select>
<input id="labelGroupInput" placeholder="new group name" data-tip="Provide a name for the new group" style="display:none; width:109px; height:10px"/> <input id="labelGroupInput" placeholder="new group name" data-tip="Provide a name for the new group" style="display:none; width:10em">
<span id="labelGroupNew" data-tip="Create new group for this label" class="icon-plus pointer"></span> <span id="labelGroupNew" data-tip="Create new group for this label" class="icon-plus pointer"></span>
<span id="labelGroupRemove" data-tip="Remove the Group with all labels" class="icon-trash-empty pointer"></span> <span id="labelGroupRemove" data-tip="Remove the Group with all labels" class="icon-trash-empty pointer"></span>
</div> </div>
@ -1984,16 +1997,16 @@
<button id="labelTextShow" data-tip="Show the edit label text section" class="icon-pencil"></button> <button id="labelTextShow" data-tip="Show the edit label text section" class="icon-pencil"></button>
<div id="labelTextSection" style="display: none"> <div id="labelTextSection" style="display: none">
<button id="labelTextHide" data-tip="Hide the edit label text section" class="icon-pencil"></button> <button id="labelTextHide" data-tip="Hide the edit label text section" class="icon-pencil"></button>
<input id="labelText" data-tip='Type to change the label. Enter "|" to move to a new line' style="width: 121px; height:12px"/> <input id="labelText" data-tip='Type to change the label. Enter "|" to move to a new line' style="width: 12em">
<span id="labelTextRandom" data-tip="Generate random name" class="icon-shuffle pointer"></span> <span id="labelTextRandom" data-tip="Generate random name" class="icon-shuffle pointer"></span>
</div> </div>
<button id="labelSizeShow" data-tip="Show the font size section" class="icon-text-height"></button> <button id="labelSizeShow" data-tip="Show the font size section" class="icon-text-height"></button>
<div id="labelSizeSection" style="display: none"> <div id="labelSizeSection" style="display: none">
<button id="labelSizeHide" data-tip="Hide the font size section" class="icon-text-height"></button> <button id="labelSizeHide" data-tip="Hide the font size section" class="icon-text-height"></button>
<input id="labelStartOffset" data-tip="Set starting offset for the particular label" type="range" min=20 max=80 style="width:79px"> <input id="labelStartOffset" data-tip="Set starting offset for the particular label" type="range" min=20 max=80 style="width:8em">
<i class="icon-text-height"></i> <i class="icon-text-height"></i>
<input id="labelRelativeSize" data-tip="Set relative size for the particular label" type="number" min=30 max=300 step=1 style="width:36px"> <input id="labelRelativeSize" data-tip="Set relative size for the particular label" type="number" min=30 max=300 step=1 style="width:3.2em">
</div> </div>
<button id="labelAlign" data-tip="Turn text path into a straight line" class="icon-resize-horizontal"></button> <button id="labelAlign" data-tip="Turn text path into a straight line" class="icon-resize-horizontal"></button>
@ -2018,7 +2031,7 @@
<input id="riverAngle" data-tip="Rotate river by angle" type="range" min="-90" max=90 step=.2> <input id="riverAngle" data-tip="Rotate river by angle" type="range" min="-90" max=90 step=.2>
<span id="riverAngleValue">0&#8457;</span> <span id="riverAngleValue">0&#8457;</span>
<i id="riverScaleIcon" class="icon-s"></i> <i id="riverScaleIcon" class="icon-s"></i>
<input id="riverScale" data-tip="Change river scale" value="1" type="number" min=.1 max=3 step=.01> <input id="riverScale" data-tip="Change river scale" value="1" type="number" style="width:3.5em" min=.1 max=3 step=.01>
<span id="riverReset" data-tip="Reset transformation to default" class="icon-cancel pointer"></span> <span id="riverReset" data-tip="Reset transformation to default" class="icon-cancel pointer"></span>
</div> </div>
@ -2033,8 +2046,8 @@
<button id="routeGroupsShow" data-tip="Show the group selection" class="icon-tags"></button> <button id="routeGroupsShow" data-tip="Show the group selection" class="icon-tags"></button>
<div id="routeGroupsSelection" style="display: none"> <div id="routeGroupsSelection" style="display: none">
<button id="routeGroupsHide" data-tip="Hide the group section" class="icon-tags"></button> <button id="routeGroupsHide" data-tip="Hide the group section" class="icon-tags"></button>
<select id="routeGroup" data-tip="Select a group for this route" style="width:135px"></select> <select id="routeGroup" data-tip="Select a group for this route" style="width:12em"></select>
<input id="routeGroupName" placeholder="new group name" data-tip="Provide a name for the new group" style="display:none; width:131px; height:10px"/> <input id="routeGroupName" placeholder="new group name" data-tip="Provide a name for the new group" style="display:none; width:12em"/>
<span id="routeGroupAdd" data-tip="Create new group for this route" class="icon-plus pointer"></span> <span id="routeGroupAdd" data-tip="Create new group for this route" class="icon-plus pointer"></span>
<span id="routeGroupRemove" data-tip="Remove all routes of this group" class="icon-trash-empty pointer"></span> <span id="routeGroupRemove" data-tip="Remove all routes of this group" class="icon-trash-empty pointer"></span>
</div> </div>
@ -2181,8 +2194,8 @@
<button id="burgGroupShow" data-tip="Show group change section" class="icon-tags"></button> <button id="burgGroupShow" data-tip="Show group change section" class="icon-tags"></button>
<div id="burgGroupSection" style="display: none"> <div id="burgGroupSection" style="display: none">
<button id="burgGroupHide" data-tip="Hide group change section" class="icon-tags"></button> <button id="burgGroupHide" data-tip="Hide group change section" class="icon-tags"></button>
<select id="burgSelectGroup" data-tip="Select a group for this burg" style="width: 117px;"></select> <select id="burgSelectGroup" data-tip="Select a group for this burg" style="width: 10em;"></select>
<input id="burgInputGroup" placeholder="new group name" data-tip="Create new Group for the Burg" style="display: none; width: 113px; height: 10px"/> <input id="burgInputGroup" placeholder="new group name" data-tip="Create new Group for the Burg" style="display: none; width: 10em"/>
<i id="burgAddGroup" data-tip="Create new group for the burg" class="icon-plus pointer"></i> <i id="burgAddGroup" data-tip="Create new group for the burg" class="icon-plus pointer"></i>
<i id="burgRemoveGroup" data-tip="Remove selected burg group" class="icon-trash pointer"></i> <i id="burgRemoveGroup" data-tip="Remove selected burg group" class="icon-trash pointer"></i>
</div> </div>
@ -2190,7 +2203,7 @@
<button id="burgNameShow" data-tip="Show name change section" class="icon-pencil"></button> <button id="burgNameShow" data-tip="Show name change section" class="icon-pencil"></button>
<div id="burgNameSection" style="display: none"> <div id="burgNameSection" style="display: none">
<button id="burgNameHide" data-tip="Hide name change section" class="icon-pencil"></button> <button id="burgNameHide" data-tip="Hide name change section" class="icon-pencil"></button>
<input id="burgNameInput" data-tip="Populate to rename the burg" style="height: 12px"/> <input id="burgNameInput" data-tip="Populate to rename the burg"/>
<span id="burgNameReCulture" data-tip="Generate culture-specific name for the burg" class="icon-book pointer"></span> <span id="burgNameReCulture" data-tip="Generate culture-specific name for the burg" class="icon-book pointer"></span>
<span id="burgNameReRandom" data-tip="Generate random name for the burg" class="icon-globe pointer"></span> <span id="burgNameReRandom" data-tip="Generate random name for the burg" class="icon-globe pointer"></span>
</div> </div>
@ -2206,8 +2219,8 @@
<button id="markerGroup" data-tip="Change marker type" class="icon-tags"></button> <button id="markerGroup" data-tip="Change marker type" class="icon-tags"></button>
<div id="markerGroupSection" style="display: none"> <div id="markerGroupSection" style="display: none">
<select id="markerSelectGroup" data-tip="Select type for the selected marker" style="width: 117px; height: 18px"></select> <select id="markerSelectGroup" data-tip="Select type for the selected marker" style="width: 10em"></select>
<input id="markerInputGroup" data-tip="Create new type for selected marker" placeholder="type new name" style="display: none; width: 113px; height: 12px"/> <input id="markerInputGroup" data-tip="Create new type for selected marker" placeholder="type new name" style="display: none; width: 10em"/>
<i id="markerAddGroup" data-tip="Create new markers type" class="icon-plus pointer"></i> <i id="markerAddGroup" data-tip="Create new markers type" class="icon-plus pointer"></i>
<i id="markerRemoveGroup" data-tip="Remove all markers of that type" class="icon-trash pointer"></i> <i id="markerRemoveGroup" data-tip="Remove all markers of that type" class="icon-trash pointer"></i>
</div> </div>
@ -2247,43 +2260,43 @@
<div id="brushesPanel" class="dialog stable" style="display: none"> <div id="brushesPanel" class="dialog stable" style="display: none">
<div id="brushesButtons" style="display: inline-block"> <div id="brushesButtons" style="display: inline-block">
<button id="brushRaise" data-tip="Raise brush: increase height of cells in radius by Power value"> <button id="brushRaise" data-tip="Raise brush: increase height of cells in radius by Power value">
<svg viewBox="15 15 70 70" height="14" width="22"> <svg viewBox="15 15 70 70" height="1em" width="1.6em">
<path d="m20,39 h60 M50,85 v-35 l-12,8 m12,-8 l12,8" fill="none" stroke="#000" stroke-width="5"></path> <path d="m20,39 h60 M50,85 v-35 l-12,8 m12,-8 l12,8" fill="none" stroke="#000" stroke-width="5"></path>
</svg> </svg>
</button> </button>
<button id="brushElevate" data-tip="Elevate brush: drag to gradually increase height of cells in radius by Power value"> <button id="brushElevate" data-tip="Elevate brush: drag to gradually increase height of cells in radius by Power value">
<svg viewBox="15 15 70 70" height="14" width="22"> <svg viewBox="15 15 70 70" height="1em" width="1.6em">
<path d="m20,50 q30,-35 60,0 M50,85 v-35 l-12,8 m12,-8 l12,8" fill="none" stroke="#000" stroke-width="5"></path> <path d="m20,50 q30,-35 60,0 M50,85 v-35 l-12,8 m12,-8 l12,8" fill="none" stroke="#000" stroke-width="5"></path>
</svg> </svg>
</button> </button>
<button id="brushLower" data-tip="Lower brush: drag to decrease height of cells in radius by Power value"> <button id="brushLower" data-tip="Lower brush: drag to decrease height of cells in radius by Power value">
<svg viewBox="15 15 70 70" height="14" width="22"> <svg viewBox="15 15 70 70" height="1em" width="1.6em">
<path d="M50,30 v35 l-12,-8 m12,8 l12,-8 M20,78 h60" fill="none" stroke="#000" stroke-width="5"></path> <path d="M50,30 v35 l-12,-8 m12,8 l12,-8 M20,78 h60" fill="none" stroke="#000" stroke-width="5"></path>
</svg> </svg>
</button> </button>
<button id="brushDepress" data-tip="Depress brush: drag to gradually decrease height of cells in radius by Power value"> <button id="brushDepress" data-tip="Depress brush: drag to gradually decrease height of cells in radius by Power value">
<svg viewBox="15 15 70 70" height="14" width="22"> <svg viewBox="15 15 70 70" height="1em" width="1.6em">
<path d="M50,30 v35 l-12,-8 m12,8 l12,-8 M20,63 q30,35 60,0" fill="none" stroke="#000" stroke-width="5"></path> <path d="M50,30 v35 l-12,-8 m12,8 l12,-8 M20,63 q30,35 60,0" fill="none" stroke="#000" stroke-width="5"></path>
</svg> </svg>
</button> </button>
<button id="brushAlign" data-tip="Align brush: drag to set height of cells in radius to height of the cell at mousepoint"> <button id="brushAlign" data-tip="Align brush: drag to set height of cells in radius to height of the cell at mousepoint">
<svg viewBox="15 15 70 70" height="14" width="22"> <svg viewBox="15 15 70 70" height="1em" width="1.6em">
<path d="m20,50 h56 m0,20 h-56" fill="none" stroke="#000" stroke-width="5"></path> <path d="m20,50 h56 m0,20 h-56" fill="none" stroke="#000" stroke-width="5"></path>
</svg> </svg>
</button> </button>
<button id="brushSmooth" data-tip="Smooth brush: drag to level height of cells in radius to height of adjacent cells"> <button id="brushSmooth" data-tip="Smooth brush: drag to level height of cells in radius to height of adjacent cells">
<svg viewBox="15 15 70 70" height="14" width="22"> <svg viewBox="15 15 70 70" height="1em" width="1.6em">
<path d="m15,60 q15,-15 30,0 q15,15 35,0" fill="none" stroke="#000" stroke-width="5"></path> <path d="m15,60 q15,-15 30,0 q15,15 35,0" fill="none" stroke="#000" stroke-width="5"></path>
</svg> </svg>
</button> </button>
<button id="brushDisrupt" data-tip="Disrupt brush: drag to randomize height of cells in radius based on Power value"> <button id="brushDisrupt" data-tip="Disrupt brush: drag to randomize height of cells in radius based on Power value">
<svg viewBox="15 15 70 70" height="14" width="22"> <svg viewBox="15 15 70 70" height="1em" width="1.6em">
<path d="m15,63 l15,-13 15,20 15,-20 15,19 15,-14" fill="none" stroke="#000" stroke-width="5"></path> <path d="m15,63 l15,-13 15,20 15,-20 15,19 15,-14" fill="none" stroke="#000" stroke-width="5"></path>
</svg> </svg>
</button> </button>
@ -2355,6 +2368,7 @@
<option value="templatePeninsula">Peninsula</option> <option value="templatePeninsula">Peninsula</option>
<option value="templatePangea">Pangea</option> <option value="templatePangea">Pangea</option>
<option value="templateIsthmus">Isthmus</option> <option value="templateIsthmus">Isthmus</option>
<option value="templateShattered">Shattered</option>
</select> </select>
</div> </div>
<div id="templateTools"> <div id="templateTools">
@ -2367,7 +2381,7 @@
<button id="templateMultiply" data-tip="Multiply all heights in range by factor" class="noicon">*</button> <button id="templateMultiply" data-tip="Multiply all heights in range by factor" class="noicon">*</button>
<button id="templateSmooth" data-tip="Smooth the map replacing cell heights by an average values of its neighbors" class="noicon">~</button> <button id="templateSmooth" data-tip="Smooth the map replacing cell heights by an average values of its neighbors" class="noicon">~</button>
</div> </div>
<div id="templateBody" data-changed=0 class="table"> <div id="templateBody" data-changed=0 class="table" style="padding:2px 0">
<div data-type="Hill"> <div data-type="Hill">
<div class="icon-check" data-tip="Click to skip the step"></div> <div class="icon-check" data-tip="Click to skip the step"></div>
<div style="width:4em">Hill</div> <div style="width:4em">Hill</div>
@ -2401,9 +2415,9 @@
<button id="convertComplete" data-tip="Complete the assignment. All unassigned colors will be considered as ocean" class="icon-check"></button> <button id="convertComplete" data-tip="Complete the assignment. All unassigned colors will be considered as ocean" class="icon-check"></button>
</div> </div>
<div data-tip="Set opacity of the loaded image" style="padding-top: 4px"><i>Overlay opacity:</i> <div data-tip="Set opacity of the loaded image" style="padding-top: 4px"><i>Overlay opacity:</i><br>
<input id="convertOverlay" type="range" min=0 max=1 step=.01 value=0 style="width: 8em"> <input id="convertOverlay" type="range" min=0 max=1 step=.01 value=0 style="width: 11.5em">
<input id="convertOverlayNumber" type="number" min=0 max=1 step=.01 value=0 style="width: 3.5em; border: 1px solid #d4d4d4"> <input id="convertOverlayNumber" type="number" min=0 max=1 step=.01 value=0 style="width: 3.5em">
</div> </div>
<div data-tip="Select a color below and assign a height value for it" id="colorsSelect" style="display: none"> <div data-tip="Select a color below and assign a height value for it" id="colorsSelect" style="display: none">
@ -2422,17 +2436,13 @@
</div> </div>
<div id="perspectivePanel" class="dialog stable" style="display: none">
<canvas id="perspective" width="480" height="150"></canvas>
</div>
<div id="biomesEditor" class="dialog stable" style="display: none"> <div id="biomesEditor" class="dialog stable" style="display: none">
<div id="biomesHeader"> <div id="biomesHeader" class="header">
<div style="margin-left: 12px" data-tip="Click to sort by biome name" class="sortable alphabetically" data-sortby="name">Biome&nbsp;</div> <div style="left:1.4em" data-tip="Click to sort by biome name" class="sortable alphabetically" data-sortby="name">Biome&nbsp;</div>
<div style="margin-left: 70px" data-tip="Click to sort by biome habitability" class="sortable hide" data-sortby="habitability">Habitability&nbsp;</div> <div style="left:12em" data-tip="Click to sort by biome habitability" class="sortable hide" data-sortby="habitability">Habitability&nbsp;</div>
<div style="margin-left: 8px" data-tip="Click to sort by biome cells number" class="sortable hide icon-sort-number-down" data-sortby="cells">Cells&nbsp;</div> <div style="left:19em" data-tip="Click to sort by biome cells number" class="sortable hide icon-sort-number-down" data-sortby="cells">Cells&nbsp;</div>
<div style="margin-left: 24px" data-tip="Click to sort by biome area" class="sortable hide" data-sortby="area">Area&nbsp;</div> <div style="left:25em" data-tip="Click to sort by biome area" class="sortable hide" data-sortby="area">Area&nbsp;</div>
<div style="margin-left: 17px" data-tip="Click to sort by biome population" class="sortable hide" data-sortby="population">Population&nbsp;</div> <div style="left:30em" data-tip="Click to sort by biome population" class="sortable hide" data-sortby="population">Population&nbsp;</div>
</div> </div>
<div id="biomesBody" class="table" data-type="absolute"></div> <div id="biomesBody" class="table" data-type="absolute"></div>
@ -2466,17 +2476,17 @@
</div> </div>
<div id="statesEditor" class="dialog stable" style="display: none"> <div id="statesEditor" class="dialog stable" style="display: none">
<div id="statesHeader"> <div id="statesHeader" class="header">
<div style="margin-left: 12px" data-tip="Click to sort by state name" class="sortable alphabetically" data-sortby="name">State&nbsp;</div> <div style="left:1.4em" data-tip="Click to sort by state name" class="sortable alphabetically" data-sortby="name">State&nbsp;</div>
<div style="margin-left: 44px" data-tip="Click to sort by state form name" class="sortable alphabetically" data-sortby="form">Form&nbsp;</div> <div style="left:8.7em" data-tip="Click to sort by state form name" class="sortable alphabetically" data-sortby="form">Form&nbsp;</div>
<div style="margin-left: 41px" data-tip="Click to sort by capital name" class="sortable alphabetically hide" data-sortby="capital">Capital&nbsp;</div> <div style="left:16em" data-tip="Click to sort by capital name" class="sortable alphabetically hide" data-sortby="capital">Capital&nbsp;</div>
<div style="margin-left: 24px" data-tip="Click to sort by state dominant culture" class="sortable alphabetically hide" data-sortby="culture">Culture&nbsp;</div> <div style="left:22.3em" data-tip="Click to sort by state dominant culture" class="sortable alphabetically hide" data-sortby="culture">Culture&nbsp;</div>
<div style="margin-left: 9px" data-tip="Click to sort by state type" class="sortable alphabetically hidden show hide" data-sortby="type">Type&nbsp;</div> <div style="left:27em" data-tip="Click to sort by state burgs count" class="sortable hide" data-sortby="burgs">Burgs&nbsp;</div>
<div style="margin-left: 19px" data-tip="Click to sort by state expansion value" class="sortable hidden show hide" data-sortby="expansionism">Expan.&nbsp;</div> <div style="left:32.5em" data-tip="Click to sort by state area" class="sortable hide icon-sort-number-down" data-sortby="area">Area&nbsp;</div>
<div style="margin-left: 12px" data-tip="Click to sort by state cells count" class="sortable hidden show hide" data-sortby="cells">Cells&nbsp;</div> <div style="left:37em" data-tip="Click to sort by state population" class="sortable hide" data-sortby="population">Population&nbsp;</div>
<div style="margin-left: 11px" data-tip="Click to sort by state burgs count" class="sortable hide" data-sortby="burgs">Burgs&nbsp;</div> <div style="left:43.5em" data-tip="Click to sort by state type" class="sortable alphabetically hidden show hide" data-sortby="type">Type&nbsp;</div>
<div style="margin-left: 20px" data-tip="Click to sort by state area" class="sortable hide icon-sort-number-down" data-sortby="area">Area&nbsp;</div> <div style="left:47em" data-tip="Click to sort by state expansion value" class="sortable hidden show hide" data-sortby="expansionism">Expansion&nbsp;</div>
<div style="margin-left: 18px" data-tip="Click to sort by state population" class="sortable hide" data-sortby="population">Population&nbsp;</div> <div style="left:53.5em" data-tip="Click to sort by state cells count" class="sortable hidden show hide" data-sortby="cells">Cells&nbsp;</div>
</div> </div>
<div id="statesBodySection" class="table" data-type="absolute"></div> <div id="statesBodySection" class="table" data-type="absolute"></div>
@ -2531,12 +2541,12 @@
<div id="provincesEditor" class="dialog stable" style="display: none"> <div id="provincesEditor" class="dialog stable" style="display: none">
<div id="provincesHeader" class="header"> <div id="provincesHeader" class="header">
<div style="margin-left: 12px" data-tip="Click to sort by province name" class="sortable alphabetically" data-sortby="name">Province&nbsp;</div> <div style="left:1.4em" data-tip="Click to sort by province name" class="sortable alphabetically" data-sortby="name">Province&nbsp;</div>
<div style="margin-left: 27px" data-tip="Click to sort by province form name" class="sortable alphabetically hide" data-sortby="form">Form&nbsp;</div> <div style="left:8.5em" data-tip="Click to sort by province form name" class="sortable alphabetically hide" data-sortby="form">Form&nbsp;</div>
<div style="margin-left: 41px" data-tip="Click to sort by province capital" class="sortable alphabetically hide" data-sortby="capital">Capital&nbsp;</div> <div style="left:15.9em" data-tip="Click to sort by province capital" class="sortable alphabetically hide" data-sortby="capital">Capital&nbsp;</div>
<div style="margin-left: 24px" data-tip="Click to sort by province owner" class="sortable alphabetically" data-sortby="state">State&nbsp;</div> <div style="left:22em" data-tip="Click to sort by province owner" class="sortable alphabetically" data-sortby="state">State&nbsp;</div>
<div style="margin-left: 31px" data-tip="Click to sort by province area" class="sortable hide" data-sortby="area">Area&nbsp;</div> <div style="left:30em" data-tip="Click to sort by province area" class="sortable hide" data-sortby="area">Area&nbsp;</div>
<div style="margin-left: 27px" data-tip="Click to sort by province population" class="sortable hide" data-sortby="population">Population&nbsp;</div> <div style="left:35.3em" data-tip="Click to sort by province population" class="sortable hide" data-sortby="population">Population&nbsp;</div>
</div> </div>
<div id="provincesBodySection" class="table" data-type="absolute"></div> <div id="provincesBodySection" class="table" data-type="absolute"></div>
@ -2550,6 +2560,7 @@
<div id="provincesBottom"> <div id="provincesBottom">
<button id="provincesEditorRefresh" data-tip="Refresh the Editor" class="icon-cw"></button> <button id="provincesEditorRefresh" data-tip="Refresh the Editor" class="icon-cw"></button>
<button id="provincesPercentage" data-tip="Toggle percentage / absolute values views" class="icon-percent"></button> <button id="provincesPercentage" data-tip="Toggle percentage / absolute values views" class="icon-percent"></button>
<button id="provincesChart" data-tip="Show provinces chart" class="icon-chart-area"></button>
<button id="provincesToggleLabels" data-tip="Toggle province labels" class="icon-font"></button> <button id="provincesToggleLabels" data-tip="Toggle province labels" class="icon-font"></button>
<button id="provincesExport" data-tip="Save provinces-related data as a text file (.csv)" class="icon-download"></button> <button id="provincesExport" data-tip="Save provinces-related data as a text file (.csv)" class="icon-download"></button>
@ -2572,9 +2583,9 @@
</div> </div>
<div id="diplomacyEditor" class="dialog stable" style="display: none"> <div id="diplomacyEditor" class="dialog stable" style="display: none">
<div id="diplomacyHeader"> <div id="diplomacyHeader" class="header">
<div style="margin-left: 2px" data-tip="Click to sort by state name" class="sortable alphabetically" data-sortby="name">State&nbsp;</div> <div style="left:.2em" data-tip="Click to sort by state name" class="sortable alphabetically" data-sortby="name">State&nbsp;</div>
<div style="margin-left: 9em" data-tip="Click to sort by diplomatical relations" class="sortable alphabetically icon-sort-name-up" data-sortby="relations">Relations&nbsp;</div> <div style="left:12.4em" data-tip="Click to sort by diplomatical relations" class="sortable alphabetically icon-sort-name-up" data-sortby="relations">Relations&nbsp;</div>
</div> </div>
<div id="diplomacyBodySection" class="table"></div> <div id="diplomacyBodySection" class="table"></div>
@ -2589,21 +2600,21 @@
</div> </div>
<div id="burgsEditor" class="dialog stable" style="display: none"> <div id="burgsEditor" class="dialog stable" style="display: none">
<div id="burgsHeader"> <div id="burgsHeader" class="header">
<div style="margin-left: 12px" data-tip="Click to sort by burg name" class="sortable alphabetically" data-sortby="name">Burg&nbsp;</div> <div style="left:1.4em" data-tip="Click to sort by burg name" class="sortable alphabetically" data-sortby="name">Burg&nbsp;</div>
<div id="burgStateHeader" style="margin-left: 35px" data-tip="Click to sort by state name" class="sortable alphabetically" data-sortby="state">State&nbsp;</div> <div style="left:7.7em" data-tip="Click to sort by culture name" class="sortable alphabetically" data-sortby="culture">Culture&nbsp;</div>
<div style="margin-left: 33px" data-tip="Click to sort by culture name" class="sortable alphabetically" data-sortby="culture">Culture&nbsp;</div> <div style="left:12em" data-tip="Click to sort by burg population" class="sortable" data-sortby="population">Population&nbsp;</div>
<div style="margin-left: 3px" data-tip="Click to sort by burg population" class="sortable" data-sortby="population">Population&nbsp;</div> <div style="left:18.7em" data-tip="Click to sort by burg type" class="sortable alphabetically" data-sortby="type">Type&nbsp;</div>
<div style="margin-left: 12px" data-tip="Click to sort by burg type" class="sortable alphabetically" data-sortby="type">Type&nbsp;</div> <div style="left:22em" data-tip="Click to sort by state name" class="sortable alphabetically" data-sortby="state" id="burgStateHeader">State&nbsp;</div>
</div> </div>
<div id="burgsBody" class="burgs-table"></div> <div id="burgsBody" class="burgs-table"></div>
<div id="burgsFilters" data-tip="Apply a filter"> <div id="burgsFilters" data-tip="Apply a filter">
<span>State: </span> <span>State: </span>
<select id="burgsFilterState" style="width:33%"></select> <select id="burgsFilterState" style="width:28%"></select>
<span>Culture:</span> <span>Culture:</span>
<select id="burgsFilterCulture" style="width:33%"></select> <select id="burgsFilterCulture" style="width:28%"></select>
</div> </div>
<div id="burgsFooter" class="totalLine"> <div id="burgsFooter" class="totalLine">
@ -2622,14 +2633,14 @@
</div> </div>
<div id="culturesEditor" class="dialog stable" style="display: none"> <div id="culturesEditor" class="dialog stable" style="display: none">
<div id="culturesHeader"> <div id="culturesHeader" class="header">
<div style="margin-left: 12px" data-tip="Click to sort by culture name" class="sortable alphabetically" data-sortby="name">Culture&nbsp;</div> <div style="left:1.4em" data-tip="Click to sort by culture name" class="sortable alphabetically" data-sortby="name">Culture&nbsp;</div>
<div style="margin-left: 15px" data-tip="Click to sort by culture cells count" class="sortable hide" data-sortby="cells">Cells&nbsp;</div> <div style="left:6.7em" data-tip="Click to sort by culture cells count" class="sortable hide" data-sortby="cells">Cells&nbsp;</div>
<div style="margin-left: 12px" data-tip="Click to sort by expansionism" class="sortable hide" data-sortby="expansionism">Expan.&nbsp;</div> <div style="left:11em" data-tip="Click to sort by expansionism" class="sortable hide" data-sortby="expansionism">Expan.&nbsp;</div>
<div style="margin-left: 14px" data-tip="Click to sort by type" class="sortable alphabetically" data-sortby="type">Type&nbsp;</div> <div style="left:15.8em" data-tip="Click to sort by type" class="sortable alphabetically" data-sortby="type">Type&nbsp;</div>
<div style="margin-left: 31px" data-tip="Click to sort by culture area" class="sortable hide" data-sortby="area">Area&nbsp;</div> <div style="left:22.2em" data-tip="Click to sort by culture area" class="sortable hide" data-sortby="area">Area&nbsp;</div>
<div style="margin-left: 17px" data-tip="Click to sort by culture population" class="sortable hide icon-sort-number-down" data-sortby="population">Population&nbsp;</div> <div style="left:26.8em" data-tip="Click to sort by culture population" class="sortable hide icon-sort-number-down" data-sortby="population">Population&nbsp;</div>
<div style="margin-left: 2px" data-tip="Click to sort by culture namesbase" class="sortable" data-sortby="base">Namesbase&nbsp;</div> <div style="left:33.8em" data-tip="Click to sort by culture namesbase" class="sortable" data-sortby="base">Namesbase&nbsp;</div>
</div> </div>
<div id="culturesBody" class="table" data-type="absolute"></div> <div id="culturesBody" class="table" data-type="absolute"></div>
@ -2702,10 +2713,10 @@
<div id="zonesEditor" class="dialog stable" style="display: none"> <div id="zonesEditor" class="dialog stable" style="display: none">
<div id="customHeader" class="header"> <div id="customHeader" class="header">
<div style="margin-left: 15px" data-tip="Zone description">Description&nbsp;</div> <div style="left:1.4em" data-tip="Zone description">Description&nbsp;</div>
<div style="margin-left: 51px" data-tip="Zone cells count" class="hide">Cells&nbsp;</div> <div style="left:13em" data-tip="Zone cells count" class="hide">Cells&nbsp;</div>
<div style="margin-left: 31px" data-tip="Zone area" class="hide">Area&nbsp;</div> <div style="left:19em" data-tip="Zone area" class="hide">Area&nbsp;</div>
<div style="margin-left: 22px" data-tip="Zone population" class="hide">Population&nbsp;</div> <div style="left:24em" data-tip="Zone population" class="hide">Population&nbsp;</div>
</div> </div>
<div id="zonesBodySection" class="table" data-type="absolute"></div> <div id="zonesBodySection" class="table" data-type="absolute"></div>
@ -2740,16 +2751,16 @@
<div id="notesEditor" class="dialog stable textual" style="display: none"> <div id="notesEditor" class="dialog stable textual" style="display: none">
<div> <div>
<span>Select object: </span> <span>Select object: </span>
<select id="notesSelect" data-tip="Select object" style="width: 120px;"></select> <select id="notesSelect" data-tip="Select object" style="width: 12em"></select>
<span>Object name: </span> <span>Object name: </span>
<input id="notesName" data-tip="Type to change object name" autocorrect="off" spellcheck="false" style="width: 120px;"> <input id="notesName" data-tip="Type to change object name" autocorrect="off" spellcheck="false" style="width: 12em">
</div> </div>
<div> <div>
<span>Legend:</span><br> <span>Legend:</span><br>
<textarea id="notesText" cols="70" rows="7" data-tip="Type object description" placeholder="Type object description"></textarea> <textarea id="notesText" cols="70" rows="7" data-tip="Type object description" placeholder="Type object description"></textarea>
</div> </div>
<div> <div>
<button id="notesFocus" data-tip="Focus map on selected object" class="icon-target"></button> <button id="notesFocus" data-tip="Focus on selected object" class="icon-target"></button>
<button id="notesDownload" data-tip="Download notes to PC" class="icon-download"></button> <button id="notesDownload" data-tip="Download notes to PC" class="icon-download"></button>
<button id="notesUpload" data-tip="Upload notes from PC" class="icon-upload"></button> <button id="notesUpload" data-tip="Upload notes from PC" class="icon-upload"></button>
<button id="notesRemove" data-tip="Remove this note" class="icon-trash"></button> <button id="notesRemove" data-tip="Remove this note" class="icon-trash"></button>
@ -2757,13 +2768,13 @@
</div> </div>
<div id="religionsEditor" class="dialog stable" style="display: none"> <div id="religionsEditor" class="dialog stable" style="display: none">
<div id="religionsHeader"> <div id="religionsHeader" class="header">
<div style="margin-left: 12px" data-tip="Click to sort by religion name" class="sortable alphabetically" data-sortby="name">Religion&nbsp;</div> <div style="left:1.4em" data-tip="Click to sort by religion name" class="sortable alphabetically" data-sortby="name">Religion&nbsp;</div>
<div style="margin-left: 68px" data-tip="Click to sort by religion type" class="sortable alphabetically icon-sort-name-down" data-sortby="type">Type&nbsp;</div> <div style="left:12.6em" data-tip="Click to sort by religion type" class="sortable alphabetically icon-sort-name-down" data-sortby="type">Type&nbsp;</div>
<div style="margin-left: 18px" data-tip="Click to sort by religion form" class="sortable alphabetically hide" data-sortby="form">Form&nbsp;</div> <div style="left:18em" data-tip="Click to sort by religion form" class="sortable alphabetically hide" data-sortby="form">Form&nbsp;</div>
<div style="margin-left: 42px" data-tip="Click to sort by supreme deity" class="sortable alphabetically hide" data-sortby="deity">Supreme Deity&nbsp;</div> <div style="left:25.1em" data-tip="Click to sort by supreme deity" class="sortable alphabetically hide" data-sortby="deity">Supreme Deity&nbsp;</div>
<div style="margin-left: 92px" data-tip="Click to sort by religion area" class="sortable hide" data-sortby="area">Area&nbsp;</div> <div style="left:42.1em" data-tip="Click to sort by religion area" class="sortable hide" data-sortby="area">Area&nbsp;</div>
<div style="margin-left: 17px" data-tip="Click to sort by number of believers (religion area population)" class="sortable hide" data-sortby="population">Believers&nbsp;</div> <div style="left:47em" data-tip="Click to sort by number of believers (religion area population)" class="sortable hide" data-sortby="population">Believers&nbsp;</div>
</div> </div>
<div id="religionsBody" class="table" data-type="absolute"></div> <div id="religionsBody" class="table" data-type="absolute"></div>
@ -2780,7 +2791,8 @@
<button id="religionsEditorRefresh" data-tip="Refresh the Editor" class="icon-cw"></button> <button id="religionsEditorRefresh" data-tip="Refresh the Editor" class="icon-cw"></button>
<button id="religionsLegend" data-tip="Toggle Legend box" class="icon-list-bullet"></button> <button id="religionsLegend" data-tip="Toggle Legend box" class="icon-list-bullet"></button>
<button id="religionsPercentage" data-tip="Toggle percentage / absolute values display mode" class="icon-percent"></button> <button id="religionsPercentage" data-tip="Toggle percentage / absolute values display mode" class="icon-percent"></button>
<button id="religionsExtinct" data-tip="Show/hide extinct religions (religions without believers)" class="icon-adjust"></button> <button id="religionsHeirarchy" data-tip="Show religions hierarchy tree" class="icon-fork"></button>
<button id="religionsExtinct" data-tip="Show/hide extinct religions (religions without cells)" class="icon-adjust"></button>
<button id="religionsManually" data-tip="Manually re-assign religions" class="icon-brush"></button> <button id="religionsManually" data-tip="Manually re-assign religions" class="icon-brush"></button>
<div id="religionsManuallyButtons" style="display: none"> <div id="religionsManuallyButtons" style="display: none">
@ -2819,7 +2831,6 @@
<div>1 map pixel =</div> <div>1 map pixel =</div>
<input id="distanceScaleOutput" type="range" min=.01 max=20 step=.1 value=3> <input id="distanceScaleOutput" type="range" min=.01 max=20 step=.1 value=3>
<input id="distanceScaleInput" data-stored="distanceScale" type="number" min=.01 max=100 step=.01 value=3 data-value=3> <input id="distanceScaleInput" data-stored="distanceScale" type="number" min=.01 max=100 step=.01 value=3 data-value=3>
<span id="distanceUnitOutput"></span>
</div> </div>
<div data-tip='Area unit name, type "square" to add ² to the distance unit'> <div data-tip='Area unit name, type "square" to add ² to the distance unit'>
@ -2968,6 +2979,7 @@
<script src="libs/polylabel.min.js"></script> <script src="libs/polylabel.min.js"></script>
<script src="libs/jquery-ui.min.js"></script> <script src="libs/jquery-ui.min.js"></script>
<script src="libs/seedrandom.min.js"></script> <script src="libs/seedrandom.min.js"></script>
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/simplex-noise/2.3.0/simplex-noise.js"></script> -->
<script src="modules/ui/layers.js"></script> <script src="modules/ui/layers.js"></script>
<script defer src="modules/ui/general.js"></script> <script defer src="modules/ui/general.js"></script>

11
libs/jquery-ui.css vendored
View file

@ -335,21 +335,21 @@ body .ui-dialog {
position: absolute; position: absolute;
right: .5em; right: .5em;
top: 53%; top: 53%;
width: 18px;
padding: 0; padding: 0;
height: 18px; width: 1.8em;
height: 1.8em;
color: #ffffff; color: #ffffff;
background: none; background: none;
font-size: 10px; font-size: .75em;
border: 1px solid #c5c5c5; border: 1px solid #c5c5c5;
} }
.ui-dialog .ui-dialog-titlebar button.ui-dialog-titlebar-collapse { .ui-dialog .ui-dialog-titlebar button.ui-dialog-titlebar-collapse {
margin: -10px 22px 0 0; margin: -1em 2.2em 0 0;
} }
.ui-dialog .ui-dialog-titlebar button.ui-dialog-titlebar-close { .ui-dialog .ui-dialog-titlebar button.ui-dialog-titlebar-close {
margin: -10px 0 0 0; margin: -1em 0 0;
} }
.ui-dialog .ui-dialog-titlebar button:active { .ui-dialog .ui-dialog-titlebar button:active {
@ -362,6 +362,7 @@ body .ui-dialog {
border: 0; border: 0;
padding: .5em 1em; padding: .5em 1em;
background: none; background: none;
overflow: auto;
} }
.ui-dialog .ui-dialog-buttonpane { .ui-dialog .ui-dialog-buttonpane {
text-align: left; text-align: left;

113
main.js
View file

@ -98,7 +98,7 @@ let customization = 0; // 0 - no; 1 = heightmap draw; 2 - states draw; 3 - add s
let mapCoordinates = {}; // map coordinates on globe let mapCoordinates = {}; // map coordinates on globe
let winds = [225, 45, 225, 315, 135, 315]; // default wind directions let winds = [225, 45, 225, 315, 135, 315]; // default wind directions
let biomesData = applyDefaultBiomesSystem(); let biomesData = applyDefaultBiomesSystem();
let nameBases = [], nameBase = []; // Cultures-related data let nameBases = Names.getNameBases(), nameBase = Names.getNameBase(); // cultures-related data
const fonts = ["Almendra+SC", "Georgia", "Arial", "Times+New+Roman", "Comic+Sans+MS", "Lucida+Sans+Unicode", "Courier+New"]; // default web-safe fonts const fonts = ["Almendra+SC", "Georgia", "Arial", "Times+New+Roman", "Comic+Sans+MS", "Lucida+Sans+Unicode", "Courier+New"]; // default web-safe fonts
let color = d3.scaleSequential(d3.interpolateSpectral); // default color scheme let color = d3.scaleSequential(d3.interpolateSpectral); // default color scheme
@ -116,7 +116,6 @@ landmass.append("rect").attr("x", 0).attr("y", 0).attr("width", graphWidth).attr
oceanPattern.append("rect").attr("fill", "url(#oceanic)").attr("x", 0).attr("y", 0).attr("width", graphWidth).attr("height", graphHeight); oceanPattern.append("rect").attr("fill", "url(#oceanic)").attr("x", 0).attr("y", 0).attr("width", graphWidth).attr("height", graphHeight);
oceanLayers.append("rect").attr("id", "oceanBase").attr("x", 0).attr("y", 0).attr("width", graphWidth).attr("height", graphHeight); oceanLayers.append("rect").attr("id", "oceanBase").attr("x", 0).attr("y", 0).attr("width", graphWidth).attr("height", graphHeight);
applyDefaultNamesData(); // always apply default namesbase load as namesdata is not stored in .map file
void function removeLoading() { void function removeLoading() {
d3.select("#loading").transition().duration(5000).style("opacity", 0).remove(); d3.select("#loading").transition().duration(5000).style("opacity", 0).remove();
d3.select("#initial").transition().duration(5000).attr("opacity", 0).remove(); d3.select("#initial").transition().duration(5000).attr("opacity", 0).remove();
@ -191,7 +190,7 @@ function showUploadErrorMessage(error, URL, random) {
Cannot load map from the <a href='${URL}' target='_blank'>link provided</a>. Cannot load map from the <a href='${URL}' target='_blank'>link provided</a>.
${random?`A new random map is generated. `:''} ${random?`A new random map is generated. `:''}
Please ensure the linked file is reachable and CORS is allowed on server side`; Please ensure the linked file is reachable and CORS is allowed on server side`;
$("#alert").dialog({title: "Loading error", width: 320, buttons: {OK: function() {$(this).dialog("close");}}}); $("#alert").dialog({title: "Loading error", width: "32em", buttons: {OK: function() {$(this).dialog("close");}}});
} }
function generateMapOnLoad() { function generateMapOnLoad() {
@ -281,79 +280,6 @@ function findBurgForMFCG(params) {
invokeActiveZooming(); invokeActiveZooming();
} }
function applyDefaultNamesData() {
// name, min length, max length, letters to allow duplication, multi-word name rate
nameBases = [
{name: "German", min: 5, max: 12, d: "lt", m: 0},
{name: "English", min: 6, max: 11, d: "", m: 0.1},
{name: "French", min: 5, max: 13, d: "nlrs", m: 0.1},
{name: "Italian", min: 5, max: 12, d: "cltr", m: 0.1},
{name: "Castillian", min: 5, max: 11, d: "lr", m: 0},
{name: "Ruthenian", min: 5, max: 10, d: "", m: 0},
{name: "Nordic", min: 6, max: 10, d: "kln", m: 0.1},
{name: "Greek", min: 5, max: 11, d: "s", m: 0.1},
{name: "Roman", min: 6, max: 11, d: "ln", m: 0.1},
{name: "Finnic", min: 5, max: 11, d: "akiut", m: 0},
{name: "Korean", min: 5, max: 11, d: "", m: 0},
{name: "Chinese", min: 5, max: 10, d: "", m: 0},
{name: "Japanese", min: 4, max: 10, d: "", m: 0},
{name: "Portuguese", min: 5, max: 11, d: "", m: 0.1},
{name: "Nahuatl", min: 6, max: 13, d: "l", m: 0},
{name: "Hungarian", min: 6, max: 13, d: "", m: 0.1},
{name: "Turkish", min: 4, max: 10, d: "", m: 0},
{name: "Berber", min: 4, max: 10, d: "s", m: 0.2},
{name: "Arabic", min: 4, max: 9, d: "ae", m: 0.2},
{name: "Inuit", min: 5, max: 15, d: "alutsn", m: 0},
{name: "Basque", min: 4, max: 11, d: "r", m: 0.1},
{name: "Nigerian", min: 4, max: 10, d: "", m: 0.3},
{name: "Celtic", min: 4, max: 12, d: "nld", m: 0},
{name: "Mesopotamian", min: 4, max: 9, d: "srpl", m: 0.1},
{name: "Iranian", min: 5, max: 11, d: "", m: 0.1},
{name: "Hawaiian", min: 5, max: 10, d: "auo", m: 1},
{name: "Karnataka", min: 5, max: 11, d: "tnl", m: 0},
{name: "Quechua", min: 6, max: 12, d: "l", m: 0},
{name: "Swahili", min: 4, max: 9, d: "", m: 0},
{name: "Vietnamese", min: 3, max: 12, d: "", m: 1},
{name: "Cantonese", min: 5, max: 11, d: "", m: 0},
{name: "Mongolian", min: 5, max: 12, d: "aou", m: .3}
];
nameBase = [
["Achern","Aichhalden","Aitern","Albbruck","Alpirsbach","Altensteig","Althengstett","Appenweier","Auggen","Wildbad","Badenen","Badenweiler","Baiersbronn","Ballrechten","Bellingen","Berghaupten","Bernau","Biberach","Biederbach","Binzen","Birkendorf","Birkenfeld","Bischweier","Blumberg","Bollen","Bollschweil","Bonndorf","Bosingen","Braunlingen","Breisach","Breisgau","Breitnau","Brigachtal","Buchenbach","Buggingen","Buhl","Buhlertal","Calw","Dachsberg","Dobel","Donaueschingen","Dornhan","Dornstetten","Dottingen","Dunningen","Durbach","Durrheim","Ebhausen","Ebringen","Efringen","Egenhausen","Ehrenkirchen","Ehrsberg","Eimeldingen","Eisenbach","Elzach","Elztal","Emmendingen","Endingen","Engelsbrand","Enz","Enzklosterle","Eschbronn","Ettenheim","Ettlingen","Feldberg","Fischerbach","Fischingen","Fluorn","Forbach","Freiamt","Freiburg","Freudenstadt","Friedenweiler","Friesenheim","Frohnd","Furtwangen","Gaggenau","Geisingen","Gengenbach","Gernsbach","Glatt","Glatten","Glottertal","Gorwihl","Gottenheim","Grafenhausen","Grenzach","Griesbach","Gutach","Gutenbach","Hag","Haiterbach","Hardt","Harmersbach","Hasel","Haslach","Hausach","Hausen","Hausern","Heitersheim","Herbolzheim","Herrenalb","Herrischried","Hinterzarten","Hochenschwand","Hofen","Hofstetten","Hohberg","Horb","Horben","Hornberg","Hufingen","Ibach","Ihringen","Inzlingen","Kandern","Kappel","Kappelrodeck","Karlsbad","Karlsruhe","Kehl","Keltern","Kippenheim","Kirchzarten","Konigsfeld","Krozingen","Kuppenheim","Kussaberg","Lahr","Lauchringen","Lauf","Laufenburg","Lautenbach","Lauterbach","Lenzkirch","Liebenzell","Loffenau","Loffingen","Lorrach","Lossburg","Mahlberg","Malsburg","Malsch","March","Marxzell","Marzell","Maulburg","Monchweiler","Muhlenbach","Mullheim","Munstertal","Murg","Nagold","Neubulach","Neuenburg","Neuhausen","Neuried","Neuweiler","Niedereschach","Nordrach","Oberharmersbach","Oberkirch","Oberndorf","Oberbach","Oberried","Oberwolfach","Offenburg","Ohlsbach","Oppenau","Ortenberg","otigheim","Ottenhofen","Ottersweier","Peterstal","Pfaffenweiler","Pfalzgrafenweiler","Pforzheim","Rastatt","Renchen","Rheinau","Rheinfelden","Rheinmunster","Rickenbach","Rippoldsau","Rohrdorf","Rottweil","Rummingen","Rust","Sackingen","Sasbach","Sasbachwalden","Schallbach","Schallstadt","Schapbach","Schenkenzell","Schiltach","Schliengen","Schluchsee","Schomberg","Schonach","Schonau","Schonenberg","Schonwald","Schopfheim","Schopfloch","Schramberg","Schuttertal","Schwenningen","Schworstadt","Seebach","Seelbach","Seewald","Sexau","Simmersfeld","Simonswald","Sinzheim","Solden","Staufen","Stegen","Steinach","Steinen","Steinmauern","Straubenhardt","Stuhlingen","Sulz","Sulzburg","Teinach","Tiefenbronn","Tiengen","Titisee","Todtmoos","Todtnau","Todtnauberg","Triberg","Tunau","Tuningen","uhlingen","Unterkirnach","Reichenbach","Utzenfeld","Villingen","Villingendorf","Vogtsburg","Vohrenbach","Waldachtal","Waldbronn","Waldkirch","Waldshut","Wehr","Weil","Weilheim","Weisenbach","Wembach","Wieden","Wiesental","Wildberg","Winzeln","Wittlingen","Wittnau","Wolfach","Wutach","Wutoschingen","Wyhlen","Zavelstein"],
["Abingdon","Albrighton","Alcester","Almondbury","Altrincham","Amersham","Andover","Appleby","Ashboume","Atherstone","Aveton","Axbridge","Aylesbury","Baldock","Bamburgh","Barton","Basingstoke","Berden","Bere","Berkeley","Berwick","Betley","Bideford","Bingley","Birmingham","Blandford","Blechingley","Bodmin","Bolton","Bootham","Boroughbridge","Boscastle","Bossinney","Bramber","Brampton","Brasted","Bretford","Bridgetown","Bridlington","Bromyard","Bruton","Buckingham","Bungay","Burton","Calne","Cambridge","Canterbury","Carlisle","Castleton","Caus","Charmouth","Chawleigh","Chichester","Chillington","Chinnor","Chipping","Chisbury","Cleobury","Clifford","Clifton","Clitheroe","Cockermouth","Coleshill","Combe","Congleton","Crafthole","Crediton","Cuddenbeck","Dalton","Darlington","Dodbrooke","Drax","Dudley","Dunstable","Dunster","Dunwich","Durham","Dymock","Exeter","Exning","Faringdon","Felton","Fenny","Finedon","Flookburgh","Fowey","Frampton","Gateshead","Gatton","Godmanchester","Grampound","Grantham","Guildford","Halesowen","Halton","Harbottle","Harlow","Hatfield","Hatherleigh","Haydon","Helston","Henley","Hertford","Heytesbury","Hinckley","Hitchin","Holme","Hornby","Horsham","Kendal","Kenilworth","Kilkhampton","Kineton","Kington","Kinver","Kirby","Knaresborough","Knutsford","Launceston","Leighton","Lewes","Linton","Louth","Luton","Lyme","Lympstone","Macclesfield","Madeley","Malborough","Maldon","Manchester","Manningtree","Marazion","Marlborough","Marshfield","Mere","Merryfield","Middlewich","Midhurst","Milborne","Mitford","Modbury","Montacute","Mousehole","Newbiggin","Newborough","Newbury","Newenden","Newent","Norham","Northleach","Noss","Oakham","Olney","Orford","Ormskirk","Oswestry","Padstow","Paignton","Penkneth","Penrith","Penzance","Pershore","Petersfield","Pevensey","Pickering","Pilton","Pontefract","Portsmouth","Preston","Quatford","Reading","Redcliff","Retford","Rockingham","Romney","Rothbury","Rothwell","Salisbury","Saltash","Seaford","Seasalter","Sherston","Shifnal","Shoreham","Sidmouth","Skipsea","Skipton","Solihull","Somerton","Southam","Southwark","Standon","Stansted","Stapleton","Stottesdon","Sudbury","Swavesey","Tamerton","Tarporley","Tetbury","Thatcham","Thaxted","Thetford","Thornbury","Tintagel","Tiverton","Torksey","Totnes","Towcester","Tregoney","Trematon","Tutbury","Uxbridge","Wallingford","Wareham","Warenmouth","Wargrave","Warton","Watchet","Watford","Wendover","Westbury","Westcheap","Weymouth","Whitford","Wickwar","Wigan","Wigmore","Winchelsea","Winkleigh","Wiscombe","Witham","Witheridge","Wiveliscombe","Woodbury","Yeovil"],
["Adon","Aillant","Amilly","Andonville","Ardon","Artenay","Ascheres","Ascoux","Attray","Aubin","Audeville","Aulnay","Autruy","Auvilliers","Auxy","Aveyron","Baccon","Bardon","Barville","Batilly","Baule","Bazoches","Beauchamps","Beaugency","Beaulieu","Beaune","Bellegarde","Boesses","Boigny","Boiscommun","Boismorand","Boisseaux","Bondaroy","Bonnee","Bonny","Bordes","Bou","Bougy","Bouilly","Boulay","Bouzonville","Bouzy","Boynes","Bray","Breteau","Briare","Briarres","Bricy","Bromeilles","Bucy","Cepoy","Cercottes","Cerdon","Cernoy","Cesarville","Chailly","Chaingy","Chalette","Chambon","Champoulet","Chanteau","Chantecoq","Chapell","Charme","Charmont","Charsonville","Chateau","Chateauneuf","Chatel","Chatenoy","Chatillon","Chaussy","Checy","Chevannes","Chevillon","Chevilly","Chevry","Chilleurs","Choux","Chuelles","Clery","Coinces","Coligny","Combleux","Combreux","Conflans","Corbeilles","Corquilleroy","Cortrat","Coudroy","Coullons","Coulmiers","Courcelles","Courcy","Courtemaux","Courtempierre","Courtenay","Cravant","Crottes","Dadonville","Dammarie","Dampierre","Darvoy","Desmonts","Dimancheville","Donnery","Dordives","Dossainville","Douchy","Dry","Echilleuses","Egry","Engenville","Epieds","Erceville","Ervauville","Escrennes","Escrignelles","Estouy","Faverelles","Fay","Feins","Ferolles","Ferrieres","Fleury","Fontenay","Foret","Foucherolles","Freville","Gatinais","Gaubertin","Gemigny","Germigny","Gidy","Gien","Girolles","Givraines","Gondreville","Grangermont","Greneville","Griselles","Guigneville","Guilly","Gyleslonains","Huetre","Huisseau","Ingrannes","Ingre","Intville","Isdes","Jargeau","Jouy","Juranville","Bussiere","Laas","Ladon","Lailly","Langesse","Leouville","Ligny","Lombreuil","Lorcy","Lorris","Loury","Louzouer","Malesherbois","Marcilly","Mardie","Mareau","Marigny","Marsainvilliers","Melleroy","Menestreau","Merinville","Messas","Meung","Mezieres","Migneres","Mignerette","Mirabeau","Montargis","Montbarrois","Montbouy","Montcresson","Montereau","Montigny","Montliard","Mormant","Morville","Moulinet","Moulon","Nancray","Nargis","Nesploy","Neuville","Neuvy","Nevoy","Nibelle","Nogent","Noyers","Ocre","Oison","Olivet","Ondreville","Onzerain","Orleans","Ormes","Orville","Oussoy","Outarville","Ouzouer","Pannecieres","Pannes","Patay","Paucourt","Pers","Pierrefitte","Pithiverais","Pithiviers","Poilly","Potier","Prefontaines","Presnoy","Pressigny","Puiseaux","Quiers","Ramoulu","Rebrechien","Rouvray","Rozieres","Rozoy","Ruan","Sandillon","Santeau","Saran","Sceaux","Seichebrieres","Semoy","Sennely","Sermaises","Sigloy","Solterre","Sougy","Sully","Sury","Tavers","Thignonville","Thimory","Thorailles","Thou","Tigy","Tivernon","Tournoisis","Trainou","Treilles","Trigueres","Trinay","Vannes","Varennes","Vennecy","Vieilles","Vienne","Viglain","Vignes","Villamblain","Villemandeur","Villemoutiers","Villemurlin","Villeneuve","Villereau","Villevoques","Villorceau","Vimory","Vitry","Vrigny","Ivre"],
["Accumoli","Acquafondata","Acquapendente","Acuto","Affile","Agosta","Alatri","Albano","Allumiere","Alvito","Amaseno","Amatrice","Anagni","Anguillara","Anticoli","Antrodoco","Anzio","Aprilia","Aquino","Arce","Arcinazzo","Ardea","Ariccia","Arlena","Arnara","Arpino","Arsoli","Artena","Ascrea","Atina","Ausonia","Bagnoregio","Barbarano","Bassano","Bassiano","Bellegra","Belmonte","Blera","Bolsena","Bomarzo","Borbona","Borgo","Borgorose","Boville","Bracciano","Broccostella","Calcata","Camerata","Campagnano","Campodimele","Campoli","Canale","Canepina","Canino","Cantalice","Cantalupo","Canterano","Capena","Capodimonte","Capranica","Caprarola","Carbognano","Casalattico","Casalvieri","Casape","Casaprota","Casperia","Cassino","Castelforte","Castelliri","Castello","Castelnuovo","Castiglione","Castro","Castrocielo","Cave","Ceccano","Celleno","Cellere","Ceprano","Cerreto","Cervara","Cervaro","Cerveteri","Ciampino","Ciciliano","Cineto","Cisterna","Cittaducale","Cittareale","Civita","Civitavecchia","Civitella","Colfelice","Collalto","Colle","Colleferro","Collegiove","Collepardo","Collevecchio","Colli","Colonna","Concerviano","Configni","Contigliano","Corchiano","Coreno","Cori","Cottanello","Esperia","Fabrica","Faleria","Fara","Farnese","Ferentino","Fiamignano","Fiano","Filacciano","Filettino","Fiuggi","Fiumicino","Fondi","Fontana","Fonte","Fontechiari","Forano","Formello","Formia","Frascati","Frasso","Frosinone","Fumone","Gaeta","Gallese","Gallicano","Gallinaro","Gavignano","Genazzano","Genzano","Gerano","Giuliano","Gorga","Gradoli","Graffignano","Greccio","Grottaferrata","Grotte","Guarcino","Guidonia","Ischia","Isola","Itri","Jenne","Labico","Labro","Ladispoli","Lanuvio","Lariano","Latera","Lenola","Leonessa","Licenza","Longone","Lubriano","Maenza","Magliano","Mandela","Manziana","Marano","Marcellina","Marcetelli","Marino","Marta","Mazzano","Mentana","Micigliano","Minturno","Mompeo","Montalto","Montasola","Monte","Montebuono","Montefiascone","Monteflavio","Montelanico","Monteleone","Montelibretti","Montenero","Monterosi","Monterotondo","Montopoli","Montorio","Moricone","Morlupo","Morolo","Morro","Nazzano","Nemi","Nepi","Nerola","Nespolo","Nettuno","Norma","Olevano","Onano","Oriolo","Orte","Orvinio","Paganico","Palestrina","Paliano","Palombara","Pastena","Patrica","Percile","Pescorocchiano","Pescosolido","Petrella","Piansano","Picinisco","Pico","Piedimonte","Piglio","Pignataro","Pisoniano","Pofi","Poggio","Poli","Pomezia","Pontecorvo","Pontinia","Ponza","Ponzano","Posta","Pozzaglia","Priverno","Proceno","Prossedi","Riano","Rieti","Rignano","Riofreddo","Ripi","Rivodutri","Rocca","Roccagiovine","Roccagorga","Roccantica","Roccasecca","Roiate","Ronciglione","Roviano","Sabaudia","Sacrofano","Salisano","Sambuci","Santa","Santi","Santopadre","Saracinesco","Scandriglia","Segni","Selci","Sermoneta","Serrone","Settefrati","Sezze","Sgurgola","Sonnino","Sora","Soriano","Sperlonga","Spigno","Stimigliano","Strangolagalli","Subiaco","Supino","Sutri","Tarano","Tarquinia","Terelle","Terracina","Tessennano","Tivoli","Toffia","Tolfa","Torre","Torri","Torrice","Torricella","Torrita","Trevi","Trevignano","Trivigliano","Turania","Tuscania","Vacone","Valentano","Vallecorsa","Vallemaio","Vallepietra","Vallerano","Vallerotonda","Vallinfreda","Valmontone","Varco","Vasanello","Vejano","Velletri","Ventotene","Veroli","Vetralla","Vicalvi","Vico","Vicovaro","Vignanello","Viterbo","Viticuso","Vitorchiano","Vivaro","Zagarolo"],
["Abanades","Ablanque","Adobes","Ajofrin","Alameda","Alaminos","Alarilla","Albalate","Albares","Albarreal","Albendiego","Alcabon","Alcanizo","Alcaudete","Alcocer","Alcolea","Alcoroches","Aldea","Aldeanueva","Algar","Algora","Alhondiga","Alique","Almadrones","Almendral","Almoguera","Almonacid","Almorox","Alocen","Alovera","Alustante","Angon","Anguita","Anover","Anquela","Arbancon","Arbeteta","Arcicollar","Argecilla","Arges","Armallones","Armuna","Arroyo","Atanzon","Atienza","Aunon","Azuqueca","Azutan","Baides","Banos","Banuelos","Barcience","Bargas","Barriopedro","Belvis","Berninches","Borox","Brihuega","Budia","Buenaventura","Bujalaro","Burguillos","Burujon","Bustares","Cabanas","Cabanillas","Calera","Caleruela","Calzada","Camarena","Campillo","Camunas","Canizar","Canredondo","Cantalojas","Cardiel","Carmena","Carranque","Carriches","Casa","Casarrubios","Casas","Casasbuenas","Caspuenas","Castejon","Castellar","Castilforte","Castillo","Castilnuevo","Cazalegas","Cebolla","Cedillo","Cendejas","Centenera","Cervera","Checa","Chequilla","Chillaron","Chiloeches","Chozas","Chueca","Cifuentes","Cincovillas","Ciruelas","Ciruelos","Cobeja","Cobeta","Cobisa","Cogollor","Cogolludo","Condemios","Congostrina","Consuegra","Copernal","Corduente","Corral","Cuerva","Domingo","Dosbarrios","Driebes","Duron","El","Embid","Erustes","Escalona","Escalonilla","Escamilla","Escariche","Escopete","Espinosa","Espinoso","Esplegares","Esquivias","Estables","Estriegana","Fontanar","Fuembellida","Fuensalida","Fuentelsaz","Gajanejos","Galve","Galvez","Garciotum","Gascuena","Gerindote","Guadamur","Henche","Heras","Herreria","Herreruela","Hijes","Hinojosa","Hita","Hombrados","Hontanar","Hontoba","Horche","Hormigos","Huecas","Huermeces","Huerta","Hueva","Humanes","Illan","Illana","Illescas","Iniestola","Irueste","Jadraque","Jirueque","Lagartera","Las","Layos","Ledanca","Lillo","Lominchar","Loranca","Los","Lucillos","Lupiana","Luzaga","Luzon","Madridejos","Magan","Majaelrayo","Malaga","Malaguilla","Malpica","Mandayona","Mantiel","Manzaneque","Maqueda","Maranchon","Marchamalo","Marjaliza","Marrupe","Mascaraque","Masegoso","Matarrubia","Matillas","Mazarete","Mazuecos","Medranda","Megina","Mejorada","Mentrida","Mesegar","Miedes","Miguel","Millana","Milmarcos","Mirabueno","Miralrio","Mocejon","Mochales","Mohedas","Molina","Monasterio","Mondejar","Montarron","Mora","Moratilla","Morenilla","Muduex","Nambroca","Navalcan","Negredo","Noblejas","Noez","Nombela","Noves","Numancia","Nuno","Ocana","Ocentejo","Olias","Olmeda","Ontigola","Orea","Orgaz","Oropesa","Otero","Palmaces","Palomeque","Pantoja","Pardos","Paredes","Pareja","Parrillas","Pastrana","Pelahustan","Penalen","Penalver","Pepino","Peralejos","Peralveche","Pinilla","Pioz","Piqueras","Polan","Portillo","Poveda","Pozo","Pradena","Prados","Puebla","Puerto","Pulgar","Quer","Quero","Quintanar","Quismondo","Rebollosa","Recas","Renera","Retamoso","Retiendas","Riba","Rielves","Rillo","Riofrio","Robledillo","Robledo","Romanillos","Romanones","Rueda","Sacecorbo","Sacedon","Saelices","Salmeron","San","Santa","Santiuste","Santo","Sartajada","Sauca","Sayaton","Segurilla","Selas","Semillas","Sesena","Setiles","Sevilleja","Sienes","Siguenza","Solanillos","Somolinos","Sonseca","Sotillo","Sotodosos","Talavera","Tamajon","Taragudo","Taravilla","Tartanedo","Tembleque","Tendilla","Terzaga","Tierzo","Tordellego","Tordelrabano","Tordesilos","Torija","Torralba","Torre","Torrecilla","Torrecuadrada","Torrejon","Torremocha","Torrico","Torrijos","Torrubia","Tortola","Tortuera","Tortuero","Totanes","Traid","Trijueque","Trillo","Turleque","Uceda","Ugena","Ujados","Urda","Utande","Valdarachas","Valdesotos","Valhermoso","Valtablado","Valverde","Velada","Viana","Vinuelas","Yebes","Yebra","Yelamos","Yeles","Yepes","Yuncler","Yunclillos","Yuncos","Yunquera","Zaorejas","Zarzuela","Zorita"],
["Belgorod","Beloberezhye","Belyi","Belz","Berestiy","Berezhets","Berezovets","Berezutsk","Bobruisk","Bolonets","Borisov","Borovsk","Bozhesk","Bratslav","Bryansk","Brynsk","Buryn","Byhov","Chechersk","Chemesov","Cheremosh","Cherlen","Chern","Chernigov","Chernitsa","Chernobyl","Chernogorod","Chertoryesk","Chetvertnia","Demyansk","Derevesk","Devyagoresk","Dichin","Dmitrov","Dorogobuch","Dorogobuzh","Drestvin","Drokov","Drutsk","Dubechin","Dubichi","Dubki","Dubkov","Dveren","Galich","Glebovo","Glinsk","Goloty","Gomiy","Gorodets","Gorodische","Gorodno","Gorohovets","Goroshin","Gorval","Goryshon","Holm","Horobor","Hoten","Hotin","Hotmyzhsk","Ilovech","Ivan","Izborsk","Izheslavl","Kamenets","Kanev","Karachev","Karna","Kavarna","Klechesk","Klyapech","Kolomyya","Kolyvan","Kopyl","Korec","Kornik","Korochunov","Korshev","Korsun","Koshkin","Kotelno","Kovyla","Kozelsk","Kozelsk","Kremenets","Krichev","Krylatsk","Ksniatin","Kulatsk","Kursk","Kursk","Lebedev","Lida","Logosko","Lomihvost","Loshesk","Loshichi","Lubech","Lubno","Lubutsk","Lutsk","Luchin","Luki","Lukoml","Luzha","Lvov","Mtsensk","Mdin","Medniki","Melecha","Merech","Meretsk","Mescherskoe","Meshkovsk","Metlitsk","Mezetsk","Mglin","Mihailov","Mikitin","Mikulino","Miloslavichi","Mogilev","Mologa","Moreva","Mosalsk","Moschiny","Mozyr","Mstislav","Mstislavets","Muravin","Nemech","Nemiza","Nerinsk","Nichan","Novgorod","Novogorodok","Obolichi","Obolensk","Obolensk","Oleshsk","Olgov","Omelnik","Opoka","Opoki","Oreshek","Orlets","Osechen","Oster","Ostrog","Ostrov","Perelai","Peremil","Peremyshl","Pererov","Peresechen","Perevitsk","Pereyaslav","Pinsk","Ples","Polotsk","Pronsk","Proposhesk","Punia","Putivl","Rechitsa","Rodno","Rogachev","Romanov","Romny","Roslavl","Rostislavl","Rostovets","Rsha","Ruza","Rybchesk","Rylsk","Rzhavesk","Rzhev","Rzhischev","Sambor","Serensk","Serensk","Serpeysk","Shilov","Shuya","Sinech","Sizhka","Skala","Slovensk","Slutsk","Smedin","Sneporod","Snitin","Snovsk","Sochevo","Sokolec","Starica","Starodub","Stepan","Sterzh","Streshin","Sutesk","Svinetsk","Svisloch","Terebovl","Ternov","Teshilov","Teterin","Tiversk","Torchevsk","Toropets","Torzhok","Tripolye","Trubchevsk","Tur","Turov","Usvyaty","Uteshkov","Vasilkov","Velil","Velye","Venev","Venicha","Verderev","Vereya","Veveresk","Viazma","Vidbesk","Vidychev","Voino","Volodimer","Volok","Volyn","Vorobesk","Voronich","Voronok","Vorotynsk","Vrev","Vruchiy","Vselug","Vyatichsk","Vyatka","Vyshegorod","Vyshgorod","Vysokoe","Yagniatin","Yaropolch","Yasenets","Yuryev","Yuryevets","Zaraysk","Zhitomel","Zholvazh","Zizhech","Zubkov","Zudechev","Zvenigorod"],
["Akureyri","Aldra","Alftanes","Andenes","Austbo","Auvog","Bakkafjordur","Ballangen","Bardal","Beisfjord","Bifrost","Bildudalur","Bjerka","Bjerkvik","Bjorkosen","Bliksvaer","Blokken","Blonduos","Bolga","Bolungarvik","Borg","Borgarnes","Bosmoen","Bostad","Bostrand","Botsvika","Brautarholt","Breiddalsvik","Bringsli","Brunahlid","Budardalur","Byggdakjarni","Dalvik","Djupivogur","Donnes","Drageid","Drangsnes","Egilsstadir","Eiteroga","Elvenes","Engavogen","Ertenvog","Eskifjordur","Evenes","Eyrarbakki","Fagernes","Fallmoen","Fellabaer","Fenes","Finnoya","Fjaer","Fjelldal","Flakstad","Flateyri","Flostrand","Fludir","Gardaber","Gardur","Gimstad","Givaer","Gjeroy","Gladstad","Godoya","Godoynes","Granmoen","Gravdal","Grenivik","Grimsey","Grindavik","Grytting","Hafnir","Halsa","Hauganes","Haugland","Hauknes","Hella","Helland","Hellissandur","Hestad","Higrav","Hnifsdalur","Hofn","Hofsos","Holand","Holar","Holen","Holkestad","Holmavik","Hopen","Hovden","Hrafnagil","Hrisey","Husavik","Husvik","Hvammstangi","Hvanneyri","Hveragerdi","Hvolsvollur","Igeroy","Indre","Inndyr","Innhavet","Innes","Isafjordur","Jarklaustur","Jarnsreykir","Junkerdal","Kaldvog","Kanstad","Karlsoy","Kavosen","Keflavik","Kjelde","Kjerstad","Klakk","Kopasker","Kopavogur","Korgen","Kristnes","Krutoga","Krystad","Kvina","Lande","Laugar","Laugaras","Laugarbakki","Laugarvatn","Laupstad","Leines","Leira","Leiren","Leland","Lenvika","Loding","Lodingen","Lonsbakki","Lopsmarka","Lovund","Luroy","Maela","Melahverfi","Meloy","Mevik","Misvaer","Mornes","Mosfellsber","Moskenes","Myken","Naurstad","Nesberg","Nesjahverfi","Nesset","Nevernes","Obygda","Ofoten","Ogskardet","Okervika","Oknes","Olafsfjordur","Oldervika","Olstad","Onstad","Oppeid","Oresvika","Orsnes","Orsvog","Osmyra","Overdal","Prestoya","Raudalaekur","Raufarhofn","Reipo","Reykholar","Reykholt","Reykjahlid","Rif","Rinoya","Rodoy","Rognan","Rosvika","Rovika","Salhus","Sanden","Sandgerdi","Sandoker","Sandset","Sandvika","Saudarkrokur","Selfoss","Selsoya","Sennesvik","Setso","Siglufjordur","Silvalen","Skagastrond","Skjerstad","Skonland","Skorvogen","Skrova","Sleneset","Snubba","Softing","Solheim","Solheimar","Sorarnoy","Sorfugloy","Sorland","Sormela","Sorvaer","Sovika","Stamsund","Stamsvika","Stave","Stokka","Stokkseyri","Storjord","Storo","Storvika","Strand","Straumen","Strendene","Sudavik","Sudureyri","Sundoya","Sydalen","Thingeyri","Thorlakshofn","Thorshofn","Tjarnabyggd","Tjotta","Tosbotn","Traelnes","Trofors","Trones","Tverro","Ulvsvog","Unnstad","Utskor","Valla","Vandved","Varmahlid","Vassos","Vevelstad","Vidrek","Vik","Vikholmen","Vogar","Vogehamn","Vopnafjordur"],
["Abdera","Abila","Abydos","Acanthus","Acharnae","Actium","Adramyttium","Aegae","Aegina","Aegium","Aenus","Agrinion","Aigosthena","Akragas","Akrai","Akrillai","Akroinon","Akrotiri","Alalia","Alexandreia","Alexandretta","Alexandria","Alinda","Amarynthos","Amaseia","Ambracia","Amida","Amisos","Amnisos","Amphicaea","Amphigeneia","Amphipolis","Amphissa","Ankon","Antigona","Antipatrea","Antioch","Antioch","Antiochia","Andros","Apamea","Aphidnae","Apollonia","Argos","Arsuf","Artanes","Artemita","Argyroupoli","Asine","Asklepios","Aspendos","Assus","Astacus","Athenai","Athmonia","Aytos","Ancient","Baris","Bhrytos","Borysthenes","Berge","Boura","Bouthroton","Brauron","Byblos","Byllis","Byzantium","Bythinion","Callipolis","Cebrene","Chalcedon","Calydon","Carystus","Chamaizi","Chalcis","Chersonesos","Chios","Chytri","Clazomenae","Cleonae","Cnidus","Colosse","Corcyra","Croton","Cyme","Cyrene","Cythera","Decelea","Delos","Delphi","Demetrias","Dicaearchia","Dimale","Didyma","Dion","Dioscurias","Dodona","Dorylaion","Dyme","Edessa","Elateia","Eleusis","Eleutherna","Emporion","Ephesus","Ephyra","Epidamnos","Epidauros","Eresos","Eretria","Erythrae","Eubea","Gangra","Gaza","Gela","Golgi","Gonnos","Gorgippia","Gournia","Gortyn","Gythium","Hagios","Hagia","Halicarnassus","Halieis","Helike","Heliopolis","Hellespontos","Helorus","Hemeroskopeion","Heraclea","Hermione","Hermonassa","Hierapetra","Hierapolis","Himera","Histria","Hubla","Hyele","Ialysos","Iasus","Idalium","Imbros","Iolcus","Itanos","Ithaca","Juktas","Kallipolis","Kamares","Kameiros","Kannia","Kamarina","Kasmenai","Katane","Kerkinitida","Kepoi","Kimmerikon","Kios","Klazomenai","Knidos","Knossos","Korinthos","Kos","Kourion","Kume","Kydonia","Kynos","Kyrenia","Lamia","Lampsacus","Laodicea","Lapithos","Larissa","Lato","Laus","Lebena","Lefkada","Lekhaion","Leibethra","Leontinoi","Lepreum","Lessa","Lilaea","Lindus","Lissus","Epizephyrian","Madytos","Magnesia","Mallia","Mantineia","Marathon","Marmara","Maroneia","Masis","Massalia","Megalopolis","Megara","Mesembria","Messene","Metapontum","Methana","Methone","Methumna","Miletos","Misenum","Mochlos","Monastiraki","Morgantina","Mulai","Mukenai","Mylasa","Myndus","Myonia","Myra","Myrmekion","Mutilene","Myos","Nauplios","Naucratis","Naupactus","Naxos","Neapoli","Neapolis","Nemea","Nicaea","Nicopolis","Nirou","Nymphaion","Nysa","Oenoe","Oenus","Odessos","Olbia","Olous","Olympia","Olynthus","Opus","Orchomenus","Oricos","Orestias","Oreus","Oropus","Onchesmos","Pactye","Pagasae","Palaikastro","Pandosia","Panticapaeum","Paphos","Parium","Paros","Parthenope","Patrae","Pavlopetri","Pegai","Pelion","Peiraies","Pella","Percote","Pergamum","Petsofa","Phaistos","Phaleron","Phanagoria","Pharae","Pharnacia","Pharos","Phaselis","Philippi","Pithekussa","Philippopolis","Platanos","Phlius","Pherae","Phocaea","Pinara","Pisa","Pitane","Pitiunt","Pixous","Plataea","Poseidonia","Potidaea","Priapus","Priene","Prousa","Pseira","Psychro","Pteleum","Pydna","Pylos","Pyrgos","Rhamnus","Rhegion","Rhithymna","Rhodes","Rhypes","Rizinia","Salamis","Same","Samos","Scyllaeum","Selinus","Seleucia","Semasus","Sestos","Scidrus","Sicyon","Side","Sidon","Siteia","Sinope","Siris","Sklavokampos","Smyrna","Soli","Sozopolis","Sparta","Stagirus","Stratos","Stymphalos","Sybaris","Surakousai","Taras","Tanagra","Tanais","Tauromenion","Tegea","Temnos","Tenedos","Tenea","Teos","Thapsos","Thassos","Thebai","Theodosia","Therma","Thespiae","Thronion","Thoricus","Thurii","Thyreum","Thyria","Tiruns","Tithoraea","Tomis","Tragurion","Trapeze","Trapezus","Tripolis","Troizen","Troliton","Troy","Tylissos","Tyras","Tyros","Tyritake","Vasiliki","Vathypetros","Zakynthos","Zakros","Zankle"],
["Abila","Adflexum","Adnicrem","Aelia","Aelius","Aeminium","Aequum","Agrippina","Agrippinae","Ala","Albanianis","Ambianum","Andautonia","Apulum","Aquae","Aquaegranni","Aquensis","Aquileia","Aquincum","Arae","Argentoratum","Ariminum","Ascrivium","Atrebatum","Atuatuca","Augusta","Aurelia","Aurelianorum","Batavar","Batavorum","Belum","Biriciana","Blestium","Bonames","Bonna","Bononia","Borbetomagus","Bovium","Bracara","Brigantium","Burgodunum","Caesaraugusta","Caesarea","Caesaromagus","Calleva","Camulodunum","Cannstatt","Cantiacorum","Capitolina","Castellum","Castra","Castrum","Cibalae","Clausentum","Colonia","Concangis","Condate","Confluentes","Conimbriga","Corduba","Coria","Corieltauvorum","Corinium","Coriovallum","Cornoviorum","Danum","Deva","Divodurum","Dobunnorum","Drusi","Dubris","Dumnoniorum","Durnovaria","Durocobrivis","Durocornovium","Duroliponte","Durovernum","Durovigutum","Eboracum","Edetanorum","Emerita","Emona","Euracini","Faventia","Flaviae","Florentia","Forum","Gerulata","Gerunda","Glevensium","Hadriani","Herculanea","Isca","Italica","Iulia","Iuliobrigensium","Iuvavum","Lactodurum","Lagentium","Lauri","Legionis","Lemanis","Lentia","Lepidi","Letocetum","Lindinis","Lindum","Londinium","Lopodunum","Lousonna","Lucus","Lugdunum","Luguvalium","Lutetia","Mancunium","Marsonia","Martius","Massa","Matilo","Mattiacorum","Mediolanum","Mod","Mogontiacum","Moridunum","Mursa","Naissus","Nervia","Nida","Nigrum","Novaesium","Noviomagus","Olicana","Ovilava","Parisiorum","Partiscum","Paterna","Pistoria","Placentia","Pollentia","Pomaria","Pons","Portus","Praetoria","Praetorium","Pullum","Ragusium","Ratae","Raurica","Regina","Regium","Regulbium","Rigomagus","Roma","Romula","Rutupiae","Salassorum","Salernum","Salona","Scalabis","Segovia","Silurum","Sirmium","Siscia","Sorviodurum","Sumelocenna","Tarraco","Taurinorum","Theranda","Traiectum","Treverorum","Tungrorum","Turicum","Ulpia","Valentia","Venetiae","Venta","Verulamium","Vesontio","Vetera","Victoriae","Victrix","Villa","Viminacium","Vindelicorum","Vindobona","Vinovia","Viroconium"],
["Aanekoski","Abjapaluoja","Ahlainen","Aholanvaara","Ahtari","Aijala","Aimala","Akaa","Alajarvi","Alatornio","Alavus","Antsla","Aspo","Bennas","Bjorkoby","Elva","Emasalo","Espoo","Esse","Evitskog","Forssa","Haapajarvi","Haapamaki","Haapavesi","Haapsalu","Haavisto","Hameenlinna","Hameenmaki","Hamina","Hanko","Harjavalta","Hattuvaara","Haukipudas","Hautajarvi","Havumaki","Heinola","Hetta","Hinkabole","Hirmula","Hossa","Huittinen","Husula","Hyryla","Hyvinkaa","Iisalmi","Ikaalinen","Ilmola","Imatra","Inari","Iskmo","Itakoski","Jamsa","Jarvenpaa","Jeppo","Jioesuu","Jiogeva","Joensuu","Jokela","Jokikyla","Jokisuu","Jormua","Juankoski","Jungsund","Jyvaskyla","Kaamasmukka","Kaarina","Kajaani","Kalajoki","Kallaste","Kankaanpaa","Kannus","Kardla","Karesuvanto","Karigasniemi","Karkkila","Karkku","Karksinuia","Karpankyla","Kaskinen","Kasnas","Kauhajoki","Kauhava","Kauniainen","Kauvatsa","Kehra","Keila","Kellokoski","Kelottijarvi","Kemi","Kemijarvi","Kerava","Keuruu","Kiikka","Kiipu","Kilinginiomme","Kiljava","Kilpisjarvi","Kitee","Kiuruvesi","Kivesjarvi","Kiviioli","Kivisuo","Klaukkala","Klovskog","Kohtlajarve","Kokemaki","Kokkola","Kolho","Koria","Koskue","Kotka","Kouva","Kouvola","Kristiina","Kaupunki","Kuhmo","Kunda","Kuopio","Kuressaare","Kurikka","Kusans","Kuusamo","Kylmalankyla","Lahti","Laitila","Lankipohja","Lansikyla","Lappeenranta","Lapua","Laurila","Lautiosaari","Lepsama","Liedakkala","Lieksa","Lihula","Littoinen","Lohja","Loimaa","Loksa","Loviisa","Luohuanylipaa","Lusi","Maardu","Maarianhamina","Malmi","Mantta","Masaby","Masala","Matasvaara","Maula","Miiluranta","Mikkeli","Mioisakula","Munapirtti","Mustvee","Muurahainen","Naantali","Nappa","Narpio","Nickby","Niinimaa","Niinisalo","Nikkila","Nilsia","Nivala","Nokia","Nummela","Nuorgam","Nurmes","Nuvvus","Obbnas","Oitti","Ojakkala","Ollola","onningeby","Orimattila","Orivesi","Otanmaki","Otava","Otepaa","Oulainen","Oulu","Outokumpu","Paavola","Paide","Paimio","Pakankyla","Paldiski","Parainen","Parkano","Parkumaki","Parola","Perttula","Pieksamaki","Pietarsaari","Pioltsamaa","Piolva","Pohjavaara","Porhola","Pori","Porrasa","Porvoo","Pudasjarvi","Purmo","Pussi","Pyhajarvi","Raahe","Raasepori","Raisio","Rajamaki","Rakvere","Rapina","Rapla","Rauma","Rautio","Reposaari","Riihimaki","Rovaniemi","Roykka","Ruonala","Ruottala","Rutalahti","Saarijarvi","Salo","Sastamala","Saue","Savonlinna","Seinajoki","Sillamae","Sindi","Siuntio","Somero","Sompujarvi","Suonenjoki","Suurejaani","Syrjantaka","Tampere","Tamsalu","Tapa","Temmes","Tiorva","Tormasenvaara","Tornio","Tottijarvi","Tulppio","Turenki","Turi","Tuukkala","Tuurala","Tuuri","Tuuski","Ulvila","Unari","Upinniemi","Utti","Uusikaarlepyy","Uusikaupunki","Vaaksy","Vaalimaa","Vaarinmaja","Vaasa","Vainikkala","Valga","Valkeakoski","Vantaa","Varkaus","Vehkapera","Vehmasmaki","Vieki","Vierumaki","Viitasaari","Viljandi","Vilppula","Viohma","Vioru","Virrat","Ylike","Ylivieska","Ylojarvi"],
["Aewor","Andong","Angang","Anjung","Anmyeon","Ansan","Anseong","Anyang","Aphae","Apo","Asan","Baebang","Baekseok","Baeksu","Beobwon","Beolgyo","Beomseo","Boeun","Bongdam","Bongdong","Bonghwa","Bongyang","Boryeong","Boseong","Buan","Bubal","Bucheon","Buksam","Busan","Busan","Busan","Buyeo","Changnyeong","Changwon","Cheonan","Cheongdo","Cheongjin","Cheongju","Cheongju","Cheongsong","Cheongyang","Cheorwon","Chirwon","Chowol","Chuncheon","Chuncheon","Chungju","Chungmu","Daecheon","Daedeok","Daegaya","Daegu","Daegu","Daegu","Daejeon","Daejeon","Daejeon","Daejeong","Daesan","Damyang","Dangjin","Danyang","Dasa","Dogye","Dolsan","Dong","Dongducheon","Donggwangyang","Donghae","Dongsong","Doyang","Eonyang","Eumseong","Gaeseong","Galmal","Gampo","Ganam","Ganggyeong","Ganghwa","Gangjin","Gangneung","Ganseong","Gapyeong","Gaun","Gaya","Geochang","Geoje","Geojin","Geoncheon","Geumho","Geumil","Geumsan","Geumseong","Geumwang","Gijang","Gimcheon","Gimhae","Gimhwa","Gimje","Gimpo","Goa","Gochang","Gochon","Goesan","Gohan","Goheung","Gokseong","Gongdo","Gongju","Gonjiam","Goseong","Goyang","Gujwa","Gumi","Gungnae","Gunpo","Gunsan","Gunsan","Gunwi","Guri","Gurye","Guryongpo","Gwacheon","Gwangcheon","Gwangju","Gwangju","Gwangju","Gwangju","Gwangmyeong","Gwangyang","Gwansan","Gyeongju","Gyeongsan","Gyeongseong","Gyeongseong","Gyeryong","Hadong","Haeju","Haenam","Hamchang","Hamheung","Hampyeong","Hamyang","Hamyeol","Hanam","Hanrim","Hapcheon","Hapdeok","Hayang","Heunghae","Heungnam","Hoengseong","Hongcheon","Hongnong","Hongseong","Hwacheon","Hwado","Hwando","Hwaseong","Hwasun","Hwawon","Hyangnam","Icheon","Iksan","Illo","Imsil","Incheon","Incheon","Incheon","Inje","Iri","Iri","Jangan","Janghang","Jangheung","Janghowon","Jangseong","Jangseungpo","Jangsu","Jecheon","Jeju","Jeomchon","Jeongeup","Jeonggwan","Jeongju","Jeongok","Jeongseon","Jeonju","Jeonju","Jeungpyeong","Jido","Jiksan","Jillyang","Jinan","Jincheon","Jindo","Jingeon","Jinhae","Jinjeop","Jinju","Jinju","Jinnampo","Jinyeong","Jocheon","Jochiwon","Jori","Judeok","Jumunjin","Maepo","Mangyeong","Masan","Masan","Migeum","Miryang","Mokcheon","Mokpo","Mokpo","Muan","Muju","Mungyeong","Munmak","Munsan","Munsan","Naeseo","Naesu","Najin","Naju","Namhae","Namji","Nampyeong","Namwon","Namyang","Namyangju","Nohwa","Nongong","Nonsan","Ochang","Ocheon","Oedong","Okcheon","Okgu","Onam","Onsan","Onyang","Opo","Osan","Osong","Paengseong","Paju","Pocheon","Pogok","Pohang","Poseung","Punggi","Pungsan","Pyeongchang","Pyeonghae","Pyeongtaek","Pyeongyang","Sabi","Sabuk","Sacheon","Samcheok","Samcheonpo","Samho","Samhyang","Samnangjin","Samrye","Sancheong","Sangdong","Sangju","Sanyang","Sapgyo","Sariwon","Sejong","Seocheon","Seogwipo","Seokjeok","Seonggeo","Seonghwan","Seongjin","Seongju","Seongnam","Seongsan","Seonsan","Seosan","Seoul","Seungju","Siheung","Sinbuk","Sindong","Sineuiju","Sintaein","Soheul","Sokcho","Songak","Songjeong","Songnim","Songtan","Sunchang","Suncheon","Suwon","Taean","Taebaek","Tongjin","Tongyeong","Uijeongbu","Uiryeong","Uiseong","Uiwang","Ujeong","Uljin","Ulleung","Ulsan","Ulsan","Unbong","Ungcheon","Ungjin","Wabu","Waegwan","Wando","Wanggeomseong","Wiryeseong","Wondeok","Wonju","Wonsan","Yangchon","Yanggu","Yangju","Yangpyeong","Yangsan","Yangyang","Yecheon","Yeocheon","Yeoju","Yeomchi","Yeoncheon","Yeongam","Yeongcheon","Yeongdeok","Yeongdong","Yeonggwang","Yeongju","Yeongwol","Yeongyang","Yeonil","Yeonmu","Yeosu","Yesan","Yongin","Yongjin","Yugu","Wayang"],
["Anding","Anlu","Anqing","Anshun","Baan","Baixing","Banyang","Baoding","Baoqing","Binzhou","Caozhou","Changbai","Changchun","Changde","Changling","Changsha","Changtu","Changzhou","Chaozhou","Cheli","Chengde","Chengdu","Chenzhou","Chizhou","Chongqing","Chuxiong","Chuzhou","Dading","Dali","Daming","Datong","Daxing","Dean","Dengke","Dengzhou","Deqing","Dexing","Dihua","Dingli","Dongan","Dongchang","Dongchuan","Dongping","Duyun","Fengtian","Fengxiang","Fengyang","Fenzhou","Funing","Fuzhou","Ganzhou","Gaoyao","Gaozhou","Gongchang","Guangnan","Guangning","Guangping","Guangxin","Guangzhou","Guide","Guilin","Guiyang","Hailong","Hailun","Hangzhou","Hanyang","Hanzhong","Heihe","Hejian","Henan","Hengzhou","Hezhong","Huaian","Huaide","Huaiqing","Huanglong","Huangzhou","Huining","Huizhou","Hulan","Huzhou","Jiading","Jian","Jianchang","Jiande","Jiangning","Jiankang","Jianning","Jiaxing","Jiayang","Jilin","Jinan","Jingjiang","Jingzhao","Jingzhou","Jinhua","Jinzhou","Jiujiang","Kaifeng","Kaihua","Kangding","Kuizhou","Laizhou","Lanzhou","Leizhou","Liangzhou","Lianzhou","Liaoyang","Lijiang","Linan","Linhuang","Linjiang","Lintao","Liping","Liuzhou","Longan","Longjiang","Longqing","Longxing","Luan","Lubin","Lubin","Luzhou","Mishan","Nanan","Nanchang","Nandian","Nankang","Nanning","Nanyang","Nenjiang","Ningan","Ningbo","Ningguo","Ninguo","Ningwu","Ningxia","Ningyuan","Pingjiang","Pingle","Pingliang","Pingyang","Puer","Puzhou","Qianzhou","Qingyang","Qingyuan","Qingzhou","Qiongzhou","Qujing","Quzhou","Raozhou","Rende","Ruian","Ruizhou","Runing","Shafeng","Shajing","Shaoqing","Shaowu","Shaoxing","Shaozhou","Shinan","Shiqian","Shouchun","Shuangcheng","Shulei","Shunde","Shunqing","Shuntian","Shuoping","Sicheng","Sien","Sinan","Sizhou","Songjiang","Suiding","Suihua","Suining","Suzhou","Taian","Taibei","Tainan","Taiping","Taiwan","Taiyuan","Taizhou","Taonan","Tengchong","Tieli","Tingzhou","Tongchuan","Tongqing","Tongren","Tongzhou","Weihui","Wensu","Wenzhou","Wuchang","Wuding","Wuzhou","Xian","Xianchun","Xianping","Xijin","Xiliang","Xincheng","Xingan","Xingde","Xinghua","Xingjing","Xingqing","Xingyi","Xingyuan","Xingzhong","Xining","Xinmen","Xiping","Xuanhua","Xunzhou","Xuzhou","Yanan","Yangzhou","Yanji","Yanping","Yanqi","Yanzhou","Yazhou","Yichang","Yidu","Yilan","Yili","Yingchang","Yingde","Yingtian","Yingzhou","Yizhou","Yongchang","Yongping","Yongshun","Yongzhou","Yuanzhou","Yuezhou","Yulin","Yunnan","Yunyang","Zezhou","Zhangde","Zhangzhou","Zhaoqing","Zhaotong","Zhenan","Zhending","Zhengding","Zhenhai","Zhenjiang","Zhenxi","Zhenyun","Zhongshan","Zunyi"],
["Abira","Aga","Aikawa","Aizumisato","Ajigasawa","Akkeshi","Amagi","Ami","Anan","Ando","Asakawa","Ashikita","Bandai","Biratori","China","Chonan","Esashi","Fuchu","Fujimi","Funagata","Genkai","Godo","Goka","Gonohe","Gyokuto","Haboro","Hamatonbetsu","Happo","Harima","Hashikami","Hayashima","Heguri","Hidaka","Higashiagatsuma","Higashiura","Hiranai","Hirogawa","Hiroo","Hodatsushimizu","Hoki","Hokuei","Hokuryu","Horokanai","Ibigawa","Ichikai","Ichikawamisato","Ichinohe","Iide","Iijima","Iizuna","Ikawa","Inagawa","Itakura","Iwaizumi","Iwate","Kagamino","Kaisei","Kamifurano","Kamiita","Kamijima","Kamikawa","Kamikawa","Kamikawa","Kaminokawa","Kamishihoro","Kamitonda","Kamiyama","Kanda","Kanna","Kasagi","Kasuya","Katsuura","Kawabe","Kawagoe","Kawajima","Kawamata","Kawamoto","Kawanehon","Kawanishi","Kawara","Kawasaki","Kawasaki","Kawatana","Kawazu","Kihoku","Kikonai","Kin","Kiso","Kitagata","Kitajima","Kiyama","Kiyosato","Kofu","Koge","Kohoku","Kokonoe","Kora","Kosa","Kosaka","Kotohira","Kudoyama","Kumejima","Kumenan","Kumiyama","Kunitomi","Kurate","Kushimoto","Kutchan","Kyonan","Kyotamba","Mashike","Matsumae","Mifune","Mihama","Minabe","Minami","Minamiechizen","Minamioguni","Minamiosumi","Minamitane","Misaki","Misasa","Misato","Miyashiro","Miyoshi","Mori","Moseushi","Mutsuzawa","Nagaizumi","Nagatoro","Nagayo","Nagomi","Nakadomari","Nakanojo","Nakashibetsu","Nakatosa","Namegawa","Namie","Nanbu","Nanporo","Naoshima","Nasu","Niseko","Nishihara","Nishiizu","Nishikatsura","Nishikawa","Nishinoshima","Nishiwaga","Nogi","Noto","Nyuzen","Oarai","Obuse","Odai","Ogawara","Oharu","Oi","Oirase","Oishida","Oiso","Oizumi","Oji","Okagaki","Oketo","Okutama","Omu","Ono","Osaki","Osakikamijima","Otobe","Otsuki","Owani","Reihoku","Rifu","Rikubetsu","Rishiri","Rokunohe","Ryuo","Saka","Sakuho","Samani","Satsuma","Sayo","Saza","Setana","Shakotan","Shibayama","Shikama","Shimamoto","Shimizu","Shimokawa","Shintomi","Shirakawa","Shisui","Shitara","Sobetsu","Sue","Sumita","Suooshima","Suttsu","Tabuse","Tachiarai","Tadami","Tadaoka","Taiji","Taiki","Takachiho","Takahama","Taketoyo","Tako","Taragi","Tateshina","Tatsugo","Tawaramoto","Teshikaga","Tobe","Toin","Tokigawa","Toma","Tomioka","Tonosho","Tosa","Toyo","Toyokoro","Toyotomi","Toyoyama","Tsubata","Tsubetsu","Tsukigata","Tsunan","Tsuno","Tsuwano","Umi","Wakasa","Yamamoto","Yamanobe","Yamatsuri","Yanaizu","Yasuda","Yoichi","Yonaguni","Yoro","Yoshino","Yubetsu","Yugawara","Yuni","Yusuhara","Yuza"],
["Abrigada","Afonsoeiro","Agueda","Aguiar","Aguilada","Alagoas","Alagoinhas","Albufeira","Alcacovas","Alcanhoes","Alcobaca","Alcochete","Alcoutim","Aldoar","Alexania","Alfeizerao","Algarve","Alenquer","Almada","Almagreira","Almeirim","Alpalhao","Alpedrinha","Alvalade","Alverca","Alvor","Alvorada","Amadora","Amapa","Amieira","Anapolis","Anhangueira","Ansiaes","Apelacao","Aracaju","Aranhas","Arega","Areira","Araguaina","Araruama","Arganil","Armacao","Arouca","Asfontes","Assenceira","Avelar","Aveiro","Azambuja","Azinheira","Azueira","Bahia","Bairros","Balsas","Barcarena","Barreiras","Barreiro","Barretos","Batalha","Beira","Beja","Benavente","Betim","Boticas","Braga","Braganca","Brasilia","Brejo","Cabecao","Cabeceiras","Cabedelo","Cabofrio","Cachoeiras","Cadafais","Calheta","Calihandriz","Calvao","Camacha","Caminha","Campinas","Canidelo","Canha","Canoas","Capinha","Carmoes","Cartaxo","Carvalhal","Carvoeiro","Cascavel","Castanhal","Castelobranco","Caueira","Caxias","Chapadinha","Chaves","Celheiras","Cocais","Coimbra","Comporta","Coentral","Conde","Copacabana","Coqueirinho","Coruche","Corumba","Couco","Cubatao","Curitiba","Damaia","Doisportos","Douradilho","Dourados","Enxames","Enxara","Erada","Erechim","Ericeira","Ermidasdosado","Ervidel","Escalhao","Escariz","Esmoriz","Estombar","Espinhal","Espinho","Esposende","Esquerdinha","Estela","Estoril","Eunapolis","Evora","Famalicao","Famoes","Fanhoes","Fanzeres","Fatela","Fatima","Faro","Felgueiras","Ferreira","Figueira","Flecheiras","Florianopolis","Fornalhas","Fortaleza","Freiria","Freixeira","Frielas","Fronteira","Funchal","Fundao","Gaeiras","Gafanhadaboahora","Goa","Goiania","Gracas","Gradil","Grainho","Gralheira","Guarulhos","Guetim","Guimaraes","Horta","Iguacu","Igrejanova","Ilhavo","Ilheus","Ipanema","Iraja","Itaboral","Itacuruca","Itaguai","Itanhaem","Itapevi","Juazeiro","Lagos","Lavacolchos","Laies","Lamego","Laranjeiras","Leiria","Limoeiro","Linhares","Lisboa","Lomba","Lorvao","Lourencomarques","Lourical","Lourinha","Luziania","Macao","Macapa","Macedo","Machava","Malveira","Manaus","Mangabeira","Mangaratiba","Marambaia","Maranhao","Maringue","Marinhais","Matacaes","Matosinhos","Maxial","Maxias","Mealhada","Meimoa","Meires","Milharado","Mira","Miranda","Mirandela","Mogadouro","Montalegre","Montesinho","Moura","Mourao","Mozelos","Negroes","Neiva","Nespereira","Nilopolis","Niteroi","Nordeste","Obidos","Odemira","Odivelas","Oeiras","Oleiros","Olhao","Olhalvo","Olhomarinho","Olinda","Olival","Oliveira","Oliveirinha","Oporto","Ourem","Ovar","Palhais","Palheiros","Palmeira","Palmela","Palmital","Pampilhosa","Pantanal","Paradinha","Parelheiros","Paripueira","Paudalho","Pedrosinho","Penafiel","Peniche","Pedrogao","Pegoes","Pinhao","Pinheiro","Pinhel","Pombal","Pontal","Pontinha","Portel","Portimao","Poxim","Quarteira","Queijas","Queluz","Quiaios","Ramalhal","Reboleira","Recife","Redinha","Ribadouro","Ribeira","Ribeirao","Rosais","Roteiro","Sabugal","Sacavem","Sagres","Sandim","Sangalhos","Santarem","Santos","Sarilhos","Sarzedas","Satao","Satuba","Seixal","Seixas","Seixezelo","Seixo","Selmes","Sepetiba","Serta","Setubal","Silvares","Silveira","Sinhaem","Sintra","Sobral","Sobralinho","Sorocaba","Tabuacotavir","Tabuleiro","Taveiro","Teixoso","Telhado","Telheiro","Tomar","Torrao","Torreira","Torresvedras","Tramagal","Trancoso","Troviscal","Vagos","Valpacos","Varzea","Vassouras","Velas","Viana","Vidigal","Vidigueira","Vidual","Viladerei","Vilamar","Vimeiro","Vinhais","Vinhos","Viseu","Vitoria","Vlamao","Vouzela"],
["Acaltepec","Acaltepecatl","Acapulco","Acatlan","Acaxochitlan","Ajuchitlan","Atotonilco","Azcapotzalco","Camotlan","Campeche","Chalco","Chapultepec","Chiapan","Chiapas","Chihuahua","Cihuatlan","Cihuatlancihuatl","Coahuila","Coatepec","Coatlan","Coatzacoalcos","Colima","Colotlan","Coyoacan","Cuauhillan","Cuauhnahuac","Cuauhtemoc","Cuernavaca","Ecatepec","Epatlan","Guanajuato","Huaxacac","Huehuetlan","Hueyapan","Ixtapa","Iztaccihuatl","Iztapalapa","Jalisco","Jocotepec","Jocotepecxocotl","Matixco","Mazatlan","Michhuahcan","Michoacan","Michoacanmichin","Minatitlan","Naucalpan","Nayarit","Nezahualcoyotl","Oaxaca","Ocotepec","Ocotlan","Olinalan","Otompan","Popocatepetl","Queretaro","Sonora","Tabasco","Tamaulipas","Tecolotlan","Tenochtitlan","Teocuitlatlan","Teocuitlatlanteotl","Teotlalco","Teotlalcoteotl","Tepotzotlan","Tepoztlantepoztli","Texcoco","Tlachco","Tlalocan","Tlaxcala","Tlaxcallan","Tollocan","Tolutepetl","Tonanytlan","Tototlan","Tuchtlan","Tuxpan","Uaxacac","Xalapa","Xochimilco","Xolotlan","Yaotlan","Yopico","Yucatan","Yztac","Zacatecas","Zacualco"],
["Aba","Abadszalok","Abony","Adony","Ajak","Albertirsa","Alsozsolca","Aszod","Babolna","Bacsalmas","Baktaloranthaza","Balassagyarmat","Balatonalmadi","Balatonboglar","Balatonfured","Balatonfuzfo","Balkany","Balmazujvaros","Barcs","Bataszek","Batonyterenye","Battonya","Bekes","Berettyoujfalu","Berhida","Biatorbagy","Bicske","Biharkeresztes","Bodajk","Boly","Bonyhad","Budakalasz","Budakeszi","Celldomolk","Csakvar","Csenger","Csongrad","Csorna","Csorvas","Csurgo","Dabas","Demecser","Derecske","Devavanya","Devecser","Dombovar","Dombrad","Dorogullo","Dunafoldvar","Dunaharaszti","Dunavarsany","Dunavecse","Edeleny","Elek","Emod","Encs","Enying","Ercsi","Fegyvernek","Fehergyarmat","Felsozsolca","Fertoszentmiklos","Fonyod","Fot","Fuzesabony","Fuzesgyarmat","Gardony","God","Gyal","Gyomaendrod","Gyomro","Hajdudorog","Hajduhadhaz","Hajdunanas","Hajdusamson","Hajduszoboszlo","Halasztelek","Harkany","Hatvan","Heves","Heviz","Ibrany","Isaszeg","Izsak","Janoshalma","Janossomorja","Jaszapati","Jaszarokszallas","Jaszfenyszaru","Jaszkiser","Kaba","Kalocsa","Kapuvar","Karcag","Kecel","Kemecse","Kenderes","Kerekegyhaza","Kerepes","Keszthely","Kisber","Kiskoros","Kiskunmajsa","Kistarcsa","Kistelek","Kisujszallas","Kisvarda","Komadi","Komarom","Komlo","Kormend","Korosladany","Koszeg","Kozarmisleny","Kunhegyes","Kunszentmarton","Kunszentmiklos","Labatlan","Lajosmizse","Lenti","Letavertes","Letenye","Lorinci","Maglod","Mako","Mandok","Marcali","Martfu","Martonvasar","Mateszalka","Melykut","Mezobereny","Mezocsat","Mezohegyes","Mezokeresztes","Mezokovacshaza","Mezokovesd","Mezotur","Mindszent","Mohacs","Monor","Mor","Morahalom","Nadudvar","Nagyatad","Nagyecsed","Nagyhalasz","Nagykallo","Nagykata","Nagykoros","Nagymaros","Nyekladhaza","Nyergesujfalu","Nyiradony","Nyirbator","Nyirmada","Nyirtelek","Ocsa","Orkeny","Oroszlany","Paks","Pannonhalma","Paszto","Pecel","Pecsvarad","Pilis","Pilisvorosvar","Polgar","Polgardi","Pomaz","Puspokladany","Pusztaszabolcs","Putnok","Racalmas","Rackeve","Rakamaz","Rakoczifalva","Sajoszentpeter","Sandorfalva","Sarbogard","Sarkad","Sarospatak","Sarvar","Satoraljaujhely","Siklos","Simontornya","Solt","Soltvadkert","Sumeg","Szabadszallas","Szarvas","Szazhalombatta","Szecseny","Szeghalom","Szendro","Szentgotthard","Szentlorinc","Szerencs","Szigethalom","Szigetvar","Szikszo","Tab","Tamasi","Tapioszele","Tapolca","Tat","Tata","Teglas","Tet","Tiszacsege","Tiszafoldvar","Tiszafured","Tiszakecske","Tiszalok","Tiszaujvaros","Tiszavasvari","Tokaj","Tokol","Tolna","Tompa","Torokbalint","Torokszentmiklos","Totkomlos","Tura","Turkeve","Ujkigyos","ujszasz","Vamospercs","Varpalota","Vasarosnameny","Vasvar","Vecses","Velence","Veresegyhaz","Verpelet","Veszto","Zahony","Zalaszentgrot","Zirc","Zsambek"],
["Adapazari","Adiyaman","Afshin","Afyon","Ari","Akchaabat","Akchakale","Akchakoca","Akdamadeni","Akhisar","Aksaray","Akshehir","Alaca","Alanya","Alapli","Alashehir","Amasya","Anamur","Antakya","Ardeshen","Artvin","Aydin","Ayvalik","Babaeski","Bafra","Balikesir","Bandirma","Bartin","Bashiskele","Batman","Bayburt","Belen","Bergama","Besni","Beypazari","Beyshehir","Biga","Bilecik","Bingul","Birecik","Bismil","Bitlis","Bodrum","Bolu","Bolvadin","Bor","Bostanichi","Boyabat","Bozuyuk","Bucak","Bulancak","Bulanik","Burdur","Burhaniye","Chan","Chanakkale","Chankiri","Charshamba","Chaycuma","Chayeli","Chayirova","Cherkezkuy","Cheshme","Ceyhan","Ceylanpinar","Chine","Chivril","Cizre","Chorlu","Chumra","Dalaman","Darica","Denizli","Derik","Derince","Develi","Devrek","Didim","Dilovasi","Dinar","Diyadin","Diyarbakir","Doubayazit","Durtyol","Duzce","Duzichi","Edirne","Edremit","Elazi","Elbistan","Emirda","Erbaa","Ercish","Erdek","Erdemli","Ereli","Ergani","Erzin","Erzincan","Erzurum","Eskishehir","Fatsa","Fethiye","Gazipasha","Gebze","Gelibolu","Gerede","Geyve","Giresun","Guksun","Gulbashi","Gulcuk","Gurnen","Gumushhane","Guroymak","Hakkari","Harbiye","Havza","Hayrabolu","Hilvan","Idil","Idir","Ilgin","Imamolu","Incirliova","Inegul","Iskenderun","Iskilip","Islahiye","Isparta","Izmit","Iznik","Kadirli","Kahramanmarash","Kahta","Kaman","Kapakli","Karabuk","Karacabey","Karadeniz Ereli","Karakupru","Karaman","Karamursel","Karapinar","Karasu","Kars","Kartepe","Kastamonu","Kemer","Keshan","Kilimli","Kilis","Kirikhan","Kirikkale","Kirklareli","Kirshehir","Kiziltepe","Kurfez","Korkuteli","Kovancilar","Kozan","Kozlu","Kozluk","Kulu","Kumluca","Kurtalan","Kushadasi","Kutahya","Luleburgaz","Malatya","Malazgirt","Malkara","Manavgat","Manisa","Mardin","Marmaris","Mersin","Merzifon","Midyat","Milas","Mula","Muratli","Mush","Mut","Nazilli","Nevshehir","Nide","Niksar","Nizip","Nusaybin","udemish","Oltu","Ordu","Orhangazi","Ortaca","Osmancik","Osmaniye","Patnos","Payas","Pazarcik","Polatli","Reyhanli","Rize","Safranbolu","Salihli","Samanda","Samsun","Sandikli","shanliurfa","Saray","Sarikamish","Sarikaya","sharkishla","shereflikochhisar","Serik","Serinyol","Seydishehir","Siirt","Silifke","Silopi","Silvan","Simav","Sinop","shirnak","Sivas","Siverek","Surke","Soma","Sorgun","Suluova","Sungurlu","Suruch","Susurluk","Tarsus","Tatvan","Tavshanli","Tekirda","Terme","Tire","Tokat","Tosya","Trabzon","Tunceli","Turgutlu","Turhal","Unye","Ushak","Uzunkurpru","Van","Vezirkurpru","Viranshehir","Yahyali","Yalova","Yenishehir","Yerkury","Yozgat","Yuksekova","Zile","Zonguldak"],
["Abkhouch","Adrar","Agadir","Agelmam","Aghmat","Agrakal","Agulmam","Ahaggar","Almou","Anfa","Annaba","Aousja","Arbat","Argoub","Arif","Asfi","Assamer","Assif","Azaghar","Azmour","Azrou","Beccar","Beja","Bennour","Benslimane","Berkane","Berrechid","Bizerte","Bouskoura","Boutferda","Dar Bouazza","Darallouch","Darchaabane","Dcheira","Denden","Djebel","Djedeida","Drargua","Essaouira","Ezzahra","Fas","Fnideq","Ghezeze","Goubellat","Grisaffen","Guelmim","Guercif","Hammamet","Harrouda","Hoceima","Idurar","Ifendassen","Ifoghas","Imilchil","Inezgane","Izoughar","Jendouba","Kacem","Kelibia","Kenitra","Kerrando","Khalidia","Khemisset","Khenifra","Khouribga","Kidal","Korba","Korbous","Lahraouyine","Larache","Leyun","Lqliaa","Manouba","Martil","Mazagan","Mcherga","Mdiq","Megrine","Mellal","Melloul","Midelt","Mohammedia","Mornag","Mrrakc","Nabeul","Nadhour","Nador","Nawaksut","Nefza","Ouarzazate","Ouazzane","Oued Zem","Oujda","Ouladteima","Qsentina","Rades","Rafraf","Safi","Sefrou","Sejnane","Settat","Sijilmassa","Skhirat","Slimane","Somaa","Sraghna","Susa","Tabarka","Taferka","Tafza","Tagbalut","Tagerdayt","Takelsa","Tanja","Tantan","Taourirt","Taroudant","Tasfelalayt","Tattiwin","Taza","Tazerka","Tazizawt","Tebourba","Teboursouk","Temara","Testour","Tetouan","Tibeskert","Tifelt","Tinariwen","Tinduf","Tinja","Tiznit","Toubkal","Trables","Tubqal","Tunes","Urup","Watlas","Wehran","Wejda","Youssoufia","Zaghouan","Zahret","Zemmour","Zriba"],
["Abadilah","Abayt","Abha","Abud","Aden","Ahwar","Ajman","Alabadilah","Alabar","Alahjer","Alain","Alaraq","Alarish","Alarjam","Alashraf","Alaswaaq","Alawali","Albarar","Albawadi","Albirk","Aldhabiyah","Alduwaid","Alfareeq","Algayed","Alhada","Alhafirah","Alhamar","Alharam","Alharidhah","Alhawtah","Alhazim","Alhrateem","Alhudaydah","Alhujun","Alhuwaya","Aljahra","Aljohar","Aljubail","Alkawd","Alkhalas","Alkhawaneej","Alkhen","Alkhhafah","Alkhobar","Alkhuznah","Alkiranah","Allisafah","Allith","Almadeed","Almardamah","Almarwah","Almasnaah","Almejammah","Almojermah","Almshaykh","Almurjan","Almuwayh","Almuzaylif","Alnaheem","Alnashifah","Alqadeimah","Alqah","Alqahma","Alqalh","Alqouz","Alquaba","Alqunfudhah","Alqurayyat","Alradha","Alraqmiah","Alsadyah","Alsafa","Alshagab","Alshoqiq","Alshuqaiq","Alsilaa","Althafeer","Alwakrah","Alwasqah","Amaq","Amran","Annaseem","Aqbiyah","Arafat","Arar","Ardah","Arrawdah","Asfan","Ashayrah","Ashshahaniyah","Askar","Assaffaniyah","Ayaar","Aziziyah","Baesh","Bahrah","Baish","Balhaf","Banizayd","Baqaa","Baqal","Bidiyah","Bisha","Biyatah","Buqhayq","Burayda","Dafiyat","Damad","Dammam","Dariyah","Daynah","Dhafar","Dhahran","Dhalkut","Dhamar","Dhubab","Dhurma","Dibab","Dirab","Doha","Dukhan","Duwaibah","Enaker","Fadhla","Fahaheel","Fanateer","Farasan","Fardah","Fujairah","Ghalilah","Ghar","Ghizlan","Ghomgyah","Ghran","Hababah","Habil","Hadiyah","Haffah","Hajanbah","Hajrah","Halban","Haqqaq","Haradh","Hasar","Hathah","Hawarwar","Hawaya","Hawiyah","Hebaa","Hefar","Hijal","Husnah","Huwailat","Huwaitah","Irqah","Isharah","Ithrah","Jamalah","Jarab","Jareef","Jarwal","Jash","Jazan","Jeddah","Jiblah","Jihanah","Jilah","Jizan","Joha","Joraibah","Juban","Jubbah","Juddah","Jumeirah","Kamaran","Keyad","Khab","Khabtsaeed","Khaiybar","Khasab","Khathirah","Khawarah","Khulais","Khulays","Klayah","Kumzar","Limah","Linah","Mabar","Madrak","Mahab","Mahalah","Makhtar","Makshosh","Manfuhah","Manifah","Manshabah","Mareah","Masdar","Mashwar","Masirah","Maskar","Masliyah","Mastabah","Maysaan","Mazhar","Mdina","Meeqat","Mirbah","Mirbat","Mokhtara","Muharraq","Muladdah","Musandam","Musaykah","Muscat","Mushayrif","Musrah","Mussafah","Mutrah","Nafhan","Nahdah","Nahwa","Najran","Nakhab","Nizwa","Oman","Qadah","Qalhat","Qamrah","Qasam","Qatabah","Qawah","Qosmah","Qurain","Quraydah","Quriyat","Qurwa","Rabigh","Radaa","Rafha","Rahlah","Rakamah","Rasheedah","Rasmadrakah","Risabah","Rustaq","Ryadh","Saabah","Saabar","Sabtaljarah","Sabya","Sadad","Sadah","Safinah","Saham","Sahlat","Saihat","Salalah","Salmalzwaher","Salmiya","Sanaa","Sanaban","Sayaa","Sayyan","Shabayah","Shabwah","Shafa","Shalim","Shaqra","Sharjah","Sharkat","Sharurah","Shatifiyah","Shibam","Shidah","Shifiyah","Shihar","Shoqra","Shoqsan","Shuwaq","Sibah","Sihmah","Sinaw","Sirwah","Sohar","Suhailah","Sulaibiya","Sunbah","Tabuk","Taif","Taqah","Tarif","Tharban","Thumrait","Thuqbah","Thuwal","Tubarjal","Turaif","Turbah","Tuwaiq","Ubar","Umaljerem","Urayarah","Urwah","Wabrah","Warbah","Yabreen","Yadamah","Yafur","Yarim","Yemen","Yiyallah","Zabid","Zahwah","Zallaq","Zinjibar","Zulumah"],
["Aaluik","Aappilattoq","Aasiaat","Agdleruussakasit","Aggas","Akia","Akilia","Akuliaruseq","Akuliarutsip","Akunnaaq","Agissat","Agssaussat","Alluitsup","Alluttoq","Aluit","Aluk","Ammassalik","Amarortalik","Amitsorsuaq","Anarusuk","Angisorsuaq","Anguniartarfik","Annertussoq","Annikitsoq","Anoraliuirsoq","Appat","Apparsuit","Apusiaajik","Arsivik","Arsuk","Ataa","Atammik","Ateqanngitsorsuaq","Atilissuaq","Attu","Aukarnersuaq","Augpalugtoq, Aumat","Auvilikavsak","Auvilkikavsaup","Avadtlek","Avallersuaq","Bjornesk","Blabaerdalen","Blomsterdalen","Brattalhid","Bredebrae","Brededal","Claushavn","Edderfulegoer","Egger","Eqalugalinnguit","Eqalugarssuit","Eqaluit","Eqqua","Etah","Graah","Hakluyt","Haredalen","Hareoen","Hundeo","Igdlorssuit","Igaliku","Igdlugdlip","Igdluluarssuk","Iginniafik","Ikamiuk","Ikamiut","Ikarissat","Ikateq","Ikeq","Ikerasak","Ikerasaarsuk","Ikermiut","Ikermoissuaq","Ikertivaq","Ikorfarssuit","Ikorfat","Ilimanaq","Illorsuit","Iluileq","Iluiteq","Ilulissat","Illunnguit","Imaarsivik","Imartunarssuk","Immikkoortukajik","Innaarsuit","Ingjald","Inneruulalik","Inussullissuaq","Iqek","Ikerasakassak","Iperaq","Ippik","Isortok","Isungartussoq","Itileq","Itivdleq","Itissaalik","Ittit","Ittoqqortoormiit","Ivingmiut","Ivittuut","Kanajoorartuut","Kangaamiut","Kangaarsuk","Kangaatsiaq","Kangeq","Kangerluk","Kangerlussuaq","Kanglinnguit","Kapisillit","Karrat","Kekertamiut","Kiatak","Kiatassuaq","Kiataussaq","Kigatak","Kigdlussat","Kinaussak","Kingittorsuaq","Kitak","Kitsissuarsuit","Kitsissut","Klenczner","Kook","Kraulshavn","Kujalleq","Kullorsuaq","Kulusuk","Kuurmiit","Kuusuaq","Laksedalen","Maniitsoq","Marrakajik","Mattaangassut","Mernoq","Mittivakkat","Moriusaq","Myggbukta","Naajaat","Nako","Nangissat","Nanortalik","Nanuuseq","Nappassoq","Narsarmijt","Narssaq","Narsarsuaq","Narssarssuk","Nasaussaq","Nasiffik","Natsiarsiorfik","Naujanguit","Niaqornaarsuk","Niaqornat","Nordfjordspasset","Nugatsiaq","Nuluuk","Nunaa","Nunarssit","Nunarsuaq","Nunataaq","Nunatakavsaup","Nutaarmiut","Nuugaatsiaq","Nuuk","Nuukullak","Nuuluk","Nuussuaq","Olonkinbyen","Oqaatsut","Oqaitsúnguit","Oqonermiut","Oodaaq","Paagussat","Palungataq","Pamialluk","Paamiut","Paatuut","Patuersoq","Perserajoq","Paornivik","Pituffik","Puugutaa","Puulkuip","Qaanaq","Qaarsorsuaq","Qaarsorsuatsiaq","Qaasuitsup","Qaersut","Qajartalik","Qallunaat","Qaneq","Qaqaarissorsuaq","Qaqit","Qaqortok","Qasigiannguit","Qasse","Qassimiut","Qeertartivaq","Qeertartivatsiaq","Qeqertaq","Qeqertarssdaq","Qeqertarsuaq","Qeqertasussuk","Qeqertarsuatsiaat","Qeqertat","Qeqqata","Qernertoq","Qernertunnguit","Qianarreq","Qilalugkiarfik","Qingagssat","Qingaq","Qoornuup","Qorlortorsuaq","Qullikorsuit","Qunnerit","Qutdleq","Ravnedalen","Ritenbenk","Rypedalen","Sarfannguit","Saarlia","Saarloq","Saatoq","Saatorsuaq","Saatup","Saattut","Sadeloe","Salleq","Salliaruseq","Sammeqqat","Sammisoq","Sanningassoq","Saqqaq","Saqqarlersuaq","Saqqarliit","Sarqaq","Sattiaatteq","Savissivik","Serfanguaq","Sermersooq","Sermersut","Sermilik","Sermiligaaq","Sermitsiaq","Simitakaja","Simiutaq","Singamaq","Siorapaluk","Sisimiut","Sisuarsuit","Skal","Skarvefjeld","Skjoldungen","Storoen","Sullorsuaq","Suunikajik","Sverdrup","Taartoq","Takiseeq","Talerua","Tarqo","Tasirliaq","Tasiusak","Tiilerilaaq","Timilersua","Timmiarmiut","Tingmjarmiut","Traill","Tukingassoq","Tuttorqortooq","Tuujuk","Tuttulissuup","Tussaaq","Uigordlit","Uigorlersuaq","Uilortussoq","Uiivaq","Ujuaakajiip","Ukkusissat","Umanat","Upernavik","Upernattivik","Upepnagssivik","Upernivik","Uttorsiutit","Uumannaq","Uummannaarsuk","Uunartoq","Uvkusigssat","Ymer"],
["Abadio","Abaltzisketa","Abanto Zierbena","Aduna","Agurain","Aia","Aiara","Aizarnazabal","Ajangiz","Albiztur","Alegia","Alkiza","Alonsotegi","Altzaga","Altzo","Amezketa","Amorebieta","Amoroto","Amurrio","Andoain","Anoeta","Antzuola","Arakaldo","Arama","Aramaio","Arantzazu","Arbatzegi ","Areatza","Aretxabaleta","Arraia","Arrankudiaga","Arrasate","Arratzu","Arratzua","Arrieta","Arrigorriaga","Artea","Artzentales","Artziniega","Asparrena","Asteasu","Astigarraga","Ataun","Atxondo","Aulesti","Azkoitia","Azpeitia","Bakio","Baliarrain","Balmaseda","Barakaldo","Barrika","Barrundia","Basauri","Bastida","Beasain","Bedia","Beizama","Belauntza","Berango","Berantevilla","Berastegi","Bergara","Bermeo","Bernedo","Berriatua","Berriz","Berrobi","Bidania","Bilar","Bilbao","Burgelu","Busturia","Deba","Derio","Dima","Donemiliaga","Donostia","Dulantzi","Durango","Ea","Eibar","Elantxobe","Elduain","Elgeta","Elgoibar","Elorrio","Erandio","Ereo","Ermua","Errenteria","Errezil","Erribera Beitia","Erriberagoitia","Errigoiti","Eskoriatza","Eskuernaga","Etxebarri","Etxebarria","Ezkio","Fika","Forua","Fruiz","Gabiria","Gaintza","Galdakao","Galdames","Gamiz","Garai","Gasteiz","Gatika","Gatzaga","Gaubea","Gauna","Gautegiz Arteaga","Gaztelu","Gernika","Gerrikaitz","Getaria","Getxo","Gizaburuaga","Goiatz","Gordexola","Gorliz","Harana","Hernani","Hernialde","Hondarribia","Ibarra","Ibarrangelu","Idiazabal","Iekora","Igorre","Ikaztegieta","Irua Oka","Irun","Irura","Iruraiz","Ispaster","Itsaso","Itsasondo","Iurreta","Izurtza","Jatabe","Kanpezu","Karrantza Harana","Kortezubi","Kripan","Kuartango","Lanestosa","Lantziego","Larrabetzu","Larraul","Lasarte","Laudio","Laukiz","Lazkao","Leaburu","Legazpi","Legorreta","Legutio","Leintz","Leioa","Lekeitio","Lemoa","Lemoiz","Leza","Lezama","Lezo","Lizartza","Loiu","Lumo","Maaria","Maeztu","Mallabia","Markina","Maruri","Maueta","Meaka","Mendaro","Mendata","Mendexa","Moreda Araba","Morga","Mundaka","Mungia","Munitibar","Murueta","Muskiz","Mutiloa","Mutriku","Muxika","Nabarniz","Oati","Oiartzun","Oion","Okondo","Olaberria","Ondarroa","Ordizia","Orendain","Orexa","Oria","Orio","Ormaiztegi","Orozko","Ortuella","Otxandio","Pasaia","Plentzia","Portugalete","Samaniego","Santurtzi","Segura","Sestao","Sondika","Sopela","Sopuerta","Soraluze","Sukarrieta","Tolosa","Trapagaran","Turtzioz","Ubarrundia","Ubide","Ugao","Urdua","Urduliz","Urizaharra","Urkabustaiz","Urnieta","Urretxu","Usurbil","Xemein","Zaia","Zaldibar","Zaldibia","Zalduondo","Zambrana","Zamudio","Zaratamo","Zarautz","Zeanuri","Zeberio","Zegama","Zerain","Zestoa","Zierbena","Zigoitia","Ziortza","Zizurkil","Zuia","Zumaia","Zumarraga"],
["Abadogo","Abafon","Abdu","Acharu","Adaba","Adealesu","Adeto","Adyongo","Afaga","Afamju","Afuje","Agbelagba","Agigbigi","Agogoke","Ahute","Aiyelaboro","Ajebe","Ajola","Akarekwu","Akessan","Akunuba","Alawode","Alkaijji","Amangam","Amaoji","Amgbaye","Amtasa","Amunigun","Anase","Aniho","Animahun","Antul","Anyoko","Apekaa","Arapagi","Asamagidi","Asande","Ataibang","Awgbagba","Awhum","Awodu","Babanana","Babateduwa","Bagu","Bakura","Bandakwai","Bangdi","Barbo","Barkeje","Basa","Basabra","Basansagawa","Bieleshin","Bilikani","Birnindodo","Braidu","Bulakawa","Buriburi","Burisidna","Busum","Bwoi","Cainnan","Chakum","Charati","Chondugh","Dabibikiri","Dagwarga","Dallok","Danalili","Dandala","Darpi","Dhayaki","Dokatofa","Doma","Dozere","Duci","Dugan","Ebelibri","Efem","Efoi","Egudu","Egundugbo","Ekoku","Ekpe","Ekwere","Erhua","Eteu","Etikagbene","Ewhoeviri","Ewhotie","Ezemaowa","Fatima","Gadege","Galakura","Galea","Gamai","Gamen","Ganjin","Gantetudu","Garangamawa","Garema","Gargar","Gari","Garinbode","Garkuwa","Garu Kime","Gazabu","Gbure","Gerti","Gidan","Giringwe","Gitabaremu","Giyagiri","Giyawa","Gmawa","Golakochi","Golumba","Guchi","Gudugu","Gunji","Gusa","Gwambula","Gwamgwam","Gwodoti","Hayinlere","Hayinmaialewa","Hirishi","Hombo","Ibefum","Iberekodo","Ibodeipa","Icharge","Ideoro","Idofin","Idofinoka","Idya","Iganmeji","Igbetar","Igbogo","Ijoko","Ijuwa","Ikawga","Ikekogbe","Ikhin","Ikoro","Ikotefe","Ikotokpora","Ikpakidout","Ikpeoniong","Ilofa","Imuogo","Inyeneke","Iorsugh","Ipawo","Ipinlerere","Isicha","Itakpa","Itoki","Iyedeame","Jameri","Jangi","Jara","Jare","Jataudakum","Jaurogomki","Jepel","Jibam","Jirgu","Jirkange","Kafinmalama","Kamkem","Katab","Katanga","Katinda","Katirije","Kaurakimba","Keffinshanu","Kellumiri","Kiagbodor","Kibiare","Kingking","Kirbutu","Kita","Kogbo","Kogogo","Kopje","Koriga","Koroko","Korokorosei","Kotoku","Kuata","Kujum","Kukau","Kunboon","Kuonubogbene","Kurawe","Kushinahu","Kwaramakeri","Ladimeji","Lafiaro","Lahaga","Laindebajanle","Laindegoro","Lajere","Lakati","Ligeri","Litenswa","Lokobimagaji","Lusabe","Maba","Madarzai","Magoi","Maialewa","Maianita","Maijuja","Mairakuni","Maleh","Malikansaa","Mallamkola","Mallammaduri","Marmara","Masagu","Masoma","Mata","Matankali","Mbalare","Megoyo","Meku","Miama","Mige","Mkporagwu","Modi","Molafa","Mshi","Msugh","Muduvu","Murnachehu","Namnai","Nanumawa","Nasudu","Ndagawo","Ndamanma","Ndiebeleagu","Ndiwulunbe","Ndonutim","Ngaruwa","Ngbande","Nguengu","Nto Ekpe","Nubudi","Nyajo","Nyido","Nyior","Obafor","Obazuwa","Odajie","Odiama","Ofunatam","Ogali","Ogan","Ogbaga","Ogbahu","Ogultu","Ogunbunmi","Ogunmakin","Ojaota","Ojirami","Ojopode","Okehin","Olugunna","Omotunde","Onipede","Onisopi","Onma","Orhere","Orya","Oshotan","Otukwang","Otunade","Pepegbene","Poros","Rafin","Rampa","Rimi","Rinjim","Robertkiri","Rugan","Rumbukawa","Sabiu","Sabon","Sabongari","Sai","Salmatappare","Sangabama","Sarabe","Seboregetore","Seibiri","Sendowa","Shafar","Shagwa","Shata","Shefunda","Shengu","Sokoron","Sunnayu","Taberlma","Tafoki","Takula","Talontan","Taraku","Tarhemba","Tayu","Ter","Timtim","Timyam","Tindirke","Tirkalou","Tokunbo","Tonga","Torlwam","Tseakaadza","Tseanongo","Tseavungu","Tsebeeve","Tsekov","Tsepaegh","Tuba","Tumbo","Tungalombo","Tungamasu","Tunganrati","Tunganyakwe","Tungenzuri","Ubimimi","Uhkirhi","Umoru","Umuabai","Umuaja","Umuajuju","Umuimo","Umuojala","Unchida","Ungua","Unguwar","Unongo","Usha","Ute","Utongbo","Vembera","Vorokotok","Wachin","Walebaga","Wurawura","Wuro","Yanbashi","Yanmedi","Yenaka","Yoku","Zamangera","Zarunkwari","Zilumo","Zulika"],
["Aberaman","Aberangell","Aberarth","Aberavon","Aberbanc","Aberbargoed","Aberbeeg","Abercanaid","Abercarn","Abercastle","Abercegir","Abercraf","Abercregan","Abercych","Abercynon","Aberdare","Aberdaron","Aberdaugleddau","Aberdeen","Aberdulais","Aberdyfi","Aberedw","Abereiddy","Abererch","Abereron","Aberfan","Aberffraw","Aberffrwd","Abergavenny","Abergele","Aberglasslyn","Abergorlech","Abergwaun","Abergwesyn","Abergwili","Abergwynfi","Abergwyngregyn","Abergynolwyn","Aberhafesp","Aberhonddu","Aberkenfig","Aberllefenni","Abermain","Abermaw","Abermorddu","Abermule","Abernant","Aberpennar","Aberporth","Aberriw","Abersoch","Abersychan","Abertawe","Aberteifi","Aberthin","Abertillery","Abertridwr","Aberystwyth","Achininver","Afonhafren","Alisaha","Antinbhearmor","Ardenna","Attacon","Beira","Bhrura","Boioduro","Bona","Boudobriga","Bravon","Brigant","Briganta","Briva","Cambodunum","Cambra","Caracta","Catumagos","Centobriga","Ceredigion","Chalain","Dinn","Diwa","Dubingen","Duro","Ebora","Ebruac","Eburodunum","Eccles","Eighe","Eireann","Ferkunos","Genua","Ghrainnse","Inbhear","Inbhir","Inbhirair","Innerleithen","Innerleven","Innerwick","Inver","Inveraldie","Inverallan","Inveralmond","Inveramsay","Inveran","Inveraray","Inverarnan","Inverbervie","Inverclyde","Inverell","Inveresk","Inverfarigaig","Invergarry","Invergordon","Invergowrie","Inverhaddon","Inverkeilor","Inverkeithing","Inverkeithney","Inverkip","Inverleigh","Inverleith","Inverloch","Inverlochlarig","Inverlochy","Invermay","Invermoriston","Inverness","Inveroran","Invershin","Inversnaid","Invertrossachs","Inverugie","Inveruglas","Inverurie","Kilninver","Kirkcaldy","Kirkintilloch","Krake","Latense","Leming","Lindomagos","Llanaber","Lochinver","Lugduno","Magoduro","Monmouthshire","Narann","Novioduno","Nowijonago","Octoduron","Penning","Pheofharain","Ricomago","Rossinver","Salodurum","Seguia","Sentica","Theorsa","Uige","Vitodurum","Windobona"],
["Adab","Akkad","Akshak","Amnanum","Arbid","Arpachiyah","Arrapha","Assur","Babilim","Badtibira","Balawat","Barsip","Borsippa","Carchemish","Chagar Bazar","Chuera","Ctesiphon ","Der","Dilbat","Diniktum","Doura","Durkurigalzu","Ekallatum","Emar","Erbil","Eridu","Eshnunn","Fakhariya ","Gawra","Girsu","Hadatu","Hamoukar","Haradum","Harran","Hatra","Idu","Irisagrig","Isin","Jemdet","Kahat","Kartukulti","Khaiber","Kish ","Kisurra","Kuara","Kutha","Lagash","Larsa ","Leilan","Marad","Mardaman","Mari","Mashkan","Mumbaqat ","Nabada","Nagar","Nerebtum","Nimrud","Nineveh","Nippur","Nuzi","Qalatjarmo","Qatara","Rawda","Seleucia","Shaduppum","Shanidar","Sharrukin","Shemshara","Shibaniba","Shuruppak","Sippar","Tarbisu","Tellagrab","Tellessawwan","Tellessweyhat","Tellhassuna","Telltaya","Telul","Terqa","Thalathat","Tutub","Ubaid ","Umma","Ur","Urfa","Urkesh","Uruk","Urum","Zabalam","Zenobia"],
["Abali","Abrisham","Absard","Abuzeydabad","Afus","Alavicheh","Alikosh","Amol","Anarak","Anbar","Andisheh","Anshan","Aran","Ardabil","Arderica","Ardestan","Arjomand","Asgaran","Asgharabad","Ashian","Awan","Babajan","Badrud","Bafran","Baghestan","Baghshad","Bahadoran","Baharan Shahr","Baharestan","Bakun","Bam","Baqershahr","Barzok","Bastam","Behistun","Bitistar","Bumahen","Bushehr","Chadegan","Chahardangeh","Chamgardan","Chermahin","Choghabonut","Chugan","Damaneh","Damavand","Darabgard","Daran","Dastgerd","Dehaq","Dehaqan","Dezful","Dizicheh","Dorcheh","Dowlatabad","Duruntash","Ecbatana","Eslamshahr","Estakhr","Ezhiyeh","Falavarjan","Farrokhi","Fasham","Ferdowsieh","Fereydunshahr","Ferunabad","Firuzkuh","Fuladshahr","Ganjdareh","Ganzak","Gaz","Geoy","Godin","Goldasht","Golestan","Golpayegan","Golshahr","Golshan","Gorgab","Guged","Habibabad","Hafshejan","Hajjifiruz","Hana","Harand","Hasanabad","Hasanlu","Hashtgerd","Hecatompylos","Hormirzad","Imanshahr","Isfahan","Jandaq","Javadabad","Jiroft","Jowsheqan ","Jowzdan","Kabnak","Kahriz Sang","Kahrizak","Kangavar","Karaj","Karkevand","Kashan","Kelishad","Kermanshah","Khaledabad","Khansar","Khorramabad","Khur","Khvorzuq","Kilan","Komeh","Komeshcheh","Konar","Kuhpayeh","Kul","Kushk","Lavasan","Laybid","Liyan","Lyan","Mahabad","Mahallat","Majlesi","Malard","Manzariyeh","Marlik","Meshkat","Meymeh","Miandasht","Mish","Mobarakeh","Nahavand","Nain","Najafabad","Naqshe","Narezzash","Nasimshahr","Nasirshahr","Nasrabad","Natanz","Neyasar","Nikabad","Nimvar","Nushabad","Pakdasht","Parand","Pardis","Parsa","Pasargadai","Patigrabana","Pir Bakran","Pishva","Qahderijan","Qahjaverestan","Qamsar","Qarchak","Qods","Rabat","Ray-shahr","Rezvanshahr","Rhages","Robat Karim","Rozveh","Rudehen","Sabashahr","Safadasht","Sagzi","Salehieh","Sandal","Sarvestan","Sedeh","Sefidshahr","Semirom","Semnan","Shadpurabad","Shah","Shahdad","Shahedshahr","Shahin","Shahpour","Shahr","Shahreza","Shahriar","Sharifabad","Shemshak","Shiraz","Shushan","Shushtar","Sialk","Sin","Sukhteh","Tabas","Tabriz","Takhte","Talkhuncheh","Talli","Tarq","Temukan","Tepe","Tiran","Tudeshk","Tureng","Urmia","Vahidieh","Vahrkana","Vanak","Varamin","Varnamkhast","Varzaneh","Vazvan","Yahya","Yarim","Yasuj","Zarrin Shahr","Zavareh","Zayandeh","Zazeran","Ziar","Zibashahr","Zranka"],
["Aapueo","Ahoa","Ahuakaio","Ahuakamalii","Ahuakeio","Ahupau","Aki","Alaakua","Alae","Alaeloa","Alaenui","Alamihi","Aleamai","Alena","Alio","Aupokopoko","Auwahi","Hahakea","Haiku","Halakaa","Halehaku","Halehana","Halemano","Haleu","Haliimaile","Hamakuapoko","Hamoa","Hanakaoo","Hanaulu","Hanawana","Hanehoi","Haneoo","Haou","Hikiaupea","Hoalua","Hokuula","Honohina","Honokahua","Honokala","Honokalani","Honokeana","Honokohau","Honokowai","Honolua","Honolulu","Honolulunui","Honomaele","Honomanu","Hononana","Honopou","Hoolawa","Hopenui","Hualele","Huelo","Hulaia","Ihuula","Ilikahi","Interisland","Kaalaea","Kaalelehinale","Kaapahu","Kaehoeho","Kaeleku","Kaeo","Kahakuloa","Kahalawe","Kahalawe","Kahalehili","Kahana","Kahilo","Kahuai","Kaiaula","Kailihiakoko","Kailua","Kainehe","Kakalahale","Kakanoni","Kakio","Kakiweka","Kalena","Kalenanui","Kaleoaihe","Kalepa","Kaliae","Kalialinui","Kalihi","Kalihi","Kalihi","Kalimaohe","Kaloi","Kamani","Kamaole","Kamehame","Kanahena","Kanaio","Kaniaula","Kaonoulu","Kaopa","Kapaloa","Kapaula","Kapewakua","Kapohue","Kapuaikini","Kapunakea","Kapuuomahuka","Kauau","Kauaula","Kaukuhalahala","Kaulalo","Kaulanamoa","Kauluohana","Kaumahalua","Kaumakani","Kaumanu","Kaunauhane","Kaunuahane","Kaupakulua","Kawaipapa","Kawaloa","Kawaloa","Kawalua","Kawela","Keaa","Keaalii","Keaaula","Keahua","Keahuapono","Keakuapauaela","Kealahou","Keanae","Keauhou","Kekuapawela","Kelawea","Keokea","Keopuka","Kepio","Kihapuhala","Kikoo","Kilolani","Kipapa","Koakupuna","Koali","Koananai","Koheo","Kolea","Kolokolo","Kooka","Kopili","Kou","Kualapa","Kuhiwa","Kuholilea","Kuhua","Kuia","Kuiaha","Kuikui","Kukoae","Kukohia","Kukuiaeo","Kukuioolu","Kukuipuka","Kukuiula","Kulahuhu","Kumunui","Lapakea","Lapalapaiki","Lapueo","Launiupoko","Loiloa","Lole","Lualailua","Maalo","Mahinahina","Mahulua","Maiana","Mailepai","Makaakini","Makaalae","Makaehu","Makaiwa","Makaliua","Makapipi","Makapuu","Makawao","Makila","Mala","Maluaka","Mamalu","Manawaiapiki","Manawainui","Maulili","Mehamenui","Miana","Mikimiki","Moalii","Moanui","Mohopili","Mohopilo","Mokae","Mokuia","Mokupapa","Mooiki","Mooloa","Moomuku","Muolea","Nahuakamalii","Nailiilipoko","Nakaaha","Nakalepo","Nakaohu","Nakapehu","Nakula","Napili","Niniau","Niumalu","Nuu","Ohia","Oloewa","Olowalu","Omaopio","Onau","Onouli","Opaeula","Opana","Opikoula","Paakea","Paeahu","Paehala","Paeohi","Pahoa","Paia","Pakakia","Pakala","Palauea","Palemo","Panaewa","Paniau","Papaaea","Papaanui","Papaauhau","Papahawahawa","Papaka","Papauluana","Pauku","Paunau","Pauwalu","Pauwela","Peahi","Piapia","Pohakanele","Pohoula","Polaiki","Polanui","Polapola","Polua","Poopoo","Popoiwi","Popoloa","Poponui","Poupouwela","Puaa","Puaaluu","Puahoowali","Puakea","Puako","Pualaea","Puehuehu","Puekahi","Pueokauiki","Pukaauhuhu","Pukalani","Pukuilua","Pulehu","Pulehuiki","Pulehunui","Punaluu","Puolua","Puou","Puuhaehae","Puuhaoa","Puuiki","Puuki","Puukohola","Puulani","Puumaneoneo","Puunau","Puunoa","Puuomaiai","Puuomaile","Uaoa","Uhao","Ukumehame","Ulaino","Ulumalu","Unknown","Various","Wahikuli","Waiahole","Waiakoa","Waianae","Waianu","Waiawa","Waiehu","Waieli","Waihee","Waikapu","Wailamoa","Wailaulau","Wailua","Wailuku","Wainee","Waiohole","Waiohonu","Waiohue","Waiohuli","Waiokama","Waiokila","Waiopai","Waiopua","Waipao","Waipio","Waipioiki","Waipionui","Waipouli","Wakiu","Wananalua"],
["Adityapatna","Adyar","Afzalpur","Aland","Alnavar","Alur","Ambikanagara","Anekal","Ankola","Annigeri","Arkalgud","Arsikere","Athni","Aurad","Badami","Bagalkot","Bagepalli","Bail","Bajpe","Bangalore","Bangarapet","Bankapura","Bannur","Bantval","Basavakalyan","Basavana","Belgaum","Beltangadi","Belur","Bhadravati","Bhalki","Bhatkal","Bhimarayanagudi","Bidar","Bijapur","Bilgi","Birur","Bommasandra","Byadgi","Challakere","Chamarajanagar","Channagiri","Channapatna","Channarayapatna","Chik","Chikmagalur","Chiknayakanhalli","Chikodi","Chincholi","Chintamani","Chitapur","Chitgoppa","Chitradurga","Dandeli","Dargajogihalli","Devadurga","Devanahalli","Dod","Donimalai","Gadag","Gajendragarh","Gangawati","Gauribidanur","Gokak","Gonikoppal","Gubbi","Gudibanda","Gulbarga","Guledgudda","Gundlupet","Gurmatkal","Haliyal","Hangal","Harapanahalli","Harihar","Hassan","Hatti","Haveri","Hebbagodi","Heggadadevankote","Hirekerur","Holalkere","Hole","Homnabad","Honavar","Honnali","Hoovina","Hosakote","Hosanagara","Hosdurga","Hospet","Hubli","Hukeri","Hungund","Hunsur","Ilkal","Indi","Jagalur","Jamkhandi","Jevargi","Jog","Kadigenahalli","Kadur","Kalghatgi","Kamalapuram","Kampli","Kanakapura","Karkal","Karwar","Khanapur","Kodiyal","Kolar","Kollegal","Konnur","Koppa","Koppal","Koratagere","Kotturu","Krishnarajanagara","Krishnarajasagara","Krishnarajpet","Kudchi","Kudligi","Kudremukh","Kumta","Kundapura","Kundgol","Kunigal","Kurgunta","Kushalnagar","Kushtagi","Lakshmeshwar","Lingsugur","Londa","Maddur","Madhugiri","Madikeri","Mahalingpur","Malavalli","Mallar","Malur","Mandya","Mangalore","Manvi","Molakalmuru","Mudalgi","Mudbidri","Muddebihal","Mudgal","Mudhol","Mudigere","Mulbagal","Mulgund","Mulki","Mulur","Mundargi","Mundgod","Munirabad","Mysore","Nagamangala","Nanjangud","Narasimharajapura","Naregal","Nargund","Navalgund","Nipani","Pandavapura","Pavagada","Piriyapatna","Pudu","Puttur","Rabkavi","Raichur","Ramanagaram","Ramdurg","Ranibennur","Raybag","Robertson","Ron","Sadalgi","Sagar","Sakleshpur","Saligram","Sandur","Sankeshwar","Saundatti","Savanur","Sedam","Shahabad","Shahpur","Shaktinagar","Shiggaon","Shikarpur","Shirhatti","Shorapur","Shrirangapattana","Siddapur","Sidlaghatta","Sindgi","Sindhnur","Sira","Siralkoppa","Sirsi","Siruguppa","Somvarpet","Sorab","Sringeri","Srinivaspur","Sulya","Talikota","Tarikere","Tekkalakote","Terdal","Thumbe","Tiptur","Tirthahalli","Tirumakudal","Tumkur","Turuvekere","Udupi","Vijayapura","Wadi","Yadgir","Yelandur","Yelbarga","Yellapur","Yenagudde"],
["Altomisayoq","Ancash","Andahuaylas","Apachekta","Apachita","Apu ","Apurimac","Arequipa","Atahuallpa","Atawalpa","Atico","Ayacucho","Ayllu","Cajamarca","Carhuac","Carhuacatac","Cashan","Caullaraju","Caxamalca","Cayesh","Chacchapunta","Chacraraju","Champara","Chanchan","Chekiacraju","Chinchey","Chontah","Chopicalqui","Chucuito","Chuito","Chullo","Chumpi","Chuncho","Chuquiapo","Churup","Cochapata","Cojup","Collota","Conococha","Copa","Corihuayrachina","Cusichaca","Despacho","Haika","Hanpiq","Hatun","Haywarisqa","Huaca","Hualcan","Huamanga","Huamashraju","Huancarhuas","Huandoy","Huantsan","Huarmihuanusca","Huascaran","Huaylas","Huayllabamba","Huichajanca","Huinayhuayna","Huinioch","Illiasca","Intipunku","Ishinca","Jahuacocha","Jirishanca","Juli","Jurau","Kakananpunta","Kamasqa","Karpay","Kausay","Khuya ","Kuelap","Llaca","Llactapata","Llanganuco","Llaqta","Llupachayoc","Machu","Mallku","Matarraju","Mikhuy","Milluacocha","Munay","Ocshapalca","Ollantaytambo","Pacamayo","Paccharaju","Pachacamac","Pachakamaq","Pachakuteq","Pachakuti","Pachamama  ","Paititi","Pajaten","Palcaraju","Pampa","Panaka","Paqarina","Paqo","Parap","Paria","Patallacta","Phuyupatamarca","Pisac","Pongos","Pucahirca","Pucaranra","Puscanturpa","Putaca","Qawaq ","Qayqa","Qochamoqo","Qollana","Qorihuayrachina","Qorimoqo","Quenuaracra","Queshque","Quillcayhuanca","Quillya","Quitaracsa","Quitaraju","Qusqu","Rajucolta","Rajutakanan","Rajutuna","Ranrahirca","Ranrapalca","Raria","Rasac","Rimarima","Riobamba","Runkuracay","Rurec","Sacsa","Saiwa","Sarapo","Sayacmarca","Sinakara","TamboColorado","Tamboccocha","Taripaypacha","Taulliraju","Tawantinsuyu","Taytanchis","Tiwanaku","Tocllaraju","Tsacra","Tuco","Tullparaju","Tumbes","Ulta","Uruashraju","Vallunaraju","Vilcabamba","Wacho ","Wankawillka","Wayra","Yachay","Yahuarraju","Yanamarey","Yanesha","Yerupaja"],
["Abim","Adjumani","Alebtong","Amolatar","Amuria","Amuru","Apac","Arua","Arusha","Babati","Baragoi","Bombo","Budaka","Bugembe","Bugiri","Buikwe","Bukedea","Bukoba","Bukomansimbi","Bukungu","Buliisa","Bundibugyo","Bungoma","Busembatya","Bushenyi","Busia","Busia","Busolwe","Butaleja","Butambala","Butere","Buwenge","Buyende","Dadaab","Dodoma","Dokolo","Eldoret","Elegu","Emali","Embu","Entebbe","Garissa","Gede","Gulu","Handeni","Hima","Hoima","Hola","Ibanda","Iganga","Iringa","Isingiro","Isiolo","Jinja","Kaabong","Kabale","Kaberamaido","Kabuyanda","Kabwohe","Kagadi","Kahama","Kajiado","Kakamega","Kakinga","Kakira","Kakiri","Kakuma","Kalangala","Kaliro","Kalisizo","Kalongo","Kalungu","Kampala","Kamuli","Kamwenge","Kanoni","Kanungu","Kapchorwa","Kapenguria","Kasese","Kasulu","Katakwi","Kayunga","Kericho","Keroka","Kiambu","Kibaale","Kibaha","Kibingo","Kiboga","Kibwezi","Kigoma","Kihiihi","Kilifi","Kira","Kiruhura","Kiryandongo","Kisii","Kisoro","Kisumu","Kitale","Kitgum","Kitui","Koboko","Korogwe","Kotido","Kumi","Kyazanga","Kyegegwa","Kyenjojo","Kyotera","Lamu","Langata","Lindi","Lodwar","Lokichoggio","Londiani","Loyangalani","Lugazi","Lukaya","Luweero","Lwakhakha","Lwengo","Lyantonde","Machakos","Mafinga","Makambako","Makindu","Malaba","Malindi","Manafwa","Mandera","Maralal","Marsabit","Masaka","Masindi","MasindiPort","Masulita","Matugga","Mayuge","Mbale","Mbarara","Mbeya","Meru","Mitooma","Mityana","Mombasa","Morogoro","Moroto","Moshi","Moyale","Moyo","Mpanda","Mpigi","Mpondwe","Mtwara","Mubende","Mukono","Mumias","Muranga","Musoma","Mutomo","Mutukula","Mwanza","Nagongera","Nairobi","Naivasha","Nakapiripirit","Nakaseke","Nakasongola","Nakuru","Namanga","Namayingo","Namutumba","Nansana","Nanyuki","Narok","Naromoru","Nebbi","Ngora","Njeru","Njombe","Nkokonjeru","Ntungamo","Nyahururu","Nyeri","Oyam","Pader","Paidha","Pakwach","Pallisa","Rakai","Ruiru","Rukungiri","Rwimi","Sanga","Sembabule","Shimoni","Shinyanga","Singida","Sironko","Songea","Soroti","Ssabagabo","Sumbawanga","Tabora","Takaungu","Tanga","Thika","Tororo","Tunduma","Vihiga","Voi","Wajir","Wakiso","Watamu","Webuye","Wobulenzi","Wote","Wundanyi","Yumbe","Zanzibar"],
["An Khe","An Nhon","Ayun Pa","Ba Don","Ba Ria","Bac Giang","Bac Kan","Bac Lieu","Bac Ninh","Bao Loc","Ben Cat","Ben Tre","Bien Hoa","Bim Son","Binh Long","Binh Minh","Buon Ho","Buon Ma Thuot","Ca Mau","Cai Lay","Cam Pha","Cam Ranh","Can Tho","Cao Bang","Cao Lanh","Chau Doc","Chi Linh","Cua Lo","Da Lat","Da Nang","Di An","Dien Ban","Dien Bien Phu","Dong Ha","Dong Hoi","Dong Trieu","Duyen Hai","Gia Nghia","Gia Rai","Go Cong","Ha Giang","Ha Long","Ha Noi","Ha Tinh","Hai Duong","Hai Phong","Hoa Binh","Hoang Mai","Hoi An","Hong Linh","Hong Ngu","Hue","Hung Yen","Huong Thuy","Huong Tra","Kien Tuong","Kon Tum","Ky Anh","La Gi","Lai Chau","Lang Son","Lao Cai","Long Khanh","Long My","Long Xuyen","Mong Cai","Muong Lay","My Hao","My Tho","Nam Dinh","Nga Bay","Nga Nam","Nghia Lo","Nha Trang","Ninh Binh","Ninh Hoa","Phan Rang Thap Cham","Phan Thiet","Pho Yen","Phu Ly","Phu My","Phu Tho","Phuoc Long","Pleiku","Quang Ngai","Quang Tri","Quang Yen","Quy Nhon","Rach Gia","Sa Dec","Sam Son","Soc Trang","Son La","Son Tay","Song Cau","Song Cong","Tam Diep","Tam Ky","Tan An","Tan Chau","Tan Uyen","Tay Ninh","Thai Binh","Thai Hoa","Thai Nguyen","Thanh Hoa","Thu Dau Mot","Thuan An","Tra Vinh","Tu Son","Tuy Hoa","Tuyen Quang","Uong Bi","Vi Thanh","Viet Tri","Vinh","Vinh Chau","Vinh Long","Vinh Yen","Vung Tau","Yen Bai"],
["Chaiwan", "Chekham", "Cheungshawan", "Chingchung", "Chinghoi", "Chingsen", "Chingshing", "Chiunam", "Chiuon", "Chiuyeung", "Chiyuen", "Choihung", "Chuehoi", "Chuiman", "Chungfa", "Chungfu", "Chungsan", "Chunguktsuen", "Dakhing", "Daopo", "Daumun", "Dingwu", "Dinpak", "Donggun", "Dongyuen", "Duenchau", "Fachau", "Fado", "Fanling", "Fatgong", "Fatshan", "Fotan", "Fuktien", "Fumun", "Funggong", "Funghoi", "Fungshun", "Fungtei", "Gamtin", "Gochau", "Goming", "Gonghoi", "Gongshing", "Goyiu", "Hanghau", "Hangmei", "Hashan", "Hengfachuen", "Hengon", "Heungchau", "Heunggong", "Heungkiu", "Hingning", "Hohfuktong", "Hoichue", "Hoifung", "Hoiping", "Hokong", "Hokshan", "Homantin", "Hotin", "Hoyuen", "Hunghom", "Hungshuikiu", "Jiuling", "Kamping", "Kamsheung", "Kamwan", "Kaulongtong", "Keilun", "Kinon", "Kinsang", "Kityeung", "Kongmun", "Kukgong", "Kwaifong", "Kwaihing", "Kwongchau", "Kwongling", "Kwongming", "Kwuntong", "Laichikok", "Laiking", "Laiwan", "Lamtei", "Lamtin", "Leitung", "Leungking", "Limkong", "Linchau", "Linnam", "Linping", "Linshan", "Loding", "Lokcheong", "Lokfu", "Lokmachau", "Longchuen", "Longgong", "Longmun", "Longping", "Longwa", "Longwu", "Lowu", "Luichau", "Lukfung", "Lukho", "Lungmun", "Macheung", "Maliushui", "Maonshan", "Mauming", "Maunam", "Meifoo", "Mingkum", "Mogong", "Mongkok", "Muichau", "Muigong", "Muiyuen", "Naiwai", "Namcheong", "Namhoi", "Namhong", "Namo", "Namsha", "Namshan", "Nganwai", "Ngchuen", "Ngoumun", "Ngwa", "Nngautaukok", "Onting", "Pakwun", "Paotoishan", "Pingshan", "Pingyuen", "Poklo", "Polam", "Pongon", "Poning", "Potau", "Puito", "Punyue", "Saiwanho", "Saiyingpun", "Samshing", "Samshui", "Samtsen", "Samyuenlei", "Sanfung", "Sanhing", "Sanhui", "Sanwai", "Sanwui", "Seiwui", "Shamshuipo", "Shanmei", "Shantau", "Shatin", "Shatinwai", "Shaukeiwan", "Shauking", "Shekkipmei", "Shekmun", "Shekpai", "Sheungshui", "Shingkui", "Shiuhing", "Shundak", "Shunyi", "Shupinwai", "Simshing", "Siuhei", "Siuhong", "Siukwan", "Siulun", "Suikai", "Taihing", "Taikoo", "Taipo", "Taishuihang", "Taiwai", "Taiwo", "Taiwohau", "Tinhau", "Tinho", "Tinking", "Tinshuiwai", "Tiukengleng", "Toishan", "Tongfong", "Tonglowan", "Tsakyoochung", "Tsamgong", "Tsangshing", "Tseungkwano", "Tsihing", "Tsimshatsui", "Tsinggong", "Tsingshantsuen", "Tsingwun", "Tsingyi", "Tsingyuen", "Tsiuchau", "Tsuenshekshan", "Tsuenwan", "Tuenmun", "Tungchung", "Waichap", "Waichau", "Waidong", "Wailoi", "Waishing", "Waiyeung", "Wanchai", "Wanfau", "Wanon", "Wanshing", "Wingon", "Wongchukhang", "Wongpo", "Wongtaisin", "Woping", "Wukaisha", "Yano", "Yaumatei", "Yauoi", "Yautong", "Yenfa", "Yeungchun", "Yeungdong", "Yeunggong", "Yeungsai", "Yeungshan", "Yimtin", "Yingdak", "Yiuping", "Yongshing", "Yongyuen", "Yuenlong", "Yuenshing", "Yuetsau", "Yuknam", "Yunping", "Yuyuen"],
["Adaatsag", "Airag", "Alag Erdene", "Altai", "Altanshiree", "Altantsogts", "Arbulag", "Baatsagaan", "Batnorov", "Batshireet", "Battsengel", "Bayan Adarga", "Bayan Agt", "Bayanbulag", "Bayandalai", "Bayandun", "Bayangovi", "Bayanjargalan", "Bayankhongor", "Bayankhutag", "Bayanlig", "Bayanmonkh", "Bayannuur", "Bayan Ondor", "Bayan Ovoo", "Bayantal", "Bayantsagaan", "Bayantumen", "Bayan Uul", "Bayanzurkh", "Berkh", "Biger", "Binder", "Bogd", "Bombogor", "Bor Ondor", "Bugat", "Bulgan", "Buregkhangai", "Burentogtokh", "Buutsagaan", "Buyant", "Chandmani", "Chandmani Ondor", "Choibalsan", "Chuluunkhoroot", "Chuluut", "Dadal", "Dalanjargalan", "Dalanzadgad", "Darkhan", "Darvi", "Dashbalbar", "Dashinchilen", "Delger", "Delgerekh", "Delgerkhaan", "Delgerkhangai", "Delgertsogt", "Deluun", "Deren", "Dorgon", "Duut", "Erdene", "Erdenebulgan", "Erdeneburen", "Erdenedalai", "Erdenemandal", "Erdenetsogt", "Galshar", "Galt", "Galuut", "Govi Ugtaal", "Gurvan", "Gurvanbulag", "Gurvansaikhan", "Gurvanzagal", "Ikhkhet", "Ikh Tamir", "Ikh Uul", "Jargalan", "Jargalant", "Jargaltkhaan", "Jinst", "Khairkhan", "Khalhgol", "Khaliun", "Khanbogd", "Khangai", "Khangal", "Khankh", "Khankhongor", "Khashaat", "Khatanbulag", "Khatgal", "Kherlen", "Khishig Ondor", "Khokh", "Kholonbuir", "Khongor", "Khotont", "Khovd", "Khovsgol", "Khuld", "Khureemaral", "Khurmen", "Khutag Ondor", "Luus", "Mandakh", "Mandal Ovoo", "Mankhan", "Manlai", "Matad", "Mogod", "Monkhkhairkhan", "Moron", "Most", "Myangad", "Nogoonnuur", "Nomgon", "Norovlin", "Noyon", "Ogii", "Olgii", "Olziit", "Omnodelger", "Ondorkhaan", "Ondorshil", "Ondor Ulaan", "Orgon", "Orkhon", "Rashaant", "Renchinlkhumbe", "Sagsai", "Saikhan", "Saikhandulaan", "Saikhan Ovoo", "Sainshand", "Saintsagaan", "Selenge", "Sergelen", "Sevrei", "Sharga", "Sharyngol", "Shine Ider", "Shinejinst", "Shiveegovi", "Sumber", "Taishir", "Tarialan", "Tariat", "Teshig", "Togrog", "Tolbo", "Tomorbulag", "Tonkhil", "Tosontsengel", "Tsagaandelger", "Tsagaannuur", "Tsagaan Ovoo", "Tsagaan Uur", "Tsakhir", "Tseel", "Tsengel", "Tsenkher", "Tsenkhermandal", "Tsetseg", "Tsetserleg", "Tsogt", "Tsogt Ovoo", "Tsogttsetsii", "Tunel", "Tuvshruulekh", "Ulaanbadrakh", "Ulaankhus", "Ulaan Uul", "Uyench", "Yesonbulag", "Zag", "Zamyn Uud", "Zereg"]
];
}
// apply default biomes data // apply default biomes data
function applyDefaultBiomesSystem() { function applyDefaultBiomesSystem() {
const name = ["Marine","Hot desert","Cold desert","Savanna","Grassland","Tropical seasonal forest","Temperate deciduous forest","Tropical rainforest","Temperate rainforest","Taiga","Tundra","Glacier","Wetland"]; const name = ["Marine","Hot desert","Cold desert","Savanna","Grassland","Tropical seasonal forest","Temperate deciduous forest","Tropical rainforest","Temperate rainforest","Taiga","Tundra","Glacier","Wetland"];
@ -397,7 +323,7 @@ function applyDefaultStyle() {
coastline.attr("opacity", .5).attr("stroke", "#1f3846").attr("stroke-width", .7).attr("filter", "url(#dropShadow)"); coastline.attr("opacity", .5).attr("stroke", "#1f3846").attr("stroke-width", .7).attr("filter", "url(#dropShadow)");
styleCoastlineAuto.checked = true; styleCoastlineAuto.checked = true;
relig.attr("opacity", .6).attr("stroke", "#777777").attr("stroke-width", .2).attr("filter", null).attr("fill-rule", "evenodd"); relig.attr("opacity", .7).attr("stroke", "#404040").attr("stroke-width", .7).attr("filter", null).attr("fill-rule", "evenodd");
cults.attr("opacity", .6).attr("stroke", "#777777").attr("stroke-width", .5).attr("filter", null).attr("fill-rule", "evenodd"); cults.attr("opacity", .6).attr("stroke", "#777777").attr("stroke-width", .5).attr("filter", null).attr("fill-rule", "evenodd");
icons.selectAll("g").attr("opacity", null).attr("fill", "#ffffff").attr("stroke", "#3e3e4b").attr("filter", null).attr("mask", null); icons.selectAll("g").attr("opacity", null).attr("fill", "#ffffff").attr("stroke", "#3e3e4b").attr("filter", null).attr("mask", null);
landmass.attr("opacity", 1).attr("fill", "#eef6fb").attr("filter", null); landmass.attr("opacity", 1).attr("fill", "#eef6fb").attr("filter", null);
@ -511,7 +437,7 @@ function showWelcomeMessage() {
<p>Thanks for all supporters on <a href='https://www.patreon.com/azgaar' target='_blank'>Patreon</a>!</i></p>`; <p>Thanks for all supporters on <a href='https://www.patreon.com/azgaar' target='_blank'>Patreon</a>!</i></p>`;
$("#alert").dialog( $("#alert").dialog(
{resizable: false, title: "Fantasy Map Generator update", width: 310, {resizable: false, title: "Fantasy Map Generator update", width: "31em",
buttons: {OK: function() {$(this).dialog("close")}}, buttons: {OK: function() {$(this).dialog("close")}},
position: {my: "center", at: "center", of: "svg"}, position: {my: "center", at: "center", of: "svg"},
close: () => localStorage.setItem("version", version)} close: () => localStorage.setItem("version", version)}
@ -628,7 +554,7 @@ void function addDragToUpload() {
alertMessage.innerHTML = 'Please upload a <b>.map</b> file you have previously downloaded'; alertMessage.innerHTML = 'Please upload a <b>.map</b> file you have previously downloaded';
$("#alert").dialog({ $("#alert").dialog({
resizable: false, title: "Invalid file format", resizable: false, title: "Invalid file format",
width: 400, buttons: { width: "40em", buttons: {
Close: function() { $(this).dialog("close"); } Close: function() { $(this).dialog("close"); }
}, position: {my: "center", at: "center", of: "svg"} }, position: {my: "center", at: "center", of: "svg"}
}); });
@ -679,6 +605,7 @@ function generate() {
BurgsAndStates.drawStateLabels(); BurgsAndStates.drawStateLabels();
addZone(); addZone();
addMarkers(); addMarkers();
Names.getMapName();
console.warn(`TOTAL: ${rn((performance.now()-timeStart)/1000,2)}s`); console.warn(`TOTAL: ${rn((performance.now()-timeStart)/1000,2)}s`);
showStatistics(); showStatistics();
@ -692,7 +619,7 @@ function generate() {
<br>If error is critical, clear the stored data and try again. <br>If error is critical, clear the stored data and try again.
<p id="errorBox">${parseError(error)}</p>`; <p id="errorBox">${parseError(error)}</p>`;
$("#alert").dialog({ $("#alert").dialog({
resizable: false, title: "Generation error", width:320, buttons: { resizable: false, title: "Generation error", width:"32em", buttons: {
"Clear data": function() {localStorage.clear(); localStorage.setItem("version", version);}, "Clear data": function() {localStorage.clear(); localStorage.setItem("version", version);},
Regenerate: function() {regenerateMap(); $(this).dialog("close");}, Regenerate: function() {regenerateMap(); $(this).dialog("close");},
Ignore: function() {$(this).dialog("close");} Ignore: function() {$(this).dialog("close");}
@ -1265,17 +1192,17 @@ function addZone() {
} }
// add some markers as an example // add some markers as an example
function addMarkers() { function addMarkers(number = 1) {
console.time("addMarkers"); console.time("addMarkers");
const cells = pack.cells; const cells = pack.cells;
void function addVolcanoes() { void function addVolcanoes() {
let mounts = Array.from(cells.i).filter(i => cells.h[i] > 70).sort((a, b) => cells.h[b] - cells.h[a]); let mounts = Array.from(cells.i).filter(i => cells.h[i] > 70).sort((a, b) => cells.h[b] - cells.h[a]);
let count = mounts.length < 10 ? 0 : Math.ceil(mounts.length / 300); let count = mounts.length < 10 ? 0 : Math.ceil(mounts.length / 300 * number);
if (count) addMarker("volcano", "🌋", 52, 52, 17.5); if (count) addMarker("volcano", "🌋", 52, 52, 17.5);
while (count) { while (count) {
const cell = mounts.splice(biased(0, mounts.length, 5), 1); const cell = mounts.splice(biased(0, mounts.length-1, 5), 1);
const x = cells.p[cell][0], y = cells.p[cell][1]; const x = cells.p[cell][0], y = cells.p[cell][1];
const id = getNextId("markerElement"); const id = getNextId("markerElement");
markers.append("use").attr("id", id) markers.append("use").attr("id", id)
@ -1292,11 +1219,11 @@ function addMarkers() {
void function addHotSprings() { void function addHotSprings() {
let springs = Array.from(cells.i).filter(i => cells.h[i] > 50).sort((a, b) => cells.h[b]-cells.h[a]); let springs = Array.from(cells.i).filter(i => cells.h[i] > 50).sort((a, b) => cells.h[b]-cells.h[a]);
let count = springs.length < 30 ? 0 : Math.ceil(springs.length / 1000); let count = springs.length < 30 ? 0 : Math.ceil(springs.length / 1000 * number);
if (count) addMarker("hot_springs", "♨", 50, 50, 19.5); if (count) addMarker("hot_springs", "♨", 50, 50, 19.5);
while (count) { while (count) {
const cell = springs.splice(biased(1, springs.length, 3), 1); const cell = springs.splice(biased(1, springs.length-1, 3), 1);
const x = cells.p[cell][0], y = cells.p[cell][1]; const x = cells.p[cell][0], y = cells.p[cell][1];
const id = getNextId("markerElement"); const id = getNextId("markerElement");
markers.append("use").attr("id", id) markers.append("use").attr("id", id)
@ -1313,7 +1240,7 @@ function addMarkers() {
void function addMines() { void function addMines() {
let hills = Array.from(cells.i).filter(i => cells.h[i] > 47 && cells.burg[i]); let hills = Array.from(cells.i).filter(i => cells.h[i] > 47 && cells.burg[i]);
let count = !hills.length ? 0 : Math.ceil(hills.length / 7); let count = !hills.length ? 0 : Math.ceil(hills.length / 7 * number);
if (!count) return; if (!count) return;
addMarker("mine", "⚒", 50, 50, 20); addMarker("mine", "⚒", 50, 50, 20);
@ -1345,7 +1272,7 @@ function addMarkers() {
.filter(i => cells.burg[i] && cells.h[i] >= 20 && cells.r[i] && cells.fl[i] > meanFlux && cells.road[i] > meanRoad) .filter(i => cells.burg[i] && cells.h[i] >= 20 && cells.r[i] && cells.fl[i] > meanFlux && cells.road[i] > meanRoad)
.sort((a, b) => (cells.road[b] + cells.fl[b] / 10) - (cells.road[a] + cells.fl[a] / 10)); .sort((a, b) => (cells.road[b] + cells.fl[b] / 10) - (cells.road[a] + cells.fl[a] / 10));
let count = !bridges.length ? 0 : Math.ceil(bridges.length / 12); let count = !bridges.length ? 0 : Math.ceil(bridges.length / 12 * number);
if (count) addMarker("bridge", "🌉", 50, 50, 16.5); if (count) addMarker("bridge", "🌉", 50, 50, 16.5);
while (count) { while (count) {
@ -1369,14 +1296,14 @@ function addMarkers() {
const maxRoad = d3.max(cells.road) * .9; const maxRoad = d3.max(cells.road) * .9;
let taverns = Array.from(cells.i).filter(i => cells.crossroad[i] && cells.h[i] >= 20 && cells.road[i] > maxRoad); let taverns = Array.from(cells.i).filter(i => cells.crossroad[i] && cells.h[i] >= 20 && cells.road[i] > maxRoad);
if (!taverns.length) return; if (!taverns.length) return;
const count = Math.ceil(4 * number);
addMarker("inn", "🍻", 50, 50, 17.5); addMarker("inn", "🍻", 50, 50, 17.5);
const color = ["Dark", "Light", "Bright", "Golden", "White", "Black", "Red", "Pink", "Purple", "Blue", "Green", "Yellow", "Amber", "Orange", "Brown", "Grey"]; const color = ["Dark", "Light", "Bright", "Golden", "White", "Black", "Red", "Pink", "Purple", "Blue", "Green", "Yellow", "Amber", "Orange", "Brown", "Grey"];
const animal = ["Antelope", "Ape", "Badger", "Bear", "Beaver", "Bison", "Boar", "Buffalo", "Cat", "Crane", "Crocodile", "Crow", "Deer", "Dog", "Eagle", "Elk", "Fox", "Goat", "Goose", "Hare", "Hawk", "Heron", "Horse", "Hyena", "Ibis", "Jackal", "Jaguar", "Lark", "Leopard", "Lion", "Mantis", "Marten", "Moose", "Mule", "Narwhal", "Owl", "Panther", "Rat", "Raven", "Rook", "Scorpion", "Shark", "Sheep", "Snake", "Spider", "Swan", "Tiger", "Turtle", "Wolf", "Wolverine", "Camel", "Falcon", "Hound", "Ox"]; const animal = ["Antelope", "Ape", "Badger", "Bear", "Beaver", "Bison", "Boar", "Buffalo", "Cat", "Crane", "Crocodile", "Crow", "Deer", "Dog", "Eagle", "Elk", "Fox", "Goat", "Goose", "Hare", "Hawk", "Heron", "Horse", "Hyena", "Ibis", "Jackal", "Jaguar", "Lark", "Leopard", "Lion", "Mantis", "Marten", "Moose", "Mule", "Narwhal", "Owl", "Panther", "Rat", "Raven", "Rook", "Scorpion", "Shark", "Sheep", "Snake", "Spider", "Swan", "Tiger", "Turtle", "Wolf", "Wolverine", "Camel", "Falcon", "Hound", "Ox"];
const adj = ["New", "Good", "High", "Old", "Great", "Big", "Major", "Happy", "Main", "Huge", "Far", "Beautiful", "Fair", "Prime", "Ancient", "Golden", "Proud", "Lucky", "Fat", "Honest", "Giant", "Distant", "Friendly", "Loud", "Hungry", "Magical", "Superior", "Peaceful", "Frozen", "Divine", "Favorable", "Brave", "Sunny", "Flying"]; const adj = ["New", "Good", "High", "Old", "Great", "Big", "Major", "Happy", "Main", "Huge", "Far", "Beautiful", "Fair", "Prime", "Ancient", "Golden", "Proud", "Lucky", "Fat", "Honest", "Giant", "Distant", "Friendly", "Loud", "Hungry", "Magical", "Superior", "Peaceful", "Frozen", "Divine", "Favorable", "Brave", "Sunny", "Flying"];
for (let i=0; i < taverns.length && i < count; i++) {
for (let i=0; i < taverns.length && i < 4; i++) {
const cell = taverns.splice(Math.floor(Math.random() * taverns.length), 1); const cell = taverns.splice(Math.floor(Math.random() * taverns.length), 1);
const x = cells.p[cell][0], y = cells.p[cell][1]; const x = cells.p[cell][0], y = cells.p[cell][1];
const id = getNextId("markerElement"); const id = getNextId("markerElement");
@ -1396,8 +1323,9 @@ function addMarkers() {
const lands = cells.i.filter(i => cells.harbor[i] > 6 && cells.c[i].some(c => cells.h[c] < 20 && cells.road[c])); const lands = cells.i.filter(i => cells.harbor[i] > 6 && cells.c[i].some(c => cells.h[c] < 20 && cells.road[c]));
const lighthouses = Array.from(lands).map(i => [i, cells.v[i][cells.c[i].findIndex(c => cells.h[c] < 20 && cells.road[c])]]); const lighthouses = Array.from(lands).map(i => [i, cells.v[i][cells.c[i].findIndex(c => cells.h[c] < 20 && cells.road[c])]]);
if (lighthouses.length) addMarker("lighthouse", "🚨", 50, 50, 16); if (lighthouses.length) addMarker("lighthouse", "🚨", 50, 50, 16);
const count = Math.ceil(4 * number);
for (let i=0; i < lighthouses.length && i < 4; i++) { for (let i=0; i < lighthouses.length && i < count; i++) {
const cell = lighthouses[i][0], vertex = lighthouses[i][1]; const cell = lighthouses[i][0], vertex = lighthouses[i][1];
const x = pack.vertices.p[vertex][0], y = pack.vertices.p[vertex][1]; const x = pack.vertices.p[vertex][0], y = pack.vertices.p[vertex][1];
const id = getNextId("markerElement"); const id = getNextId("markerElement");
@ -1415,8 +1343,9 @@ function addMarkers() {
void function addWaterfalls() { void function addWaterfalls() {
const waterfalls = cells.i.filter(i => cells.r[i] && cells.h[i] > 70); const waterfalls = cells.i.filter(i => cells.r[i] && cells.h[i] > 70);
if (waterfalls.length) addMarker("waterfall", "⟱", 50, 54, 16.5); if (waterfalls.length) addMarker("waterfall", "⟱", 50, 54, 16.5);
const count = Math.ceil(3 * number);
for (let i=0; i < waterfalls.length && i < 3; i++) { for (let i=0; i < waterfalls.length && i < count; i++) {
const cell = waterfalls[i]; const cell = waterfalls[i];
const x = cells.p[cell][0], y = cells.p[cell][1]; const x = cells.p[cell][0], y = cells.p[cell][1];
const id = getNextId("markerElement"); const id = getNextId("markerElement");
@ -1433,7 +1362,7 @@ function addMarkers() {
void function addBattlefields() { void function addBattlefields() {
let battlefields = Array.from(cells.i).filter(i => cells.pop[i] > 2 && cells.h[i] < 50 && cells.h[i] > 25); let battlefields = Array.from(cells.i).filter(i => cells.pop[i] > 2 && cells.h[i] < 50 && cells.h[i] > 25);
let count = battlefields.length < 100 ? 0 : Math.ceil(battlefields.length / 500); let count = battlefields.length < 100 ? 0 : Math.ceil(battlefields.length / 500 * number);
const era = Names.getCulture(0, 3, 7, "", 0) + " Era"; const era = Names.getCulture(0, 3, 7, "", 0) + " Era";
if (count) addMarker("battlefield", "⚔", 50, 50, 20); if (count) addMarker("battlefield", "⚔", 50, 50, 20);

View file

@ -762,9 +762,11 @@
if (s.form === "Monarchy") { if (s.form === "Monarchy") {
const form = monarchy[expTiers[s.i]]; const form = monarchy[expTiers[s.i]];
// Default name depend on exponent tier, some culture bases have special names for tiers // Default name depends on exponent tier, some culture bases have special names for tiers
if (s.diplomacy) {
if (form === "Duchy" && s.neighbors.size > 1 && rand(6) < s.neighbors.size && s.diplomacy.includes("Vassal")) return "Marches"; // some vassal dutchies on borderland if (form === "Duchy" && s.neighbors.size > 1 && rand(6) < s.neighbors.size && s.diplomacy.includes("Vassal")) return "Marches"; // some vassal dutchies on borderland
if (Math.random() < .3 && s.diplomacy.includes("Vassal")) return "Protectorate"; // some vassals if (Math.random() < .3 && s.diplomacy.includes("Vassal")) return "Protectorate"; // some vassals
}
if (base === 16 && (form === "Empire" || form === "Kingdom")) return "Sultanate"; // Turkic if (base === 16 && (form === "Empire" || form === "Kingdom")) return "Sultanate"; // Turkic
if (base === 5 && (form === "Empire" || form === "Kingdom")) return "Tsardom"; // Ruthenian if (base === 5 && (form === "Empire" || form === "Kingdom")) return "Tsardom"; // Ruthenian

View file

@ -58,7 +58,10 @@
// check whether all bases are valid. If not, load default namesbase // check whether all bases are valid. If not, load default namesbase
const invalidBase = pack.cultures.some(c => !nameBase[c.base]); const invalidBase = pack.cultures.some(c => !nameBase[c.base]);
if (invalidBase) applyDefaultNamesData(); if (invalidBase) {
nameBases = Names.getNameBases();
nameBase = Names.getNameBase();
}
function getRandomCultures(c) { function getRandomCultures(c) {
const d = getDefault(); const d = getDefault();

View file

@ -8,8 +8,7 @@
const generate = function() { const generate = function() {
console.time('generateHeightmap'); console.time('generateHeightmap');
cells = grid.cells; cells = grid.cells, p = grid.points;
p = grid.points;
cells.h = new Uint8Array(grid.points.length); cells.h = new Uint8Array(grid.points.length);
const input = document.getElementById("templateInput"); const input = document.getElementById("templateInput");
@ -19,12 +18,13 @@
"High Island": 22, "High Island": 22,
"Low Island": 10, "Low Island": 10,
"Continents": 20, "Continents": 20,
"Archipelago": 32, "Archipelago": 30,
"Mediterranean":3, "Mediterranean":3,
"Peninsula": 3, "Peninsula": 3,
"Pangea": 2, "Pangea": 2,
"Isthmus": 2, "Isthmus": 2,
"Atoll": 1}; "Atoll": 1,
"Shattered": 2};
input.value = rw(templates); input.value = rw(templates);
} }
@ -39,6 +39,7 @@
case "Peninsula": templatePeninsula(); break; case "Peninsula": templatePeninsula(); break;
case "Pangea": templatePangea(); break; case "Pangea": templatePangea(); break;
case "Isthmus": templateIsthmus(); break; case "Isthmus": templateIsthmus(); break;
case "Shattered": templateShattered(); break;
} }
console.timeEnd('generateHeightmap'); console.timeEnd('generateHeightmap');
@ -193,6 +194,14 @@
addStep("Trough", "4-8", "15-30", "70-100", "80-100"); addStep("Trough", "4-8", "15-30", "70-100", "80-100");
} }
// Heighmap Template: Shattered
function templateShattered() {
addStep("Hill", "8", "35-40", "15-85", "30-70");
addStep("Trough", "10-20", "40-50", "5-95", "5-95");
addStep("Range", "5-7", "30-40", "10-90", "20-80");
addStep("Pit", "12-20", "30-40", "15-85", "20-80");
}
function getBlobPower() { function getBlobPower() {
switch (+densityInput.value) { switch (+densityInput.value) {
case 1: return .98; case 1: return .98;

View file

@ -104,7 +104,12 @@
// generate short name for culture // generate short name for culture
const getCultureShort = function(culture) { const getCultureShort = function(culture) {
if (culture === undefined) {console.error("Please define a culture"); return;} if (culture === undefined) {console.error("Please define a culture"); return;}
const base = pack.cultures[culture].base; let base = pack.cultures[culture].base;
if (nameBases[base] === undefined) {
tip(`Namebase for culture ${pack.cultures[culture].name} does not exist.
Please upload custom namebases of change the base in Cultures Editor`, false, "error");
base = 1;
}
const min = nameBases[base].min-1; const min = nameBases[base].min-1;
const max = Math.max(nameBases[base].max-2, min); const max = Math.max(nameBases[base].max-2, min);
return getBase(base, min, max, "", 0); return getBase(base, min, max, "", 0);
@ -151,7 +156,10 @@
else if (base === 17) suffix = rnd < .8 ? "a" : "ia"; // Berber else if (base === 17) suffix = rnd < .8 ? "a" : "ia"; // Berber
else if (base === 18) suffix = rnd < .8 ? "a" : "ia"; // Arabic else if (base === 18) suffix = rnd < .8 ? "a" : "ia"; // Arabic
else suffix = "ia" // other else suffix = "ia" // other
return validateSuffix(name, suffix);
}
function validateSuffix(name, suffix) {
if (name.slice(-1 * suffix.length) === suffix) return name; // no suffix if name already ends with it if (name.slice(-1 * suffix.length) === suffix) return name; // no suffix if name already ends with it
const s1 = suffix.charAt(0); const s1 = suffix.charAt(0);
if (name.slice(-1) === s1) name = name.slice(0, -1); // remove name last letter if it's a suffix first letter if (name.slice(-1) === s1) name = name.slice(0, -1); // remove name last letter if it's a suffix first letter
@ -160,5 +168,100 @@
return name + suffix; return name + suffix;
} }
return {getBase, getCulture, getCultureShort, getState, updateChain, updateChains}; // generato name for the map
const getMapName = function(force) {
if (!force && locked("mapName")) return;
if (force && locked("mapName")) unlock("mapName");
const base = Math.random() < .7 ? 2 : Math.random() < .5 ? rand(0, 6) : rand(0, 31);
if (!nameBases[base]) {tip("Namebase is not found", false, "error"); return ""};
const min = nameBases[base].min-1;
const max = Math.max(nameBases[base].max-3, min);
const baseName = getBase(base, min, max, "", 0);
const name = Math.random() < .7 ? addSuffix(baseName) : baseName;
mapName.value = name;
}
function addSuffix(name) {
const suffix = Math.random() < .8 ? "ia" : "land";
if (suffix === "ia" && name.length > 6) name = name.slice(0, -(name.length-3)); else
if (suffix === "land" && name.length > 6) name = name.slice(0, -(name.length-5));
return validateSuffix(name, suffix);
}
const getNameBases = function() {
// name, min length, max length, letters to allow duplication, multi-word name rate
return [
{name: "German", min: 5, max: 12, d: "lt", m: 0},
{name: "English", min: 6, max: 11, d: "", m: 0.1},
{name: "French", min: 5, max: 13, d: "nlrs", m: 0.1},
{name: "Italian", min: 5, max: 12, d: "cltr", m: 0.1},
{name: "Castillian", min: 5, max: 11, d: "lr", m: 0},
{name: "Ruthenian", min: 5, max: 10, d: "", m: 0},
{name: "Nordic", min: 6, max: 10, d: "kln", m: 0.1},
{name: "Greek", min: 5, max: 11, d: "s", m: 0.1},
{name: "Roman", min: 6, max: 11, d: "ln", m: 0.1},
{name: "Finnic", min: 5, max: 11, d: "akiut", m: 0},
{name: "Korean", min: 5, max: 11, d: "", m: 0},
{name: "Chinese", min: 5, max: 10, d: "", m: 0},
{name: "Japanese", min: 4, max: 10, d: "", m: 0},
{name: "Portuguese", min: 5, max: 11, d: "", m: 0.1},
{name: "Nahuatl", min: 6, max: 13, d: "l", m: 0},
{name: "Hungarian", min: 6, max: 13, d: "", m: 0.1},
{name: "Turkish", min: 4, max: 10, d: "", m: 0},
{name: "Berber", min: 4, max: 10, d: "s", m: 0.2},
{name: "Arabic", min: 4, max: 9, d: "ae", m: 0.2},
{name: "Inuit", min: 5, max: 15, d: "alutsn", m: 0},
{name: "Basque", min: 4, max: 11, d: "r", m: 0.1},
{name: "Nigerian", min: 4, max: 10, d: "", m: 0.3},
{name: "Celtic", min: 4, max: 12, d: "nld", m: 0},
{name: "Mesopotamian", min: 4, max: 9, d: "srpl", m: 0.1},
{name: "Iranian", min: 5, max: 11, d: "", m: 0.1},
{name: "Hawaiian", min: 5, max: 10, d: "auo", m: 1},
{name: "Karnataka", min: 5, max: 11, d: "tnl", m: 0},
{name: "Quechua", min: 6, max: 12, d: "l", m: 0},
{name: "Swahili", min: 4, max: 9, d: "", m: 0},
{name: "Vietnamese", min: 3, max: 12, d: "", m: 1},
{name: "Cantonese", min: 5, max: 11, d: "", m: 0},
{name: "Mongolian", min: 5, max: 12, d: "aou", m: .3}
];
}
const getNameBase = function() {
return [
["Achern","Aichhalden","Aitern","Albbruck","Alpirsbach","Altensteig","Althengstett","Appenweier","Auggen","Wildbad","Badenen","Badenweiler","Baiersbronn","Ballrechten","Bellingen","Berghaupten","Bernau","Biberach","Biederbach","Binzen","Birkendorf","Birkenfeld","Bischweier","Blumberg","Bollen","Bollschweil","Bonndorf","Bosingen","Braunlingen","Breisach","Breisgau","Breitnau","Brigachtal","Buchenbach","Buggingen","Buhl","Buhlertal","Calw","Dachsberg","Dobel","Donaueschingen","Dornhan","Dornstetten","Dottingen","Dunningen","Durbach","Durrheim","Ebhausen","Ebringen","Efringen","Egenhausen","Ehrenkirchen","Ehrsberg","Eimeldingen","Eisenbach","Elzach","Elztal","Emmendingen","Endingen","Engelsbrand","Enz","Enzklosterle","Eschbronn","Ettenheim","Ettlingen","Feldberg","Fischerbach","Fischingen","Fluorn","Forbach","Freiamt","Freiburg","Freudenstadt","Friedenweiler","Friesenheim","Frohnd","Furtwangen","Gaggenau","Geisingen","Gengenbach","Gernsbach","Glatt","Glatten","Glottertal","Gorwihl","Gottenheim","Grafenhausen","Grenzach","Griesbach","Gutach","Gutenbach","Hag","Haiterbach","Hardt","Harmersbach","Hasel","Haslach","Hausach","Hausen","Hausern","Heitersheim","Herbolzheim","Herrenalb","Herrischried","Hinterzarten","Hochenschwand","Hofen","Hofstetten","Hohberg","Horb","Horben","Hornberg","Hufingen","Ibach","Ihringen","Inzlingen","Kandern","Kappel","Kappelrodeck","Karlsbad","Karlsruhe","Kehl","Keltern","Kippenheim","Kirchzarten","Konigsfeld","Krozingen","Kuppenheim","Kussaberg","Lahr","Lauchringen","Lauf","Laufenburg","Lautenbach","Lauterbach","Lenzkirch","Liebenzell","Loffenau","Loffingen","Lorrach","Lossburg","Mahlberg","Malsburg","Malsch","March","Marxzell","Marzell","Maulburg","Monchweiler","Muhlenbach","Mullheim","Munstertal","Murg","Nagold","Neubulach","Neuenburg","Neuhausen","Neuried","Neuweiler","Niedereschach","Nordrach","Oberharmersbach","Oberkirch","Oberndorf","Oberbach","Oberried","Oberwolfach","Offenburg","Ohlsbach","Oppenau","Ortenberg","otigheim","Ottenhofen","Ottersweier","Peterstal","Pfaffenweiler","Pfalzgrafenweiler","Pforzheim","Rastatt","Renchen","Rheinau","Rheinfelden","Rheinmunster","Rickenbach","Rippoldsau","Rohrdorf","Rottweil","Rummingen","Rust","Sackingen","Sasbach","Sasbachwalden","Schallbach","Schallstadt","Schapbach","Schenkenzell","Schiltach","Schliengen","Schluchsee","Schomberg","Schonach","Schonau","Schonenberg","Schonwald","Schopfheim","Schopfloch","Schramberg","Schuttertal","Schwenningen","Schworstadt","Seebach","Seelbach","Seewald","Sexau","Simmersfeld","Simonswald","Sinzheim","Solden","Staufen","Stegen","Steinach","Steinen","Steinmauern","Straubenhardt","Stuhlingen","Sulz","Sulzburg","Teinach","Tiefenbronn","Tiengen","Titisee","Todtmoos","Todtnau","Todtnauberg","Triberg","Tunau","Tuningen","uhlingen","Unterkirnach","Reichenbach","Utzenfeld","Villingen","Villingendorf","Vogtsburg","Vohrenbach","Waldachtal","Waldbronn","Waldkirch","Waldshut","Wehr","Weil","Weilheim","Weisenbach","Wembach","Wieden","Wiesental","Wildberg","Winzeln","Wittlingen","Wittnau","Wolfach","Wutach","Wutoschingen","Wyhlen","Zavelstein"],
["Abingdon","Albrighton","Alcester","Almondbury","Altrincham","Amersham","Andover","Appleby","Ashboume","Atherstone","Aveton","Axbridge","Aylesbury","Baldock","Bamburgh","Barton","Basingstoke","Berden","Bere","Berkeley","Berwick","Betley","Bideford","Bingley","Birmingham","Blandford","Blechingley","Bodmin","Bolton","Bootham","Boroughbridge","Boscastle","Bossinney","Bramber","Brampton","Brasted","Bretford","Bridgetown","Bridlington","Bromyard","Bruton","Buckingham","Bungay","Burton","Calne","Cambridge","Canterbury","Carlisle","Castleton","Caus","Charmouth","Chawleigh","Chichester","Chillington","Chinnor","Chipping","Chisbury","Cleobury","Clifford","Clifton","Clitheroe","Cockermouth","Coleshill","Combe","Congleton","Crafthole","Crediton","Cuddenbeck","Dalton","Darlington","Dodbrooke","Drax","Dudley","Dunstable","Dunster","Dunwich","Durham","Dymock","Exeter","Exning","Faringdon","Felton","Fenny","Finedon","Flookburgh","Fowey","Frampton","Gateshead","Gatton","Godmanchester","Grampound","Grantham","Guildford","Halesowen","Halton","Harbottle","Harlow","Hatfield","Hatherleigh","Haydon","Helston","Henley","Hertford","Heytesbury","Hinckley","Hitchin","Holme","Hornby","Horsham","Kendal","Kenilworth","Kilkhampton","Kineton","Kington","Kinver","Kirby","Knaresborough","Knutsford","Launceston","Leighton","Lewes","Linton","Louth","Luton","Lyme","Lympstone","Macclesfield","Madeley","Malborough","Maldon","Manchester","Manningtree","Marazion","Marlborough","Marshfield","Mere","Merryfield","Middlewich","Midhurst","Milborne","Mitford","Modbury","Montacute","Mousehole","Newbiggin","Newborough","Newbury","Newenden","Newent","Norham","Northleach","Noss","Oakham","Olney","Orford","Ormskirk","Oswestry","Padstow","Paignton","Penkneth","Penrith","Penzance","Pershore","Petersfield","Pevensey","Pickering","Pilton","Pontefract","Portsmouth","Preston","Quatford","Reading","Redcliff","Retford","Rockingham","Romney","Rothbury","Rothwell","Salisbury","Saltash","Seaford","Seasalter","Sherston","Shifnal","Shoreham","Sidmouth","Skipsea","Skipton","Solihull","Somerton","Southam","Southwark","Standon","Stansted","Stapleton","Stottesdon","Sudbury","Swavesey","Tamerton","Tarporley","Tetbury","Thatcham","Thaxted","Thetford","Thornbury","Tintagel","Tiverton","Torksey","Totnes","Towcester","Tregoney","Trematon","Tutbury","Uxbridge","Wallingford","Wareham","Warenmouth","Wargrave","Warton","Watchet","Watford","Wendover","Westbury","Westcheap","Weymouth","Whitford","Wickwar","Wigan","Wigmore","Winchelsea","Winkleigh","Wiscombe","Witham","Witheridge","Wiveliscombe","Woodbury","Yeovil"],
["Adon","Aillant","Amilly","Andonville","Ardon","Artenay","Ascheres","Ascoux","Attray","Aubin","Audeville","Aulnay","Autruy","Auvilliers","Auxy","Aveyron","Baccon","Bardon","Barville","Batilly","Baule","Bazoches","Beauchamps","Beaugency","Beaulieu","Beaune","Bellegarde","Boesses","Boigny","Boiscommun","Boismorand","Boisseaux","Bondaroy","Bonnee","Bonny","Bordes","Bou","Bougy","Bouilly","Boulay","Bouzonville","Bouzy","Boynes","Bray","Breteau","Briare","Briarres","Bricy","Bromeilles","Bucy","Cepoy","Cercottes","Cerdon","Cernoy","Cesarville","Chailly","Chaingy","Chalette","Chambon","Champoulet","Chanteau","Chantecoq","Chapell","Charme","Charmont","Charsonville","Chateau","Chateauneuf","Chatel","Chatenoy","Chatillon","Chaussy","Checy","Chevannes","Chevillon","Chevilly","Chevry","Chilleurs","Choux","Chuelles","Clery","Coinces","Coligny","Combleux","Combreux","Conflans","Corbeilles","Corquilleroy","Cortrat","Coudroy","Coullons","Coulmiers","Courcelles","Courcy","Courtemaux","Courtempierre","Courtenay","Cravant","Crottes","Dadonville","Dammarie","Dampierre","Darvoy","Desmonts","Dimancheville","Donnery","Dordives","Dossainville","Douchy","Dry","Echilleuses","Egry","Engenville","Epieds","Erceville","Ervauville","Escrennes","Escrignelles","Estouy","Faverelles","Fay","Feins","Ferolles","Ferrieres","Fleury","Fontenay","Foret","Foucherolles","Freville","Gatinais","Gaubertin","Gemigny","Germigny","Gidy","Gien","Girolles","Givraines","Gondreville","Grangermont","Greneville","Griselles","Guigneville","Guilly","Gyleslonains","Huetre","Huisseau","Ingrannes","Ingre","Intville","Isdes","Jargeau","Jouy","Juranville","Bussiere","Laas","Ladon","Lailly","Langesse","Leouville","Ligny","Lombreuil","Lorcy","Lorris","Loury","Louzouer","Malesherbois","Marcilly","Mardie","Mareau","Marigny","Marsainvilliers","Melleroy","Menestreau","Merinville","Messas","Meung","Mezieres","Migneres","Mignerette","Mirabeau","Montargis","Montbarrois","Montbouy","Montcresson","Montereau","Montigny","Montliard","Mormant","Morville","Moulinet","Moulon","Nancray","Nargis","Nesploy","Neuville","Neuvy","Nevoy","Nibelle","Nogent","Noyers","Ocre","Oison","Olivet","Ondreville","Onzerain","Orleans","Ormes","Orville","Oussoy","Outarville","Ouzouer","Pannecieres","Pannes","Patay","Paucourt","Pers","Pierrefitte","Pithiverais","Pithiviers","Poilly","Potier","Prefontaines","Presnoy","Pressigny","Puiseaux","Quiers","Ramoulu","Rebrechien","Rouvray","Rozieres","Rozoy","Ruan","Sandillon","Santeau","Saran","Sceaux","Seichebrieres","Semoy","Sennely","Sermaises","Sigloy","Solterre","Sougy","Sully","Sury","Tavers","Thignonville","Thimory","Thorailles","Thou","Tigy","Tivernon","Tournoisis","Trainou","Treilles","Trigueres","Trinay","Vannes","Varennes","Vennecy","Vieilles","Vienne","Viglain","Vignes","Villamblain","Villemandeur","Villemoutiers","Villemurlin","Villeneuve","Villereau","Villevoques","Villorceau","Vimory","Vitry","Vrigny","Ivre"],
["Accumoli","Acquafondata","Acquapendente","Acuto","Affile","Agosta","Alatri","Albano","Allumiere","Alvito","Amaseno","Amatrice","Anagni","Anguillara","Anticoli","Antrodoco","Anzio","Aprilia","Aquino","Arce","Arcinazzo","Ardea","Ariccia","Arlena","Arnara","Arpino","Arsoli","Artena","Ascrea","Atina","Ausonia","Bagnoregio","Barbarano","Bassano","Bassiano","Bellegra","Belmonte","Blera","Bolsena","Bomarzo","Borbona","Borgo","Borgorose","Boville","Bracciano","Broccostella","Calcata","Camerata","Campagnano","Campodimele","Campoli","Canale","Canepina","Canino","Cantalice","Cantalupo","Canterano","Capena","Capodimonte","Capranica","Caprarola","Carbognano","Casalattico","Casalvieri","Casape","Casaprota","Casperia","Cassino","Castelforte","Castelliri","Castello","Castelnuovo","Castiglione","Castro","Castrocielo","Cave","Ceccano","Celleno","Cellere","Ceprano","Cerreto","Cervara","Cervaro","Cerveteri","Ciampino","Ciciliano","Cineto","Cisterna","Cittaducale","Cittareale","Civita","Civitavecchia","Civitella","Colfelice","Collalto","Colle","Colleferro","Collegiove","Collepardo","Collevecchio","Colli","Colonna","Concerviano","Configni","Contigliano","Corchiano","Coreno","Cori","Cottanello","Esperia","Fabrica","Faleria","Fara","Farnese","Ferentino","Fiamignano","Fiano","Filacciano","Filettino","Fiuggi","Fiumicino","Fondi","Fontana","Fonte","Fontechiari","Forano","Formello","Formia","Frascati","Frasso","Frosinone","Fumone","Gaeta","Gallese","Gallicano","Gallinaro","Gavignano","Genazzano","Genzano","Gerano","Giuliano","Gorga","Gradoli","Graffignano","Greccio","Grottaferrata","Grotte","Guarcino","Guidonia","Ischia","Isola","Itri","Jenne","Labico","Labro","Ladispoli","Lanuvio","Lariano","Latera","Lenola","Leonessa","Licenza","Longone","Lubriano","Maenza","Magliano","Mandela","Manziana","Marano","Marcellina","Marcetelli","Marino","Marta","Mazzano","Mentana","Micigliano","Minturno","Mompeo","Montalto","Montasola","Monte","Montebuono","Montefiascone","Monteflavio","Montelanico","Monteleone","Montelibretti","Montenero","Monterosi","Monterotondo","Montopoli","Montorio","Moricone","Morlupo","Morolo","Morro","Nazzano","Nemi","Nepi","Nerola","Nespolo","Nettuno","Norma","Olevano","Onano","Oriolo","Orte","Orvinio","Paganico","Palestrina","Paliano","Palombara","Pastena","Patrica","Percile","Pescorocchiano","Pescosolido","Petrella","Piansano","Picinisco","Pico","Piedimonte","Piglio","Pignataro","Pisoniano","Pofi","Poggio","Poli","Pomezia","Pontecorvo","Pontinia","Ponza","Ponzano","Posta","Pozzaglia","Priverno","Proceno","Prossedi","Riano","Rieti","Rignano","Riofreddo","Ripi","Rivodutri","Rocca","Roccagiovine","Roccagorga","Roccantica","Roccasecca","Roiate","Ronciglione","Roviano","Sabaudia","Sacrofano","Salisano","Sambuci","Santa","Santi","Santopadre","Saracinesco","Scandriglia","Segni","Selci","Sermoneta","Serrone","Settefrati","Sezze","Sgurgola","Sonnino","Sora","Soriano","Sperlonga","Spigno","Stimigliano","Strangolagalli","Subiaco","Supino","Sutri","Tarano","Tarquinia","Terelle","Terracina","Tessennano","Tivoli","Toffia","Tolfa","Torre","Torri","Torrice","Torricella","Torrita","Trevi","Trevignano","Trivigliano","Turania","Tuscania","Vacone","Valentano","Vallecorsa","Vallemaio","Vallepietra","Vallerano","Vallerotonda","Vallinfreda","Valmontone","Varco","Vasanello","Vejano","Velletri","Ventotene","Veroli","Vetralla","Vicalvi","Vico","Vicovaro","Vignanello","Viterbo","Viticuso","Vitorchiano","Vivaro","Zagarolo"],
["Abanades","Ablanque","Adobes","Ajofrin","Alameda","Alaminos","Alarilla","Albalate","Albares","Albarreal","Albendiego","Alcabon","Alcanizo","Alcaudete","Alcocer","Alcolea","Alcoroches","Aldea","Aldeanueva","Algar","Algora","Alhondiga","Alique","Almadrones","Almendral","Almoguera","Almonacid","Almorox","Alocen","Alovera","Alustante","Angon","Anguita","Anover","Anquela","Arbancon","Arbeteta","Arcicollar","Argecilla","Arges","Armallones","Armuna","Arroyo","Atanzon","Atienza","Aunon","Azuqueca","Azutan","Baides","Banos","Banuelos","Barcience","Bargas","Barriopedro","Belvis","Berninches","Borox","Brihuega","Budia","Buenaventura","Bujalaro","Burguillos","Burujon","Bustares","Cabanas","Cabanillas","Calera","Caleruela","Calzada","Camarena","Campillo","Camunas","Canizar","Canredondo","Cantalojas","Cardiel","Carmena","Carranque","Carriches","Casa","Casarrubios","Casas","Casasbuenas","Caspuenas","Castejon","Castellar","Castilforte","Castillo","Castilnuevo","Cazalegas","Cebolla","Cedillo","Cendejas","Centenera","Cervera","Checa","Chequilla","Chillaron","Chiloeches","Chozas","Chueca","Cifuentes","Cincovillas","Ciruelas","Ciruelos","Cobeja","Cobeta","Cobisa","Cogollor","Cogolludo","Condemios","Congostrina","Consuegra","Copernal","Corduente","Corral","Cuerva","Domingo","Dosbarrios","Driebes","Duron","El","Embid","Erustes","Escalona","Escalonilla","Escamilla","Escariche","Escopete","Espinosa","Espinoso","Esplegares","Esquivias","Estables","Estriegana","Fontanar","Fuembellida","Fuensalida","Fuentelsaz","Gajanejos","Galve","Galvez","Garciotum","Gascuena","Gerindote","Guadamur","Henche","Heras","Herreria","Herreruela","Hijes","Hinojosa","Hita","Hombrados","Hontanar","Hontoba","Horche","Hormigos","Huecas","Huermeces","Huerta","Hueva","Humanes","Illan","Illana","Illescas","Iniestola","Irueste","Jadraque","Jirueque","Lagartera","Las","Layos","Ledanca","Lillo","Lominchar","Loranca","Los","Lucillos","Lupiana","Luzaga","Luzon","Madridejos","Magan","Majaelrayo","Malaga","Malaguilla","Malpica","Mandayona","Mantiel","Manzaneque","Maqueda","Maranchon","Marchamalo","Marjaliza","Marrupe","Mascaraque","Masegoso","Matarrubia","Matillas","Mazarete","Mazuecos","Medranda","Megina","Mejorada","Mentrida","Mesegar","Miedes","Miguel","Millana","Milmarcos","Mirabueno","Miralrio","Mocejon","Mochales","Mohedas","Molina","Monasterio","Mondejar","Montarron","Mora","Moratilla","Morenilla","Muduex","Nambroca","Navalcan","Negredo","Noblejas","Noez","Nombela","Noves","Numancia","Nuno","Ocana","Ocentejo","Olias","Olmeda","Ontigola","Orea","Orgaz","Oropesa","Otero","Palmaces","Palomeque","Pantoja","Pardos","Paredes","Pareja","Parrillas","Pastrana","Pelahustan","Penalen","Penalver","Pepino","Peralejos","Peralveche","Pinilla","Pioz","Piqueras","Polan","Portillo","Poveda","Pozo","Pradena","Prados","Puebla","Puerto","Pulgar","Quer","Quero","Quintanar","Quismondo","Rebollosa","Recas","Renera","Retamoso","Retiendas","Riba","Rielves","Rillo","Riofrio","Robledillo","Robledo","Romanillos","Romanones","Rueda","Sacecorbo","Sacedon","Saelices","Salmeron","San","Santa","Santiuste","Santo","Sartajada","Sauca","Sayaton","Segurilla","Selas","Semillas","Sesena","Setiles","Sevilleja","Sienes","Siguenza","Solanillos","Somolinos","Sonseca","Sotillo","Sotodosos","Talavera","Tamajon","Taragudo","Taravilla","Tartanedo","Tembleque","Tendilla","Terzaga","Tierzo","Tordellego","Tordelrabano","Tordesilos","Torija","Torralba","Torre","Torrecilla","Torrecuadrada","Torrejon","Torremocha","Torrico","Torrijos","Torrubia","Tortola","Tortuera","Tortuero","Totanes","Traid","Trijueque","Trillo","Turleque","Uceda","Ugena","Ujados","Urda","Utande","Valdarachas","Valdesotos","Valhermoso","Valtablado","Valverde","Velada","Viana","Vinuelas","Yebes","Yebra","Yelamos","Yeles","Yepes","Yuncler","Yunclillos","Yuncos","Yunquera","Zaorejas","Zarzuela","Zorita"],
["Belgorod","Beloberezhye","Belyi","Belz","Berestiy","Berezhets","Berezovets","Berezutsk","Bobruisk","Bolonets","Borisov","Borovsk","Bozhesk","Bratslav","Bryansk","Brynsk","Buryn","Byhov","Chechersk","Chemesov","Cheremosh","Cherlen","Chern","Chernigov","Chernitsa","Chernobyl","Chernogorod","Chertoryesk","Chetvertnia","Demyansk","Derevesk","Devyagoresk","Dichin","Dmitrov","Dorogobuch","Dorogobuzh","Drestvin","Drokov","Drutsk","Dubechin","Dubichi","Dubki","Dubkov","Dveren","Galich","Glebovo","Glinsk","Goloty","Gomiy","Gorodets","Gorodische","Gorodno","Gorohovets","Goroshin","Gorval","Goryshon","Holm","Horobor","Hoten","Hotin","Hotmyzhsk","Ilovech","Ivan","Izborsk","Izheslavl","Kamenets","Kanev","Karachev","Karna","Kavarna","Klechesk","Klyapech","Kolomyya","Kolyvan","Kopyl","Korec","Kornik","Korochunov","Korshev","Korsun","Koshkin","Kotelno","Kovyla","Kozelsk","Kozelsk","Kremenets","Krichev","Krylatsk","Ksniatin","Kulatsk","Kursk","Kursk","Lebedev","Lida","Logosko","Lomihvost","Loshesk","Loshichi","Lubech","Lubno","Lubutsk","Lutsk","Luchin","Luki","Lukoml","Luzha","Lvov","Mtsensk","Mdin","Medniki","Melecha","Merech","Meretsk","Mescherskoe","Meshkovsk","Metlitsk","Mezetsk","Mglin","Mihailov","Mikitin","Mikulino","Miloslavichi","Mogilev","Mologa","Moreva","Mosalsk","Moschiny","Mozyr","Mstislav","Mstislavets","Muravin","Nemech","Nemiza","Nerinsk","Nichan","Novgorod","Novogorodok","Obolichi","Obolensk","Obolensk","Oleshsk","Olgov","Omelnik","Opoka","Opoki","Oreshek","Orlets","Osechen","Oster","Ostrog","Ostrov","Perelai","Peremil","Peremyshl","Pererov","Peresechen","Perevitsk","Pereyaslav","Pinsk","Ples","Polotsk","Pronsk","Proposhesk","Punia","Putivl","Rechitsa","Rodno","Rogachev","Romanov","Romny","Roslavl","Rostislavl","Rostovets","Rsha","Ruza","Rybchesk","Rylsk","Rzhavesk","Rzhev","Rzhischev","Sambor","Serensk","Serensk","Serpeysk","Shilov","Shuya","Sinech","Sizhka","Skala","Slovensk","Slutsk","Smedin","Sneporod","Snitin","Snovsk","Sochevo","Sokolec","Starica","Starodub","Stepan","Sterzh","Streshin","Sutesk","Svinetsk","Svisloch","Terebovl","Ternov","Teshilov","Teterin","Tiversk","Torchevsk","Toropets","Torzhok","Tripolye","Trubchevsk","Tur","Turov","Usvyaty","Uteshkov","Vasilkov","Velil","Velye","Venev","Venicha","Verderev","Vereya","Veveresk","Viazma","Vidbesk","Vidychev","Voino","Volodimer","Volok","Volyn","Vorobesk","Voronich","Voronok","Vorotynsk","Vrev","Vruchiy","Vselug","Vyatichsk","Vyatka","Vyshegorod","Vyshgorod","Vysokoe","Yagniatin","Yaropolch","Yasenets","Yuryev","Yuryevets","Zaraysk","Zhitomel","Zholvazh","Zizhech","Zubkov","Zudechev","Zvenigorod"],
["Akureyri","Aldra","Alftanes","Andenes","Austbo","Auvog","Bakkafjordur","Ballangen","Bardal","Beisfjord","Bifrost","Bildudalur","Bjerka","Bjerkvik","Bjorkosen","Bliksvaer","Blokken","Blonduos","Bolga","Bolungarvik","Borg","Borgarnes","Bosmoen","Bostad","Bostrand","Botsvika","Brautarholt","Breiddalsvik","Bringsli","Brunahlid","Budardalur","Byggdakjarni","Dalvik","Djupivogur","Donnes","Drageid","Drangsnes","Egilsstadir","Eiteroga","Elvenes","Engavogen","Ertenvog","Eskifjordur","Evenes","Eyrarbakki","Fagernes","Fallmoen","Fellabaer","Fenes","Finnoya","Fjaer","Fjelldal","Flakstad","Flateyri","Flostrand","Fludir","Gardaber","Gardur","Gimstad","Givaer","Gjeroy","Gladstad","Godoya","Godoynes","Granmoen","Gravdal","Grenivik","Grimsey","Grindavik","Grytting","Hafnir","Halsa","Hauganes","Haugland","Hauknes","Hella","Helland","Hellissandur","Hestad","Higrav","Hnifsdalur","Hofn","Hofsos","Holand","Holar","Holen","Holkestad","Holmavik","Hopen","Hovden","Hrafnagil","Hrisey","Husavik","Husvik","Hvammstangi","Hvanneyri","Hveragerdi","Hvolsvollur","Igeroy","Indre","Inndyr","Innhavet","Innes","Isafjordur","Jarklaustur","Jarnsreykir","Junkerdal","Kaldvog","Kanstad","Karlsoy","Kavosen","Keflavik","Kjelde","Kjerstad","Klakk","Kopasker","Kopavogur","Korgen","Kristnes","Krutoga","Krystad","Kvina","Lande","Laugar","Laugaras","Laugarbakki","Laugarvatn","Laupstad","Leines","Leira","Leiren","Leland","Lenvika","Loding","Lodingen","Lonsbakki","Lopsmarka","Lovund","Luroy","Maela","Melahverfi","Meloy","Mevik","Misvaer","Mornes","Mosfellsber","Moskenes","Myken","Naurstad","Nesberg","Nesjahverfi","Nesset","Nevernes","Obygda","Ofoten","Ogskardet","Okervika","Oknes","Olafsfjordur","Oldervika","Olstad","Onstad","Oppeid","Oresvika","Orsnes","Orsvog","Osmyra","Overdal","Prestoya","Raudalaekur","Raufarhofn","Reipo","Reykholar","Reykholt","Reykjahlid","Rif","Rinoya","Rodoy","Rognan","Rosvika","Rovika","Salhus","Sanden","Sandgerdi","Sandoker","Sandset","Sandvika","Saudarkrokur","Selfoss","Selsoya","Sennesvik","Setso","Siglufjordur","Silvalen","Skagastrond","Skjerstad","Skonland","Skorvogen","Skrova","Sleneset","Snubba","Softing","Solheim","Solheimar","Sorarnoy","Sorfugloy","Sorland","Sormela","Sorvaer","Sovika","Stamsund","Stamsvika","Stave","Stokka","Stokkseyri","Storjord","Storo","Storvika","Strand","Straumen","Strendene","Sudavik","Sudureyri","Sundoya","Sydalen","Thingeyri","Thorlakshofn","Thorshofn","Tjarnabyggd","Tjotta","Tosbotn","Traelnes","Trofors","Trones","Tverro","Ulvsvog","Unnstad","Utskor","Valla","Vandved","Varmahlid","Vassos","Vevelstad","Vidrek","Vik","Vikholmen","Vogar","Vogehamn","Vopnafjordur"],
["Abdera","Abila","Abydos","Acanthus","Acharnae","Actium","Adramyttium","Aegae","Aegina","Aegium","Aenus","Agrinion","Aigosthena","Akragas","Akrai","Akrillai","Akroinon","Akrotiri","Alalia","Alexandreia","Alexandretta","Alexandria","Alinda","Amarynthos","Amaseia","Ambracia","Amida","Amisos","Amnisos","Amphicaea","Amphigeneia","Amphipolis","Amphissa","Ankon","Antigona","Antipatrea","Antioch","Antioch","Antiochia","Andros","Apamea","Aphidnae","Apollonia","Argos","Arsuf","Artanes","Artemita","Argyroupoli","Asine","Asklepios","Aspendos","Assus","Astacus","Athenai","Athmonia","Aytos","Ancient","Baris","Bhrytos","Borysthenes","Berge","Boura","Bouthroton","Brauron","Byblos","Byllis","Byzantium","Bythinion","Callipolis","Cebrene","Chalcedon","Calydon","Carystus","Chamaizi","Chalcis","Chersonesos","Chios","Chytri","Clazomenae","Cleonae","Cnidus","Colosse","Corcyra","Croton","Cyme","Cyrene","Cythera","Decelea","Delos","Delphi","Demetrias","Dicaearchia","Dimale","Didyma","Dion","Dioscurias","Dodona","Dorylaion","Dyme","Edessa","Elateia","Eleusis","Eleutherna","Emporion","Ephesus","Ephyra","Epidamnos","Epidauros","Eresos","Eretria","Erythrae","Eubea","Gangra","Gaza","Gela","Golgi","Gonnos","Gorgippia","Gournia","Gortyn","Gythium","Hagios","Hagia","Halicarnassus","Halieis","Helike","Heliopolis","Hellespontos","Helorus","Hemeroskopeion","Heraclea","Hermione","Hermonassa","Hierapetra","Hierapolis","Himera","Histria","Hubla","Hyele","Ialysos","Iasus","Idalium","Imbros","Iolcus","Itanos","Ithaca","Juktas","Kallipolis","Kamares","Kameiros","Kannia","Kamarina","Kasmenai","Katane","Kerkinitida","Kepoi","Kimmerikon","Kios","Klazomenai","Knidos","Knossos","Korinthos","Kos","Kourion","Kume","Kydonia","Kynos","Kyrenia","Lamia","Lampsacus","Laodicea","Lapithos","Larissa","Lato","Laus","Lebena","Lefkada","Lekhaion","Leibethra","Leontinoi","Lepreum","Lessa","Lilaea","Lindus","Lissus","Epizephyrian","Madytos","Magnesia","Mallia","Mantineia","Marathon","Marmara","Maroneia","Masis","Massalia","Megalopolis","Megara","Mesembria","Messene","Metapontum","Methana","Methone","Methumna","Miletos","Misenum","Mochlos","Monastiraki","Morgantina","Mulai","Mukenai","Mylasa","Myndus","Myonia","Myra","Myrmekion","Mutilene","Myos","Nauplios","Naucratis","Naupactus","Naxos","Neapoli","Neapolis","Nemea","Nicaea","Nicopolis","Nirou","Nymphaion","Nysa","Oenoe","Oenus","Odessos","Olbia","Olous","Olympia","Olynthus","Opus","Orchomenus","Oricos","Orestias","Oreus","Oropus","Onchesmos","Pactye","Pagasae","Palaikastro","Pandosia","Panticapaeum","Paphos","Parium","Paros","Parthenope","Patrae","Pavlopetri","Pegai","Pelion","Peiraies","Pella","Percote","Pergamum","Petsofa","Phaistos","Phaleron","Phanagoria","Pharae","Pharnacia","Pharos","Phaselis","Philippi","Pithekussa","Philippopolis","Platanos","Phlius","Pherae","Phocaea","Pinara","Pisa","Pitane","Pitiunt","Pixous","Plataea","Poseidonia","Potidaea","Priapus","Priene","Prousa","Pseira","Psychro","Pteleum","Pydna","Pylos","Pyrgos","Rhamnus","Rhegion","Rhithymna","Rhodes","Rhypes","Rizinia","Salamis","Same","Samos","Scyllaeum","Selinus","Seleucia","Semasus","Sestos","Scidrus","Sicyon","Side","Sidon","Siteia","Sinope","Siris","Sklavokampos","Smyrna","Soli","Sozopolis","Sparta","Stagirus","Stratos","Stymphalos","Sybaris","Surakousai","Taras","Tanagra","Tanais","Tauromenion","Tegea","Temnos","Tenedos","Tenea","Teos","Thapsos","Thassos","Thebai","Theodosia","Therma","Thespiae","Thronion","Thoricus","Thurii","Thyreum","Thyria","Tiruns","Tithoraea","Tomis","Tragurion","Trapeze","Trapezus","Tripolis","Troizen","Troliton","Troy","Tylissos","Tyras","Tyros","Tyritake","Vasiliki","Vathypetros","Zakynthos","Zakros","Zankle"],
["Abila","Adflexum","Adnicrem","Aelia","Aelius","Aeminium","Aequum","Agrippina","Agrippinae","Ala","Albanianis","Ambianum","Andautonia","Apulum","Aquae","Aquaegranni","Aquensis","Aquileia","Aquincum","Arae","Argentoratum","Ariminum","Ascrivium","Atrebatum","Atuatuca","Augusta","Aurelia","Aurelianorum","Batavar","Batavorum","Belum","Biriciana","Blestium","Bonames","Bonna","Bononia","Borbetomagus","Bovium","Bracara","Brigantium","Burgodunum","Caesaraugusta","Caesarea","Caesaromagus","Calleva","Camulodunum","Cannstatt","Cantiacorum","Capitolina","Castellum","Castra","Castrum","Cibalae","Clausentum","Colonia","Concangis","Condate","Confluentes","Conimbriga","Corduba","Coria","Corieltauvorum","Corinium","Coriovallum","Cornoviorum","Danum","Deva","Divodurum","Dobunnorum","Drusi","Dubris","Dumnoniorum","Durnovaria","Durocobrivis","Durocornovium","Duroliponte","Durovernum","Durovigutum","Eboracum","Edetanorum","Emerita","Emona","Euracini","Faventia","Flaviae","Florentia","Forum","Gerulata","Gerunda","Glevensium","Hadriani","Herculanea","Isca","Italica","Iulia","Iuliobrigensium","Iuvavum","Lactodurum","Lagentium","Lauri","Legionis","Lemanis","Lentia","Lepidi","Letocetum","Lindinis","Lindum","Londinium","Lopodunum","Lousonna","Lucus","Lugdunum","Luguvalium","Lutetia","Mancunium","Marsonia","Martius","Massa","Matilo","Mattiacorum","Mediolanum","Mod","Mogontiacum","Moridunum","Mursa","Naissus","Nervia","Nida","Nigrum","Novaesium","Noviomagus","Olicana","Ovilava","Parisiorum","Partiscum","Paterna","Pistoria","Placentia","Pollentia","Pomaria","Pons","Portus","Praetoria","Praetorium","Pullum","Ragusium","Ratae","Raurica","Regina","Regium","Regulbium","Rigomagus","Roma","Romula","Rutupiae","Salassorum","Salernum","Salona","Scalabis","Segovia","Silurum","Sirmium","Siscia","Sorviodurum","Sumelocenna","Tarraco","Taurinorum","Theranda","Traiectum","Treverorum","Tungrorum","Turicum","Ulpia","Valentia","Venetiae","Venta","Verulamium","Vesontio","Vetera","Victoriae","Victrix","Villa","Viminacium","Vindelicorum","Vindobona","Vinovia","Viroconium"],
["Aanekoski","Abjapaluoja","Ahlainen","Aholanvaara","Ahtari","Aijala","Aimala","Akaa","Alajarvi","Alatornio","Alavus","Antsla","Aspo","Bennas","Bjorkoby","Elva","Emasalo","Espoo","Esse","Evitskog","Forssa","Haapajarvi","Haapamaki","Haapavesi","Haapsalu","Haavisto","Hameenlinna","Hameenmaki","Hamina","Hanko","Harjavalta","Hattuvaara","Haukipudas","Hautajarvi","Havumaki","Heinola","Hetta","Hinkabole","Hirmula","Hossa","Huittinen","Husula","Hyryla","Hyvinkaa","Iisalmi","Ikaalinen","Ilmola","Imatra","Inari","Iskmo","Itakoski","Jamsa","Jarvenpaa","Jeppo","Jioesuu","Jiogeva","Joensuu","Jokela","Jokikyla","Jokisuu","Jormua","Juankoski","Jungsund","Jyvaskyla","Kaamasmukka","Kaarina","Kajaani","Kalajoki","Kallaste","Kankaanpaa","Kannus","Kardla","Karesuvanto","Karigasniemi","Karkkila","Karkku","Karksinuia","Karpankyla","Kaskinen","Kasnas","Kauhajoki","Kauhava","Kauniainen","Kauvatsa","Kehra","Keila","Kellokoski","Kelottijarvi","Kemi","Kemijarvi","Kerava","Keuruu","Kiikka","Kiipu","Kilinginiomme","Kiljava","Kilpisjarvi","Kitee","Kiuruvesi","Kivesjarvi","Kiviioli","Kivisuo","Klaukkala","Klovskog","Kohtlajarve","Kokemaki","Kokkola","Kolho","Koria","Koskue","Kotka","Kouva","Kouvola","Kristiina","Kaupunki","Kuhmo","Kunda","Kuopio","Kuressaare","Kurikka","Kusans","Kuusamo","Kylmalankyla","Lahti","Laitila","Lankipohja","Lansikyla","Lappeenranta","Lapua","Laurila","Lautiosaari","Lepsama","Liedakkala","Lieksa","Lihula","Littoinen","Lohja","Loimaa","Loksa","Loviisa","Luohuanylipaa","Lusi","Maardu","Maarianhamina","Malmi","Mantta","Masaby","Masala","Matasvaara","Maula","Miiluranta","Mikkeli","Mioisakula","Munapirtti","Mustvee","Muurahainen","Naantali","Nappa","Narpio","Nickby","Niinimaa","Niinisalo","Nikkila","Nilsia","Nivala","Nokia","Nummela","Nuorgam","Nurmes","Nuvvus","Obbnas","Oitti","Ojakkala","Ollola","onningeby","Orimattila","Orivesi","Otanmaki","Otava","Otepaa","Oulainen","Oulu","Outokumpu","Paavola","Paide","Paimio","Pakankyla","Paldiski","Parainen","Parkano","Parkumaki","Parola","Perttula","Pieksamaki","Pietarsaari","Pioltsamaa","Piolva","Pohjavaara","Porhola","Pori","Porrasa","Porvoo","Pudasjarvi","Purmo","Pussi","Pyhajarvi","Raahe","Raasepori","Raisio","Rajamaki","Rakvere","Rapina","Rapla","Rauma","Rautio","Reposaari","Riihimaki","Rovaniemi","Roykka","Ruonala","Ruottala","Rutalahti","Saarijarvi","Salo","Sastamala","Saue","Savonlinna","Seinajoki","Sillamae","Sindi","Siuntio","Somero","Sompujarvi","Suonenjoki","Suurejaani","Syrjantaka","Tampere","Tamsalu","Tapa","Temmes","Tiorva","Tormasenvaara","Tornio","Tottijarvi","Tulppio","Turenki","Turi","Tuukkala","Tuurala","Tuuri","Tuuski","Ulvila","Unari","Upinniemi","Utti","Uusikaarlepyy","Uusikaupunki","Vaaksy","Vaalimaa","Vaarinmaja","Vaasa","Vainikkala","Valga","Valkeakoski","Vantaa","Varkaus","Vehkapera","Vehmasmaki","Vieki","Vierumaki","Viitasaari","Viljandi","Vilppula","Viohma","Vioru","Virrat","Ylike","Ylivieska","Ylojarvi"],
["Aewor","Andong","Angang","Anjung","Anmyeon","Ansan","Anseong","Anyang","Aphae","Apo","Asan","Baebang","Baekseok","Baeksu","Beobwon","Beolgyo","Beomseo","Boeun","Bongdam","Bongdong","Bonghwa","Bongyang","Boryeong","Boseong","Buan","Bubal","Bucheon","Buksam","Busan","Busan","Busan","Buyeo","Changnyeong","Changwon","Cheonan","Cheongdo","Cheongjin","Cheongju","Cheongju","Cheongsong","Cheongyang","Cheorwon","Chirwon","Chowol","Chuncheon","Chuncheon","Chungju","Chungmu","Daecheon","Daedeok","Daegaya","Daegu","Daegu","Daegu","Daejeon","Daejeon","Daejeon","Daejeong","Daesan","Damyang","Dangjin","Danyang","Dasa","Dogye","Dolsan","Dong","Dongducheon","Donggwangyang","Donghae","Dongsong","Doyang","Eonyang","Eumseong","Gaeseong","Galmal","Gampo","Ganam","Ganggyeong","Ganghwa","Gangjin","Gangneung","Ganseong","Gapyeong","Gaun","Gaya","Geochang","Geoje","Geojin","Geoncheon","Geumho","Geumil","Geumsan","Geumseong","Geumwang","Gijang","Gimcheon","Gimhae","Gimhwa","Gimje","Gimpo","Goa","Gochang","Gochon","Goesan","Gohan","Goheung","Gokseong","Gongdo","Gongju","Gonjiam","Goseong","Goyang","Gujwa","Gumi","Gungnae","Gunpo","Gunsan","Gunsan","Gunwi","Guri","Gurye","Guryongpo","Gwacheon","Gwangcheon","Gwangju","Gwangju","Gwangju","Gwangju","Gwangmyeong","Gwangyang","Gwansan","Gyeongju","Gyeongsan","Gyeongseong","Gyeongseong","Gyeryong","Hadong","Haeju","Haenam","Hamchang","Hamheung","Hampyeong","Hamyang","Hamyeol","Hanam","Hanrim","Hapcheon","Hapdeok","Hayang","Heunghae","Heungnam","Hoengseong","Hongcheon","Hongnong","Hongseong","Hwacheon","Hwado","Hwando","Hwaseong","Hwasun","Hwawon","Hyangnam","Icheon","Iksan","Illo","Imsil","Incheon","Incheon","Incheon","Inje","Iri","Iri","Jangan","Janghang","Jangheung","Janghowon","Jangseong","Jangseungpo","Jangsu","Jecheon","Jeju","Jeomchon","Jeongeup","Jeonggwan","Jeongju","Jeongok","Jeongseon","Jeonju","Jeonju","Jeungpyeong","Jido","Jiksan","Jillyang","Jinan","Jincheon","Jindo","Jingeon","Jinhae","Jinjeop","Jinju","Jinju","Jinnampo","Jinyeong","Jocheon","Jochiwon","Jori","Judeok","Jumunjin","Maepo","Mangyeong","Masan","Masan","Migeum","Miryang","Mokcheon","Mokpo","Mokpo","Muan","Muju","Mungyeong","Munmak","Munsan","Munsan","Naeseo","Naesu","Najin","Naju","Namhae","Namji","Nampyeong","Namwon","Namyang","Namyangju","Nohwa","Nongong","Nonsan","Ochang","Ocheon","Oedong","Okcheon","Okgu","Onam","Onsan","Onyang","Opo","Osan","Osong","Paengseong","Paju","Pocheon","Pogok","Pohang","Poseung","Punggi","Pungsan","Pyeongchang","Pyeonghae","Pyeongtaek","Pyeongyang","Sabi","Sabuk","Sacheon","Samcheok","Samcheonpo","Samho","Samhyang","Samnangjin","Samrye","Sancheong","Sangdong","Sangju","Sanyang","Sapgyo","Sariwon","Sejong","Seocheon","Seogwipo","Seokjeok","Seonggeo","Seonghwan","Seongjin","Seongju","Seongnam","Seongsan","Seonsan","Seosan","Seoul","Seungju","Siheung","Sinbuk","Sindong","Sineuiju","Sintaein","Soheul","Sokcho","Songak","Songjeong","Songnim","Songtan","Sunchang","Suncheon","Suwon","Taean","Taebaek","Tongjin","Tongyeong","Uijeongbu","Uiryeong","Uiseong","Uiwang","Ujeong","Uljin","Ulleung","Ulsan","Ulsan","Unbong","Ungcheon","Ungjin","Wabu","Waegwan","Wando","Wanggeomseong","Wiryeseong","Wondeok","Wonju","Wonsan","Yangchon","Yanggu","Yangju","Yangpyeong","Yangsan","Yangyang","Yecheon","Yeocheon","Yeoju","Yeomchi","Yeoncheon","Yeongam","Yeongcheon","Yeongdeok","Yeongdong","Yeonggwang","Yeongju","Yeongwol","Yeongyang","Yeonil","Yeonmu","Yeosu","Yesan","Yongin","Yongjin","Yugu","Wayang"],
["Anding","Anlu","Anqing","Anshun","Baan","Baixing","Banyang","Baoding","Baoqing","Binzhou","Caozhou","Changbai","Changchun","Changde","Changling","Changsha","Changtu","Changzhou","Chaozhou","Cheli","Chengde","Chengdu","Chenzhou","Chizhou","Chongqing","Chuxiong","Chuzhou","Dading","Dali","Daming","Datong","Daxing","Dean","Dengke","Dengzhou","Deqing","Dexing","Dihua","Dingli","Dongan","Dongchang","Dongchuan","Dongping","Duyun","Fengtian","Fengxiang","Fengyang","Fenzhou","Funing","Fuzhou","Ganzhou","Gaoyao","Gaozhou","Gongchang","Guangnan","Guangning","Guangping","Guangxin","Guangzhou","Guide","Guilin","Guiyang","Hailong","Hailun","Hangzhou","Hanyang","Hanzhong","Heihe","Hejian","Henan","Hengzhou","Hezhong","Huaian","Huaide","Huaiqing","Huanglong","Huangzhou","Huining","Huizhou","Hulan","Huzhou","Jiading","Jian","Jianchang","Jiande","Jiangning","Jiankang","Jianning","Jiaxing","Jiayang","Jilin","Jinan","Jingjiang","Jingzhao","Jingzhou","Jinhua","Jinzhou","Jiujiang","Kaifeng","Kaihua","Kangding","Kuizhou","Laizhou","Lanzhou","Leizhou","Liangzhou","Lianzhou","Liaoyang","Lijiang","Linan","Linhuang","Linjiang","Lintao","Liping","Liuzhou","Longan","Longjiang","Longqing","Longxing","Luan","Lubin","Lubin","Luzhou","Mishan","Nanan","Nanchang","Nandian","Nankang","Nanning","Nanyang","Nenjiang","Ningan","Ningbo","Ningguo","Ninguo","Ningwu","Ningxia","Ningyuan","Pingjiang","Pingle","Pingliang","Pingyang","Puer","Puzhou","Qianzhou","Qingyang","Qingyuan","Qingzhou","Qiongzhou","Qujing","Quzhou","Raozhou","Rende","Ruian","Ruizhou","Runing","Shafeng","Shajing","Shaoqing","Shaowu","Shaoxing","Shaozhou","Shinan","Shiqian","Shouchun","Shuangcheng","Shulei","Shunde","Shunqing","Shuntian","Shuoping","Sicheng","Sien","Sinan","Sizhou","Songjiang","Suiding","Suihua","Suining","Suzhou","Taian","Taibei","Tainan","Taiping","Taiwan","Taiyuan","Taizhou","Taonan","Tengchong","Tieli","Tingzhou","Tongchuan","Tongqing","Tongren","Tongzhou","Weihui","Wensu","Wenzhou","Wuchang","Wuding","Wuzhou","Xian","Xianchun","Xianping","Xijin","Xiliang","Xincheng","Xingan","Xingde","Xinghua","Xingjing","Xingqing","Xingyi","Xingyuan","Xingzhong","Xining","Xinmen","Xiping","Xuanhua","Xunzhou","Xuzhou","Yanan","Yangzhou","Yanji","Yanping","Yanqi","Yanzhou","Yazhou","Yichang","Yidu","Yilan","Yili","Yingchang","Yingde","Yingtian","Yingzhou","Yizhou","Yongchang","Yongping","Yongshun","Yongzhou","Yuanzhou","Yuezhou","Yulin","Yunnan","Yunyang","Zezhou","Zhangde","Zhangzhou","Zhaoqing","Zhaotong","Zhenan","Zhending","Zhengding","Zhenhai","Zhenjiang","Zhenxi","Zhenyun","Zhongshan","Zunyi"],
["Abira","Aga","Aikawa","Aizumisato","Ajigasawa","Akkeshi","Amagi","Ami","Anan","Ando","Asakawa","Ashikita","Bandai","Biratori","China","Chonan","Esashi","Fuchu","Fujimi","Funagata","Genkai","Godo","Goka","Gonohe","Gyokuto","Haboro","Hamatonbetsu","Happo","Harima","Hashikami","Hayashima","Heguri","Hidaka","Higashiagatsuma","Higashiura","Hiranai","Hirogawa","Hiroo","Hodatsushimizu","Hoki","Hokuei","Hokuryu","Horokanai","Ibigawa","Ichikai","Ichikawamisato","Ichinohe","Iide","Iijima","Iizuna","Ikawa","Inagawa","Itakura","Iwaizumi","Iwate","Kagamino","Kaisei","Kamifurano","Kamiita","Kamijima","Kamikawa","Kamikawa","Kamikawa","Kaminokawa","Kamishihoro","Kamitonda","Kamiyama","Kanda","Kanna","Kasagi","Kasuya","Katsuura","Kawabe","Kawagoe","Kawajima","Kawamata","Kawamoto","Kawanehon","Kawanishi","Kawara","Kawasaki","Kawasaki","Kawatana","Kawazu","Kihoku","Kikonai","Kin","Kiso","Kitagata","Kitajima","Kiyama","Kiyosato","Kofu","Koge","Kohoku","Kokonoe","Kora","Kosa","Kosaka","Kotohira","Kudoyama","Kumejima","Kumenan","Kumiyama","Kunitomi","Kurate","Kushimoto","Kutchan","Kyonan","Kyotamba","Mashike","Matsumae","Mifune","Mihama","Minabe","Minami","Minamiechizen","Minamioguni","Minamiosumi","Minamitane","Misaki","Misasa","Misato","Miyashiro","Miyoshi","Mori","Moseushi","Mutsuzawa","Nagaizumi","Nagatoro","Nagayo","Nagomi","Nakadomari","Nakanojo","Nakashibetsu","Nakatosa","Namegawa","Namie","Nanbu","Nanporo","Naoshima","Nasu","Niseko","Nishihara","Nishiizu","Nishikatsura","Nishikawa","Nishinoshima","Nishiwaga","Nogi","Noto","Nyuzen","Oarai","Obuse","Odai","Ogawara","Oharu","Oi","Oirase","Oishida","Oiso","Oizumi","Oji","Okagaki","Oketo","Okutama","Omu","Ono","Osaki","Osakikamijima","Otobe","Otsuki","Owani","Reihoku","Rifu","Rikubetsu","Rishiri","Rokunohe","Ryuo","Saka","Sakuho","Samani","Satsuma","Sayo","Saza","Setana","Shakotan","Shibayama","Shikama","Shimamoto","Shimizu","Shimokawa","Shintomi","Shirakawa","Shisui","Shitara","Sobetsu","Sue","Sumita","Suooshima","Suttsu","Tabuse","Tachiarai","Tadami","Tadaoka","Taiji","Taiki","Takachiho","Takahama","Taketoyo","Tako","Taragi","Tateshina","Tatsugo","Tawaramoto","Teshikaga","Tobe","Toin","Tokigawa","Toma","Tomioka","Tonosho","Tosa","Toyo","Toyokoro","Toyotomi","Toyoyama","Tsubata","Tsubetsu","Tsukigata","Tsunan","Tsuno","Tsuwano","Umi","Wakasa","Yamamoto","Yamanobe","Yamatsuri","Yanaizu","Yasuda","Yoichi","Yonaguni","Yoro","Yoshino","Yubetsu","Yugawara","Yuni","Yusuhara","Yuza"],
["Abrigada","Afonsoeiro","Agueda","Aguiar","Aguilada","Alagoas","Alagoinhas","Albufeira","Alcacovas","Alcanhoes","Alcobaca","Alcochete","Alcoutim","Aldoar","Alexania","Alfeizerao","Algarve","Alenquer","Almada","Almagreira","Almeirim","Alpalhao","Alpedrinha","Alvalade","Alverca","Alvor","Alvorada","Amadora","Amapa","Amieira","Anapolis","Anhangueira","Ansiaes","Apelacao","Aracaju","Aranhas","Arega","Areira","Araguaina","Araruama","Arganil","Armacao","Arouca","Asfontes","Assenceira","Avelar","Aveiro","Azambuja","Azinheira","Azueira","Bahia","Bairros","Balsas","Barcarena","Barreiras","Barreiro","Barretos","Batalha","Beira","Beja","Benavente","Betim","Boticas","Braga","Braganca","Brasilia","Brejo","Cabecao","Cabeceiras","Cabedelo","Cabofrio","Cachoeiras","Cadafais","Calheta","Calihandriz","Calvao","Camacha","Caminha","Campinas","Canidelo","Canha","Canoas","Capinha","Carmoes","Cartaxo","Carvalhal","Carvoeiro","Cascavel","Castanhal","Castelobranco","Caueira","Caxias","Chapadinha","Chaves","Celheiras","Cocais","Coimbra","Comporta","Coentral","Conde","Copacabana","Coqueirinho","Coruche","Corumba","Couco","Cubatao","Curitiba","Damaia","Doisportos","Douradilho","Dourados","Enxames","Enxara","Erada","Erechim","Ericeira","Ermidasdosado","Ervidel","Escalhao","Escariz","Esmoriz","Estombar","Espinhal","Espinho","Esposende","Esquerdinha","Estela","Estoril","Eunapolis","Evora","Famalicao","Famoes","Fanhoes","Fanzeres","Fatela","Fatima","Faro","Felgueiras","Ferreira","Figueira","Flecheiras","Florianopolis","Fornalhas","Fortaleza","Freiria","Freixeira","Frielas","Fronteira","Funchal","Fundao","Gaeiras","Gafanhadaboahora","Goa","Goiania","Gracas","Gradil","Grainho","Gralheira","Guarulhos","Guetim","Guimaraes","Horta","Iguacu","Igrejanova","Ilhavo","Ilheus","Ipanema","Iraja","Itaboral","Itacuruca","Itaguai","Itanhaem","Itapevi","Juazeiro","Lagos","Lavacolchos","Laies","Lamego","Laranjeiras","Leiria","Limoeiro","Linhares","Lisboa","Lomba","Lorvao","Lourencomarques","Lourical","Lourinha","Luziania","Macao","Macapa","Macedo","Machava","Malveira","Manaus","Mangabeira","Mangaratiba","Marambaia","Maranhao","Maringue","Marinhais","Matacaes","Matosinhos","Maxial","Maxias","Mealhada","Meimoa","Meires","Milharado","Mira","Miranda","Mirandela","Mogadouro","Montalegre","Montesinho","Moura","Mourao","Mozelos","Negroes","Neiva","Nespereira","Nilopolis","Niteroi","Nordeste","Obidos","Odemira","Odivelas","Oeiras","Oleiros","Olhao","Olhalvo","Olhomarinho","Olinda","Olival","Oliveira","Oliveirinha","Oporto","Ourem","Ovar","Palhais","Palheiros","Palmeira","Palmela","Palmital","Pampilhosa","Pantanal","Paradinha","Parelheiros","Paripueira","Paudalho","Pedrosinho","Penafiel","Peniche","Pedrogao","Pegoes","Pinhao","Pinheiro","Pinhel","Pombal","Pontal","Pontinha","Portel","Portimao","Poxim","Quarteira","Queijas","Queluz","Quiaios","Ramalhal","Reboleira","Recife","Redinha","Ribadouro","Ribeira","Ribeirao","Rosais","Roteiro","Sabugal","Sacavem","Sagres","Sandim","Sangalhos","Santarem","Santos","Sarilhos","Sarzedas","Satao","Satuba","Seixal","Seixas","Seixezelo","Seixo","Selmes","Sepetiba","Serta","Setubal","Silvares","Silveira","Sinhaem","Sintra","Sobral","Sobralinho","Sorocaba","Tabuacotavir","Tabuleiro","Taveiro","Teixoso","Telhado","Telheiro","Tomar","Torrao","Torreira","Torresvedras","Tramagal","Trancoso","Troviscal","Vagos","Valpacos","Varzea","Vassouras","Velas","Viana","Vidigal","Vidigueira","Vidual","Viladerei","Vilamar","Vimeiro","Vinhais","Vinhos","Viseu","Vitoria","Vlamao","Vouzela"],
["Acaltepec","Acaltepecatl","Acapulco","Acatlan","Acaxochitlan","Ajuchitlan","Atotonilco","Azcapotzalco","Camotlan","Campeche","Chalco","Chapultepec","Chiapan","Chiapas","Chihuahua","Cihuatlan","Cihuatlancihuatl","Coahuila","Coatepec","Coatlan","Coatzacoalcos","Colima","Colotlan","Coyoacan","Cuauhillan","Cuauhnahuac","Cuauhtemoc","Cuernavaca","Ecatepec","Epatlan","Guanajuato","Huaxacac","Huehuetlan","Hueyapan","Ixtapa","Iztaccihuatl","Iztapalapa","Jalisco","Jocotepec","Jocotepecxocotl","Matixco","Mazatlan","Michhuahcan","Michoacan","Michoacanmichin","Minatitlan","Naucalpan","Nayarit","Nezahualcoyotl","Oaxaca","Ocotepec","Ocotlan","Olinalan","Otompan","Popocatepetl","Queretaro","Sonora","Tabasco","Tamaulipas","Tecolotlan","Tenochtitlan","Teocuitlatlan","Teocuitlatlanteotl","Teotlalco","Teotlalcoteotl","Tepotzotlan","Tepoztlantepoztli","Texcoco","Tlachco","Tlalocan","Tlaxcala","Tlaxcallan","Tollocan","Tolutepetl","Tonanytlan","Tototlan","Tuchtlan","Tuxpan","Uaxacac","Xalapa","Xochimilco","Xolotlan","Yaotlan","Yopico","Yucatan","Yztac","Zacatecas","Zacualco"],
["Aba","Abadszalok","Abony","Adony","Ajak","Albertirsa","Alsozsolca","Aszod","Babolna","Bacsalmas","Baktaloranthaza","Balassagyarmat","Balatonalmadi","Balatonboglar","Balatonfured","Balatonfuzfo","Balkany","Balmazujvaros","Barcs","Bataszek","Batonyterenye","Battonya","Bekes","Berettyoujfalu","Berhida","Biatorbagy","Bicske","Biharkeresztes","Bodajk","Boly","Bonyhad","Budakalasz","Budakeszi","Celldomolk","Csakvar","Csenger","Csongrad","Csorna","Csorvas","Csurgo","Dabas","Demecser","Derecske","Devavanya","Devecser","Dombovar","Dombrad","Dorogullo","Dunafoldvar","Dunaharaszti","Dunavarsany","Dunavecse","Edeleny","Elek","Emod","Encs","Enying","Ercsi","Fegyvernek","Fehergyarmat","Felsozsolca","Fertoszentmiklos","Fonyod","Fot","Fuzesabony","Fuzesgyarmat","Gardony","God","Gyal","Gyomaendrod","Gyomro","Hajdudorog","Hajduhadhaz","Hajdunanas","Hajdusamson","Hajduszoboszlo","Halasztelek","Harkany","Hatvan","Heves","Heviz","Ibrany","Isaszeg","Izsak","Janoshalma","Janossomorja","Jaszapati","Jaszarokszallas","Jaszfenyszaru","Jaszkiser","Kaba","Kalocsa","Kapuvar","Karcag","Kecel","Kemecse","Kenderes","Kerekegyhaza","Kerepes","Keszthely","Kisber","Kiskoros","Kiskunmajsa","Kistarcsa","Kistelek","Kisujszallas","Kisvarda","Komadi","Komarom","Komlo","Kormend","Korosladany","Koszeg","Kozarmisleny","Kunhegyes","Kunszentmarton","Kunszentmiklos","Labatlan","Lajosmizse","Lenti","Letavertes","Letenye","Lorinci","Maglod","Mako","Mandok","Marcali","Martfu","Martonvasar","Mateszalka","Melykut","Mezobereny","Mezocsat","Mezohegyes","Mezokeresztes","Mezokovacshaza","Mezokovesd","Mezotur","Mindszent","Mohacs","Monor","Mor","Morahalom","Nadudvar","Nagyatad","Nagyecsed","Nagyhalasz","Nagykallo","Nagykata","Nagykoros","Nagymaros","Nyekladhaza","Nyergesujfalu","Nyiradony","Nyirbator","Nyirmada","Nyirtelek","Ocsa","Orkeny","Oroszlany","Paks","Pannonhalma","Paszto","Pecel","Pecsvarad","Pilis","Pilisvorosvar","Polgar","Polgardi","Pomaz","Puspokladany","Pusztaszabolcs","Putnok","Racalmas","Rackeve","Rakamaz","Rakoczifalva","Sajoszentpeter","Sandorfalva","Sarbogard","Sarkad","Sarospatak","Sarvar","Satoraljaujhely","Siklos","Simontornya","Solt","Soltvadkert","Sumeg","Szabadszallas","Szarvas","Szazhalombatta","Szecseny","Szeghalom","Szendro","Szentgotthard","Szentlorinc","Szerencs","Szigethalom","Szigetvar","Szikszo","Tab","Tamasi","Tapioszele","Tapolca","Tat","Tata","Teglas","Tet","Tiszacsege","Tiszafoldvar","Tiszafured","Tiszakecske","Tiszalok","Tiszaujvaros","Tiszavasvari","Tokaj","Tokol","Tolna","Tompa","Torokbalint","Torokszentmiklos","Totkomlos","Tura","Turkeve","Ujkigyos","ujszasz","Vamospercs","Varpalota","Vasarosnameny","Vasvar","Vecses","Velence","Veresegyhaz","Verpelet","Veszto","Zahony","Zalaszentgrot","Zirc","Zsambek"],
["Adapazari","Adiyaman","Afshin","Afyon","Ari","Akchaabat","Akchakale","Akchakoca","Akdamadeni","Akhisar","Aksaray","Akshehir","Alaca","Alanya","Alapli","Alashehir","Amasya","Anamur","Antakya","Ardeshen","Artvin","Aydin","Ayvalik","Babaeski","Bafra","Balikesir","Bandirma","Bartin","Bashiskele","Batman","Bayburt","Belen","Bergama","Besni","Beypazari","Beyshehir","Biga","Bilecik","Bingul","Birecik","Bismil","Bitlis","Bodrum","Bolu","Bolvadin","Bor","Bostanichi","Boyabat","Bozuyuk","Bucak","Bulancak","Bulanik","Burdur","Burhaniye","Chan","Chanakkale","Chankiri","Charshamba","Chaycuma","Chayeli","Chayirova","Cherkezkuy","Cheshme","Ceyhan","Ceylanpinar","Chine","Chivril","Cizre","Chorlu","Chumra","Dalaman","Darica","Denizli","Derik","Derince","Develi","Devrek","Didim","Dilovasi","Dinar","Diyadin","Diyarbakir","Doubayazit","Durtyol","Duzce","Duzichi","Edirne","Edremit","Elazi","Elbistan","Emirda","Erbaa","Ercish","Erdek","Erdemli","Ereli","Ergani","Erzin","Erzincan","Erzurum","Eskishehir","Fatsa","Fethiye","Gazipasha","Gebze","Gelibolu","Gerede","Geyve","Giresun","Guksun","Gulbashi","Gulcuk","Gurnen","Gumushhane","Guroymak","Hakkari","Harbiye","Havza","Hayrabolu","Hilvan","Idil","Idir","Ilgin","Imamolu","Incirliova","Inegul","Iskenderun","Iskilip","Islahiye","Isparta","Izmit","Iznik","Kadirli","Kahramanmarash","Kahta","Kaman","Kapakli","Karabuk","Karacabey","Karadeniz Ereli","Karakupru","Karaman","Karamursel","Karapinar","Karasu","Kars","Kartepe","Kastamonu","Kemer","Keshan","Kilimli","Kilis","Kirikhan","Kirikkale","Kirklareli","Kirshehir","Kiziltepe","Kurfez","Korkuteli","Kovancilar","Kozan","Kozlu","Kozluk","Kulu","Kumluca","Kurtalan","Kushadasi","Kutahya","Luleburgaz","Malatya","Malazgirt","Malkara","Manavgat","Manisa","Mardin","Marmaris","Mersin","Merzifon","Midyat","Milas","Mula","Muratli","Mush","Mut","Nazilli","Nevshehir","Nide","Niksar","Nizip","Nusaybin","udemish","Oltu","Ordu","Orhangazi","Ortaca","Osmancik","Osmaniye","Patnos","Payas","Pazarcik","Polatli","Reyhanli","Rize","Safranbolu","Salihli","Samanda","Samsun","Sandikli","shanliurfa","Saray","Sarikamish","Sarikaya","sharkishla","shereflikochhisar","Serik","Serinyol","Seydishehir","Siirt","Silifke","Silopi","Silvan","Simav","Sinop","shirnak","Sivas","Siverek","Surke","Soma","Sorgun","Suluova","Sungurlu","Suruch","Susurluk","Tarsus","Tatvan","Tavshanli","Tekirda","Terme","Tire","Tokat","Tosya","Trabzon","Tunceli","Turgutlu","Turhal","Unye","Ushak","Uzunkurpru","Van","Vezirkurpru","Viranshehir","Yahyali","Yalova","Yenishehir","Yerkury","Yozgat","Yuksekova","Zile","Zonguldak"],
["Abkhouch","Adrar","Agadir","Agelmam","Aghmat","Agrakal","Agulmam","Ahaggar","Almou","Anfa","Annaba","Aousja","Arbat","Argoub","Arif","Asfi","Assamer","Assif","Azaghar","Azmour","Azrou","Beccar","Beja","Bennour","Benslimane","Berkane","Berrechid","Bizerte","Bouskoura","Boutferda","Dar Bouazza","Darallouch","Darchaabane","Dcheira","Denden","Djebel","Djedeida","Drargua","Essaouira","Ezzahra","Fas","Fnideq","Ghezeze","Goubellat","Grisaffen","Guelmim","Guercif","Hammamet","Harrouda","Hoceima","Idurar","Ifendassen","Ifoghas","Imilchil","Inezgane","Izoughar","Jendouba","Kacem","Kelibia","Kenitra","Kerrando","Khalidia","Khemisset","Khenifra","Khouribga","Kidal","Korba","Korbous","Lahraouyine","Larache","Leyun","Lqliaa","Manouba","Martil","Mazagan","Mcherga","Mdiq","Megrine","Mellal","Melloul","Midelt","Mohammedia","Mornag","Mrrakc","Nabeul","Nadhour","Nador","Nawaksut","Nefza","Ouarzazate","Ouazzane","Oued Zem","Oujda","Ouladteima","Qsentina","Rades","Rafraf","Safi","Sefrou","Sejnane","Settat","Sijilmassa","Skhirat","Slimane","Somaa","Sraghna","Susa","Tabarka","Taferka","Tafza","Tagbalut","Tagerdayt","Takelsa","Tanja","Tantan","Taourirt","Taroudant","Tasfelalayt","Tattiwin","Taza","Tazerka","Tazizawt","Tebourba","Teboursouk","Temara","Testour","Tetouan","Tibeskert","Tifelt","Tinariwen","Tinduf","Tinja","Tiznit","Toubkal","Trables","Tubqal","Tunes","Urup","Watlas","Wehran","Wejda","Youssoufia","Zaghouan","Zahret","Zemmour","Zriba"],
["Abadilah","Abayt","Abha","Abud","Aden","Ahwar","Ajman","Alabadilah","Alabar","Alahjer","Alain","Alaraq","Alarish","Alarjam","Alashraf","Alaswaaq","Alawali","Albarar","Albawadi","Albirk","Aldhabiyah","Alduwaid","Alfareeq","Algayed","Alhada","Alhafirah","Alhamar","Alharam","Alharidhah","Alhawtah","Alhazim","Alhrateem","Alhudaydah","Alhujun","Alhuwaya","Aljahra","Aljohar","Aljubail","Alkawd","Alkhalas","Alkhawaneej","Alkhen","Alkhhafah","Alkhobar","Alkhuznah","Alkiranah","Allisafah","Allith","Almadeed","Almardamah","Almarwah","Almasnaah","Almejammah","Almojermah","Almshaykh","Almurjan","Almuwayh","Almuzaylif","Alnaheem","Alnashifah","Alqadeimah","Alqah","Alqahma","Alqalh","Alqouz","Alquaba","Alqunfudhah","Alqurayyat","Alradha","Alraqmiah","Alsadyah","Alsafa","Alshagab","Alshoqiq","Alshuqaiq","Alsilaa","Althafeer","Alwakrah","Alwasqah","Amaq","Amran","Annaseem","Aqbiyah","Arafat","Arar","Ardah","Arrawdah","Asfan","Ashayrah","Ashshahaniyah","Askar","Assaffaniyah","Ayaar","Aziziyah","Baesh","Bahrah","Baish","Balhaf","Banizayd","Baqaa","Baqal","Bidiyah","Bisha","Biyatah","Buqhayq","Burayda","Dafiyat","Damad","Dammam","Dariyah","Daynah","Dhafar","Dhahran","Dhalkut","Dhamar","Dhubab","Dhurma","Dibab","Dirab","Doha","Dukhan","Duwaibah","Enaker","Fadhla","Fahaheel","Fanateer","Farasan","Fardah","Fujairah","Ghalilah","Ghar","Ghizlan","Ghomgyah","Ghran","Hababah","Habil","Hadiyah","Haffah","Hajanbah","Hajrah","Halban","Haqqaq","Haradh","Hasar","Hathah","Hawarwar","Hawaya","Hawiyah","Hebaa","Hefar","Hijal","Husnah","Huwailat","Huwaitah","Irqah","Isharah","Ithrah","Jamalah","Jarab","Jareef","Jarwal","Jash","Jazan","Jeddah","Jiblah","Jihanah","Jilah","Jizan","Joha","Joraibah","Juban","Jubbah","Juddah","Jumeirah","Kamaran","Keyad","Khab","Khabtsaeed","Khaiybar","Khasab","Khathirah","Khawarah","Khulais","Khulays","Klayah","Kumzar","Limah","Linah","Mabar","Madrak","Mahab","Mahalah","Makhtar","Makshosh","Manfuhah","Manifah","Manshabah","Mareah","Masdar","Mashwar","Masirah","Maskar","Masliyah","Mastabah","Maysaan","Mazhar","Mdina","Meeqat","Mirbah","Mirbat","Mokhtara","Muharraq","Muladdah","Musandam","Musaykah","Muscat","Mushayrif","Musrah","Mussafah","Mutrah","Nafhan","Nahdah","Nahwa","Najran","Nakhab","Nizwa","Oman","Qadah","Qalhat","Qamrah","Qasam","Qatabah","Qawah","Qosmah","Qurain","Quraydah","Quriyat","Qurwa","Rabigh","Radaa","Rafha","Rahlah","Rakamah","Rasheedah","Rasmadrakah","Risabah","Rustaq","Ryadh","Saabah","Saabar","Sabtaljarah","Sabya","Sadad","Sadah","Safinah","Saham","Sahlat","Saihat","Salalah","Salmalzwaher","Salmiya","Sanaa","Sanaban","Sayaa","Sayyan","Shabayah","Shabwah","Shafa","Shalim","Shaqra","Sharjah","Sharkat","Sharurah","Shatifiyah","Shibam","Shidah","Shifiyah","Shihar","Shoqra","Shoqsan","Shuwaq","Sibah","Sihmah","Sinaw","Sirwah","Sohar","Suhailah","Sulaibiya","Sunbah","Tabuk","Taif","Taqah","Tarif","Tharban","Thumrait","Thuqbah","Thuwal","Tubarjal","Turaif","Turbah","Tuwaiq","Ubar","Umaljerem","Urayarah","Urwah","Wabrah","Warbah","Yabreen","Yadamah","Yafur","Yarim","Yemen","Yiyallah","Zabid","Zahwah","Zallaq","Zinjibar","Zulumah"],
["Aaluik","Aappilattoq","Aasiaat","Agdleruussakasit","Aggas","Akia","Akilia","Akuliaruseq","Akuliarutsip","Akunnaaq","Agissat","Agssaussat","Alluitsup","Alluttoq","Aluit","Aluk","Ammassalik","Amarortalik","Amitsorsuaq","Anarusuk","Angisorsuaq","Anguniartarfik","Annertussoq","Annikitsoq","Anoraliuirsoq","Appat","Apparsuit","Apusiaajik","Arsivik","Arsuk","Ataa","Atammik","Ateqanngitsorsuaq","Atilissuaq","Attu","Aukarnersuaq","Augpalugtoq, Aumat","Auvilikavsak","Auvilkikavsaup","Avadtlek","Avallersuaq","Bjornesk","Blabaerdalen","Blomsterdalen","Brattalhid","Bredebrae","Brededal","Claushavn","Edderfulegoer","Egger","Eqalugalinnguit","Eqalugarssuit","Eqaluit","Eqqua","Etah","Graah","Hakluyt","Haredalen","Hareoen","Hundeo","Igdlorssuit","Igaliku","Igdlugdlip","Igdluluarssuk","Iginniafik","Ikamiuk","Ikamiut","Ikarissat","Ikateq","Ikeq","Ikerasak","Ikerasaarsuk","Ikermiut","Ikermoissuaq","Ikertivaq","Ikorfarssuit","Ikorfat","Ilimanaq","Illorsuit","Iluileq","Iluiteq","Ilulissat","Illunnguit","Imaarsivik","Imartunarssuk","Immikkoortukajik","Innaarsuit","Ingjald","Inneruulalik","Inussullissuaq","Iqek","Ikerasakassak","Iperaq","Ippik","Isortok","Isungartussoq","Itileq","Itivdleq","Itissaalik","Ittit","Ittoqqortoormiit","Ivingmiut","Ivittuut","Kanajoorartuut","Kangaamiut","Kangaarsuk","Kangaatsiaq","Kangeq","Kangerluk","Kangerlussuaq","Kanglinnguit","Kapisillit","Karrat","Kekertamiut","Kiatak","Kiatassuaq","Kiataussaq","Kigatak","Kigdlussat","Kinaussak","Kingittorsuaq","Kitak","Kitsissuarsuit","Kitsissut","Klenczner","Kook","Kraulshavn","Kujalleq","Kullorsuaq","Kulusuk","Kuurmiit","Kuusuaq","Laksedalen","Maniitsoq","Marrakajik","Mattaangassut","Mernoq","Mittivakkat","Moriusaq","Myggbukta","Naajaat","Nako","Nangissat","Nanortalik","Nanuuseq","Nappassoq","Narsarmijt","Narssaq","Narsarsuaq","Narssarssuk","Nasaussaq","Nasiffik","Natsiarsiorfik","Naujanguit","Niaqornaarsuk","Niaqornat","Nordfjordspasset","Nugatsiaq","Nuluuk","Nunaa","Nunarssit","Nunarsuaq","Nunataaq","Nunatakavsaup","Nutaarmiut","Nuugaatsiaq","Nuuk","Nuukullak","Nuuluk","Nuussuaq","Olonkinbyen","Oqaatsut","Oqaitsúnguit","Oqonermiut","Oodaaq","Paagussat","Palungataq","Pamialluk","Paamiut","Paatuut","Patuersoq","Perserajoq","Paornivik","Pituffik","Puugutaa","Puulkuip","Qaanaq","Qaarsorsuaq","Qaarsorsuatsiaq","Qaasuitsup","Qaersut","Qajartalik","Qallunaat","Qaneq","Qaqaarissorsuaq","Qaqit","Qaqortok","Qasigiannguit","Qasse","Qassimiut","Qeertartivaq","Qeertartivatsiaq","Qeqertaq","Qeqertarssdaq","Qeqertarsuaq","Qeqertasussuk","Qeqertarsuatsiaat","Qeqertat","Qeqqata","Qernertoq","Qernertunnguit","Qianarreq","Qilalugkiarfik","Qingagssat","Qingaq","Qoornuup","Qorlortorsuaq","Qullikorsuit","Qunnerit","Qutdleq","Ravnedalen","Ritenbenk","Rypedalen","Sarfannguit","Saarlia","Saarloq","Saatoq","Saatorsuaq","Saatup","Saattut","Sadeloe","Salleq","Salliaruseq","Sammeqqat","Sammisoq","Sanningassoq","Saqqaq","Saqqarlersuaq","Saqqarliit","Sarqaq","Sattiaatteq","Savissivik","Serfanguaq","Sermersooq","Sermersut","Sermilik","Sermiligaaq","Sermitsiaq","Simitakaja","Simiutaq","Singamaq","Siorapaluk","Sisimiut","Sisuarsuit","Skal","Skarvefjeld","Skjoldungen","Storoen","Sullorsuaq","Suunikajik","Sverdrup","Taartoq","Takiseeq","Talerua","Tarqo","Tasirliaq","Tasiusak","Tiilerilaaq","Timilersua","Timmiarmiut","Tingmjarmiut","Traill","Tukingassoq","Tuttorqortooq","Tuujuk","Tuttulissuup","Tussaaq","Uigordlit","Uigorlersuaq","Uilortussoq","Uiivaq","Ujuaakajiip","Ukkusissat","Umanat","Upernavik","Upernattivik","Upepnagssivik","Upernivik","Uttorsiutit","Uumannaq","Uummannaarsuk","Uunartoq","Uvkusigssat","Ymer"],
["Abadio","Abaltzisketa","Abanto Zierbena","Aduna","Agurain","Aia","Aiara","Aizarnazabal","Ajangiz","Albiztur","Alegia","Alkiza","Alonsotegi","Altzaga","Altzo","Amezketa","Amorebieta","Amoroto","Amurrio","Andoain","Anoeta","Antzuola","Arakaldo","Arama","Aramaio","Arantzazu","Arbatzegi ","Areatza","Aretxabaleta","Arraia","Arrankudiaga","Arrasate","Arratzu","Arratzua","Arrieta","Arrigorriaga","Artea","Artzentales","Artziniega","Asparrena","Asteasu","Astigarraga","Ataun","Atxondo","Aulesti","Azkoitia","Azpeitia","Bakio","Baliarrain","Balmaseda","Barakaldo","Barrika","Barrundia","Basauri","Bastida","Beasain","Bedia","Beizama","Belauntza","Berango","Berantevilla","Berastegi","Bergara","Bermeo","Bernedo","Berriatua","Berriz","Berrobi","Bidania","Bilar","Bilbao","Burgelu","Busturia","Deba","Derio","Dima","Donemiliaga","Donostia","Dulantzi","Durango","Ea","Eibar","Elantxobe","Elduain","Elgeta","Elgoibar","Elorrio","Erandio","Ereo","Ermua","Errenteria","Errezil","Erribera Beitia","Erriberagoitia","Errigoiti","Eskoriatza","Eskuernaga","Etxebarri","Etxebarria","Ezkio","Fika","Forua","Fruiz","Gabiria","Gaintza","Galdakao","Galdames","Gamiz","Garai","Gasteiz","Gatika","Gatzaga","Gaubea","Gauna","Gautegiz Arteaga","Gaztelu","Gernika","Gerrikaitz","Getaria","Getxo","Gizaburuaga","Goiatz","Gordexola","Gorliz","Harana","Hernani","Hernialde","Hondarribia","Ibarra","Ibarrangelu","Idiazabal","Iekora","Igorre","Ikaztegieta","Irua Oka","Irun","Irura","Iruraiz","Ispaster","Itsaso","Itsasondo","Iurreta","Izurtza","Jatabe","Kanpezu","Karrantza Harana","Kortezubi","Kripan","Kuartango","Lanestosa","Lantziego","Larrabetzu","Larraul","Lasarte","Laudio","Laukiz","Lazkao","Leaburu","Legazpi","Legorreta","Legutio","Leintz","Leioa","Lekeitio","Lemoa","Lemoiz","Leza","Lezama","Lezo","Lizartza","Loiu","Lumo","Maaria","Maeztu","Mallabia","Markina","Maruri","Maueta","Meaka","Mendaro","Mendata","Mendexa","Moreda Araba","Morga","Mundaka","Mungia","Munitibar","Murueta","Muskiz","Mutiloa","Mutriku","Muxika","Nabarniz","Oati","Oiartzun","Oion","Okondo","Olaberria","Ondarroa","Ordizia","Orendain","Orexa","Oria","Orio","Ormaiztegi","Orozko","Ortuella","Otxandio","Pasaia","Plentzia","Portugalete","Samaniego","Santurtzi","Segura","Sestao","Sondika","Sopela","Sopuerta","Soraluze","Sukarrieta","Tolosa","Trapagaran","Turtzioz","Ubarrundia","Ubide","Ugao","Urdua","Urduliz","Urizaharra","Urkabustaiz","Urnieta","Urretxu","Usurbil","Xemein","Zaia","Zaldibar","Zaldibia","Zalduondo","Zambrana","Zamudio","Zaratamo","Zarautz","Zeanuri","Zeberio","Zegama","Zerain","Zestoa","Zierbena","Zigoitia","Ziortza","Zizurkil","Zuia","Zumaia","Zumarraga"],
["Abadogo","Abafon","Abdu","Acharu","Adaba","Adealesu","Adeto","Adyongo","Afaga","Afamju","Afuje","Agbelagba","Agigbigi","Agogoke","Ahute","Aiyelaboro","Ajebe","Ajola","Akarekwu","Akessan","Akunuba","Alawode","Alkaijji","Amangam","Amaoji","Amgbaye","Amtasa","Amunigun","Anase","Aniho","Animahun","Antul","Anyoko","Apekaa","Arapagi","Asamagidi","Asande","Ataibang","Awgbagba","Awhum","Awodu","Babanana","Babateduwa","Bagu","Bakura","Bandakwai","Bangdi","Barbo","Barkeje","Basa","Basabra","Basansagawa","Bieleshin","Bilikani","Birnindodo","Braidu","Bulakawa","Buriburi","Burisidna","Busum","Bwoi","Cainnan","Chakum","Charati","Chondugh","Dabibikiri","Dagwarga","Dallok","Danalili","Dandala","Darpi","Dhayaki","Dokatofa","Doma","Dozere","Duci","Dugan","Ebelibri","Efem","Efoi","Egudu","Egundugbo","Ekoku","Ekpe","Ekwere","Erhua","Eteu","Etikagbene","Ewhoeviri","Ewhotie","Ezemaowa","Fatima","Gadege","Galakura","Galea","Gamai","Gamen","Ganjin","Gantetudu","Garangamawa","Garema","Gargar","Gari","Garinbode","Garkuwa","Garu Kime","Gazabu","Gbure","Gerti","Gidan","Giringwe","Gitabaremu","Giyagiri","Giyawa","Gmawa","Golakochi","Golumba","Guchi","Gudugu","Gunji","Gusa","Gwambula","Gwamgwam","Gwodoti","Hayinlere","Hayinmaialewa","Hirishi","Hombo","Ibefum","Iberekodo","Ibodeipa","Icharge","Ideoro","Idofin","Idofinoka","Idya","Iganmeji","Igbetar","Igbogo","Ijoko","Ijuwa","Ikawga","Ikekogbe","Ikhin","Ikoro","Ikotefe","Ikotokpora","Ikpakidout","Ikpeoniong","Ilofa","Imuogo","Inyeneke","Iorsugh","Ipawo","Ipinlerere","Isicha","Itakpa","Itoki","Iyedeame","Jameri","Jangi","Jara","Jare","Jataudakum","Jaurogomki","Jepel","Jibam","Jirgu","Jirkange","Kafinmalama","Kamkem","Katab","Katanga","Katinda","Katirije","Kaurakimba","Keffinshanu","Kellumiri","Kiagbodor","Kibiare","Kingking","Kirbutu","Kita","Kogbo","Kogogo","Kopje","Koriga","Koroko","Korokorosei","Kotoku","Kuata","Kujum","Kukau","Kunboon","Kuonubogbene","Kurawe","Kushinahu","Kwaramakeri","Ladimeji","Lafiaro","Lahaga","Laindebajanle","Laindegoro","Lajere","Lakati","Ligeri","Litenswa","Lokobimagaji","Lusabe","Maba","Madarzai","Magoi","Maialewa","Maianita","Maijuja","Mairakuni","Maleh","Malikansaa","Mallamkola","Mallammaduri","Marmara","Masagu","Masoma","Mata","Matankali","Mbalare","Megoyo","Meku","Miama","Mige","Mkporagwu","Modi","Molafa","Mshi","Msugh","Muduvu","Murnachehu","Namnai","Nanumawa","Nasudu","Ndagawo","Ndamanma","Ndiebeleagu","Ndiwulunbe","Ndonutim","Ngaruwa","Ngbande","Nguengu","Nto Ekpe","Nubudi","Nyajo","Nyido","Nyior","Obafor","Obazuwa","Odajie","Odiama","Ofunatam","Ogali","Ogan","Ogbaga","Ogbahu","Ogultu","Ogunbunmi","Ogunmakin","Ojaota","Ojirami","Ojopode","Okehin","Olugunna","Omotunde","Onipede","Onisopi","Onma","Orhere","Orya","Oshotan","Otukwang","Otunade","Pepegbene","Poros","Rafin","Rampa","Rimi","Rinjim","Robertkiri","Rugan","Rumbukawa","Sabiu","Sabon","Sabongari","Sai","Salmatappare","Sangabama","Sarabe","Seboregetore","Seibiri","Sendowa","Shafar","Shagwa","Shata","Shefunda","Shengu","Sokoron","Sunnayu","Taberlma","Tafoki","Takula","Talontan","Taraku","Tarhemba","Tayu","Ter","Timtim","Timyam","Tindirke","Tirkalou","Tokunbo","Tonga","Torlwam","Tseakaadza","Tseanongo","Tseavungu","Tsebeeve","Tsekov","Tsepaegh","Tuba","Tumbo","Tungalombo","Tungamasu","Tunganrati","Tunganyakwe","Tungenzuri","Ubimimi","Uhkirhi","Umoru","Umuabai","Umuaja","Umuajuju","Umuimo","Umuojala","Unchida","Ungua","Unguwar","Unongo","Usha","Ute","Utongbo","Vembera","Vorokotok","Wachin","Walebaga","Wurawura","Wuro","Yanbashi","Yanmedi","Yenaka","Yoku","Zamangera","Zarunkwari","Zilumo","Zulika"],
["Aberaman","Aberangell","Aberarth","Aberavon","Aberbanc","Aberbargoed","Aberbeeg","Abercanaid","Abercarn","Abercastle","Abercegir","Abercraf","Abercregan","Abercych","Abercynon","Aberdare","Aberdaron","Aberdaugleddau","Aberdeen","Aberdulais","Aberdyfi","Aberedw","Abereiddy","Abererch","Abereron","Aberfan","Aberffraw","Aberffrwd","Abergavenny","Abergele","Aberglasslyn","Abergorlech","Abergwaun","Abergwesyn","Abergwili","Abergwynfi","Abergwyngregyn","Abergynolwyn","Aberhafesp","Aberhonddu","Aberkenfig","Aberllefenni","Abermain","Abermaw","Abermorddu","Abermule","Abernant","Aberpennar","Aberporth","Aberriw","Abersoch","Abersychan","Abertawe","Aberteifi","Aberthin","Abertillery","Abertridwr","Aberystwyth","Achininver","Afonhafren","Alisaha","Antinbhearmor","Ardenna","Attacon","Beira","Bhrura","Boioduro","Bona","Boudobriga","Bravon","Brigant","Briganta","Briva","Cambodunum","Cambra","Caracta","Catumagos","Centobriga","Ceredigion","Chalain","Dinn","Diwa","Dubingen","Duro","Ebora","Ebruac","Eburodunum","Eccles","Eighe","Eireann","Ferkunos","Genua","Ghrainnse","Inbhear","Inbhir","Inbhirair","Innerleithen","Innerleven","Innerwick","Inver","Inveraldie","Inverallan","Inveralmond","Inveramsay","Inveran","Inveraray","Inverarnan","Inverbervie","Inverclyde","Inverell","Inveresk","Inverfarigaig","Invergarry","Invergordon","Invergowrie","Inverhaddon","Inverkeilor","Inverkeithing","Inverkeithney","Inverkip","Inverleigh","Inverleith","Inverloch","Inverlochlarig","Inverlochy","Invermay","Invermoriston","Inverness","Inveroran","Invershin","Inversnaid","Invertrossachs","Inverugie","Inveruglas","Inverurie","Kilninver","Kirkcaldy","Kirkintilloch","Krake","Latense","Leming","Lindomagos","Llanaber","Lochinver","Lugduno","Magoduro","Monmouthshire","Narann","Novioduno","Nowijonago","Octoduron","Penning","Pheofharain","Ricomago","Rossinver","Salodurum","Seguia","Sentica","Theorsa","Uige","Vitodurum","Windobona"],
["Adab","Akkad","Akshak","Amnanum","Arbid","Arpachiyah","Arrapha","Assur","Babilim","Badtibira","Balawat","Barsip","Borsippa","Carchemish","Chagar Bazar","Chuera","Ctesiphon ","Der","Dilbat","Diniktum","Doura","Durkurigalzu","Ekallatum","Emar","Erbil","Eridu","Eshnunn","Fakhariya ","Gawra","Girsu","Hadatu","Hamoukar","Haradum","Harran","Hatra","Idu","Irisagrig","Isin","Jemdet","Kahat","Kartukulti","Khaiber","Kish ","Kisurra","Kuara","Kutha","Lagash","Larsa ","Leilan","Marad","Mardaman","Mari","Mashkan","Mumbaqat ","Nabada","Nagar","Nerebtum","Nimrud","Nineveh","Nippur","Nuzi","Qalatjarmo","Qatara","Rawda","Seleucia","Shaduppum","Shanidar","Sharrukin","Shemshara","Shibaniba","Shuruppak","Sippar","Tarbisu","Tellagrab","Tellessawwan","Tellessweyhat","Tellhassuna","Telltaya","Telul","Terqa","Thalathat","Tutub","Ubaid ","Umma","Ur","Urfa","Urkesh","Uruk","Urum","Zabalam","Zenobia"],
["Abali","Abrisham","Absard","Abuzeydabad","Afus","Alavicheh","Alikosh","Amol","Anarak","Anbar","Andisheh","Anshan","Aran","Ardabil","Arderica","Ardestan","Arjomand","Asgaran","Asgharabad","Ashian","Awan","Babajan","Badrud","Bafran","Baghestan","Baghshad","Bahadoran","Baharan Shahr","Baharestan","Bakun","Bam","Baqershahr","Barzok","Bastam","Behistun","Bitistar","Bumahen","Bushehr","Chadegan","Chahardangeh","Chamgardan","Chermahin","Choghabonut","Chugan","Damaneh","Damavand","Darabgard","Daran","Dastgerd","Dehaq","Dehaqan","Dezful","Dizicheh","Dorcheh","Dowlatabad","Duruntash","Ecbatana","Eslamshahr","Estakhr","Ezhiyeh","Falavarjan","Farrokhi","Fasham","Ferdowsieh","Fereydunshahr","Ferunabad","Firuzkuh","Fuladshahr","Ganjdareh","Ganzak","Gaz","Geoy","Godin","Goldasht","Golestan","Golpayegan","Golshahr","Golshan","Gorgab","Guged","Habibabad","Hafshejan","Hajjifiruz","Hana","Harand","Hasanabad","Hasanlu","Hashtgerd","Hecatompylos","Hormirzad","Imanshahr","Isfahan","Jandaq","Javadabad","Jiroft","Jowsheqan ","Jowzdan","Kabnak","Kahriz Sang","Kahrizak","Kangavar","Karaj","Karkevand","Kashan","Kelishad","Kermanshah","Khaledabad","Khansar","Khorramabad","Khur","Khvorzuq","Kilan","Komeh","Komeshcheh","Konar","Kuhpayeh","Kul","Kushk","Lavasan","Laybid","Liyan","Lyan","Mahabad","Mahallat","Majlesi","Malard","Manzariyeh","Marlik","Meshkat","Meymeh","Miandasht","Mish","Mobarakeh","Nahavand","Nain","Najafabad","Naqshe","Narezzash","Nasimshahr","Nasirshahr","Nasrabad","Natanz","Neyasar","Nikabad","Nimvar","Nushabad","Pakdasht","Parand","Pardis","Parsa","Pasargadai","Patigrabana","Pir Bakran","Pishva","Qahderijan","Qahjaverestan","Qamsar","Qarchak","Qods","Rabat","Ray-shahr","Rezvanshahr","Rhages","Robat Karim","Rozveh","Rudehen","Sabashahr","Safadasht","Sagzi","Salehieh","Sandal","Sarvestan","Sedeh","Sefidshahr","Semirom","Semnan","Shadpurabad","Shah","Shahdad","Shahedshahr","Shahin","Shahpour","Shahr","Shahreza","Shahriar","Sharifabad","Shemshak","Shiraz","Shushan","Shushtar","Sialk","Sin","Sukhteh","Tabas","Tabriz","Takhte","Talkhuncheh","Talli","Tarq","Temukan","Tepe","Tiran","Tudeshk","Tureng","Urmia","Vahidieh","Vahrkana","Vanak","Varamin","Varnamkhast","Varzaneh","Vazvan","Yahya","Yarim","Yasuj","Zarrin Shahr","Zavareh","Zayandeh","Zazeran","Ziar","Zibashahr","Zranka"],
["Aapueo","Ahoa","Ahuakaio","Ahuakamalii","Ahuakeio","Ahupau","Aki","Alaakua","Alae","Alaeloa","Alaenui","Alamihi","Aleamai","Alena","Alio","Aupokopoko","Auwahi","Hahakea","Haiku","Halakaa","Halehaku","Halehana","Halemano","Haleu","Haliimaile","Hamakuapoko","Hamoa","Hanakaoo","Hanaulu","Hanawana","Hanehoi","Haneoo","Haou","Hikiaupea","Hoalua","Hokuula","Honohina","Honokahua","Honokala","Honokalani","Honokeana","Honokohau","Honokowai","Honolua","Honolulu","Honolulunui","Honomaele","Honomanu","Hononana","Honopou","Hoolawa","Hopenui","Hualele","Huelo","Hulaia","Ihuula","Ilikahi","Interisland","Kaalaea","Kaalelehinale","Kaapahu","Kaehoeho","Kaeleku","Kaeo","Kahakuloa","Kahalawe","Kahalawe","Kahalehili","Kahana","Kahilo","Kahuai","Kaiaula","Kailihiakoko","Kailua","Kainehe","Kakalahale","Kakanoni","Kakio","Kakiweka","Kalena","Kalenanui","Kaleoaihe","Kalepa","Kaliae","Kalialinui","Kalihi","Kalihi","Kalihi","Kalimaohe","Kaloi","Kamani","Kamaole","Kamehame","Kanahena","Kanaio","Kaniaula","Kaonoulu","Kaopa","Kapaloa","Kapaula","Kapewakua","Kapohue","Kapuaikini","Kapunakea","Kapuuomahuka","Kauau","Kauaula","Kaukuhalahala","Kaulalo","Kaulanamoa","Kauluohana","Kaumahalua","Kaumakani","Kaumanu","Kaunauhane","Kaunuahane","Kaupakulua","Kawaipapa","Kawaloa","Kawaloa","Kawalua","Kawela","Keaa","Keaalii","Keaaula","Keahua","Keahuapono","Keakuapauaela","Kealahou","Keanae","Keauhou","Kekuapawela","Kelawea","Keokea","Keopuka","Kepio","Kihapuhala","Kikoo","Kilolani","Kipapa","Koakupuna","Koali","Koananai","Koheo","Kolea","Kolokolo","Kooka","Kopili","Kou","Kualapa","Kuhiwa","Kuholilea","Kuhua","Kuia","Kuiaha","Kuikui","Kukoae","Kukohia","Kukuiaeo","Kukuioolu","Kukuipuka","Kukuiula","Kulahuhu","Kumunui","Lapakea","Lapalapaiki","Lapueo","Launiupoko","Loiloa","Lole","Lualailua","Maalo","Mahinahina","Mahulua","Maiana","Mailepai","Makaakini","Makaalae","Makaehu","Makaiwa","Makaliua","Makapipi","Makapuu","Makawao","Makila","Mala","Maluaka","Mamalu","Manawaiapiki","Manawainui","Maulili","Mehamenui","Miana","Mikimiki","Moalii","Moanui","Mohopili","Mohopilo","Mokae","Mokuia","Mokupapa","Mooiki","Mooloa","Moomuku","Muolea","Nahuakamalii","Nailiilipoko","Nakaaha","Nakalepo","Nakaohu","Nakapehu","Nakula","Napili","Niniau","Niumalu","Nuu","Ohia","Oloewa","Olowalu","Omaopio","Onau","Onouli","Opaeula","Opana","Opikoula","Paakea","Paeahu","Paehala","Paeohi","Pahoa","Paia","Pakakia","Pakala","Palauea","Palemo","Panaewa","Paniau","Papaaea","Papaanui","Papaauhau","Papahawahawa","Papaka","Papauluana","Pauku","Paunau","Pauwalu","Pauwela","Peahi","Piapia","Pohakanele","Pohoula","Polaiki","Polanui","Polapola","Polua","Poopoo","Popoiwi","Popoloa","Poponui","Poupouwela","Puaa","Puaaluu","Puahoowali","Puakea","Puako","Pualaea","Puehuehu","Puekahi","Pueokauiki","Pukaauhuhu","Pukalani","Pukuilua","Pulehu","Pulehuiki","Pulehunui","Punaluu","Puolua","Puou","Puuhaehae","Puuhaoa","Puuiki","Puuki","Puukohola","Puulani","Puumaneoneo","Puunau","Puunoa","Puuomaiai","Puuomaile","Uaoa","Uhao","Ukumehame","Ulaino","Ulumalu","Unknown","Various","Wahikuli","Waiahole","Waiakoa","Waianae","Waianu","Waiawa","Waiehu","Waieli","Waihee","Waikapu","Wailamoa","Wailaulau","Wailua","Wailuku","Wainee","Waiohole","Waiohonu","Waiohue","Waiohuli","Waiokama","Waiokila","Waiopai","Waiopua","Waipao","Waipio","Waipioiki","Waipionui","Waipouli","Wakiu","Wananalua"],
["Adityapatna","Adyar","Afzalpur","Aland","Alnavar","Alur","Ambikanagara","Anekal","Ankola","Annigeri","Arkalgud","Arsikere","Athni","Aurad","Badami","Bagalkot","Bagepalli","Bail","Bajpe","Bangalore","Bangarapet","Bankapura","Bannur","Bantval","Basavakalyan","Basavana","Belgaum","Beltangadi","Belur","Bhadravati","Bhalki","Bhatkal","Bhimarayanagudi","Bidar","Bijapur","Bilgi","Birur","Bommasandra","Byadgi","Challakere","Chamarajanagar","Channagiri","Channapatna","Channarayapatna","Chik","Chikmagalur","Chiknayakanhalli","Chikodi","Chincholi","Chintamani","Chitapur","Chitgoppa","Chitradurga","Dandeli","Dargajogihalli","Devadurga","Devanahalli","Dod","Donimalai","Gadag","Gajendragarh","Gangawati","Gauribidanur","Gokak","Gonikoppal","Gubbi","Gudibanda","Gulbarga","Guledgudda","Gundlupet","Gurmatkal","Haliyal","Hangal","Harapanahalli","Harihar","Hassan","Hatti","Haveri","Hebbagodi","Heggadadevankote","Hirekerur","Holalkere","Hole","Homnabad","Honavar","Honnali","Hoovina","Hosakote","Hosanagara","Hosdurga","Hospet","Hubli","Hukeri","Hungund","Hunsur","Ilkal","Indi","Jagalur","Jamkhandi","Jevargi","Jog","Kadigenahalli","Kadur","Kalghatgi","Kamalapuram","Kampli","Kanakapura","Karkal","Karwar","Khanapur","Kodiyal","Kolar","Kollegal","Konnur","Koppa","Koppal","Koratagere","Kotturu","Krishnarajanagara","Krishnarajasagara","Krishnarajpet","Kudchi","Kudligi","Kudremukh","Kumta","Kundapura","Kundgol","Kunigal","Kurgunta","Kushalnagar","Kushtagi","Lakshmeshwar","Lingsugur","Londa","Maddur","Madhugiri","Madikeri","Mahalingpur","Malavalli","Mallar","Malur","Mandya","Mangalore","Manvi","Molakalmuru","Mudalgi","Mudbidri","Muddebihal","Mudgal","Mudhol","Mudigere","Mulbagal","Mulgund","Mulki","Mulur","Mundargi","Mundgod","Munirabad","Mysore","Nagamangala","Nanjangud","Narasimharajapura","Naregal","Nargund","Navalgund","Nipani","Pandavapura","Pavagada","Piriyapatna","Pudu","Puttur","Rabkavi","Raichur","Ramanagaram","Ramdurg","Ranibennur","Raybag","Robertson","Ron","Sadalgi","Sagar","Sakleshpur","Saligram","Sandur","Sankeshwar","Saundatti","Savanur","Sedam","Shahabad","Shahpur","Shaktinagar","Shiggaon","Shikarpur","Shirhatti","Shorapur","Shrirangapattana","Siddapur","Sidlaghatta","Sindgi","Sindhnur","Sira","Siralkoppa","Sirsi","Siruguppa","Somvarpet","Sorab","Sringeri","Srinivaspur","Sulya","Talikota","Tarikere","Tekkalakote","Terdal","Thumbe","Tiptur","Tirthahalli","Tirumakudal","Tumkur","Turuvekere","Udupi","Vijayapura","Wadi","Yadgir","Yelandur","Yelbarga","Yellapur","Yenagudde"],
["Altomisayoq","Ancash","Andahuaylas","Apachekta","Apachita","Apu ","Apurimac","Arequipa","Atahuallpa","Atawalpa","Atico","Ayacucho","Ayllu","Cajamarca","Carhuac","Carhuacatac","Cashan","Caullaraju","Caxamalca","Cayesh","Chacchapunta","Chacraraju","Champara","Chanchan","Chekiacraju","Chinchey","Chontah","Chopicalqui","Chucuito","Chuito","Chullo","Chumpi","Chuncho","Chuquiapo","Churup","Cochapata","Cojup","Collota","Conococha","Copa","Corihuayrachina","Cusichaca","Despacho","Haika","Hanpiq","Hatun","Haywarisqa","Huaca","Hualcan","Huamanga","Huamashraju","Huancarhuas","Huandoy","Huantsan","Huarmihuanusca","Huascaran","Huaylas","Huayllabamba","Huichajanca","Huinayhuayna","Huinioch","Illiasca","Intipunku","Ishinca","Jahuacocha","Jirishanca","Juli","Jurau","Kakananpunta","Kamasqa","Karpay","Kausay","Khuya ","Kuelap","Llaca","Llactapata","Llanganuco","Llaqta","Llupachayoc","Machu","Mallku","Matarraju","Mikhuy","Milluacocha","Munay","Ocshapalca","Ollantaytambo","Pacamayo","Paccharaju","Pachacamac","Pachakamaq","Pachakuteq","Pachakuti","Pachamama  ","Paititi","Pajaten","Palcaraju","Pampa","Panaka","Paqarina","Paqo","Parap","Paria","Patallacta","Phuyupatamarca","Pisac","Pongos","Pucahirca","Pucaranra","Puscanturpa","Putaca","Qawaq ","Qayqa","Qochamoqo","Qollana","Qorihuayrachina","Qorimoqo","Quenuaracra","Queshque","Quillcayhuanca","Quillya","Quitaracsa","Quitaraju","Qusqu","Rajucolta","Rajutakanan","Rajutuna","Ranrahirca","Ranrapalca","Raria","Rasac","Rimarima","Riobamba","Runkuracay","Rurec","Sacsa","Saiwa","Sarapo","Sayacmarca","Sinakara","TamboColorado","Tamboccocha","Taripaypacha","Taulliraju","Tawantinsuyu","Taytanchis","Tiwanaku","Tocllaraju","Tsacra","Tuco","Tullparaju","Tumbes","Ulta","Uruashraju","Vallunaraju","Vilcabamba","Wacho ","Wankawillka","Wayra","Yachay","Yahuarraju","Yanamarey","Yanesha","Yerupaja"],
["Abim","Adjumani","Alebtong","Amolatar","Amuria","Amuru","Apac","Arua","Arusha","Babati","Baragoi","Bombo","Budaka","Bugembe","Bugiri","Buikwe","Bukedea","Bukoba","Bukomansimbi","Bukungu","Buliisa","Bundibugyo","Bungoma","Busembatya","Bushenyi","Busia","Busia","Busolwe","Butaleja","Butambala","Butere","Buwenge","Buyende","Dadaab","Dodoma","Dokolo","Eldoret","Elegu","Emali","Embu","Entebbe","Garissa","Gede","Gulu","Handeni","Hima","Hoima","Hola","Ibanda","Iganga","Iringa","Isingiro","Isiolo","Jinja","Kaabong","Kabale","Kaberamaido","Kabuyanda","Kabwohe","Kagadi","Kahama","Kajiado","Kakamega","Kakinga","Kakira","Kakiri","Kakuma","Kalangala","Kaliro","Kalisizo","Kalongo","Kalungu","Kampala","Kamuli","Kamwenge","Kanoni","Kanungu","Kapchorwa","Kapenguria","Kasese","Kasulu","Katakwi","Kayunga","Kericho","Keroka","Kiambu","Kibaale","Kibaha","Kibingo","Kiboga","Kibwezi","Kigoma","Kihiihi","Kilifi","Kira","Kiruhura","Kiryandongo","Kisii","Kisoro","Kisumu","Kitale","Kitgum","Kitui","Koboko","Korogwe","Kotido","Kumi","Kyazanga","Kyegegwa","Kyenjojo","Kyotera","Lamu","Langata","Lindi","Lodwar","Lokichoggio","Londiani","Loyangalani","Lugazi","Lukaya","Luweero","Lwakhakha","Lwengo","Lyantonde","Machakos","Mafinga","Makambako","Makindu","Malaba","Malindi","Manafwa","Mandera","Maralal","Marsabit","Masaka","Masindi","MasindiPort","Masulita","Matugga","Mayuge","Mbale","Mbarara","Mbeya","Meru","Mitooma","Mityana","Mombasa","Morogoro","Moroto","Moshi","Moyale","Moyo","Mpanda","Mpigi","Mpondwe","Mtwara","Mubende","Mukono","Mumias","Muranga","Musoma","Mutomo","Mutukula","Mwanza","Nagongera","Nairobi","Naivasha","Nakapiripirit","Nakaseke","Nakasongola","Nakuru","Namanga","Namayingo","Namutumba","Nansana","Nanyuki","Narok","Naromoru","Nebbi","Ngora","Njeru","Njombe","Nkokonjeru","Ntungamo","Nyahururu","Nyeri","Oyam","Pader","Paidha","Pakwach","Pallisa","Rakai","Ruiru","Rukungiri","Rwimi","Sanga","Sembabule","Shimoni","Shinyanga","Singida","Sironko","Songea","Soroti","Ssabagabo","Sumbawanga","Tabora","Takaungu","Tanga","Thika","Tororo","Tunduma","Vihiga","Voi","Wajir","Wakiso","Watamu","Webuye","Wobulenzi","Wote","Wundanyi","Yumbe","Zanzibar"],
["An Khe","An Nhon","Ayun Pa","Ba Don","Ba Ria","Bac Giang","Bac Kan","Bac Lieu","Bac Ninh","Bao Loc","Ben Cat","Ben Tre","Bien Hoa","Bim Son","Binh Long","Binh Minh","Buon Ho","Buon Ma Thuot","Ca Mau","Cai Lay","Cam Pha","Cam Ranh","Can Tho","Cao Bang","Cao Lanh","Chau Doc","Chi Linh","Cua Lo","Da Lat","Da Nang","Di An","Dien Ban","Dien Bien Phu","Dong Ha","Dong Hoi","Dong Trieu","Duyen Hai","Gia Nghia","Gia Rai","Go Cong","Ha Giang","Ha Long","Ha Noi","Ha Tinh","Hai Duong","Hai Phong","Hoa Binh","Hoang Mai","Hoi An","Hong Linh","Hong Ngu","Hue","Hung Yen","Huong Thuy","Huong Tra","Kien Tuong","Kon Tum","Ky Anh","La Gi","Lai Chau","Lang Son","Lao Cai","Long Khanh","Long My","Long Xuyen","Mong Cai","Muong Lay","My Hao","My Tho","Nam Dinh","Nga Bay","Nga Nam","Nghia Lo","Nha Trang","Ninh Binh","Ninh Hoa","Phan Rang Thap Cham","Phan Thiet","Pho Yen","Phu Ly","Phu My","Phu Tho","Phuoc Long","Pleiku","Quang Ngai","Quang Tri","Quang Yen","Quy Nhon","Rach Gia","Sa Dec","Sam Son","Soc Trang","Son La","Son Tay","Song Cau","Song Cong","Tam Diep","Tam Ky","Tan An","Tan Chau","Tan Uyen","Tay Ninh","Thai Binh","Thai Hoa","Thai Nguyen","Thanh Hoa","Thu Dau Mot","Thuan An","Tra Vinh","Tu Son","Tuy Hoa","Tuyen Quang","Uong Bi","Vi Thanh","Viet Tri","Vinh","Vinh Chau","Vinh Long","Vinh Yen","Vung Tau","Yen Bai"],
["Chaiwan", "Chekham", "Cheungshawan", "Chingchung", "Chinghoi", "Chingsen", "Chingshing", "Chiunam", "Chiuon", "Chiuyeung", "Chiyuen", "Choihung", "Chuehoi", "Chuiman", "Chungfa", "Chungfu", "Chungsan", "Chunguktsuen", "Dakhing", "Daopo", "Daumun", "Dingwu", "Dinpak", "Donggun", "Dongyuen", "Duenchau", "Fachau", "Fado", "Fanling", "Fatgong", "Fatshan", "Fotan", "Fuktien", "Fumun", "Funggong", "Funghoi", "Fungshun", "Fungtei", "Gamtin", "Gochau", "Goming", "Gonghoi", "Gongshing", "Goyiu", "Hanghau", "Hangmei", "Hashan", "Hengfachuen", "Hengon", "Heungchau", "Heunggong", "Heungkiu", "Hingning", "Hohfuktong", "Hoichue", "Hoifung", "Hoiping", "Hokong", "Hokshan", "Homantin", "Hotin", "Hoyuen", "Hunghom", "Hungshuikiu", "Jiuling", "Kamping", "Kamsheung", "Kamwan", "Kaulongtong", "Keilun", "Kinon", "Kinsang", "Kityeung", "Kongmun", "Kukgong", "Kwaifong", "Kwaihing", "Kwongchau", "Kwongling", "Kwongming", "Kwuntong", "Laichikok", "Laiking", "Laiwan", "Lamtei", "Lamtin", "Leitung", "Leungking", "Limkong", "Linchau", "Linnam", "Linping", "Linshan", "Loding", "Lokcheong", "Lokfu", "Lokmachau", "Longchuen", "Longgong", "Longmun", "Longping", "Longwa", "Longwu", "Lowu", "Luichau", "Lukfung", "Lukho", "Lungmun", "Macheung", "Maliushui", "Maonshan", "Mauming", "Maunam", "Meifoo", "Mingkum", "Mogong", "Mongkok", "Muichau", "Muigong", "Muiyuen", "Naiwai", "Namcheong", "Namhoi", "Namhong", "Namo", "Namsha", "Namshan", "Nganwai", "Ngchuen", "Ngoumun", "Ngwa", "Nngautaukok", "Onting", "Pakwun", "Paotoishan", "Pingshan", "Pingyuen", "Poklo", "Polam", "Pongon", "Poning", "Potau", "Puito", "Punyue", "Saiwanho", "Saiyingpun", "Samshing", "Samshui", "Samtsen", "Samyuenlei", "Sanfung", "Sanhing", "Sanhui", "Sanwai", "Sanwui", "Seiwui", "Shamshuipo", "Shanmei", "Shantau", "Shatin", "Shatinwai", "Shaukeiwan", "Shauking", "Shekkipmei", "Shekmun", "Shekpai", "Sheungshui", "Shingkui", "Shiuhing", "Shundak", "Shunyi", "Shupinwai", "Simshing", "Siuhei", "Siuhong", "Siukwan", "Siulun", "Suikai", "Taihing", "Taikoo", "Taipo", "Taishuihang", "Taiwai", "Taiwo", "Taiwohau", "Tinhau", "Tinho", "Tinking", "Tinshuiwai", "Tiukengleng", "Toishan", "Tongfong", "Tonglowan", "Tsakyoochung", "Tsamgong", "Tsangshing", "Tseungkwano", "Tsihing", "Tsimshatsui", "Tsinggong", "Tsingshantsuen", "Tsingwun", "Tsingyi", "Tsingyuen", "Tsiuchau", "Tsuenshekshan", "Tsuenwan", "Tuenmun", "Tungchung", "Waichap", "Waichau", "Waidong", "Wailoi", "Waishing", "Waiyeung", "Wanchai", "Wanfau", "Wanon", "Wanshing", "Wingon", "Wongchukhang", "Wongpo", "Wongtaisin", "Woping", "Wukaisha", "Yano", "Yaumatei", "Yauoi", "Yautong", "Yenfa", "Yeungchun", "Yeungdong", "Yeunggong", "Yeungsai", "Yeungshan", "Yimtin", "Yingdak", "Yiuping", "Yongshing", "Yongyuen", "Yuenlong", "Yuenshing", "Yuetsau", "Yuknam", "Yunping", "Yuyuen"],
["Adaatsag", "Airag", "Alag Erdene", "Altai", "Altanshiree", "Altantsogts", "Arbulag", "Baatsagaan", "Batnorov", "Batshireet", "Battsengel", "Bayan Adarga", "Bayan Agt", "Bayanbulag", "Bayandalai", "Bayandun", "Bayangovi", "Bayanjargalan", "Bayankhongor", "Bayankhutag", "Bayanlig", "Bayanmonkh", "Bayannuur", "Bayan Ondor", "Bayan Ovoo", "Bayantal", "Bayantsagaan", "Bayantumen", "Bayan Uul", "Bayanzurkh", "Berkh", "Biger", "Binder", "Bogd", "Bombogor", "Bor Ondor", "Bugat", "Bulgan", "Buregkhangai", "Burentogtokh", "Buutsagaan", "Buyant", "Chandmani", "Chandmani Ondor", "Choibalsan", "Chuluunkhoroot", "Chuluut", "Dadal", "Dalanjargalan", "Dalanzadgad", "Darkhan", "Darvi", "Dashbalbar", "Dashinchilen", "Delger", "Delgerekh", "Delgerkhaan", "Delgerkhangai", "Delgertsogt", "Deluun", "Deren", "Dorgon", "Duut", "Erdene", "Erdenebulgan", "Erdeneburen", "Erdenedalai", "Erdenemandal", "Erdenetsogt", "Galshar", "Galt", "Galuut", "Govi Ugtaal", "Gurvan", "Gurvanbulag", "Gurvansaikhan", "Gurvanzagal", "Ikhkhet", "Ikh Tamir", "Ikh Uul", "Jargalan", "Jargalant", "Jargaltkhaan", "Jinst", "Khairkhan", "Khalhgol", "Khaliun", "Khanbogd", "Khangai", "Khangal", "Khankh", "Khankhongor", "Khashaat", "Khatanbulag", "Khatgal", "Kherlen", "Khishig Ondor", "Khokh", "Kholonbuir", "Khongor", "Khotont", "Khovd", "Khovsgol", "Khuld", "Khureemaral", "Khurmen", "Khutag Ondor", "Luus", "Mandakh", "Mandal Ovoo", "Mankhan", "Manlai", "Matad", "Mogod", "Monkhkhairkhan", "Moron", "Most", "Myangad", "Nogoonnuur", "Nomgon", "Norovlin", "Noyon", "Ogii", "Olgii", "Olziit", "Omnodelger", "Ondorkhaan", "Ondorshil", "Ondor Ulaan", "Orgon", "Orkhon", "Rashaant", "Renchinlkhumbe", "Sagsai", "Saikhan", "Saikhandulaan", "Saikhan Ovoo", "Sainshand", "Saintsagaan", "Selenge", "Sergelen", "Sevrei", "Sharga", "Sharyngol", "Shine Ider", "Shinejinst", "Shiveegovi", "Sumber", "Taishir", "Tarialan", "Tariat", "Teshig", "Togrog", "Tolbo", "Tomorbulag", "Tonkhil", "Tosontsengel", "Tsagaandelger", "Tsagaannuur", "Tsagaan Ovoo", "Tsagaan Uur", "Tsakhir", "Tseel", "Tsengel", "Tsenkher", "Tsenkhermandal", "Tsetseg", "Tsetserleg", "Tsogt", "Tsogt Ovoo", "Tsogttsetsii", "Tunel", "Tuvshruulekh", "Ulaanbadrakh", "Ulaankhus", "Ulaan Uul", "Uyench", "Yesonbulag", "Zag", "Zamyn Uud", "Zereg"]
];
}
return {getBase, getCulture, getCultureShort, getState, updateChain, updateChains, getNameBase, getNameBases, getMapName};
}))); })));

View file

@ -35,7 +35,7 @@
Heresy:{"Heresy":1} Heresy:{"Heresy":1}
}; };
const methods = {"Random + type":3, "Random + ism":1, "Supreme + ism":5, "Faith of + Supreme":3, "Place + ism":1, "Culture + ism":2, "Place + ian + type":6, "Culture + type":4}; const methods = {"Random + type":3, "Random + ism":1, "Supreme + ism":5, "Faith of + Supreme":5, "Place + ism":1, "Culture + ism":2, "Place + ian + type":6, "Culture + type":4};
const types = { const types = {
"Shamanism":{"Beliefs":3, "Shamanism":2, "Spirits":1}, "Shamanism":{"Beliefs":3, "Shamanism":2, "Spirits":1},
@ -65,11 +65,14 @@
const form = rw(forms.Folk); const form = rw(forms.Folk);
const name = c.name + " " + rw(types[form]); const name = c.name + " " + rw(types[form]);
const deity = form === "Animism" ? null : getDeityName(c.i); const deity = form === "Animism" ? null : getDeityName(c.i);
const color = getRandomColor(); // `url(#hatch${rand(8,13)})`; const color = getMixedColor(c.color, .1, 0); // `url(#hatch${rand(8,13)})`;
religions.push({i: c.i, name, color, culture: c.i, type:"Folk", form, deity}); religions.push({i: c.i, name, color, culture: c.i, type:"Folk", form, deity, center: c.center, origin:0});
}); });
if (religionsInput.value == 0 || pack.cultures.length < 2) return; if (religionsInput.value == 0 || pack.cultures.length < 2) {
religions.filter(r => r.i).forEach(r => r.code = getCode(r.name));
return;
}
const sorted = cells.i.filter(i => cells.s[i] > 2).sort((a, b) => cells.s[b] - cells.s[a]); // filtered and sorted array of indexes const sorted = cells.i.filter(i => cells.s[i] > 2).sort((a, b) => cells.s[b] - cells.s[a]); // filtered and sorted array of indexes
const religionsTree = d3.quadtree(); const religionsTree = d3.quadtree();
@ -99,14 +102,14 @@
if (religionsTree.find(x, y, s) !== undefined) continue; // to close to existing religion if (religionsTree.find(x, y, s) !== undefined) continue; // to close to existing religion
// add "Old" to name of the folk religion on this culture // add "Old" to name of the folk religion on this culture
const folk = religions.find(r => expansion === "culture" && r.culture === culture && r.type === "Folk"); const folk = religions.find(r => r.culture === culture && r.type === "Folk");
if (folk && folk.name.slice(0,3) !== "Old") folk.name = "Old " + folk.name; if (folk && expansion === "culture" && folk.name.slice(0,3) !== "Old") folk.name = "Old " + folk.name;
const origin = folk ? folk.i : 0;
const expansionism = rand(3, 8); const expansionism = rand(3, 8);
const color = getRandomColor(); // `url(#hatch${rand(0,5)})`; const color = getMixedColor(religions[origin].color, .3, 0); // `url(#hatch${rand(0,5)})`;
religions.push({i: religions.length, name, color, culture, type:"Organized", form, deity, expansion, expansionism, center}); religions.push({i: religions.length, name, color, culture, type:"Organized", form, deity, expansion, expansionism, center, origin});
religionsTree.add([x, y]); religionsTree.add([x, y]);
//debug.append("circle").attr("cx", x).attr("cy", y).attr("r", 2).attr("fill", "blue");
} }
// generate cults // generate cults
@ -120,11 +123,13 @@
if (religionsTree.find(x, y, s) !== undefined) continue; // to close to existing religion if (religionsTree.find(x, y, s) !== undefined) continue; // to close to existing religion
const culture = cells.culture[center]; const culture = cells.culture[center];
const folk = religions.find(r => r.culture === culture && r.type === "Folk");
const origin = folk ? folk.i : 0;
const deity = getDeityName(culture); const deity = getDeityName(culture);
const name = getCultName(form, center); const name = getCultName(form, center);
const expansionism = gauss(1.1, .5, 0, 5); const expansionism = gauss(1.1, .5, 0, 5);
const color = getRandomColor(); // "url(#hatch7)"; const color = getMixedColor(cultures[culture].color, .5, 0); // "url(#hatch7)";
religions.push({i: religions.length, name, color, culture, type:"Cult", form, deity, expansion:"global", expansionism, center}); religions.push({i: religions.length, name, color, culture, type:"Cult", form, deity, expansion:"global", expansionism, center, origin});
religionsTree.add([x, y]); religionsTree.add([x, y]);
//debug.append("circle").attr("cx", x).attr("cy", y).attr("r", 2).attr("fill", "red"); //debug.append("circle").attr("cx", x).attr("cy", y).attr("r", 2).attr("fill", "red");
} }
@ -145,14 +150,15 @@
const culture = cells.culture[center]; const culture = cells.culture[center];
const name = getCultName("Heresy", center); const name = getCultName("Heresy", center);
const expansionism = gauss(1.2, .5, 0, 5); const expansionism = gauss(1.2, .5, 0, 5);
const color = getRandomColor(); // "url(#hatch6)"; const color = getMixedColor(r.color, .4, .2); // "url(#hatch6)";
religions.push({i: religions.length, name, color, culture, type:"Heresy", form:"Heresy", deity: r.deity, expansion:"global", expansionism, center}); religions.push({i: religions.length, name, color, culture, type:"Heresy", form:r.form, deity: r.deity, expansion:"global", expansionism, center, origin:r.i});
religionsTree.add([x, y]); religionsTree.add([x, y]);
//debug.append("circle").attr("cx", x).attr("cy", y).attr("r", 2).attr("fill", "green"); //debug.append("circle").attr("cx", x).attr("cy", y).attr("r", 2).attr("fill", "green");
} }
}); });
expandHeresies(); expandHeresies();
checkCenters();
console.timeEnd('generateReligions'); console.timeEnd('generateReligions');
} }
@ -162,22 +168,23 @@
const r = cells.religion[center]; const r = cells.religion[center];
const i = religions.length; const i = religions.length;
const culture = cells.culture[center]; const culture = cells.culture[center];
const color = getRandomColor(); const color = getMixedColor(religions[r].color, .3, 0);
const type = religions[r].type === "Organized" ? rw({Organized:4, Cult:1, Heresy:2}) : rw({Organized:5, Cult:2}); const type = religions[r].type === "Organized" ? rw({Organized:4, Cult:1, Heresy:2}) : rw({Organized:5, Cult:2});
const form = rw(forms[type]); const form = rw(forms[type]);
const deity = form === "Heresy" ? religions[r].deity : form === "Non-theism" ? null : getDeityName(culture); const deity = type === "Heresy" ? religions[r].deity : form === "Non-theism" ? null : getDeityName(culture);
let name, expansion; let name, expansion;
if (type === "Organized") [name, expansion] = getReligionName(form, deity, center) if (type === "Organized") [name, expansion] = getReligionName(form, deity, center)
else {name = getCultName(form, center); expansion = "global";} else {name = getCultName(form, center); expansion = "global";}
const formName = type === "Heresy" ? religions[r].form : form;
religions.push({i, name, color, culture, type, form, deity, expansion, expansionism:0, center, area: 0, rural: 0, urban: 0}); const code = getCode(name);
religions.push({i, name, color, culture, type, form:formName, deity, expansion, expansionism:0, center, cells:0, area:0, rural:0, urban:0, origin:r, code});
cells.religion[center] = i;
} }
// growth algorithm to assign cells to religions // growth algorithm to assign cells to religions
const expandReligions = function() { const expandReligions = function() {
console.time("expandReligions");
const cells = pack.cells, religions = pack.religions; const cells = pack.cells, religions = pack.religions;
const queue = new PriorityQueue({comparator: (a, b) => a.p - b.p}); const queue = new PriorityQueue({comparator: (a, b) => a.p - b.p});
const cost = []; const cost = [];
@ -215,17 +222,15 @@
} }
}); });
} }
console.timeEnd("expandReligions");
} }
// growth algorithm to assign cells to heresies // growth algorithm to assign cells to heresies
const expandHeresies = function() { const expandHeresies = function() {
console.time("expandHeresies");
const cells = pack.cells, religions = pack.religions; const cells = pack.cells, religions = pack.religions;
const queue = new PriorityQueue({comparator: (a, b) => a.p - b.p}); const queue = new PriorityQueue({comparator: (a, b) => a.p - b.p});
const cost = []; const cost = [];
religions.filter(r => r.form === "Heresy").forEach(r => { religions.filter(r => r.type === "Heresy").forEach(r => {
const b = cells.religion[r.center]; // "base" religion id const b = cells.religion[r.center]; // "base" religion id
cells.religion[r.center] = r.i; // heresy id cells.religion[r.center] = r.i; // heresy id
queue.queue({e:r.center, p:0, r:r.i, b}); queue.queue({e:r.center, p:0, r:r.i, b});
@ -253,8 +258,31 @@
} }
}); });
} }
//debug.selectAll(".text").data(cost).enter().append("text").attr("x", (d, e) => cells.p[e][0]-1).attr("y", (d, e) => cells.p[e][1]-1).text(d => d ? rn(d) : "").attr("font-size", 2); }
console.timeEnd("expandHeresies");
function checkCenters() {
const cells = pack.cells, religions = pack.religions;
religions.filter(r => r.i).forEach(r => {
r.code = getCode(r.name);
// move religion center if it's not within religion area after expansion
if (cells.religion[r.center] === r.i) return; // in area
const religCells = cells.i.filter(i => cells.religion[i] === r.i);
if (!religCells.length) return; // extinct religion
r.center = religCells.sort((a,b) => b.pop - a.pop)[0];
});
}
// assign a unique two-letters code (abbreviation)
function getCode(rawName) {
const name = rawName.replace("Old ", ""); // remove Old prefix
const words = name.split(" "), letters = words.join("");
let code = words.length === 2 ? words[0][0]+words[1][0] : letters.slice(0,2);
for (let i=1; i < letters.length-1 && pack.religions.some(r => r.code === code); i++) {
code = letters[0] + letters[i].toUpperCase();
}
return code;
} }
// get supreme deity name // get supreme deity name
@ -299,7 +327,7 @@
if (m === "Random + type") return [random() + " " + type(), "global"]; if (m === "Random + type") return [random() + " " + type(), "global"];
if (m === "Random + ism") return [trimVowels(random()) + "ism", "global"]; if (m === "Random + ism") return [trimVowels(random()) + "ism", "global"];
if (m === "Supreme + ism" && deity) return [trimVowels(supreme()) + "ism", "global"]; if (m === "Supreme + ism" && deity) return [trimVowels(supreme()) + "ism", "global"];
if (m === "Faith of + Supreme" && deity) return ["Faith of " + supreme(), "global"]; if (m === "Faith of + Supreme" && deity) return [ra(['Faith', 'Way', 'Path', 'Word', 'Witnesses']) + " of " + supreme(), "global"];
if (m === "Place + ism") return [place() + "ism", "state"]; if (m === "Place + ism") return [place() + "ism", "state"];
if (m === "Culture + ism") return [trimVowels(culture()) + "ism", "culture"]; if (m === "Culture + ism") return [trimVowels(culture()) + "ism", "culture"];
if (m === "Place + ian + type") return [place("adj") + " " + type(), "state"]; if (m === "Place + ian + type") return [place("adj") + " " + type(), "state"];

View file

@ -222,7 +222,9 @@ function saveAsImage(type) {
// load fonts as dataURI so they will be available in downloaded svg/png // load fonts as dataURI so they will be available in downloaded svg/png
GFontToDataURI(getFontsToLoad()).then(cssRules => { GFontToDataURI(getFontsToLoad()).then(cssRules => {
clone.select("defs").append("style").text(cssRules.join('\n')); clone.select("defs").append("style").text(cssRules.join('\n'));
const svg_xml = (new XMLSerializer()).serializeToString(clone.node()); clone.append("metadata").text("<dc:format>image/svg+xml</dc:format>");
const serialized = (new XMLSerializer()).serializeToString(clone.node());
const svg_xml = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>` + serialized;
clone.remove(); clone.remove();
const blob = new Blob([svg_xml], {type: 'image/svg+xml;charset=utf-8'}); const blob = new Blob([svg_xml], {type: 'image/svg+xml;charset=utf-8'});
const url = window.URL.createObjectURL(blob); const url = window.URL.createObjectURL(blob);
@ -239,7 +241,7 @@ function saveAsImage(type) {
img.onload = function() { img.onload = function() {
window.URL.revokeObjectURL(url); window.URL.revokeObjectURL(url);
ctx.drawImage(img, 0, 0, canvas.width, canvas.height); ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
link.download = "fantasy_map_" + Date.now() + ".png"; link.download = getFileName() + ".png";
canvas.toBlob(function(blob) { canvas.toBlob(function(blob) {
link.href = window.URL.createObjectURL(blob); link.href = window.URL.createObjectURL(blob);
document.body.appendChild(link); document.body.appendChild(link);
@ -251,7 +253,7 @@ function saveAsImage(type) {
}); });
} }
} else { } else {
link.download = "fantasy_map_" + Date.now() + ".svg"; link.download = getFileName() + ".svg";
link.href = url; link.href = url;
document.body.appendChild(link); document.body.appendChild(link);
link.click(); link.click();
@ -323,7 +325,6 @@ function GFontToDataURI(url) {
// prepare map data for saving // prepare map data for saving
function getMapData() { function getMapData() {
if (customization) return false;
console.time("createMapDataBlob"); console.time("createMapDataBlob");
return new Promise(resolve => { return new Promise(resolve => {
@ -331,9 +332,13 @@ function getMapData() {
const dateString = date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate(); const dateString = date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate();
const license = "File can be loaded in azgaar.github.io/Fantasy-Map-Generator"; const license = "File can be loaded in azgaar.github.io/Fantasy-Map-Generator";
const params = [version, license, dateString, seed, graphWidth, graphHeight].join("|"); const params = [version, license, dateString, seed, graphWidth, graphHeight].join("|");
const options = [distanceUnitInput.value, distanceScaleInput.value, areaUnit.value, heightUnit.value, heightExponentInput.value, temperatureScale.value, const options = [distanceUnitInput.value, distanceScaleInput.value, areaUnit.value,
barSize.value, barLabel.value, barBackOpacity.value, barBackColor.value, barPosX.value, barPosY.value, populationRate.value, urbanization.value, heightUnit.value, heightExponentInput.value, temperatureScale.value,
mapSizeOutput.value, latitudeOutput.value, temperatureEquatorOutput.value, temperaturePoleOutput.value, precOutput.value, JSON.stringify(winds)].join("|"); barSize.value, barLabel.value, barBackOpacity.value, barBackColor.value,
barPosX.value, barPosY.value, populationRate.value, urbanization.value,
mapSizeOutput.value, latitudeOutput.value, temperatureEquatorOutput.value,
temperaturePoleOutput.value, precOutput.value, JSON.stringify(winds),
mapName.value].join("|");
const coords = JSON.stringify(mapCoordinates); const coords = JSON.stringify(mapCoordinates);
const biomes = [biomesData.color, biomesData.habitability, biomesData.name].join("|"); const biomes = [biomesData.color, biomesData.habitability, biomesData.name].join("|");
const notesData = JSON.stringify(notes); const notesData = JSON.stringify(notes);
@ -356,13 +361,21 @@ function getMapData() {
const religions = JSON.stringify(pack.religions); const religions = JSON.stringify(pack.religions);
const provinces = JSON.stringify(pack.provinces); const provinces = JSON.stringify(pack.provinces);
// store name array only if it is not the same as default
const defaultNB = Names.getNameBase();
const namesData = nameBases.map((b,i) => {
const names = defaultNB[i] && defaultNB[i].join("") === nameBase[i].join("") ? "" : nameBase[i];
return `${b.name}|${b.min}|${b.max}|${b.d}|${b.m}|${names}`;
}).join("/");
// data format as below // data format as below
const data = [params, options, coords, biomes, notesData, svg_xml, const data = [params, options, coords, biomes, notesData, svg_xml,
gridGeneral, grid.cells.h, grid.cells.prec, grid.cells.f, grid.cells.t, grid.cells.temp, gridGeneral, grid.cells.h, grid.cells.prec, grid.cells.f, grid.cells.t, grid.cells.temp,
features, cultures, states, burgs, features, cultures, states, burgs,
pack.cells.biome, pack.cells.burg, pack.cells.conf, pack.cells.culture, pack.cells.fl, pack.cells.biome, pack.cells.burg, pack.cells.conf, pack.cells.culture, pack.cells.fl,
pack.cells.pop, pack.cells.r, pack.cells.road, pack.cells.s, pack.cells.state, pack.cells.pop, pack.cells.r, pack.cells.road, pack.cells.s, pack.cells.state,
pack.cells.religion, pack.cells.province, pack.cells.crossroad, religions, provinces].join("\r\n"); pack.cells.religion, pack.cells.province, pack.cells.crossroad, religions, provinces,
namesData].join("\r\n");
const blob = new Blob([data], {type: "text/plain"}); const blob = new Blob([data], {type: "text/plain"});
console.timeEnd("createMapDataBlob"); console.timeEnd("createMapDataBlob");
@ -374,12 +387,12 @@ function getMapData() {
// Download .map file // Download .map file
async function saveMap() { async function saveMap() {
if (customization) {tip("Map cannot be saved when edit mode is active, please exit the mode and retry", false, "error"); return;} if (customization) {tip("Map cannot be saved when edit mode is active, please exit the mode and retry", false, "error"); return;}
closeDialogs(); closeDialogs("#alert");
const blob = await getMapData(); const blob = await getMapData();
const URL = window.URL.createObjectURL(blob); const URL = window.URL.createObjectURL(blob);
const link = document.createElement("a"); const link = document.createElement("a");
link.download = "fantasy_map_" + Date.now() + ".map"; link.download = getFileName() + ".map";
link.href = URL; link.href = URL;
document.body.appendChild(link); document.body.appendChild(link);
link.click(); link.click();
@ -392,7 +405,7 @@ function saveGeoJSON() {
alertMessage.innerHTML = `You can export map data in GeoJSON format used in GIS tools such as QGIS. alertMessage.innerHTML = `You can export map data in GeoJSON format used in GIS tools such as QGIS.
Check out <a href="https://github.com/Azgaar/Fantasy-Map-Generator/wiki/GIS-data-export" target="_blank">wiki-page</a> for guidance`; Check out <a href="https://github.com/Azgaar/Fantasy-Map-Generator/wiki/GIS-data-export" target="_blank">wiki-page</a> for guidance`;
$("#alert").dialog({title: "GIS data export", resizable: false, width: 320, position: {my: "center", at: "center", of: "svg"}, $("#alert").dialog({title: "GIS data export", resizable: false, width: "32em", position: {my: "center", at: "center", of: "svg"},
buttons: { buttons: {
Cells: saveGeoJSON_Cells, Cells: saveGeoJSON_Cells,
Routes: saveGeoJSON_Roads, Routes: saveGeoJSON_Roads,
@ -422,7 +435,7 @@ function saveGeoJSON_Roads() {
const url = window.URL.createObjectURL(dataBlob); const url = window.URL.createObjectURL(dataBlob);
const link = document.createElement("a"); const link = document.createElement("a");
document.body.appendChild(link); document.body.appendChild(link);
link.download = "fmg_routes_" + Date.now() + ".geojson"; link.download = getFileName("Routes") + ".geojson";
link.href = url; link.href = url;
link.click(); link.click();
window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000); window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000);
@ -447,7 +460,7 @@ function saveGeoJSON_Rivers() {
const url = window.URL.createObjectURL(dataBlob); const url = window.URL.createObjectURL(dataBlob);
const link = document.createElement("a"); const link = document.createElement("a");
document.body.appendChild(link); document.body.appendChild(link);
link.download = "fmg_rivers_" + Date.now() + ".geojson"; link.download = getFileName("Rivers") + ".geojson";
link.href = url; link.href = url;
link.click(); link.click();
window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000); window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000);
@ -483,6 +496,92 @@ function getRiverPoints(node) {
return points; return points;
} }
async function quickSave() {
if (customization) {tip("Map cannot be saved when edit mode is active, please exit the mode and retry", false, "error"); return;}
const blob = await getMapData();
if (blob) ldb.set("lastMap", blob); // auto-save map
tip("Map is saved to browser memory", true, "success", 2000);
}
function quickLoad() {
ldb.get("lastMap", blob => {
if (blob) {
loadMapPrompt(blob);
} else {
tip("No map stored. Save map to storage first", true, "error", 2000);
console.error("No map stored");
}
});
}
function loadMapPrompt(blob) {
const workingTime = (Date.now() - last(mapHistory).created) / 60000; // minutes
if (workingTime < 5) {loadLastSavedMap(); return;}
alertMessage.innerHTML = `Are you sure you want to load saved map?<br>
All unsaved changes made to the current map will be lost`;
$("#alert").dialog({resizable: false, title: "Load saved map",
buttons: {
Cancel: function() {$(this).dialog("close");},
Load: function() {loadLastSavedMap(); $(this).dialog("close");}
}
});
function loadLastSavedMap() {
console.warn("Load last saved map");
try {
uploadFile(blob);
}
catch(error) {
console.error(error);
tip("Cannot load last saved map", true, "error", 2000);
}
}
}
const saveReminder = function() {
if (localStorage.getItem("noReminder")) return;
const message = ["Please don't forget to save your work as a .map file",
"Please remember to save work as a .map file",
"Saving in .map format will ensure your data won't be lost in case of issues",
"Safety is number one priority. Please save the map",
"Don't forget to save your map on a regular basis!",
"Just a gentle reminder for you to save the map",
"Please forget to save your progress (saving as .map is the best option)",
"Don't want to be reminded about need to save? Press CTRL+Q"];
saveReminder.reminder = setInterval(() => {
if (customization) return;
tip(ra(message), true, "warn", 2500);
}, 1e6);
saveReminder.status = 1;
}
saveReminder();
function toggleSaveReminder() {
if (saveReminder.status) {
tip("Save reminder is turned off. Press CTRL+Q again to re-initiate", true, "warn", 2000);
clearInterval(saveReminder.reminder);
localStorage.setItem("noReminder", true);
saveReminder.status = 0;
} else {
tip("Save reminder is turned on. Press CTRL+Q to turn off", true, "warn", 2000);
localStorage.removeItem("noReminder");
saveReminder();
}
}
function getFileName(dataType) {
const name = mapName.value;
const type = dataType ? dataType + " " : "";
const date = new Date();
const datFormatter = new Intl.DateTimeFormat("en", {month: "short", day: "numeric"});
const timeFormatter = new Intl.DateTimeFormat("ru", {hour: "numeric", minute: "numeric"});
const day = datFormatter.format(date).replace(" ", "");
const time = timeFormatter.format(date).replace(":", "-");
return name + " " + type + day + " " + time;
}
function saveGeoJSON_Cells() { function saveGeoJSON_Cells() {
let data = "{ \"type\": \"FeatureCollection\", \"features\": [\n"; let data = "{ \"type\": \"FeatureCollection\", \"features\": [\n";
@ -521,7 +620,7 @@ function saveGeoJSON_Cells() {
const url = window.URL.createObjectURL(dataBlob); const url = window.URL.createObjectURL(dataBlob);
const link = document.createElement("a"); const link = document.createElement("a");
document.body.appendChild(link); document.body.appendChild(link);
link.download = "fmg_cells_" + Date.now() + ".geojson"; link.download = getFileName("Cells") + ".geojson";
link.href = url; link.href = url;
link.click(); link.click();
window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000); window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000);
@ -553,7 +652,7 @@ function uploadFile(file, callback) {
<br>The map will be auto-updated. In case of issues please keep using an ${archive} of the Generator`; <br>The map will be auto-updated. In case of issues please keep using an ${archive} of the Generator`;
} }
alertMessage.innerHTML = message; alertMessage.innerHTML = message;
$("#alert").dialog({title: "Version conflict", width: 380, buttons: { $("#alert").dialog({title: "Version conflict", width: "38em", buttons: {
OK: function() {$(this).dialog("close"); if (load) parseLoadedData(data);} OK: function() {$(this).dialog("close"); if (load) parseLoadedData(data);}
}}); }});
}; };
@ -564,6 +663,11 @@ function uploadFile(file, callback) {
function parseLoadedData(data) { function parseLoadedData(data) {
try { try {
// exit customization
closeDialogs();
customization = 0;
if (customizationMenu.offsetParent) styleTab.click();
const reliefIcons = document.getElementById("defs-relief").innerHTML; // save relief icons const reliefIcons = document.getElementById("defs-relief").innerHTML; // save relief icons
const hatching = document.getElementById("hatching").cloneNode(true); // save hatching const hatching = document.getElementById("hatching").cloneNode(true); // save hatching
@ -598,6 +702,7 @@ function parseLoadedData(data) {
if (options[17]) temperaturePoleInput.value = temperaturePoleOutput.value = options[17]; if (options[17]) temperaturePoleInput.value = temperaturePoleOutput.value = options[17];
if (options[18]) precInput.value = precOutput.value = options[18]; if (options[18]) precInput.value = precOutput.value = options[18];
if (options[19]) winds = JSON.parse(options[19]); if (options[19]) winds = JSON.parse(options[19]);
if (options[20]) mapName.value = options[20];
}() }()
void function parseConfiguration() { void function parseConfiguration() {
@ -710,6 +815,16 @@ function parseLoadedData(data) {
cells.religion = data[26] ? Uint16Array.from(data[26].split(",")) : new Uint16Array(cells.i.length); cells.religion = data[26] ? Uint16Array.from(data[26].split(",")) : new Uint16Array(cells.i.length);
cells.province = data[27] ? Uint16Array.from(data[27].split(",")) : new Uint16Array(cells.i.length); cells.province = data[27] ? Uint16Array.from(data[27].split(",")) : new Uint16Array(cells.i.length);
cells.crossroad = data[28] ? Uint16Array.from(data[28].split(",")) : new Uint16Array(cells.i.length); cells.crossroad = data[28] ? Uint16Array.from(data[28].split(",")) : new Uint16Array(cells.i.length);
if (data[31]) {
const namesDL = data[31].split("/");
namesDL.forEach((d, i) => {
const e = d.split("|");
if (!e.length) return;
nameBases[i] = {name:e[0], min:e[1], max:e[2], d:e[3], m:e[4]};
if(e[5]) nameBase[i] = e[5].split(",");
});
}
}() }()
void function restoreLayersState() { void function restoreLayersState() {
@ -838,6 +953,17 @@ function parseLoadedData(data) {
if (!s.diplomacy) continue; if (!s.diplomacy) continue;
s.diplomacy = s.diplomacy.map(r => r === "Sympathy" ? "Friendly" : r); s.diplomacy = s.diplomacy.map(r => r === "Sympathy" ? "Friendly" : r);
} }
// labels should be toggled via style attribute, so remove display attribute
labels.attr("display", null);
// v 1.0 added religions heirarchy tree
if (pack.religions[1] && !pack.religions[1].code) {
pack.religions.filter(r => r.i).forEach(r => {
r.origin = 0;
r.code = r.name.slice(0, 2);
});
}
} }
}() }()
@ -858,7 +984,7 @@ function parseLoadedData(data) {
<br>generate a new random map or cancel the loading <br>generate a new random map or cancel the loading
<p id="errorBox">${parseError(error)}</p>`; <p id="errorBox">${parseError(error)}</p>`;
$("#alert").dialog({ $("#alert").dialog({
resizable: false, title: "Loading error", maxWidth:500, buttons: { resizable: false, title: "Loading error", maxWidth:"50em", buttons: {
"Select file": function() {$(this).dialog("close"); mapToLoad.click();}, "Select file": function() {$(this).dialog("close"); mapToLoad.click();},
"New map": function() {$(this).dialog("close"); regenerateMap();}, "New map": function() {$(this).dialog("close"); regenerateMap();},
Cancel: function() {$(this).dialog("close")} Cancel: function() {$(this).dialog("close")}
@ -867,79 +993,3 @@ function parseLoadedData(data) {
} }
} }
async function quickSave() {
const blob = await getMapData();
if (blob) ldb.set("lastMap", blob); // auto-save map
tip("Map is saved to browser memory", true, "success", 2000);
}
function quickLoad() {
ldb.get("lastMap", blob => {
if (blob) {
loadMapPrompt(blob);
} else {
tip("No map stored. Save map to storage first", true, "error", 2000);
console.error("No map stored");
}
});
}
function loadMapPrompt(blob) {
const workingTime = (Date.now() - last(mapHistory).created) / 60000; // minutes
if (workingTime < 10) {loadLastSavedMap(); return;}
alertMessage.innerHTML = `Are you sure you want to load saved map?<br>
All unsaved changes made to the current map will be lost`;
$("#alert").dialog({resizable: false, title: "Load saved map",
buttons: {
Cancel: function() {$(this).dialog("close");},
Load: function() {loadLastSavedMap(); $(this).dialog("close");}
}
});
function loadLastSavedMap() {
console.warn("Load last saved map");
closeDialogs();
try {
uploadFile(blob);
}
catch(error) {
console.error(error);
tip("Cannot load last saved map", true, "error", 2000);
}
}
}
const saveReminder = function() {
if (localStorage.getItem("noReminder")) return;
const message = ["Please don't forget to save your work as a .map file",
"Please remember to save work as a .map file",
"Saving in .map format will ensure your data won't be lost in case of issues",
"Safety is number one priority. Please save the map",
"Don't forget to save your map on a regular basis!",
"Just a gentle reminder for you to save the map",
"Please forget to save your progress (saving as .map is the best option)",
"Don't want to be reminded about need to save? Press CTRL+Q"];
saveReminder.reminder = setInterval(() => {
if (customization) return;
tip(ra(message), true, "warn", 2500);
}, 1e6);
saveReminder.status = 1;
}
saveReminder();
function toggleSaveReminder() {
if (saveReminder.status) {
tip("Save reminder is turned off. Press CTRL+Q again to re-initiate", true, "warn", 2000);
clearInterval(saveReminder.reminder);
localStorage.setItem("noReminder", true);
saveReminder.status = 0;
} else {
tip("Save reminder is turned on. Press CTRL+Q to turn off", true, "warn", 2000);
localStorage.removeItem("noReminder");
saveReminder();
}
}

View file

@ -85,7 +85,7 @@ function editBiomes() {
lines += `<div class="states biomes" data-id="${i}" data-name="${b.name[i]}" data-habitability="${b.habitability[i]}" lines += `<div class="states biomes" data-id="${i}" data-name="${b.name[i]}" data-habitability="${b.habitability[i]}"
data-cells=${b.cells[i]} data-area=${area} data-population=${population} data-color=${b.color[i]}> data-cells=${b.cells[i]} data-area=${area} data-population=${population} data-color=${b.color[i]}>
<svg data-tip="Biomes fill style. Click to change" width="9" height="9" style="margin-bottom:-1px"><rect x="0" y="0" width="9" height="9" fill="${b.color[i]}" class="zoneFill"></svg> <svg data-tip="Biomes fill style. Click to change" width=".9em" height=".9em" style="margin-bottom:-1px"><rect x="0" y="0" width="100%" height="100%" fill="${b.color[i]}" class="zoneFill"></svg>
<input data-tip="Biome name. Click and type to change" class="biomeName" value="${b.name[i]}" autocorrect="off" spellcheck="false"> <input data-tip="Biome name. Click and type to change" class="biomeName" value="${b.name[i]}" autocorrect="off" spellcheck="false">
<span data-tip="Biome habitability percent" class="hide">%</span> <span data-tip="Biome habitability percent" class="hide">%</span>
<input data-tip="Biome habitability percent. Click and set new value to change" type="number" min=0 max=9999 step=1 class="biomeHabitability hide" value=${b.habitability[i]}> <input data-tip="Biome habitability percent. Click and set new value to change" type="number" min=0 max=9999 step=1 class="biomeHabitability hide" value=${b.habitability[i]}>
@ -205,7 +205,7 @@ function editBiomes() {
const unit = areaUnit.value === "square" ? " " + distanceUnitInput.value + "²" : " " + areaUnit.value; const unit = areaUnit.value === "square" ? " " + distanceUnitInput.value + "²" : " " + areaUnit.value;
const line = `<div class="states biomes" data-id="${i}" data-name="${b.name[i]}" data-habitability=${b.habitability[i]} data-cells=0 data-area=0 data-population=0 data-color=${b.color[i]}> const line = `<div class="states biomes" data-id="${i}" data-name="${b.name[i]}" data-habitability=${b.habitability[i]} data-cells=0 data-area=0 data-population=0 data-color=${b.color[i]}>
<svg data-tip="Biomes fill style. Click to change" width="9" height="9" style="margin-bottom:-1px"><rect x="0" y="0" width="9" height="9" fill="${b.color[i]}" class="zoneFill"></svg> <svg data-tip="Biomes fill style. Click to change" width=".9em" height=".9em" style="margin-bottom:-1px"><rect x="0" y="0" width="100%" height="100%" fill="${b.color[i]}" class="zoneFill"></svg>
<input data-tip="Biome name. Click and type to change" class="biomeName" value="${b.name[i]}" autocorrect="off" spellcheck="false"> <input data-tip="Biome name. Click and type to change" class="biomeName" value="${b.name[i]}" autocorrect="off" spellcheck="false">
<span data-tip="Biome habitability percent" class="hide">%</span> <span data-tip="Biome habitability percent" class="hide">%</span>
<input data-tip="Biome habitability percent. Click and set new value to change" type="number" min=0 max=9999 step=1 class="biomeHabitability hide" value=${b.habitability[i]}> <input data-tip="Biome habitability percent. Click and set new value to change" type="number" min=0 max=9999 step=1 class="biomeHabitability hide" value=${b.habitability[i]}>
@ -253,7 +253,7 @@ function editBiomes() {
const url = window.URL.createObjectURL(dataBlob); const url = window.URL.createObjectURL(dataBlob);
const link = document.createElement("a"); const link = document.createElement("a");
document.body.appendChild(link); document.body.appendChild(link);
link.download = "biomes_data" + Date.now() + ".csv"; link.download = getFileName("Biomes") + ".csv";
link.href = url; link.href = url;
link.click(); link.click();
window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000); window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000);

View file

@ -75,7 +75,6 @@ function editBurgs() {
lines += `<div class="states" data-id=${b.i} data-name=${b.name} data-state=${state} data-culture=${culture} data-population=${population} data-type=${type}> lines += `<div class="states" data-id=${b.i} data-name=${b.name} data-state=${state} data-culture=${culture} data-population=${population} data-type=${type}>
<span data-tip="Click to zoom into view" class="icon-dot-circled pointer"></span> <span data-tip="Click to zoom into view" class="icon-dot-circled pointer"></span>
<input data-tip="Burg name. Click and type to change" class="burgName" value="${b.name}" autocorrect="off" spellcheck="false"> <input data-tip="Burg name. Click and type to change" class="burgName" value="${b.name}" autocorrect="off" spellcheck="false">
<span data-tip="Burg state" class="burgState ${showState}">${state}</span>
<select data-tip="Dominant culture. Click to change" class="stateCulture">${getCultureOptions(b.culture)}</select> <select data-tip="Dominant culture. Click to change" class="stateCulture">${getCultureOptions(b.culture)}</select>
<span data-tip="Burg population" class="icon-male"></span> <span data-tip="Burg population" class="icon-male"></span>
<input data-tip="Burg population. Type to change" class="burgPopulation" value=${si(population)}> <input data-tip="Burg population. Type to change" class="burgPopulation" value=${si(population)}>
@ -83,6 +82,7 @@ function editBurgs() {
<span data-tip="${b.capital ? ' This burg is a state capital' : 'Click to assign a capital status'}" class="icon-star-empty${b.capital ? '' : ' inactive pointer'}"></span> <span data-tip="${b.capital ? ' This burg is a state capital' : 'Click to assign a capital status'}" class="icon-star-empty${b.capital ? '' : ' inactive pointer'}"></span>
<span data-tip="Click to toggle port status" class="icon-anchor pointer${b.port ? '' : ' inactive'}" style="font-size:.9em"></span> <span data-tip="Click to toggle port status" class="icon-anchor pointer${b.port ? '' : ' inactive'}" style="font-size:.9em"></span>
</div> </div>
<span data-tip="Burg state" class="burgState ${showState}">${state}</span>
<span data-tip="Remove burg" class="icon-trash-empty"></span> <span data-tip="Remove burg" class="icon-trash-empty"></span>
</div>`; </div>`;
} }
@ -252,7 +252,7 @@ function editBurgs() {
} }
function downloadBurgsData() { function downloadBurgsData() {
let data = "Id,Burg,State,Culture,Population,Capital,Port,Longitude,Latitude,Elevation\n"; // headers let data = "Id,Burg,State,Culture,Population,Longitude,Latitude,Elevation ("+heightUnit.value+"),Capital,Port\n"; // headers
const valid = pack.burgs.filter(b => b.i && !b.removed); // all valid burgs const valid = pack.burgs.filter(b => b.i && !b.removed); // all valid burgs
valid.forEach(b => { valid.forEach(b => {
@ -261,20 +261,22 @@ function editBurgs() {
data += pack.states[b.state].name + ","; data += pack.states[b.state].name + ",";
data += pack.cultures[b.culture].name + ","; data += pack.cultures[b.culture].name + ",";
data += rn(b.population * populationRate.value * urbanization.value) + ","; data += rn(b.population * populationRate.value * urbanization.value) + ",";
data += b.capital ? "capital," : ",";
data += b.port ? "port," : ",";
// add geography data // add geography data
data += mapCoordinates.lonW + (b.x / graphWidth) * mapCoordinates.lonT + ","; data += mapCoordinates.lonW + (b.x / graphWidth) * mapCoordinates.lonT + ",";
data += mapCoordinates.latN - (b.y / graphHeight) * mapCoordinates.latT + ","; // this is inverted in QGIS otherwise data += mapCoordinates.latN - (b.y / graphHeight) * mapCoordinates.latT + ","; // this is inverted in QGIS otherwise
data += parseInt(getFriendlyHeight(pack.cells.h[b.cell])) + "\n"; data += parseInt(getHeight(pack.cells.h[b.cell])) + ",";
// add status data
data += b.capital ? "capital," : ",";
data += b.port ? "port\n" : "\n";
}); });
const dataBlob = new Blob([data], {type: "text/plain"}); const dataBlob = new Blob([data], {type: "text/plain"});
const url = window.URL.createObjectURL(dataBlob); const url = window.URL.createObjectURL(dataBlob);
const link = document.createElement("a"); const link = document.createElement("a");
document.body.appendChild(link); document.body.appendChild(link);
link.download = "burgs_data" + Date.now() + ".csv"; link.download = getFileName("Burgs") + ".csv";
link.href = url; link.href = url;
link.click(); link.click();
window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000); window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000);

View file

@ -89,13 +89,13 @@ function editCultures() {
lines += `<div class="states cultures" data-id=${c.i} data-name="${c.name}" data-color="${c.color}" data-cells=${c.cells} lines += `<div class="states cultures" data-id=${c.i} data-name="${c.name}" data-color="${c.color}" data-cells=${c.cells}
data-area=${area} data-population=${population} data-base=${c.base} data-type=${c.type} data-expansionism=${c.expansionism}> data-area=${area} data-population=${population} data-base=${c.base} data-type=${c.type} data-expansionism=${c.expansionism}>
<svg data-tip="Culture fill style. Click to change" width="9" height="9" style="margin-bottom:-1px"><rect x="0" y="0" width="9" height="9" fill="${c.color}" class="zoneFill"></svg> <svg data-tip="Culture fill style. Click to change" width=".9em" height=".9em" style="margin-bottom:-1px"><rect x="0" y="0" width="100%" height="100%" fill="${c.color}" class="zoneFill"></svg>
<input data-tip="Culture name. Click and type to change" class="cultureName" value="${c.name}" autocorrect="off" spellcheck="false"> <input data-tip="Culture name. Click and type to change" class="cultureName" value="${c.name}" autocorrect="off" spellcheck="false">
<span data-tip="Cells count" class="icon-check-empty hide"></span> <span data-tip="Cells count" class="icon-check-empty hide"></span>
<div data-tip="Cells count" class="stateCells hide">${c.cells}</div> <div data-tip="Cells count" class="stateCells hide">${c.cells}</div>
<span data-tip="Culture expansionism (defines competitive size)" class="icon-resize-full hide"></span> <span data-tip="Culture expansionism. Defines competitive size" class="icon-resize-full hide"></span>
<input data-tip="Expansionism (defines competitive size)" class="statePower hide" type="number" min=0 max=99 step=.1 value=${c.expansionism}> <input data-tip="Culture expansionism. Defines competitive size. Click to change" class="statePower hide" type="number" min=0 max=99 step=.1 value=${c.expansionism}>
<select data-tip="Culture type" class="cultureType">${getTypeOptions(c.type)}</select> <select data-tip="Culture type. Defines growth model. Click to change" class="cultureType">${getTypeOptions(c.type)}</select>
<span data-tip="Culture area" style="padding-right: 4px" class="icon-map-o hide"></span> <span data-tip="Culture area" style="padding-right: 4px" class="icon-map-o hide"></span>
<div data-tip="Culture area" class="biomeArea hide">${si(area) + unit}</div> <div data-tip="Culture area" class="biomeArea hide">${si(area) + unit}</div>
<span data-tip="${populationTip}" class="icon-male hide"></span> <span data-tip="${populationTip}" class="icon-male hide"></span>
@ -302,6 +302,7 @@ function editCultures() {
debug.select("#cultureCenters").style("display", "none"); debug.select("#cultureCenters").style("display", "none");
culturesEditor.querySelectorAll(".hide").forEach(el => el.classList.add("hidden")); culturesEditor.querySelectorAll(".hide").forEach(el => el.classList.add("hidden"));
culturesHeader.querySelector("div[data-sortby='type']").style.left = "6.8em";
culturesFooter.style.display = "none"; culturesFooter.style.display = "none";
culturesHeader.querySelector("div[data-sortby='base']").style.marginLeft = "21px"; culturesHeader.querySelector("div[data-sortby='base']").style.marginLeft = "21px";
body.querySelectorAll("div > input, select, span, svg").forEach(e => e.style.pointerEvents = "none"); body.querySelectorAll("div > input, select, span, svg").forEach(e => e.style.pointerEvents = "none");
@ -398,6 +399,7 @@ function editCultures() {
document.getElementById("culturesManuallyButtons").style.display = "none"; document.getElementById("culturesManuallyButtons").style.display = "none";
culturesEditor.querySelectorAll(".hide").forEach(el => el.classList.remove("hidden")); culturesEditor.querySelectorAll(".hide").forEach(el => el.classList.remove("hidden"));
culturesHeader.querySelector("div[data-sortby='type']").style.left = "15.8em";
culturesFooter.style.display = "block"; culturesFooter.style.display = "block";
culturesHeader.querySelector("div[data-sortby='base']").style.marginLeft = "2px"; culturesHeader.querySelector("div[data-sortby='base']").style.marginLeft = "2px";
body.querySelectorAll("div > input, select, span, svg").forEach(e => e.style.pointerEvents = "all"); body.querySelectorAll("div > input, select, span, svg").forEach(e => e.style.pointerEvents = "all");
@ -477,7 +479,7 @@ function editCultures() {
const url = window.URL.createObjectURL(dataBlob); const url = window.URL.createObjectURL(dataBlob);
const link = document.createElement("a"); const link = document.createElement("a");
document.body.appendChild(link); document.body.appendChild(link);
link.download = "cultures_data" + Date.now() + ".csv"; link.download = getFileName("Cultures") + ".csv";
link.href = url; link.href = url;
link.click(); link.click();
window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000); window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000);

View file

@ -204,7 +204,7 @@ function editDiplomacy() {
const url = window.URL.createObjectURL(dataBlob); const url = window.URL.createObjectURL(dataBlob);
const link = document.createElement("a"); const link = document.createElement("a");
document.body.appendChild(link); document.body.appendChild(link);
link.download = "state_relations_history" + Date.now() + ".txt"; link.download = getFileName("Relations history") + ".txt";
link.href = url; link.href = url;
link.click(); link.click();
window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000); window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000);
@ -252,7 +252,7 @@ function editDiplomacy() {
const url = window.URL.createObjectURL(dataBlob); const url = window.URL.createObjectURL(dataBlob);
const link = document.createElement("a"); const link = document.createElement("a");
document.body.appendChild(link); document.body.appendChild(link);
link.download = "state_relations_data" + Date.now() + ".csv"; link.download = getFileName("Relations") + ".csv";
link.href = url; link.href = url;
link.click(); link.click();
window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000); window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000);

View file

@ -145,15 +145,18 @@ function updateCellInfo(point, i, g) {
// get user-friendly (real-world) height value from map data // get user-friendly (real-world) height value from map data
function getFriendlyHeight(p) { function getFriendlyHeight(p) {
const packH = pack.cells.h[findCell(p[0], p[1])];
const gridH = grid.cells.h[findGridCell(p[0], p[1])];
const h = packH < 20 ? gridH : packH;
return getHeight(h);
}
function getHeight(h) {
const unit = heightUnit.value; const unit = heightUnit.value;
let unitRatio = 3.281; // default calculations are in feet let unitRatio = 3.281; // default calculations are in feet
if (unit === "m") unitRatio = 1; // if meter if (unit === "m") unitRatio = 1; // if meter
else if (unit === "f") unitRatio = 0.5468; // if fathom else if (unit === "f") unitRatio = 0.5468; // if fathom
const packH = pack.cells.h[findCell(p[0], p[1])];
const gridH = grid.cells.h[findGridCell(p[0], p[1])];
const h = packH < 20 ? gridH : packH;
let height = -990; let height = -990;
if (h >= 20) height = Math.pow(h - 18, +heightExponentInput.value); if (h >= 20) height = Math.pow(h - 18, +heightExponentInput.value);
else if (h < 20 && h > 0) height = (h - 20) / h * 50; else if (h < 20 && h > 0) height = (h - 20) / h * 50;
@ -226,14 +229,21 @@ function applyOption(select, option) {
select.value = option; select.value = option;
} }
// prevent default browser behavior for FMG-used hotkeys
document.addEventListener("keydown", event => {
if ([112, 113, 117, 120, 9].includes(event.keyCode)) event.preventDefault(); // F1, F2, F6, F9, Tab
});
// Hotkeys, see github.com/Azgaar/Fantasy-Map-Generator/wiki/Hotkeys // Hotkeys, see github.com/Azgaar/Fantasy-Map-Generator/wiki/Hotkeys
document.addEventListener("keydown", function(event) { document.addEventListener("keyup", event => {
const active = document.activeElement.tagName; const active = document.activeElement.tagName;
if (active === "INPUT" || active === "SELECT" || active === "TEXTAREA") return; // don't trigger if user inputs a text if (active === "INPUT" || active === "SELECT" || active === "TEXTAREA") return; // don't trigger if user inputs a text
if (active === "DIV" && document.activeElement.contentEditable === "true") return; // don't trigger if user inputs a text if (active === "DIV" && document.activeElement.contentEditable === "true") return; // don't trigger if user inputs a text
event.stopPropagation();
const key = event.keyCode, ctrl = event.ctrlKey, shift = event.shiftKey, meta = event.metaKey; const key = event.keyCode, ctrl = event.ctrlKey, shift = event.shiftKey, meta = event.metaKey;
if (key === 27) {closeDialogs(); hideOptions();} // Escape to close all dialogs if (key === 27) {closeDialogs(); hideOptions();} // Escape to close all dialogs
else if (key === 9) {toggleOptions(event); event.preventDefault();} // Tab to toggle options else if (key === 9) toggleOptions(event); // Tab to toggle options
else if (key === 113) regeneratePrompt(); // "F2" for new map else if (key === 113) regeneratePrompt(); // "F2" for new map
else if (key === 46) removeElementOnKey(); // "Delete" to remove the selected element else if (key === 46) removeElementOnKey(); // "Delete" to remove the selected element

View file

@ -11,9 +11,11 @@ function editHeightmap() {
<p>If you need to change the coastline and keep the data, you may try the <i>risk</i> edit option. <p>If you need to change the coastline and keep the data, you may try the <i>risk</i> edit option.
The data will be restored as much as possible, but the coastline change can cause unexpected fluctuations and errors.</p> The data will be restored as much as possible, but the coastline change can cause unexpected fluctuations and errors.</p>
<p>Check out <a href="https://github.com/Azgaar/Fantasy-Map-Generator/wiki/Heightmap-customization" target="_blank">wiki</a> for guidance.</p>`; <p>Check out <a href="https://github.com/Azgaar/Fantasy-Map-Generator/wiki/Heightmap-customization" target="_blank">wiki</a> for guidance.</p>
$("#alert").dialog({resizable: false, title: "Edit Heightmap", width: 300, <p>Please <span class="pseudoLink" onclick=saveMap(); editHeightmap();>save the map</span> before edditing the heightmap!</p>`;
$("#alert").dialog({resizable: false, title: "Edit Heightmap", width: "28em",
buttons: { buttons: {
Erase: function() {enterHeightmapEditMode("erase");}, Erase: function() {enterHeightmapEditMode("erase");},
Keep: function() {enterHeightmapEditMode("keep");}, Keep: function() {enterHeightmapEditMode("keep");},
@ -34,7 +36,6 @@ function editHeightmap() {
document.getElementById("applyTemplate").addEventListener("click", openTemplateEditor); document.getElementById("applyTemplate").addEventListener("click", openTemplateEditor);
document.getElementById("convertImage").addEventListener("click", openImageConverter); document.getElementById("convertImage").addEventListener("click", openImageConverter);
document.getElementById("heightmapPreview").addEventListener("click", toggleHeightmapPreview); document.getElementById("heightmapPreview").addEventListener("click", toggleHeightmapPreview);
document.getElementById("perspectiveView").addEventListener("click", openPerspectivePanel);
document.getElementById("finalizeHeightmap").addEventListener("click", finalizeHeightmap); document.getElementById("finalizeHeightmap").addEventListener("click", finalizeHeightmap);
document.getElementById("renderOcean").addEventListener("click", mockHeightmap); document.getElementById("renderOcean").addEventListener("click", mockHeightmap);
document.getElementById("templateUndo").addEventListener("click", () => restoreHistory(edits.n-1)); document.getElementById("templateUndo").addEventListener("click", () => restoreHistory(edits.n-1));
@ -389,7 +390,6 @@ function getHeight(h) {
if (!noStat) updateStatistics(); if (!noStat) updateStatistics();
if (document.getElementById("preview")) drawHeightmapPreview(); // update heightmap preview if opened if (document.getElementById("preview")) drawHeightmapPreview(); // update heightmap preview if opened
if ($("#perspectivePanel").is(":visible")) drawPerspective(); // update perspective view if opened
} }
// restoreHistory // restoreHistory
@ -403,7 +403,6 @@ function getHeight(h) {
updateStatistics(); updateStatistics();
if (document.getElementById("preview")) drawHeightmapPreview(); // update heightmap preview if opened if (document.getElementById("preview")) drawHeightmapPreview(); // update heightmap preview if opened
if ($("#perspectivePanel").is(":visible")) drawPerspective(); // update perspective view if opened
} }
// restart edits from 1st step // restart edits from 1st step
@ -418,7 +417,7 @@ function getHeight(h) {
function openBrushesPanel() { function openBrushesPanel() {
if ($("#brushesPanel").is(":visible")) return; if ($("#brushesPanel").is(":visible")) return;
$("#brushesPanel").dialog({ $("#brushesPanel").dialog({
title: "Paint Brushes", minHeight: 40, width: "auto", maxWidth: 200, resizable: false, title: "Paint Brushes", resizable: false,
position: {my: "right top", at: "right-10 top+10", of: "svg"} position: {my: "right top", at: "right-10 top+10", of: "svg"}
}).on('dialogclose', exitBrushMode); }).on('dialogclose', exitBrushMode);
@ -570,7 +569,7 @@ function getHeight(h) {
if (modules.openTemplateEditor) return; if (modules.openTemplateEditor) return;
modules.openTemplateEditor = true; modules.openTemplateEditor = true;
$("#templateBody").sortable({items: "div", handle: ".icon-resize-vertical", containment: "parent", axis: "y"}); $("#templateBody").sortable({items: "> div", handle: ".icon-resize-vertical", containment: "#templateBody", axis: "y"});
// add listeners // add listeners
body.addEventListener("click", function(ev) { body.addEventListener("click", function(ev) {
@ -799,6 +798,13 @@ function getHeight(h) {
addStep("Trough", "4-8", "15-30", "70-100", "80-100"); addStep("Trough", "4-8", "15-30", "70-100", "80-100");
} }
else if (template === "templateShattered") {
addStep("Hill", "8", "35-40", "15-85", "30-70");
addStep("Trough", "10-20", "40-50", "5-95", "5-95");
addStep("Range", "5-7", "30-40", "10-90", "20-80");
addStep("Pit", "12-20", "30-40", "15-85", "20-80");
}
} }
function executeTemplate() { function executeTemplate() {
@ -896,7 +902,7 @@ function getHeight(h) {
closeDialogs("#imageConverter"); closeDialogs("#imageConverter");
$("#imageConverter").dialog({ $("#imageConverter").dialog({
title: "Image Converter", minHeight: "auto", width: "22.5em", resizable: false, title: "Image Converter", minHeight: "auto", width: "19.5em", resizable: false,
position: {my: "right top", at: "right-10 top+10", of: "svg"} position: {my: "right top", at: "right-10 top+10", of: "svg"}
}).on('dialogclose', closeImageConverter); }).on('dialogclose', closeImageConverter);
@ -924,7 +930,7 @@ function getHeight(h) {
const container = d3.select("#colorScheme"); const container = d3.select("#colorScheme");
container.selectAll("div").data(d3.range(101)).enter().append("div").attr("data-color", i => i) container.selectAll("div").data(d3.range(101)).enter().append("div").attr("data-color", i => i)
.style("background-color", i => color(1-i/100)) .style("background-color", i => color(1-i/100))
.style("width", i => i < 20 || i > 70 ? "3px" : "1px") .style("width", i => i < 20 || i > 70 ? ".2em" : ".1em")
.on("touchmove mousemove", showPalleteHeight).on("click", assignHeight); .on("touchmove mousemove", showPalleteHeight).on("click", assignHeight);
}() }()
@ -1117,7 +1123,7 @@ function getHeight(h) {
preview.width = grid.cellsX; preview.width = grid.cellsX;
preview.height = grid.cellsY; preview.height = grid.cellsY;
document.body.insertBefore(preview, optionsContainer); document.body.insertBefore(preview, optionsContainer);
preview.addEventListener("mouseover", () => tip("Heightmap preview. Click to download the image")); preview.addEventListener("mouseover", () => tip("Heightmap preview. Click to download a screen-sized image"));
preview.addEventListener("click", downloadPreview); preview.addEventListener("click", downloadPreview);
drawHeightmapPreview(); drawHeightmapPreview();
} }
@ -1153,19 +1159,30 @@ function getHeight(h) {
document.body.insertBefore(canvas, optionsContainer); document.body.insertBefore(canvas, optionsContainer);
ctx.drawImage(img, 0, 0, svgWidth, svgHeight); ctx.drawImage(img, 0, 0, svgWidth, svgHeight);
// const simplex = new SimplexNoise(); // SimplexNoise by Jonas Wagner
// const noise = (nx, ny) => simplex.noise2D(nx, ny) / 2 + .5;
// const imageData = ctx.getImageData(0, 0, svgWidth, svgHeight); // const imageData = ctx.getImageData(0, 0, svgWidth, svgHeight);
// for (let i=0; i < imageData.data.length; i+=4) { // for (let i=0; i < imageData.data.length; i+=4) {
// const v = Math.min(rn(imageData.data[i] * gauss(1, .05, .9, 1.1, 3)), 255); // const v = imageData.data[i];
// imageData.data[i] = v; // if (v < 51) {
// imageData.data[i+1] = v; // // water
// imageData.data[i+2] = v; // // imageData.data[i] = imageData.data[i+1] = imageData.data[i+2] = 46;
// continue;
// }
// const x = i / 4 % svgWidth, y = Math.floor(i / 4 / svgWidth);
// const nx = x / svgWidth - .5, ny = y / svgHeight - .5;
// const n = noise(4 * nx, 4 * ny) / 4 + noise(16 * nx, 16 * ny) / 16;
// const nv = Math.max(Math.min((v + 255 * n) / 2, 255), 51);
// imageData.data[i] = imageData.data[i+1] = imageData.data[i+2] = nv;
// } // }
// ctx.putImageData(imageData, 0, 0); // ctx.putImageData(imageData, 0, 0);
const imgBig = canvas.toDataURL("image/png"); const imgBig = canvas.toDataURL("image/png");
const link = document.createElement("a"); const link = document.createElement("a");
link.target = "_blank"; link.target = "_blank";
link.download = "heightmap_" + Date.now() + ".png"; link.download = getFileName("Heightmap") + ".png";
link.href = imgBig; link.href = imgBig;
document.body.appendChild(link); document.body.appendChild(link);
link.click(); link.click();
@ -1173,68 +1190,4 @@ function getHeight(h) {
} }
} }
function openPerspectivePanel() {
if ($("#perspectivePanel").is(":visible")) return;
$("#perspectivePanel").dialog({
title: "Perspective View", minHeight: "auto", width: 510, height: 200,
position: {my: "center center", at: "center center", of: "svg"}
});
drawPerspective();
}
function drawPerspective() {
const width = 320, height = 180;
const wRatio = graphWidth / width, hRatio = graphHeight / height;
const lineCount = 320, lineGranularity = 90;
const perspective = document.getElementById("perspective");
const pContext = perspective.getContext("2d");
const lines = [];
let i = lineCount;
while (i--) {
const x = i / lineCount * width | 0;
const canvasPoints = [];
lines.push(canvasPoints);
let j = Math.floor(lineGranularity);
while (j--) {
const y = j / lineGranularity * height | 0;
let index = findGridCell(x * wRatio, y * hRatio);
let h = grid.cells.h[index] - 20;
if (h < 1) h = 0;
canvasPoints.push([x, y, h]);
}
}
pContext.clearRect(0, 0, perspective.width, perspective.height);
for (let canvasPoints of lines) {
for (let i = 0; i < canvasPoints.length - 1; i++) {
const pt1 = canvasPoints[i];
const pt2 = canvasPoints[i + 1];
const avHeight = (pt1[2] + pt2[2]) / 200;
pContext.beginPath();
pContext.moveTo(...transformPt(pt1));
pContext.lineTo(...transformPt(pt2));
let clr = "rgb(81, 103, 169)"; // water
if (avHeight !== 0) {clr = color(1 - avHeight - 0.2);}
pContext.strokeStyle = clr;
pContext.stroke();
}
for (let i = 0; i < canvasPoints.length - 1; i++) {
}
}
}
function transformPt(pt) {
const width = 320, maxHeight = 0.2;
var [x, y] = projectIsometric(pt[0],pt[1]);
return [x + width / 2 + 10, y + 10 - pt[2] * maxHeight];
}
function projectIsometric(x, y) {
const scale = 1, yProj = 4;
return [(x - y) * scale, (x + y) / yProj * scale];
}
} }

View file

@ -104,6 +104,7 @@ function getCurrentPreset() {
if (JSON.stringify(presets[preset]) !== JSON.stringify(layers)) continue; if (JSON.stringify(presets[preset]) !== JSON.stringify(layers)) continue;
layersPreset.value = preset; layersPreset.value = preset;
removePresetButton.style.display = defaultPresets[preset] ? "none" : "inline-block"; removePresetButton.style.display = defaultPresets[preset] ? "none" : "inline-block";
savePresetButton.style.display = "none";
return; return;
} }
@ -849,8 +850,8 @@ function drawGrid() {
const d = points.map(p => "M" + p + hex).join(""); const d = points.map(p => "M" + p + hex).join("");
gridOverlay.append("path").attr("d", d); gridOverlay.append("path").attr("d", d);
} else if (type === "square") { } else if (type === "square") {
const pathX = d3.range(size, svgWidth, size).map(x => "M" + rn(x, 2) + ",0v" + svgHeight); const pathX = d3.range(size, svgWidth, size).map(x => "M" + rn(x, 2) + ",0v" + svgHeight).join(" ");
const pathY = d3.range(size, svgHeight, size).map(y => "M0," + rn(y, 2) + "h" + svgWidth); const pathY = d3.range(size, svgHeight, size).map(y => "M0," + rn(y, 2) + "h" + svgWidth).join(" ");
gridOverlay.append("path").attr("d", pathX + pathY); gridOverlay.append("path").attr("d", pathX + pathY);
} }
@ -944,6 +945,9 @@ function toggleCompass() {
const tr = `translate(80 80) scale(.25)`; const tr = `translate(80 80) scale(.25)`;
d3.select("#rose").attr("transform", tr); d3.select("#rose").attr("transform", tr);
compass.append("use").attr("xlink:href","#rose"); compass.append("use").attr("xlink:href","#rose");
// prolongate rose lines
svg.select("g#rose > g#sL > line#sL1").attr("y1", -19000).attr("y2", 19000);
svg.select("g#rose > g#sL > line#sL2").attr("x1", -19000).attr("x2", 19000);
} }
} else { } else {
$('#compass').fadeOut(); $('#compass').fadeOut();
@ -1011,11 +1015,11 @@ function toggleMarkers() {
function toggleLabels() { function toggleLabels() {
if (!layerIsOn("toggleLabels")) { if (!layerIsOn("toggleLabels")) {
turnButtonOn("toggleLabels"); turnButtonOn("toggleLabels");
labels.attr("display", null) labels.style("display", null)
invokeActiveZooming(); invokeActiveZooming();
} else { } else {
turnButtonOff("toggleLabels"); turnButtonOff("toggleLabels");
labels.attr("display", "none"); labels.style("display", "none");
} }
} }

View file

@ -268,9 +268,9 @@ function drawScaleBar() {
// fit ScaleBar to map size // fit ScaleBar to map size
function fitScaleBar() { function fitScaleBar() {
if (!scaleBar.select("rect").size()) return; if (!scaleBar.select("rect").size() || scaleBar.style("display") === "none") return;
const px = isNaN(+barPosX.value) ? 99 : barPosX.value / 100; const px = isNaN(+barPosX.value) ? .99 : barPosX.value / 100;
const py = isNaN(+barPosY.value) ? 99 : barPosY.value / 100; const py = isNaN(+barPosY.value) ? .99 : barPosY.value / 100;
const bbox = scaleBar.select("rect").node().getBBox(); const bbox = scaleBar.select("rect").node().getBBox();
const x = rn(svgWidth * px - bbox.width + 10), y = rn(svgHeight * py - bbox.height + 20); const x = rn(svgWidth * px - bbox.width + 10), y = rn(svgHeight * py - bbox.height + 20);
scaleBar.attr("transform", `translate(${x},${y})`); scaleBar.attr("transform", `translate(${x},${y})`);

View file

@ -27,17 +27,14 @@ function editNamesbase() {
updateInputs(); updateInputs();
$("#namesbaseEditor").dialog({ $("#namesbaseEditor").dialog({
title: "Namesbase Editor", width: 468, title: "Namesbase Editor", width: "42.5em",
position: {my: "center", at: "center", of: "svg"} position: {my: "center", at: "center", of: "svg"}
}); });
function createBasesList() { function createBasesList() {
const select = document.getElementById("namesbaseSelect"); const select = document.getElementById("namesbaseSelect");
select.innerHTML = ""; select.innerHTML = "";
nameBases.forEach(function(b, i) { nameBases.forEach((b, i) => select.options.add(new Option(b.name, i)));
const option = new Option(b.name, i);
select.options.add(option);
});
} }
function updateInputs() { function updateInputs() {
@ -130,7 +127,8 @@ function editNamesbase() {
buttons: { buttons: {
Restore: function() { Restore: function() {
$(this).dialog("close"); $(this).dialog("close");
applyDefaultNamesData(); nameBases = Names.getNameBases();
nameBase = Names.getNameBase();
createBasesList(); createBasesList();
updateInputs(); updateInputs();
Names.updateChains(); Names.updateChains();
@ -145,7 +143,7 @@ function editNamesbase() {
const dataBlob = new Blob([data.join("\r\n")], {type:"text/plain"}); const dataBlob = new Blob([data.join("\r\n")], {type:"text/plain"});
const url = window.URL.createObjectURL(dataBlob); const url = window.URL.createObjectURL(dataBlob);
const link = document.createElement("a"); const link = document.createElement("a");
link.download = "namesbase" + Date.now() + ".txt"; link.download = getFileName("Namesbase") + ".txt";
link.href = url; link.href = url;
link.click(); link.click();
} }

View file

@ -27,7 +27,7 @@ function editNotes(id, name) {
// open a dialog // open a dialog
$("#notesEditor").dialog({ $("#notesEditor").dialog({
title: "Notes Editor", minWidth: Math.min(svgWidth, 400), title: "Notes Editor", minWidth: "40em",
position: {my: "center", at: "center", of: "svg"} position: {my: "center", at: "center", of: "svg"}
}); });
@ -108,7 +108,7 @@ function editNotes(id, name) {
const dataBlob = new Blob([legendString],{type:"text/plain"}); const dataBlob = new Blob([legendString],{type:"text/plain"});
const url = window.URL.createObjectURL(dataBlob); const url = window.URL.createObjectURL(dataBlob);
const link = document.createElement("a"); const link = document.createElement("a");
link.download = "notes" + Date.now() + ".txt"; link.download = getFileName("Notes") + ".txt";
link.href = url; link.href = url;
link.click(); link.click();
} }

View file

@ -61,8 +61,9 @@ options.querySelector("div.tab").addEventListener("click", function(event) {
if (id === "styleTab") styleContent.style.display = "block"; else if (id === "styleTab") styleContent.style.display = "block"; else
if (id === "optionsTab") optionsContent.style.display = "block"; else if (id === "optionsTab") optionsContent.style.display = "block"; else
if (id === "toolsTab" && (!customization || customization === 10)) toolsContent.style.display = "block"; else if (id === "toolsTab") customization === 1
if (id === "toolsTab" && customization && customization !== 10) customizationMenu.style.display = "block"; else ? customizationMenu.style.display = "block"
: toolsContent.style.display = "block"; else
if (id === "aboutTab") aboutContent.style.display = "block"; if (id === "aboutTab") aboutContent.style.display = "block";
}); });
@ -343,17 +344,18 @@ styleClippingInput.addEventListener("change", function() {
styleGridType.addEventListener("change", function() { styleGridType.addEventListener("change", function() {
if (layerIsOn("toggleGrid")) drawGrid(); if (layerIsOn("toggleGrid")) drawGrid();
calculateFriendlyGridSize();
}); });
styleGridSize.addEventListener("input", function() { styleGridSize.addEventListener("input", function() {
if (layerIsOn("toggleGrid")) drawGrid(); if (layerIsOn("toggleGrid")) drawGrid();
styleGridSizeOutput.value = this.value;
calculateFriendlyGridSize(); calculateFriendlyGridSize();
}); });
function calculateFriendlyGridSize() { function calculateFriendlyGridSize() {
const size = styleGridSize.value * Math.cos(30 * Math.PI / 180) * 2;; const square = styleGridType.value === "square";
const friendly = "(" + rn(size * distanceScaleInput.value) + " " + distanceUnitInput.value + ")"; const size = square ? styleGridSize.value : styleGridSize.value * Math.cos(30 * Math.PI / 180) * 2;
const friendly = `${rn(size * distanceScaleInput.value, 2)} ${distanceUnitInput.value}`;
styleGridSizeFriendly.value = friendly; styleGridSizeFriendly.value = friendly;
} }
@ -584,6 +586,7 @@ styleStatesHaloOpacity.addEventListener("input", function() {
// request to restore default style on button click // request to restore default style on button click
function askToRestoreDefaultStyle() { function askToRestoreDefaultStyle() {
if (customization) {tip("Please exit the customization mode first", false, "error"); return;}
alertMessage.innerHTML = "Are you sure you want to restore default style for all elements?"; alertMessage.innerHTML = "Are you sure you want to restore default style for all elements?";
$("#alert").dialog({resizable: false, title: "Restore default style", $("#alert").dialog({resizable: false, title: "Restore default style",
buttons: { buttons: {
@ -600,9 +603,9 @@ function askToRestoreDefaultStyle() {
// request a URL to image to be used as a texture // request a URL to image to be used as a texture
function textureProvideURL() { function textureProvideURL() {
alertMessage.innerHTML = `Provide an image URL to be used as a texture: alertMessage.innerHTML = `Provide an image URL to be used as a texture:
<input id="textureURL" type="url" style="width: 254px" placeholder="http://www.example.com/image.jpg" oninput="fetchTextureURL(this.value)"> <input id="textureURL" type="url" style="width: 24em" placeholder="http://www.example.com/image.jpg" oninput="fetchTextureURL(this.value)">
<div style="border: 1px solid darkgrey; height: 144px; margin-top: 2px"><canvas id="preview" width="256px" height="144px"></canvas></div>`; <div style="border: 1px solid darkgrey; height: 144px; margin-top: 2px"><canvas id="preview" width="256px" height="144px"></canvas></div>`;
$("#alert").dialog({resizable: false, title: "Load custom texture", width: 280, $("#alert").dialog({resizable: false, title: "Load custom texture", width: "26em",
buttons: { buttons: {
Apply: function() { Apply: function() {
const name = textureURL.value.split("/").pop(); const name = textureURL.value.split("/").pop();
@ -677,7 +680,8 @@ optionsContent.addEventListener("input", function(event) {
else if (id === "neutralOutput") neutralInput.value = value; else if (id === "neutralOutput") neutralInput.value = value;
else if (id === "manorsInput") changeBurgsNumberSlider(value); else if (id === "manorsInput") changeBurgsNumberSlider(value);
else if (id === "religionsInput") religionsOutput.value = value; else if (id === "religionsInput") religionsOutput.value = value;
else if (id === "uiSizeInput" || id === "uiSizeOutput") changeUIsize(value); else if (id === "uiSizeInput") uiSizeOutput.value = value;
else if (id === "uiSizeOutput") changeUIsize(value);
else if (id === "tooltipSizeInput" || id === "tooltipSizeOutput") changeTooltipSize(value); else if (id === "tooltipSizeInput" || id === "tooltipSizeOutput") changeTooltipSize(value);
else if (id === "transparencyInput") changeDialogsTransparency(value); else if (id === "transparencyInput") changeDialogsTransparency(value);
else if (id === "pngResolutionInput") pngResolutionOutput.value = value; else if (id === "pngResolutionInput") pngResolutionOutput.value = value;
@ -689,6 +693,7 @@ optionsContent.addEventListener("change", function(event) {
const id = event.target.id, value = event.target.value; const id = event.target.id, value = event.target.value;
if (id === "zoomExtentMin" || id === "zoomExtentMax") changeZoomExtent(value); if (id === "zoomExtentMin" || id === "zoomExtentMax") changeZoomExtent(value);
else if (id === "optionsSeed") generateMapWithSeed(); else if (id === "optionsSeed") generateMapWithSeed();
else if (id === "uiSizeInput") changeUIsize(value);
}); });
optionsContent.addEventListener("click", function(event) { optionsContent.addEventListener("click", function(event) {
@ -801,9 +806,10 @@ function changeBurgsNumberSlider(value) {
} }
function changeUIsize(value) { function changeUIsize(value) {
if (isNaN(+value) || +value > 4 || +value < .5) return;
uiSizeInput.value = uiSizeOutput.value = value; uiSizeInput.value = uiSizeOutput.value = value;
document.getElementsByTagName("body")[0].style.fontSize = value * 11 + "px"; document.getElementsByTagName("body")[0].style.fontSize = value * 11 + "px";
document.getElementById("options").style.width = (value - 1) * 300 / 2 + 300 + "px"; document.getElementById("options").style.width = value * 300 + "px";
} }
function changeTooltipSize(value) { function changeTooltipSize(value) {
@ -855,9 +861,11 @@ function applyStoredOptions() {
if (localStorage.getItem("winds")) winds = localStorage.getItem("winds").split(",").map(w => +w); if (localStorage.getItem("winds")) winds = localStorage.getItem("winds").split(",").map(w => +w);
changeDialogsTransparency(localStorage.getItem("transparency") || 15); changeDialogsTransparency(localStorage.getItem("transparency") || 15);
if (localStorage.getItem("uiSize")) changeUIsize(localStorage.getItem("uiSize"));
if (localStorage.getItem("tooltipSize")) changeTooltipSize(localStorage.getItem("tooltipSize")); if (localStorage.getItem("tooltipSize")) changeTooltipSize(localStorage.getItem("tooltipSize"));
if (localStorage.getItem("regions")) changeStatesNumber(localStorage.getItem("regions")); if (localStorage.getItem("regions")) changeStatesNumber(localStorage.getItem("regions"));
if (localStorage.getItem("uiSize")) changeUIsize(localStorage.getItem("uiSize"));
else changeUIsize(Math.max(Math.min(rn(mapWidthInput.value / 1280, 1), 2.5), 1));
} }
// randomize options if randomization is allowed (not locked) // randomize options if randomization is allowed (not locked)
@ -885,7 +893,7 @@ function randomizeOptions() {
const US = navigator.language === "en-US"; const US = navigator.language === "en-US";
const UK = navigator.language === "en-GB"; const UK = navigator.language === "en-GB";
if (!locked("distanceScale")) distanceScaleOutput.value = distanceScaleInput.value = gauss(3, 1, 1, 5); if (!locked("distanceScale")) distanceScaleOutput.value = distanceScaleInput.value = gauss(3, 1, 1, 5);
if (!stored("distanceUnit")) distanceUnitInput.value = distanceUnitOutput.value = US || UK ? "mi" : "km"; if (!stored("distanceUnit")) distanceUnitInput.value = US || UK ? "mi" : "km";
if (!stored("heightUnit")) heightUnit.value = US || UK ? "ft" : "m"; if (!stored("heightUnit")) heightUnit.value = US || UK ? "ft" : "m";
if (!stored("temperatureScale")) temperatureScale.value = US ? "°F" : "°C"; if (!stored("temperatureScale")) temperatureScale.value = US ? "°F" : "°C";
} }
@ -1004,7 +1012,7 @@ document.getElementById("sticked").addEventListener("click", function(event) {
function regeneratePrompt() { function regeneratePrompt() {
const workingTime = (Date.now() - last(mapHistory).created) / 60000; // minutes const workingTime = (Date.now() - last(mapHistory).created) / 60000; // minutes
if (workingTime < 10) {regenerateMap(); return;} if (workingTime < 5) {regenerateMap(); return;}
alertMessage.innerHTML = `Are you sure you want to generate a new map?<br> alertMessage.innerHTML = `Are you sure you want to generate a new map?<br>
All unsaved changes made to the current map will be lost`; All unsaved changes made to the current map will be lost`;
@ -1035,22 +1043,6 @@ function toggleSavePane() {
} }
} }
// async function saveDropbox() {
// const filename = "fantasy_map_" + Date.now() + ".map";
// const options = {
// files: [{'url': '...', 'filename': 'fantasy_map.map'}],
// success: function () {alert("Success! Files saved to your Dropbox.")},
// progress: function (progress) {console.log(progress)},
// cancel: function (cancel) {console.log(cancel)},
// error: function (error) {console.log(error)}
// };
// // working file: "https://dl.dropbox.com/s/llg93mwyonyzdmu/test.map?dl=1";
// const dataBlob = await getMapData();
// const URL = window.URL.createObjectURL(dataBlob);
// Dropbox.save(URL, filename, options);
// }
function toggleLoadPane() { function toggleLoadPane() {
if (loadDropdown.style.display === "block") {loadDropdown.style.display = "none"; return;} if (loadDropdown.style.display === "block") {loadDropdown.style.display = "none"; return;}
loadDropdown.style.display = "block"; loadDropdown.style.display = "block";
@ -1059,15 +1051,14 @@ function toggleLoadPane() {
function loadURL() { function loadURL() {
const pattern = /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/; const pattern = /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/;
const inner = `Provide URL to a .map file: const inner = `Provide URL to a .map file:
<input id="mapURL" type="url" style="width: 254px" placeholder="https://e-cloud.com/test.map"> <input id="mapURL" type="url" style="width: 24em" placeholder="https://e-cloud.com/test.map">
<br><i>Please note server should allow CORS for file to be loaded. If CORS is not allowed, save file to Dropbox and provide a direct link</i>`; <br><i>Please note server should allow CORS for file to be loaded. If CORS is not allowed, save file to Dropbox and provide a direct link</i>`;
alertMessage.innerHTML = inner; alertMessage.innerHTML = inner;
$("#alert").dialog({resizable: false, title: "Load map from URL", width: 280, $("#alert").dialog({resizable: false, title: "Load map from URL", width: "26em",
buttons: { buttons: {
Load: function() { Load: function() {
const value = mapURL.value; const value = mapURL.value;
if (!pattern.test(value)) {tip("Please provide a valid URL", false, "error"); return;} if (!pattern.test(value)) {tip("Please provide a valid URL", false, "error"); return;}
closeDialogs();
loadMapFromURL(value); loadMapFromURL(value);
$(this).dialog("close"); $(this).dialog("close");
}, },
@ -1076,26 +1067,6 @@ function loadURL() {
}); });
} }
// function loadDropbox() {
// const options = {
// success: function(file) {send_files(file)},
// cancel: function() {},
// linkType: "preview",
// multiselect: false,
// extensions:['.map'],
// };
// Dropbox.choose(options);
// function send_files(file) {
// const subject = "Shared File Links";
// let body = "";
// for (let i=0; i < file.length; i++) {
// body += file[i].name + "\n" + file[i].link + "\n\n";
// }
// location.href = 'mailto:coworker@example.com?Subject=' + escape(subject) + '&body='+ escape(body),'200','200';
// }
// }
// load map // load map
document.getElementById("mapToLoad").addEventListener("change", function() { document.getElementById("mapToLoad").addEventListener("change", function() {
const fileToLoad = this.files[0]; const fileToLoad = this.files[0];

View file

@ -22,6 +22,7 @@ function editProvinces() {
document.getElementById("provincesEditorRefresh").addEventListener("click", refreshProvincesEditor); document.getElementById("provincesEditorRefresh").addEventListener("click", refreshProvincesEditor);
document.getElementById("provincesFilterState").addEventListener("change", provincesEditorAddLines); document.getElementById("provincesFilterState").addEventListener("change", provincesEditorAddLines);
document.getElementById("provincesPercentage").addEventListener("click", togglePercentageMode); document.getElementById("provincesPercentage").addEventListener("click", togglePercentageMode);
document.getElementById("provincesChart").addEventListener("click", showChart);
document.getElementById("provincesToggleLabels").addEventListener("click", toggleLabels); document.getElementById("provincesToggleLabels").addEventListener("click", toggleLabels);
document.getElementById("provincesExport").addEventListener("click", downloadProvincesData); document.getElementById("provincesExport").addEventListener("click", downloadProvincesData);
document.getElementById("provincesRemoveAll").addEventListener("click", removeAllProvinces); document.getElementById("provincesRemoveAll").addEventListener("click", removeAllProvinces);
@ -106,15 +107,15 @@ function editProvinces() {
const capital = p.burg ? pack.burgs[p.burg].name : ''; const capital = p.burg ? pack.burgs[p.burg].name : '';
const focused = defs.select("#fog #focusProvince"+p.i).size(); const focused = defs.select("#fog #focusProvince"+p.i).size();
lines += `<div class="states" data-id=${p.i} data-name=${p.name} data-form=${p.formName} data-color="${p.color}" data-capital="${capital}" data-state="${stateName}" data-area=${area} data-population=${population}> lines += `<div class="states" data-id=${p.i} data-name=${p.name} data-form=${p.formName} data-color="${p.color}" data-capital="${capital}" data-state="${stateName}" data-area=${area} data-population=${population}>
<svg data-tip="Province fill style. Click to change" width="9" height="9" style="margin-bottom:-1px"><rect x="0" y="0" width="9" height="9" fill="${p.color}" class="zoneFill"></svg> <svg data-tip="Province fill style. Click to change" width=".9em" height=".9em" style="margin-bottom:-1px"><rect x="0" y="0" width="100%" height="100%" fill="${p.color}" class="zoneFill"></svg>
<input data-tip="Province name. Click and type to change" class="stateName" value="${p.name}" autocorrect="off" spellcheck="false"> <input data-tip="Province name. Click and type to change" class="stateName" value="${p.name}" autocorrect="off" spellcheck="false">
<span data-tip="Click to re-generate province name" class="icon-arrows-cw stateName hoverButton placeholder"></span> <span data-tip="Click to re-generate province name" class="icon-arrows-cw stateName hoverButton placeholder"></span>
<span data-tip="Click to open province COA in the Iron Arachne Heraldry Generator" class="icon-fleur pointer hide"></span> <span data-tip="Click to open province COA in the Iron Arachne Heraldry Generator" class="icon-fleur pointer hide"></span>
<input data-tip="Province form name. Click and type to change" class="stateForm" value="${p.formName}" autocorrect="off" spellcheck="false"> <input data-tip="Province form name. Click and type to change" class="stateForm hide" value="${p.formName}" autocorrect="off" spellcheck="false">
<span data-tip="Click to re-generate form name" class="icon-arrows-cw stateForm hoverButton placeholder"></span> <span data-tip="Click to re-generate form name" class="icon-arrows-cw stateForm hoverButton placeholder"></span>
<span data-tip="Province capital. Click to zoom into view" class="icon-star-empty pointer hide ${p.burg?'':'placeholder'}"></span> <span data-tip="Province capital. Click to zoom into view" class="icon-star-empty pointer hide ${p.burg?'':'placeholder'}"></span>
<select data-tip="Province capital. Click to select from burgs within the state. No capital means the province is governed from the state capital" class="cultureBase hide ${p.burgs.length?'':'placeholder'}">${p.burgs.length ? getCapitalOptions(p.burgs, p.burg) : ''}</select> <select data-tip="Province capital. Click to select from burgs within the state. No capital means the province is governed from the state capital" class="cultureBase hide ${p.burgs.length?'':'placeholder'}">${p.burgs.length ? getCapitalOptions(p.burgs, p.burg) : ''}</select>
<input data-tip="Province owner" class="provinceOwner" value="${stateName}" disabled hide"> <input data-tip="Province owner" class="provinceOwner" value="${stateName}" disabled">
<span data-tip="Province area" style="padding-right: 4px" class="icon-map-o hide"></span> <span data-tip="Province area" style="padding-right: 4px" class="icon-map-o hide"></span>
<div data-tip="Province area" class="biomeArea hide">${si(area) + unit}</div> <div data-tip="Province area" class="biomeArea hide">${si(area) + unit}</div>
<span data-tip="${populationTip}" class="icon-male hide"></span> <span data-tip="${populationTip}" class="icon-male hide"></span>
@ -151,17 +152,25 @@ function editProvinces() {
function provinceHighlightOn(event) { function provinceHighlightOn(event) {
if (!customization) event.target.querySelectorAll(".hoverButton").forEach(el => el.classList.remove("placeholder")); if (!customization) event.target.querySelectorAll(".hoverButton").forEach(el => el.classList.remove("placeholder"));
const province = +event.target.dataset.id;
const el = body.querySelector(`div[data-id='${province}']`);
if (el) el.classList.add("active");
if (!layerIsOn("toggleProvinces")) return; if (!layerIsOn("toggleProvinces")) return;
if (customization) return; if (customization) return;
const province = +event.target.dataset.id;
const animate = d3.transition().duration(2000).ease(d3.easeSinIn); const animate = d3.transition().duration(2000).ease(d3.easeSinIn);
provs.select("#province"+province).raise().transition(animate).attr("stroke-width", 2.5).attr("stroke", "#d0240f"); provs.select("#province"+province).raise().transition(animate).attr("stroke-width", 2.5).attr("stroke", "#d0240f");
} }
function provinceHighlightOff(event) { function provinceHighlightOff(event) {
if (!customization) event.target.querySelectorAll(".hoverButton").forEach(el => el.classList.add("placeholder")); if (!customization) event.target.querySelectorAll(".hoverButton").forEach(el => el.classList.add("placeholder"));
if (!layerIsOn("toggleProvinces")) return;
const province = +event.target.dataset.id; const province = +event.target.dataset.id;
const el = body.querySelector(`div[data-id='${province}']`);
if (el) el.classList.remove("active");
if (!layerIsOn("toggleProvinces")) return;
provs.select("#province"+province).transition().attr("stroke-width", null).attr("stroke", null); provs.select("#province"+province).transition().attr("stroke-width", null).attr("stroke", null);
} }
@ -272,6 +281,119 @@ function editProvinces() {
} }
} }
function showChart() {
// build hierarchy tree
const states = pack.states.map(s => {
return {id:s.i, state: s.i?0:null, color: s.i && s.color[0] === "#" ? d3.color(s.color).darker() : "#666"}
});
const provinces = pack.provinces.filter(p => p.i && !p.removed);
provinces.forEach(p => p.id = p.i + states.length - 1);
const data = states.concat(provinces);
const root = d3.stratify().parentId(d => d.state)(data).sum(d => d.area);
const width = 300 + 300 * uiSizeOutput.value, height = 90 + 90 * uiSizeOutput.value;
const margin = {top: 10, right: 10, bottom: 0, left: 10};
const w = width - margin.left - margin.right;
const h = height - margin.top - margin.bottom;
const treeLayout = d3.treemap().size([w, h]).padding(2);
// prepare svg
alertMessage.innerHTML = `<select id="provincesTreeType" style="display:block; margin-left:13px; font-size:11px">
<option value="area" selected>Area</option>
<option value="population">Total population</option>
<option value="rural">Rural population</option>
<option value="urban">Urban population</option>
</select>`;
alertMessage.innerHTML += `<div id='provinceInfo' class='chartInfo'>&#8205;</div>`;
const svg = d3.select("#alertMessage").insert("svg", "#provinceInfo").attr("id", "provincesTree")
.attr("width", width).attr("height", height).attr("font-size", "10px");
const graph = svg.append("g").attr("transform", `translate(10, 0)`);
document.getElementById("provincesTreeType").addEventListener("change", updateChart);
treeLayout(root);
const node = graph.selectAll("g").data(root.leaves()).enter()
.append("g").attr("data-id", d => d.data.i)
.on("mouseenter", d => showInfo(event, d))
.on("mouseleave", d => hideInfo(event, d));
function showInfo(ev, d) {
d3.select(ev.target).select("rect").classed("selected", 1);
const name = d.data.fullName;
const state = pack.states[d.data.state].fullName;
const unit = areaUnit.value === "square" ? " " + distanceUnitInput.value + "²" : " " + areaUnit.value;
const area = d.data.area * (distanceScaleInput.value ** 2) + unit;
const rural = rn(d.data.rural * populationRate.value);
const urban = rn(d.data.urban * populationRate.value * urbanization.value);
const value = provincesTreeType.value === "area" ? "Area: " + area
: provincesTreeType.value === "rural" ? "Rural population: " + si(rural)
: provincesTreeType.value === "urban" ? "Urban population: " + si(urban)
: "Population: " + si(rural + urban);
provinceInfo.innerHTML = `${name}. ${state}. ${value}`;
provinceHighlightOn(ev);
}
function hideInfo(ev) {
provinceHighlightOff(ev);
if (!document.getElementById("provinceInfo")) return;
provinceInfo.innerHTML = "&#8205;";
d3.select(ev.target).select("rect").classed("selected", 0);
}
node.append("rect").attr("stroke", d => d.parent.data.color)
.attr("stroke-width", 1).attr("fill", d => d.data.color)
.attr("x", d => d.x0).attr("y", d => d.y0)
.attr("width", d => d.x1 - d.x0).attr("height", d => d.y1 - d.y0);
node.append("text").attr("dx", ".2em").attr("dy", "1em")
.attr("x", d => d.x0).attr("y", d => d.y0);
function hideNonfittingLabels() {
node.select("text").each(function(d) {
this.innerHTML = d.data.name;
let b = this.getBBox();
if (b.y + b.height > d.y1 + 1) this.innerHTML = "";
for(let i=0; i < 15 && b.width > 0 && b.x + b.width > d.x1; i++) {
if (this.innerHTML.length < 3) {this.innerHTML = ""; break;}
this.innerHTML = this.innerHTML.slice(0, -2) + "…";
b = this.getBBox();
}
})
}
function updateChart() {
const value = this.value === "area" ? d => d.area
: this.value === "rural" ? d => d.rural
: this.value === "urban" ? d => d.urban
: d => d.rural + d.urban;
const newRoot = d3.stratify().parentId(d => d.state)(data).sum(value);
node.data(treeLayout(newRoot).leaves())
node.select("rect").transition().duration(1500)
.attr("x", d => d.x0).attr("y", d => d.y0)
.attr("width", d => d.x1 - d.x0).attr("height", d => d.y1 - d.y0);
node.select("text").attr("opacity", 1).transition().duration(1500)
.attr("x", d => d.x0).attr("y", d => d.y0);
setTimeout(hideNonfittingLabels, 2000);
}
$("#alert").dialog({
title: "Provinces chart", width: fitContent(),
position: {my: "left bottom", at: "left+10 bottom-10", of: "svg"}, buttons: {},
close: () => {alertMessage.innerHTML = "";}
});
hideNonfittingLabels();
}
function toggleLabels() { function toggleLabels() {
const hidden = provs.select("#provinceLabels").style("display") === "none"; const hidden = provs.select("#provinceLabels").style("display") === "none";
provs.select("#provinceLabels").style("display", `${hidden ? "block" : "none"}`); provs.select("#provinceLabels").style("display", `${hidden ? "block" : "none"}`);
@ -291,6 +413,7 @@ function editProvinces() {
document.getElementById("provincesManuallyButtons").style.display = "inline-block"; document.getElementById("provincesManuallyButtons").style.display = "inline-block";
provincesEditor.querySelectorAll(".hide").forEach(el => el.classList.add("hidden")); provincesEditor.querySelectorAll(".hide").forEach(el => el.classList.add("hidden"));
provincesHeader.querySelector("div[data-sortby='state']").style.left = "7.7em";
provincesFooter.style.display = "none"; provincesFooter.style.display = "none";
body.querySelectorAll("div > input, select, span, svg").forEach(e => e.style.pointerEvents = "none"); body.querySelectorAll("div > input, select, span, svg").forEach(e => e.style.pointerEvents = "none");
$("#provincesEditor").dialog({position: {my: "right top", at: "right-10 top+10", of: "svg", collision: "fit"}}); $("#provincesEditor").dialog({position: {my: "right top", at: "right-10 top+10", of: "svg", collision: "fit"}});
@ -399,6 +522,7 @@ function editProvinces() {
document.getElementById("provincesManuallyButtons").style.display = "none"; document.getElementById("provincesManuallyButtons").style.display = "none";
provincesEditor.querySelectorAll(".hide:not(.show)").forEach(el => el.classList.remove("hidden")); provincesEditor.querySelectorAll(".hide:not(.show)").forEach(el => el.classList.remove("hidden"));
provincesHeader.querySelector("div[data-sortby='state']").style.left = "22em";
provincesFooter.style.display = "block"; provincesFooter.style.display = "block";
body.querySelectorAll("div > input, select, span, svg").forEach(e => e.style.pointerEvents = "all"); body.querySelectorAll("div > input, select, span, svg").forEach(e => e.style.pointerEvents = "all");
if(!close) $("#provincesEditor").dialog({position: {my: "right top", at: "right-10 top+10", of: "svg", collision: "fit"}}); if(!close) $("#provincesEditor").dialog({position: {my: "right top", at: "right-10 top+10", of: "svg", collision: "fit"}});
@ -482,7 +606,7 @@ function editProvinces() {
const url = window.URL.createObjectURL(dataBlob); const url = window.URL.createObjectURL(dataBlob);
const link = document.createElement("a"); const link = document.createElement("a");
document.body.appendChild(link); document.body.appendChild(link);
link.download = "provinces_data" + Date.now() + ".csv"; link.download = getFileName("Provinces") + ".csv";
link.href = url; link.href = url;
link.click(); link.click();
window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000); window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000);

View file

@ -12,7 +12,7 @@ function editReliefIcon() {
updateReliefSizeInput(); updateReliefSizeInput();
$("#reliefEditor").dialog({ $("#reliefEditor").dialog({
title: "Edit Relief Icons", resizable: false, width: 294, title: "Edit Relief Icons", resizable: false, width: "27em",
position: {my: "left top", at: "left+10 top+10", of: "#map"}, position: {my: "left top", at: "left+10 top+10", of: "#map"},
close: closeReliefEditor close: closeReliefEditor
}); });

View file

@ -10,8 +10,8 @@ function editReligions() {
const body = document.getElementById("religionsBody"); const body = document.getElementById("religionsBody");
const animate = d3.transition().duration(1500).ease(d3.easeSinIn); const animate = d3.transition().duration(1500).ease(d3.easeSinIn);
drawReligionCenters();
refreshReligionsEditor(); refreshReligionsEditor();
drawReligionCenters();
if (modules.editReligions) return; if (modules.editReligions) return;
modules.editReligions = true; modules.editReligions = true;
@ -25,6 +25,7 @@ function editReligions() {
document.getElementById("religionsEditorRefresh").addEventListener("click", refreshReligionsEditor); document.getElementById("religionsEditorRefresh").addEventListener("click", refreshReligionsEditor);
document.getElementById("religionsLegend").addEventListener("click", toggleLegend); document.getElementById("religionsLegend").addEventListener("click", toggleLegend);
document.getElementById("religionsPercentage").addEventListener("click", togglePercentageMode); document.getElementById("religionsPercentage").addEventListener("click", togglePercentageMode);
document.getElementById("religionsHeirarchy").addEventListener("click", showHierarchy);
document.getElementById("religionsExtinct").addEventListener("click", toggleExtinct); document.getElementById("religionsExtinct").addEventListener("click", toggleExtinct);
document.getElementById("religionsManually").addEventListener("click", enterReligionsManualAssignent); document.getElementById("religionsManually").addEventListener("click", enterReligionsManualAssignent);
document.getElementById("religionsManuallyApply").addEventListener("click", applyReligionsManualAssignent); document.getElementById("religionsManuallyApply").addEventListener("click", applyReligionsManualAssignent);
@ -39,11 +40,12 @@ function editReligions() {
function religionsCollectStatistics() { function religionsCollectStatistics() {
const cells = pack.cells, religions = pack.religions; const cells = pack.cells, religions = pack.religions;
religions.forEach(r => r.area = r.rural = r.urban = 0); religions.forEach(r => r.cells = r.area = r.rural = r.urban = 0);
for (const i of cells.i) { for (const i of cells.i) {
if (cells.h[i] < 20) continue; if (cells.h[i] < 20) continue;
const r = cells.religion[i]; const r = cells.religion[i];
religions[r].cells += 1;
religions[r].area += cells.area[i]; religions[r].area += cells.area[i];
religions[r].rural += cells.pop[i]; religions[r].rural += cells.pop[i];
if (cells.burg[i]) religions[r].urban += pack.burgs[cells.burg[i]].population; if (cells.burg[i]) religions[r].urban += pack.burgs[cells.burg[i]].population;
@ -62,7 +64,7 @@ function editReligions() {
const rural = r.rural * populationRate.value; const rural = r.rural * populationRate.value;
const urban = r.urban * populationRate.value * urbanization.value; const urban = r.urban * populationRate.value * urbanization.value;
const population = rn(rural + urban); const population = rn(rural + urban);
if (r.i && !population && body.dataset.extinct !== "show") continue; // hide extinct religions if (r.i && !r.cells && body.dataset.extinct !== "show") continue; // hide extinct religions
const populationTip = `Believers: ${si(population)}; Rural areas: ${si(rural)}; Urban areas: ${si(urban)}`; const populationTip = `Believers: ${si(population)}; Rural areas: ${si(rural)}; Urban areas: ${si(urban)}`;
totalArea += area; totalArea += area;
totalPopulation += population; totalPopulation += population;
@ -70,7 +72,7 @@ function editReligions() {
if (r.i) { if (r.i) {
lines += `<div class="states religions" data-id=${r.i} data-name="${r.name}" data-color="${r.color}" data-area=${area} lines += `<div class="states religions" data-id=${r.i} data-name="${r.name}" data-color="${r.color}" data-area=${area}
data-population=${population} data-type=${r.type} data-form=${r.form} data-deity="${r.deity?r.deity:''}" data-expansionism=${r.expansionism}> data-population=${population} data-type=${r.type} data-form=${r.form} data-deity="${r.deity?r.deity:''}" data-expansionism=${r.expansionism}>
<svg data-tip="Religion fill style. Click to change" width="9" height="9" style="margin-bottom:-1px"><rect x="0" y="0" width="9" height="9" fill="${r.color}" class="zoneFill"></svg> <svg data-tip="Religion fill style. Click to change" width=".9em" height=".9em" style="margin-bottom:-1px"><rect x="0" y="0" width="100%" height="100%" fill="${r.color}" class="zoneFill"></svg>
<input data-tip="Religion name. Click and type to change" class="religionName" value="${r.name}" autocorrect="off" spellcheck="false"> <input data-tip="Religion name. Click and type to change" class="religionName" value="${r.name}" autocorrect="off" spellcheck="false">
<select data-tip="Religion type" class="religionType">${getTypeOptions(r.type)}</select> <select data-tip="Religion type" class="religionType">${getTypeOptions(r.type)}</select>
<input data-tip="Religion form" class="religionForm hide" value="${r.form}" autocorrect="off" spellcheck="false"> <input data-tip="Religion form" class="religionForm hide" value="${r.form}" autocorrect="off" spellcheck="false">
@ -136,18 +138,44 @@ function editReligions() {
} }
function religionHighlightOn(event) { function religionHighlightOn(event) {
const religion = +event.target.dataset.id;
const info = document.getElementById("religionInfo");
if (info) {
d3.select("#religionHierarchy").select("g[data-id='"+religion+"'] > path").classed("selected", 1);
const r = pack.religions[religion];
const type = r.name.includes(r.type) ? ""
: r.type === "Folk" || r.type === "Organized"
? ". " + r.type + " religion" : ". " + r.type;
const form = r.form === r.type || r.name.includes(r.form) ? "" : ". " + r.form;
const rural = r.rural * populationRate.value;
const urban = r.urban * populationRate.value * urbanization.value;
const population = rural + urban > 0 ? ". " + si(rn(rural + urban)) + " believers" : ". Extinct";
const hint = ". Drag to change the origin";
info.innerHTML = `${r.name}${type}${form}${population}${hint}`;
}
const el = body.querySelector(`div[data-id='${religion}']`);
if (el) el.classList.add("active");
if (!layerIsOn("toggleReligions")) return; if (!layerIsOn("toggleReligions")) return;
if (customization) return; if (customization) return;
const religion = +event.target.dataset.id;
relig.select("#religion"+religion).raise().transition(animate).attr("stroke-width", 2.5).attr("stroke", "#c13119"); relig.select("#religion"+religion).raise().transition(animate).attr("stroke-width", 2.5).attr("stroke", "#c13119");
debug.select("#cultureCenter"+religion).raise().transition(animate).attr("r", 8).attr("stroke", "#c13119"); debug.select("#religionsCenter"+religion).raise().transition(animate).attr("r", 8).attr("stroke-width", 2).attr("stroke", "#c13119");
} }
function religionHighlightOff(event) { function religionHighlightOff(event) {
if (!layerIsOn("toggleReligions")) return;
const religion = +event.target.dataset.id; const religion = +event.target.dataset.id;
const info = document.getElementById("religionInfo");
if (info) {
d3.select("#religionHierarchy").select("g[data-id='"+religion+"'] > path").classed("selected", 0);
info.innerHTML = "&#8205;";
}
const el = body.querySelector(`div[data-id='${religion}']`)
if (el) el.classList.remove("active");
relig.select("#religion"+religion).transition().attr("stroke-width", null).attr("stroke", null); relig.select("#religion"+religion).transition().attr("stroke-width", null).attr("stroke", null);
debug.select("#cultureCenter"+religion).transition().attr("r", 6).attr("stroke", null); debug.select("#religionsCenter"+religion).transition().attr("r", 4).attr("stroke-width", 1.2).attr("stroke", null);
} }
function religionChangeColor() { function religionChangeColor() {
@ -159,7 +187,7 @@ function editReligions() {
el.setAttribute("fill", fill); el.setAttribute("fill", fill);
pack.religions[religion].color = fill; pack.religions[religion].color = fill;
relig.select("#religion"+religion).attr("fill", fill); relig.select("#religion"+religion).attr("fill", fill);
debug.select("#cultureCenter"+religion).attr("fill", fill); debug.select("#religionsCenter"+religion).attr("fill", fill);
} }
openPicker(currentFill, callback); openPicker(currentFill, callback);
@ -202,28 +230,33 @@ function editReligions() {
if (customization) return; if (customization) return;
const religion = +this.parentNode.dataset.id; const religion = +this.parentNode.dataset.id;
relig.select("#religion"+religion).remove(); relig.select("#religion"+religion).remove();
debug.select("#cultureCenter"+religion).remove(); debug.select("#religionsCenter"+religion).remove();
pack.cells.religion.forEach((r, i) => {if(r === religion) pack.cells.religion[i] = 0;}); pack.cells.religion.forEach((r, i) => {if(r === religion) pack.cells.religion[i] = 0;});
pack.religions[religion].removed = true; pack.religions[religion].removed = true;
const origin = pack.religions[religion].origin;
pack.religions.forEach(r => {if(r.origin === religion) r.origin = origin;});
refreshReligionsEditor(); refreshReligionsEditor();
} }
function drawReligionCenters() { function drawReligionCenters() {
const tooltip = "Drag to move the religion center (it won't affect religions distribution)";
debug.select("#religionCenters").remove(); debug.select("#religionCenters").remove();
const religionCenters = debug.append("g").attr("id", "religionCenters") const religionCenters = debug.append("g").attr("id", "religionCenters")
.attr("stroke-width", 2).attr("stroke", "#444444").style("cursor", "move"); .attr("stroke-width", 1.2).attr("stroke", "#444444").style("cursor", "move");
const data = pack.religions.filter(r => r.center && !r.removed); const data = pack.religions.filter(r => r.i && r.center && r.cells && !r.removed);
religionCenters.selectAll("circle").data(data).enter().append("circle") religionCenters.selectAll("circle").data(data).enter().append("circle")
.attr("id", d => "cultureCenter"+d.i).attr("data-id", d => d.i) .attr("id", d => "religionsCenter"+d.i).attr("data-id", d => d.i)
.attr("r", 6).attr("fill", d => pack.religions[d.i].color) .attr("r", 4).attr("fill", d => d.color)
.attr("cx", d => pack.cells.p[d.center][0]).attr("cy", d => pack.cells.p[d.center][1]) .attr("cx", d => pack.cells.p[d.center][0]).attr("cy", d => pack.cells.p[d.center][1])
.on("mouseenter", d => {tip(tooltip, true); body.querySelector(`div[data-id='${d.i}']`).classList.add("selected"); religionHighlightOn(event);}) .on("mouseenter", d => {
.on("mouseleave", d => {tip('', true); body.querySelector(`div[data-id='${d.i}']`).classList.remove("selected"); religionHighlightOff(event);}) tip(d.name+ ". Drag to move the religion center", true);
.call(d3.drag().on("start", religionCenterDrag)); religionHighlightOn(event);
}).on("mouseleave", d => {
tip('', true);
religionHighlightOff(event);
}).call(d3.drag().on("start", religionCenterDrag));
} }
function religionCenterDrag() { function religionCenterDrag() {
@ -259,6 +292,87 @@ function editReligions() {
} }
} }
function showHierarchy() {
// build hierarchy tree
pack.religions[0].origin = null;
const religions = pack.religions.filter(r => !r.removed);
const root = d3.stratify().id(d => d.i).parentId(d => d.origin)(religions);
const treeWidth = root.leaves().length;
const treeHeight = root.height;
const width = treeWidth * 40, height = treeHeight * 60;
const margin = {top: 10, right: 10, bottom: -5, left: 10};
const w = width - margin.left - margin.right;
const h = height + 30 - margin.top - margin.bottom;
const treeLayout = d3.tree().size([w, h]);
// prepare svg
alertMessage.innerHTML = "<div id='religionInfo' class='chartInfo'>&#8205;</div>";
const svg = d3.select("#alertMessage").insert("svg", "#religionInfo").attr("id", "religionHierarchy")
.attr("width", width).attr("height", height).style("text-anchor", "middle");
const graph = svg.append("g").attr("transform", `translate(10, -45)`);
const links = graph.append("g").attr("fill", "none").attr("stroke", "#aaaaaa");
const nodes = graph.append("g");
renderTree();
function renderTree() {
treeLayout(root);
links.selectAll('path').data(root.links()).enter()
.append('path').attr("d", d => {return "M" + d.source.x + "," + d.source.y
+ "C" + d.source.x + "," + (d.source.y * 3 + d.target.y) / 4
+ " " + d.target.x + "," + (d.source.y * 2 + d.target.y) / 3
+ " " + d.target.x + "," + d.target.y;});
const node = nodes.selectAll('g').data(root.descendants()).enter()
.append('g').attr("data-id", d => d.data.i).attr("stroke", "#333333")
.attr("transform", d => `translate(${d.x}, ${d.y})`)
.on("mouseenter", () => religionHighlightOn(event))
.on("mouseleave", () => religionHighlightOff(event))
.call(d3.drag().on("start", d => dragToReorigin(d)));
node.append("path").attr("d", d => {
if (d.data.type === "Folk") return "M11.3,0A11.3,11.3,0,1,1,-11.3,0A11.3,11.3,0,1,1,11.3,0"; else // circle
if (d.data.type === "Heresy") return "M0,-14L14,0L0,14L-14,0Z"; else // diamond
if (d.data.type === "Cult") return "M-6.5,-11.26l13,0l6.5,11.26l-6.5,11.26l-13,0l-6.5,-11.26Z"; else // hex
if (!d.data.i) return "M5,0A5,5,0,1,1,-5,0A5,5,0,1,1,5,0"; else // small circle
return "M-11,-11h22v22h-22Z"; // square
}).attr("fill", d => d.data.i ? d.data.color : "#ffffff")
.attr("stroke-dasharray", d => d.data.cells ? "null" : "1");
node.append("text").attr("dy", ".35em").text(d => d.data.i ? d.data.code : '');
}
$("#alert").dialog({
title: "Religions tree", width: fitContent(), resizable: false,
position: {my: "left center", at: "left+10 center", of: "svg"}, buttons: {},
close: () => {alertMessage.innerHTML = "";}
});
function dragToReorigin(d) {
console.log("dragToReorigin");
const originLine = graph.append("path")
.attr("class", "dragLine").attr("d", `M${d.x},${d.y}L${d.x},${d.y}`);
d3.event.on("drag", () => {
originLine.attr("d", `M${d.x},${d.y}L${d3.event.x},${d3.event.y}`)
});
d3.event.on("end", () => {
originLine.remove();
const selected = graph.select("path.selected");
if (!selected.size()) return;
const religion = d.data.i;
const oldOrigin = d.data.origin;
let newOrigin = selected.datum().data.i;
if (newOrigin == oldOrigin) return; // already a child of the selected node
if (newOrigin == religion) newOrigin = 0; // move to top
if (newOrigin && d.descendants().some(node => node.id == newOrigin)) return; // cannot be a child of its own child
pack.religions[religion].origin = d.data.origin = newOrigin; // change data
showHierarchy() // update hierarchy
});
}
}
function toggleExtinct() { function toggleExtinct() {
body.dataset.extinct = body.dataset.extinct !== "show" ? "show" : "hide"; body.dataset.extinct = body.dataset.extinct !== "show" ? "show" : "hide";
religionsEditorAddLines(); religionsEditorAddLines();
@ -354,6 +468,7 @@ function editReligions() {
if (changed.size()) { if (changed.size()) {
drawReligions(); drawReligions();
refreshReligionsEditor(); refreshReligionsEditor();
drawReligionCenters();
} }
exitReligionsManualAssignment(); exitReligionsManualAssignment();
} }
@ -402,10 +517,11 @@ function editReligions() {
if (occupied) {tip("This cell is already a religion center. Please select a different cell", false, "error"); return;} if (occupied) {tip("This cell is already a religion center. Please select a different cell", false, "error"); return;}
if (d3.event.shiftKey === false) exitAddReligionMode(); if (d3.event.shiftKey === false) exitAddReligionMode();
Religions.add(center); Religions.add(center);
drawReligions();
refreshReligionsEditor();
drawReligionCenters(); drawReligionCenters();
religionsEditorAddLines();
} }
function downloadReligionsData() { function downloadReligionsData() {
@ -427,7 +543,7 @@ function editReligions() {
const url = window.URL.createObjectURL(dataBlob); const url = window.URL.createObjectURL(dataBlob);
const link = document.createElement("a"); const link = document.createElement("a");
document.body.appendChild(link); document.body.appendChild(link);
link.download = "religions_data" + Date.now() + ".csv"; link.download = getFileName("Religions") + ".csv";
link.href = url; link.href = url;
link.click(); link.click();
window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000); window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000);

View file

@ -91,24 +91,24 @@ function editStates() {
<span class="icon-star-empty placeholder hide"></span> <span class="icon-star-empty placeholder hide"></span>
<input class="stateCapital placeholder hide"> <input class="stateCapital placeholder hide">
<select class="stateCulture placeholder hide">${getCultureOptions(0)}</select> <select class="stateCulture placeholder hide">${getCultureOptions(0)}</select>
<select class="cultureType ${hidden} placeholder show hide">${getTypeOptions(0)}</select>
<span class="icon-resize-full ${hidden} placeholder show hide"></span>
<input class="statePower ${hidden} placeholder show hide" type="number" value=0>
<span data-tip="Cells count" class="icon-check-empty ${hidden} show hide"></span>
<div data-tip="Cells count" class="stateCells ${hidden} show hide">${s.cells}</div>
<span data-tip="Burgs count" style="padding-right: 1px" class="icon-dot-circled hide"></span> <span data-tip="Burgs count" style="padding-right: 1px" class="icon-dot-circled hide"></span>
<div data-tip="Burgs count" class="stateBurgs hide">${s.burgs}</div> <div data-tip="Burgs count" class="stateBurgs hide">${s.burgs}</div>
<span data-tip="State area" style="padding-right: 4px" class="icon-map-o hide"></span> <span data-tip="State area" style="padding-right: 4px" class="icon-map-o hide"></span>
<div data-tip="State area" class="biomeArea hide">${si(area) + unit}</div> <div data-tip="State area" class="biomeArea hide">${si(area) + unit}</div>
<span data-tip="${populationTip}" class="icon-male hide"></span> <span data-tip="${populationTip}" class="icon-male hide"></span>
<div data-tip="${populationTip}" class="culturePopulation hide">${si(population)}</div> <div data-tip="${populationTip}" class="culturePopulation hide">${si(population)}</div>
<select class="cultureType ${hidden} placeholder show hide">${getTypeOptions(0)}</select>
<span class="icon-resize-full ${hidden} placeholder show hide"></span>
<input class="statePower ${hidden} placeholder show hide" type="number" value=0>
<span data-tip="Cells count" class="icon-check-empty ${hidden} show hide"></span>
<div data-tip="Cells count" class="stateCells ${hidden} show hide">${s.cells}</div>
</div>`; </div>`;
continue; continue;
} }
const capital = pack.burgs[s.capital].name; const capital = pack.burgs[s.capital].name;
lines += `<div class="states" data-id=${s.i} data-name="${s.name}" data-form="${s.formName}" data-capital="${capital}" data-color="${s.color}" data-cells=${s.cells} lines += `<div class="states" data-id=${s.i} data-name="${s.name}" data-form="${s.formName}" data-capital="${capital}" data-color="${s.color}" data-cells=${s.cells}
data-area=${area} data-population=${population} data-burgs=${s.burgs} data-culture=${pack.cultures[s.culture].name} data-type=${s.type} data-expansionism=${s.expansionism}> data-area=${area} data-population=${population} data-burgs=${s.burgs} data-culture=${pack.cultures[s.culture].name} data-type=${s.type} data-expansionism=${s.expansionism}>
<svg data-tip="State fill style. Click to change" width="9" height="9" style="margin-bottom:-1px"><rect x="0" y="0" width="9" height="9" fill="${s.color}" class="zoneFill"></svg> <svg data-tip="State fill style. Click to change" width=".9em" height=".9em" style="margin-bottom:-1px"><rect x="0" y="0" width="100%" height="100%" fill="${s.color}" class="zoneFill"></svg>
<input data-tip="State name. Click and type to change" class="stateName" value="${s.name}" autocorrect="off" spellcheck="false"> <input data-tip="State name. Click and type to change" class="stateName" value="${s.name}" autocorrect="off" spellcheck="false">
<span data-tip="Click to re-generate name" class="icon-arrows-cw stateName hoverButton placeholder"></span> <span data-tip="Click to re-generate name" class="icon-arrows-cw stateName hoverButton placeholder"></span>
<span data-tip="Click to open state COA in the Iron Arachne Heraldry Generator" class="icon-fleur pointer hide"></span> <span data-tip="Click to open state COA in the Iron Arachne Heraldry Generator" class="icon-fleur pointer hide"></span>
@ -117,17 +117,17 @@ function editStates() {
<span data-tip="State capital. Click to zoom into view" class="icon-star-empty pointer hide"></span> <span data-tip="State capital. Click to zoom into view" class="icon-star-empty pointer hide"></span>
<input data-tip="Capital name. Click and type to rename" class="stateCapital hide" value="${capital}" autocorrect="off" spellcheck="false"/> <input data-tip="Capital name. Click and type to rename" class="stateCapital hide" value="${capital}" autocorrect="off" spellcheck="false"/>
<select data-tip="Dominant culture. Click to change" class="stateCulture hide">${getCultureOptions(s.culture)}</select> <select data-tip="Dominant culture. Click to change" class="stateCulture hide">${getCultureOptions(s.culture)}</select>
<select data-tip="State type. Click to change" class="cultureType ${hidden} show hide">${getTypeOptions(s.type)}</select>
<span data-tip="State expansionism" class="icon-resize-full ${hidden} show hide"></span>
<input data-tip="Expansionism (defines competitive size). Change to re-calculate states based on new value" class="statePower ${hidden} show hide" type="number" min=0 max=99 step=.1 value=${s.expansionism}>
<span data-tip="Cells count" class="icon-check-empty ${hidden} show hide"></span>
<div data-tip="Cells count" class="stateCells ${hidden} show hide">${s.cells}</div>
<span data-tip="Burgs count" style="padding-right: 1px" class="icon-dot-circled hide"></span> <span data-tip="Burgs count" style="padding-right: 1px" class="icon-dot-circled hide"></span>
<div data-tip="Burgs count" class="stateBurgs hide">${s.burgs}</div> <div data-tip="Burgs count" class="stateBurgs hide">${s.burgs}</div>
<span data-tip="State area" style="padding-right: 4px" class="icon-map-o hide"></span> <span data-tip="State area" style="padding-right: 4px" class="icon-map-o hide"></span>
<div data-tip="State area" class="biomeArea hide">${si(area) + unit}</div> <div data-tip="State area" class="biomeArea hide">${si(area) + unit}</div>
<span data-tip="${populationTip}" class="icon-male hide"></span> <span data-tip="${populationTip}" class="icon-male hide"></span>
<div data-tip="${populationTip}" class="culturePopulation hide">${si(population)}</div> <div data-tip="${populationTip}" class="culturePopulation hide">${si(population)}</div>
<select data-tip="State type. Defines growth model. Click to change" class="cultureType ${hidden} show hide">${getTypeOptions(s.type)}</select>
<span data-tip="State expansionism" class="icon-resize-full ${hidden} show hide"></span>
<input data-tip="Expansionism (defines competitive size). Change to re-calculate states based on new value" class="statePower ${hidden} show hide" type="number" min=0 max=99 step=.1 value=${s.expansionism}>
<span data-tip="Cells count" class="icon-check-empty ${hidden} show hide"></span>
<div data-tip="Cells count" class="stateCells ${hidden} show hide">${s.cells}</div>
<span data-tip="Toggle state focus" class="icon-pin ${focused?'':' inactive'} hide"></span> <span data-tip="Toggle state focus" class="icon-pin ${focused?'':' inactive'} hide"></span>
<span data-tip="Remove the state" class="icon-trash-empty hide"></span> <span data-tip="Remove the state" class="icon-trash-empty hide"></span>
</div>`; </div>`;
@ -690,7 +690,7 @@ function editStates() {
const url = window.URL.createObjectURL(dataBlob); const url = window.URL.createObjectURL(dataBlob);
const link = document.createElement("a"); const link = document.createElement("a");
document.body.appendChild(link); document.body.appendChild(link);
link.download = "states_data" + Date.now() + ".csv"; link.download = getFileName("States") + ".csv";
link.href = url; link.href = url;
link.click(); link.click();
window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000); window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000);

View file

@ -30,14 +30,15 @@ toolsContent.addEventListener("click", function(event) {
Proceed: function() {processFeatureRegeneration(button); $(this).dialog("close");}, Proceed: function() {processFeatureRegeneration(button); $(this).dialog("close");},
Cancel: function() {$(this).dialog("close");} Cancel: function() {$(this).dialog("close");}
}, },
create: function() { open: function() {
const pane = $(this).dialog("widget").find(".ui-dialog-buttonpane"); const pane = $(this).dialog("widget").find(".ui-dialog-buttonpane");
$('<input id="dontAsk" class="checkbox" type="checkbox"><label for="dontAsk" class="checkbox-label dontAsk"><i>do not ask again</i></label>').prependTo(pane); $('<span><input id="dontAsk" class="checkbox" type="checkbox"><label for="dontAsk" class="checkbox-label dontAsk"><i>do not ask again</i></label><span>').prependTo(pane);
}, },
close: function() { close: function() {
const box = $(this).dialog("widget").find(".checkbox")[0]; const box = $(this).dialog("widget").find(".checkbox")[0];
if (!box) return; if (!box) return;
if (box.checked) sessionStorage.setItem("regenerateFeatureDontAsk", true); if (box.checked) sessionStorage.setItem("regenerateFeatureDontAsk", true);
$(this).dialog("destroy");
} }
}); });
} }
@ -59,7 +60,8 @@ function processFeatureRegeneration(button) {
if (button === "regenerateBurgs") regenerateBurgs(); else if (button === "regenerateBurgs") regenerateBurgs(); else
if (button === "regenerateStates") regenerateStates(); else if (button === "regenerateStates") regenerateStates(); else
if (button === "regenerateProvinces") regenerateProvinces(); else if (button === "regenerateProvinces") regenerateProvinces(); else
if (button === "regenerateReligions") regenerateReligions(); if (button === "regenerateReligions") regenerateReligions(); else
if (button === "regenerateMarkers") regenerateMarkers();
} }
function regenerateRivers() { function regenerateRivers() {
@ -199,6 +201,11 @@ function regenerateReligions() {
if (!layerIsOn("toggleReligions")) toggleReligions(); else drawReligions(); if (!layerIsOn("toggleReligions")) toggleReligions(); else drawReligions();
} }
function regenerateMarkers() {
markers.selectAll("use").remove();
addMarkers(gauss(1, .5, .3, 5, 2));
}
function unpressClickToAddButton() { function unpressClickToAddButton() {
addFeature.querySelectorAll("button.pressed").forEach(b => b.classList.remove("pressed")); addFeature.querySelectorAll("button.pressed").forEach(b => b.classList.remove("pressed"));
restoreDefaultEvents(); restoreDefaultEvents();
@ -340,7 +347,7 @@ function addRiverOnClick() {
alertMessage.innerHTML = `<p>Heightmap is depressed and the system had to change the heightmap to allow water flux.</p> alertMessage.innerHTML = `<p>Heightmap is depressed and the system had to change the heightmap to allow water flux.</p>
Would you like to <i>keep</i> the changes or <i>restore</i> the initial heightmap?`; Would you like to <i>keep</i> the changes or <i>restore</i> the initial heightmap?`;
$("#alert").dialog({resizable: false, title: "Heightmap is changed", width: 300, modal: true, $("#alert").dialog({resizable: false, title: "Heightmap is changed", width: "30em", modal: true,
buttons: { buttons: {
Keep: function() {$(this).dialog("close");}, Keep: function() {$(this).dialog("close");},
Restore: function() { Restore: function() {

View file

@ -15,8 +15,6 @@ function editUnits() {
document.getElementById("distanceUnitInput").addEventListener("change", changeDistanceUnit); document.getElementById("distanceUnitInput").addEventListener("change", changeDistanceUnit);
document.getElementById("distanceScaleOutput").addEventListener("input", changeDistanceScale); document.getElementById("distanceScaleOutput").addEventListener("input", changeDistanceScale);
document.getElementById("distanceScaleInput").addEventListener("change", changeDistanceScale); document.getElementById("distanceScaleInput").addEventListener("change", changeDistanceScale);
document.getElementById("distanceScaleInput").addEventListener("mouseenter", hideDistanceUnitOutput);
document.getElementById("distanceScaleInput").addEventListener("mouseleave", showDistanceUnitOutput);
document.getElementById("areaUnit").addEventListener("change", () => lock("areaUnit")); document.getElementById("areaUnit").addEventListener("change", () => lock("areaUnit"));
document.getElementById("heightUnit").addEventListener("change", changeHeightUnit); document.getElementById("heightUnit").addEventListener("change", changeHeightUnit);
document.getElementById("heightExponentInput").addEventListener("input", changeHeightExponent); document.getElementById("heightExponentInput").addEventListener("input", changeHeightExponent);
@ -45,10 +43,8 @@ function editUnits() {
if (this.value === "custom_name") { if (this.value === "custom_name") {
const custom = prompt("Provide a custom name for distance unit"); const custom = prompt("Provide a custom name for distance unit");
if (custom) this.options.add(new Option(custom, custom, false, true)); if (custom) this.options.add(new Option(custom, custom, false, true));
else {this.value = document.getElementById("distanceUnitOutput").innerHTML; return;};
} }
document.getElementById("distanceUnitOutput").innerHTML = this.value;
lock("distanceUnit"); lock("distanceUnit");
drawScaleBar(); drawScaleBar();
calculateFriendlyGridSize(); calculateFriendlyGridSize();
@ -71,9 +67,6 @@ function editUnits() {
calculateFriendlyGridSize(); calculateFriendlyGridSize();
} }
function hideDistanceUnitOutput() {document.getElementById("distanceUnitOutput").style.opacity = .2;}
function showDistanceUnitOutput() {document.getElementById("distanceUnitOutput").style.opacity = 1;}
function changeHeightUnit() { function changeHeightUnit() {
if (this.value === "custom_name") { if (this.value === "custom_name") {
const custom = prompt("Provide a custom name for height unit"); const custom = prompt("Provide a custom name for height unit");
@ -163,7 +156,7 @@ function editUnits() {
// units // units
const US = navigator.language === "en-US"; const US = navigator.language === "en-US";
const UK = navigator.language === "en-GB"; const UK = navigator.language === "en-GB";
distanceUnitInput.value = distanceUnitOutput.value = US || UK ? "mi" : "km"; distanceUnitInput.value = US || UK ? "mi" : "km";
heightUnit.value = US || UK ? "ft" : "m"; heightUnit.value = US || UK ? "ft" : "m";
temperatureScale.value = US ? "°F" : "°C"; temperatureScale.value = US ? "°F" : "°C";
areaUnit.value = "square"; areaUnit.value = "square";

View file

@ -1,6 +1,6 @@
function editWorld() { function editWorld() {
if (customization) return; if (customization) return;
$("#worldConfigurator").dialog({title: "Configure World", resizable: false, width: 460, $("#worldConfigurator").dialog({title: "Configure World", resizable: false, width: "42em",
buttons: { buttons: {
"Whole World": () => applyPreset(100, 50), "Whole World": () => applyPreset(100, 50),
"Northern": () => applyPreset(33, 25), "Northern": () => applyPreset(33, 25),

View file

@ -55,7 +55,7 @@ function editZones() {
const focused = defs.select("#fog #focus"+this.id).size(); const focused = defs.select("#fog #focus"+this.id).size();
lines += `<div class="states" data-id="${this.id}" data-fill="${fill}" data-description="${description}" data-cells=${c.length} data-area=${area} data-population=${population}> lines += `<div class="states" data-id="${this.id}" data-fill="${fill}" data-description="${description}" data-cells=${c.length} data-area=${area} data-population=${population}>
<svg data-tip="Zone fill style. Click to change" width="9" height="9" style="margin-bottom:-1px"><rect x="0" y="0" width="9" height="9" fill="${fill}" class="zoneFill"></svg> <svg data-tip="Zone fill style. Click to change" width=".9em" height=".9em" style="margin-bottom:-1px"><rect x="0" y="0" width="100%" height="100%" fill="${fill}" class="zoneFill"></svg>
<input data-tip="Zone description. Click and type to change" class="religionName" value="${description}" autocorrect="off" spellcheck="false"> <input data-tip="Zone description. Click and type to change" class="religionName" value="${description}" autocorrect="off" spellcheck="false">
<span data-tip="Cells count" class="icon-check-empty hide"></span> <span data-tip="Cells count" class="icon-check-empty hide"></span>
<div data-tip="Cells count" class="stateCells hide">${c.length}</div> <div data-tip="Cells count" class="stateCells hide">${c.length}</div>
@ -310,7 +310,7 @@ function editZones() {
const unit = areaUnit.value === "square" ? " " + distanceUnitInput.value + "²" : " " + areaUnit.value; const unit = areaUnit.value === "square" ? " " + distanceUnitInput.value + "²" : " " + areaUnit.value;
const line = `<div class="states" data-id="${id}" data-fill="${fill}" data-description="${description}" data-cells=0 data-area=0 data-population=0> const line = `<div class="states" data-id="${id}" data-fill="${fill}" data-description="${description}" data-cells=0 data-area=0 data-population=0>
<svg data-tip="Zone fill style. Click to change" width="9" height="9" style="margin-bottom:-1px"><rect x="0" y="0" width="9" height="9" fill="${fill}" class="zoneFill"></svg> <svg data-tip="Zone fill style. Click to change" width=".9em" height=".9em" style="margin-bottom:-1px"><rect x="0" y="0" width="100%" height="100%" fill="${fill}" class="zoneFill"></svg>
<input data-tip="Zone description. Click and type to change" class="religionName" value="${description}" autocorrect="off" spellcheck="false"> <input data-tip="Zone description. Click and type to change" class="religionName" value="${description}" autocorrect="off" spellcheck="false">
<span data-tip="Cells count" class="icon-check-empty hide"></span> <span data-tip="Cells count" class="icon-check-empty hide"></span>
<div data-tip="Cells count" class="stateCells hide">0</div> <div data-tip="Cells count" class="stateCells hide">0</div>
@ -345,7 +345,7 @@ function editZones() {
const url = window.URL.createObjectURL(dataBlob); const url = window.URL.createObjectURL(dataBlob);
const link = document.createElement("a"); const link = document.createElement("a");
document.body.appendChild(link); document.body.appendChild(link);
link.download = "zones_data" + Date.now() + ".csv"; link.download = getFileName("Zones") + ".csv";
link.href = url; link.href = url;
link.click(); link.click();
window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000); window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000);

View file

@ -201,7 +201,7 @@ function getRandomColor() {
// mix a color with a random color // mix a color with a random color
function getMixedColor(color, mix = .2, bright = .3) { function getMixedColor(color, mix = .2, bright = .3) {
const c = color[0] === "#" ? color : getRandomColor(); // if provided color is not hex (e.g. harching), generate random one const c = color && color[0] === "#" ? color : getRandomColor(); // if provided color is not hex (e.g. harching), generate random one
return d3.color(d3.interpolate(c, getRandomColor())(mix)).brighter(bright).hex(); return d3.color(d3.interpolate(c, getRandomColor())(mix)).brighter(bright).hex();
} }
@ -478,7 +478,7 @@ function analizeNamesbase() {
if (string[i] === string[i-1]) doubleArray[string[i]]++; if (string[i] === string[i-1]) doubleArray[string[i]]++;
} }
for (const l in doubleArray) {if(doubleArray[l] > size/35) double += l;} for (const l in doubleArray) {if(doubleArray[l] > size/35) double += l;}
const multi = rn(d3.mean(d.map(n => (n.match(/ /g)||[]).length)),2); const multi = rn(d3.mean(d.map(n => (n.match(/ /g)||[]).length-1)),2);
result.push({name:b.name, size, min, max, mean, median, common, double, multi}); result.push({name:b.name, size, min, max, mean, median, common, double, multi});
}); });
console.table(result); console.table(result);