Merge branch 'master' of https://github.com/Azgaar/Fantasy-Map-Generator into urquhart-routes

This commit is contained in:
Azgaar 2024-06-19 19:00:07 +02:00
commit b30358859c
8 changed files with 210 additions and 137 deletions

View file

@ -4952,34 +4952,44 @@
<button id="zonesManually" data-tip="Re-assign zones" class="icon-brush"></button> <button id="zonesManually" data-tip="Re-assign zones" class="icon-brush"></button>
<div id="zonesManuallyButtons" style="display: none"> <div id="zonesManuallyButtons" style="display: none">
<label data-tip="Change brush size" data-shortcut="+ (increase), (decrease)" class="italic" <div>
>Brush: <label data-tip="Change brush size" data-shortcut="+ (increase), (decrease)" class="italic"
<input >Brush:
id="zonesBrush" <input
oninput="tip('Brush size: '+this.value); zonesBrushNumber.value = this.value" id="zonesBrush"
type="range" oninput="tip('Brush size: '+this.value); zonesBrushNumber.value = this.value"
min="5" type="range"
max="50" min="5"
value="7" max="50"
style="width: 9em" value="7"
/> style="width: 9em"
<input />
id="zonesBrushNumber" <input
oninput="tip('Brush size: '+this.value); zonesBrush.value = this.value" id="zonesBrushNumber"
type="number" oninput="tip('Brush size: '+this.value); zonesBrush.value = this.value"
min="5" type="number"
max="50" min="5"
value="7" max="50"
/> </label value="7"
><br /> />
<button id="zonesManuallyApply" data-tip="Apply assignment" class="icon-check"></button> </label>
<button id="zonesManuallyCancel" data-tip="Cancel assignment" class="icon-cancel"></button> </div>
<button
id="zonesRemove" <div>
data-tip="Click to toggle the removal mode on brush dragging" <input id="zonesBrushLandOnly" class="checkbox" type="checkbox" checked />
data-shortcut="Ctrl" <label for="zonesBrushLandOnly" class="checkbox-label"><i>Change land only</i></label>
class="icon-eraser" </div>
></button>
<div style="margin-top: 0.3em">
<button id="zonesManuallyApply" data-tip="Apply assignment" class="icon-check"></button>
<button id="zonesManuallyCancel" data-tip="Cancel assignment" class="icon-cancel"></button>
<button
id="zonesRemove"
data-tip="Click to toggle the removal mode on brush dragging"
data-shortcut="Ctrl"
class="icon-eraser"
></button>
</div>
</div> </div>
<button id="zonesAdd" data-tip="Add new zone layer" class="icon-plus"></button> <button id="zonesAdd" data-tip="Add new zone layer" class="icon-plus"></button>
@ -8125,7 +8135,7 @@
<script src="modules/burgs-and-states.js?v=1.97.07"></script> <script src="modules/burgs-and-states.js?v=1.97.07"></script>
<script src="modules/routes-generator.js"></script> <script src="modules/routes-generator.js"></script>
<script src="modules/religions-generator.js?v=1.93.08"></script> <script src="modules/religions-generator.js?v=1.93.08"></script>
<script src="modules/military-generator.js?v=1.96.01"></script> <script src="modules/military-generator.js?v=1.97.14"></script>
<script src="modules/markers-generator.js?v=1.93.04"></script> <script src="modules/markers-generator.js?v=1.93.04"></script>
<script src="modules/coa-generator.js?v=1.91.05"></script> <script src="modules/coa-generator.js?v=1.91.05"></script>
<script src="modules/submap.js?v=1.96.00"></script> <script src="modules/submap.js?v=1.96.00"></script>
@ -8143,8 +8153,8 @@
<script defer src="modules/relief-icons.js"></script> <script defer src="modules/relief-icons.js"></script>
<script defer src="modules/ui/style.js?v=1.96.00"></script> <script defer src="modules/ui/style.js?v=1.96.00"></script>
<script defer src="modules/ui/editors.js?v=1.97.00"></script> <script defer src="modules/ui/editors.js?v=1.97.12"></script>
<script defer src="modules/ui/tools.js?v=1.96.03"></script> <script defer src="modules/ui/tools.js?v=1.97.12"></script>
<script defer src="modules/ui/world-configurator.js?v=1.98.00"></script> <script defer src="modules/ui/world-configurator.js?v=1.98.00"></script>
<script defer src="modules/ui/heightmap-editor.js?v=1.96.00"></script> <script defer src="modules/ui/heightmap-editor.js?v=1.96.00"></script>
<script defer src="modules/ui/provinces-editor.js?v=1.96.00"></script> <script defer src="modules/ui/provinces-editor.js?v=1.96.00"></script>
@ -8166,14 +8176,14 @@
<script defer src="modules/ui/units-editor.js?v=1.96.00"></script> <script defer src="modules/ui/units-editor.js?v=1.96.00"></script>
<script defer src="modules/ui/notes-editor.js?v=1.97.09"></script> <script defer src="modules/ui/notes-editor.js?v=1.97.09"></script>
<script defer src="modules/ui/diplomacy-editor.js?v=1.88.04"></script> <script defer src="modules/ui/diplomacy-editor.js?v=1.88.04"></script>
<script defer src="modules/ui/zones-editor.js"></script> <script defer src="modules/ui/zones-editor.js?v=1.97.13"></script>
<script defer src="modules/ui/burgs-overview.js?v=1.97.00"></script> <script defer src="modules/ui/burgs-overview.js?v=1.97.00"></script>
<script defer src="modules/ui/routes-overview.js"></script> <script defer src="modules/ui/routes-overview.js"></script>
<script defer src="modules/ui/rivers-overview.js"></script> <script defer src="modules/ui/rivers-overview.js"></script>
<script defer src="modules/ui/military-overview.js?v=1.96.07"></script> <script defer src="modules/ui/military-overview.js?v=1.96.07"></script>
<script defer src="modules/ui/regiments-overview.js?v=1.89.20"></script> <script defer src="modules/ui/regiments-overview.js?v=1.89.20"></script>
<script defer src="modules/ui/markers-overview.js?v=1.89.38"></script> <script defer src="modules/ui/markers-overview.js?v=1.89.38"></script>
<script defer src="modules/ui/regiment-editor.js"></script> <script defer src="modules/ui/regiment-editor.js?v=1.97.14"></script>
<script defer src="modules/ui/battle-screen.js"></script> <script defer src="modules/ui/battle-screen.js"></script>
<script defer src="modules/ui/emblems-editor.js?v=1.91.00"></script> <script defer src="modules/ui/emblems-editor.js?v=1.91.00"></script>
<script defer src="modules/ui/markers-editor.js"></script> <script defer src="modules/ui/markers-editor.js"></script>

View file

@ -358,7 +358,9 @@ window.Military = (function () {
.attr("id", d => "regiment" + s + "-" + d.i) .attr("id", d => "regiment" + s + "-" + d.i)
.attr("data-name", d => d.name) .attr("data-name", d => d.name)
.attr("data-state", s) .attr("data-state", s)
.attr("data-id", d => d.i); .attr("data-id", d => d.i)
.attr("transform", d => (d.angle ? `rotate(${d.angle})` : null))
.attr("transform-origin", d => `${d.x}px ${d.y}px`);
g.append("rect") g.append("rect")
.attr("x", d => x(d)) .attr("x", d => x(d))
.attr("y", d => y(d)) .attr("y", d => y(d))
@ -404,7 +406,9 @@ window.Military = (function () {
.attr("id", "regiment" + stateId + "-" + reg.i) .attr("id", "regiment" + stateId + "-" + reg.i)
.attr("data-name", reg.name) .attr("data-name", reg.name)
.attr("data-state", stateId) .attr("data-state", stateId)
.attr("data-id", reg.i); .attr("data-id", reg.i)
.attr("transform", `rotate(${reg.angle || 0})`)
.attr("transform-origin", `${reg.x}px ${reg.y}px`);
g.append("rect").attr("x", x1).attr("y", y1).attr("width", w).attr("height", h); g.append("rect").attr("x", x1).attr("y", y1).attr("width", w).attr("height", h);
g.append("text").attr("x", reg.x).attr("y", reg.y).text(getTotal(reg)); g.append("text").attr("x", reg.x).attr("y", reg.y).text(getTotal(reg));
g.append("rect") g.append("rect")

View file

@ -290,7 +290,7 @@ window.Names = (function () {
{name: "Iranian", i: 24, min: 5, max: 11, d: "", m: .1, b: "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,Kahrizak,Kahriz Sang,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"}, {name: "Iranian", i: 24, min: 5, max: 11, d: "", m: .1, b: "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,Kahrizak,Kahriz Sang,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"},
{name: "Hawaiian", i: 25, min: 5, max: 10, d: "auo", m: 1, b: "Aapueo,Ahoa,Ahuakaio,Ahupau,Alaakua,Alae,Alaeloa,Alamihi,Aleamai,Alena,Alio,Aupokopoko,Halakaa,Haleu,Haliimaile,Hamoa,Hanakaoo,Hanaulu,Hanawana,Hanehoi,Haou,Hikiaupea,Hokuula,Honohina,Honokahua,Honokeana,Honokohau,Honolulu,Honomaele,Hononana,Honopou,Hoolawa,Huelo,Kaalaea,Kaapahu,Kaeo,Kahalehili,Kahana,Kahuai,Kailua,Kainehe,Kakalahale,Kakanoni,Kalenanui,Kaleoaihe,Kalialinui,Kalihi,Kalimaohe,Kaloi,Kamani,Kamehame,Kanahena,Kaniaula,Kaonoulu,Kapaloa,Kapohue,Kapuaikini,Kapunakea,Kauau,Kaulalo,Kaulanamoa,Kauluohana,Kaumakani,Kaumanu,Kaunauhane,Kaupakulua,Kawaloa,Keaa,Keaaula,Keahua,Keahuapono,Kealahou,Keanae,Keauhou,Kelawea,Keokea,Keopuka,Kikoo,Kipapa,Koakupuna,Koali,Kolokolo,Kopili,Kou,Kualapa,Kuhiwa,Kuholilea,Kuhua,Kuia,Kuikui,Kukoae,Kukohia,Kukuiaeo,Kukuipuka,Kukuiula,Kulahuhu,Lapakea,Lapueo,Launiupoko,Lole,Maalo,Mahinahina,Mailepai,Makaakini,Makaalae,Makaehu,Makaiwa,Makaliua,Makapipi,Makapuu,Maluaka,Manawainui,Mehamenui,Moalii,Moanui,Mohopili,Mokae,Mokuia,Mokupapa,Mooiki,Mooloa,Moomuku,Muolea,Nakaaha,Nakalepo,Nakaohu,Nakapehu,Nakula,Napili,Niniau,Nuu,Oloewa,Olowalu,Omaopio,Onau,Onouli,Opaeula,Opana,Opikoula,Paakea,Paeahu,Paehala,Paeohi,Pahoa,Paia,Pakakia,Palauea,Palemo,Paniau,Papaaea,Papaanui,Papaauhau,Papaka,Papauluana,Pauku,Paunau,Pauwalu,Pauwela,Pohakanele,Polaiki,Polanui,Polapola,Poopoo,Poponui,Poupouwela,Puahoowali,Puakea,Puako,Pualaea,Puehuehu,Pueokauiki,Pukaauhuhu,Pukuilua,Pulehu,Puolua,Puou,Puuhaehae,Puuiki,Puuki,Puulani,Puunau,Puuomaile,Uaoa,Uhao,Ukumehame,Ulaino,Ulumalu,Wahikuli,Waianae,Waianu,Waiawa,Waiehu,Waieli,Waikapu,Wailamoa,Wailaulau,Wainee,Waiohole,Waiohonu,Waiohuli,Waiokama,Waiokila,Waiopai,Waiopua,Waipao,Waipionui,Waipouli"}, {name: "Hawaiian", i: 25, min: 5, max: 10, d: "auo", m: 1, b: "Aapueo,Ahoa,Ahuakaio,Ahupau,Alaakua,Alae,Alaeloa,Alamihi,Aleamai,Alena,Alio,Aupokopoko,Halakaa,Haleu,Haliimaile,Hamoa,Hanakaoo,Hanaulu,Hanawana,Hanehoi,Haou,Hikiaupea,Hokuula,Honohina,Honokahua,Honokeana,Honokohau,Honolulu,Honomaele,Hononana,Honopou,Hoolawa,Huelo,Kaalaea,Kaapahu,Kaeo,Kahalehili,Kahana,Kahuai,Kailua,Kainehe,Kakalahale,Kakanoni,Kalenanui,Kaleoaihe,Kalialinui,Kalihi,Kalimaohe,Kaloi,Kamani,Kamehame,Kanahena,Kaniaula,Kaonoulu,Kapaloa,Kapohue,Kapuaikini,Kapunakea,Kauau,Kaulalo,Kaulanamoa,Kauluohana,Kaumakani,Kaumanu,Kaunauhane,Kaupakulua,Kawaloa,Keaa,Keaaula,Keahua,Keahuapono,Kealahou,Keanae,Keauhou,Kelawea,Keokea,Keopuka,Kikoo,Kipapa,Koakupuna,Koali,Kolokolo,Kopili,Kou,Kualapa,Kuhiwa,Kuholilea,Kuhua,Kuia,Kuikui,Kukoae,Kukohia,Kukuiaeo,Kukuipuka,Kukuiula,Kulahuhu,Lapakea,Lapueo,Launiupoko,Lole,Maalo,Mahinahina,Mailepai,Makaakini,Makaalae,Makaehu,Makaiwa,Makaliua,Makapipi,Makapuu,Maluaka,Manawainui,Mehamenui,Moalii,Moanui,Mohopili,Mokae,Mokuia,Mokupapa,Mooiki,Mooloa,Moomuku,Muolea,Nakaaha,Nakalepo,Nakaohu,Nakapehu,Nakula,Napili,Niniau,Nuu,Oloewa,Olowalu,Omaopio,Onau,Onouli,Opaeula,Opana,Opikoula,Paakea,Paeahu,Paehala,Paeohi,Pahoa,Paia,Pakakia,Palauea,Palemo,Paniau,Papaaea,Papaanui,Papaauhau,Papaka,Papauluana,Pauku,Paunau,Pauwalu,Pauwela,Pohakanele,Polaiki,Polanui,Polapola,Poopoo,Poponui,Poupouwela,Puahoowali,Puakea,Puako,Pualaea,Puehuehu,Pueokauiki,Pukaauhuhu,Pukuilua,Pulehu,Puolua,Puou,Puuhaehae,Puuiki,Puuki,Puulani,Puunau,Puuomaile,Uaoa,Uhao,Ukumehame,Ulaino,Ulumalu,Wahikuli,Waianae,Waianu,Waiawa,Waiehu,Waieli,Waikapu,Wailamoa,Wailaulau,Wainee,Waiohole,Waiohonu,Waiohuli,Waiokama,Waiokila,Waiopai,Waiopua,Waipao,Waipionui,Waipouli"},
{name: "Karnataka", i: 26, min: 5, max: 11, d: "tnl", m: 0, b: "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"}, {name: "Karnataka", i: 26, min: 5, max: 11, d: "tnl", m: 0, b: "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"},
{name: "Quechua", i: 27, min: 6, max: 12, d: "l", m: 0, b: "Alpahuaycco,Anchihuay,Anqea,Apurimac,Arequipa,Atahuallpa,Atawalpa,Atico,Ayacucho,Ayahuanco,Ayllu,Cajamarca,Canayre,Canchacancha,Carhuac,Carhuacatac,Cashan,Caullaraju,Caxamalca,Cayesh,Ccahuasno,Ccarhuacc,Ccopayoc,Chacchapunta,Chacraraju,Challhuamayo,Champara,Chanchan,Chekiacraju,Chillihua,Chinchey,Chontah,Chopicalqui,Chucuito,Chuito,Chullo,Chumpi,Chuncho,Chupahuacho,Chuquiapo,Chuquisaca,Churup,Cocapata,Cochabamba,Cojup,Collota,Conococha,Corihuayrachina,Cuchoquesera,Cusichaca,Haika,Hanpiq,Hatun,Haywarisqa,Huaca,Huachinga,Hualcan,Hualchancca,Huamanga,Huamashraju,Huancarhuas,Huandoy,Huantsan,Huanupampa,Huarmihuanusca,Huascaran,Huaylas,Huayllabamba,Huayrana,Huaytara,Huichajanca,Huinayhuayna,Huinche,Huinioch,Illiasca,Intipunku,Iquicha,Ishinca,Jahuacocha,Jirishanca,Juli,Jurau,Kakananpunta,Kamasqa,Karpay,Kausay,Khuya,Kuelap,Lanccochayocc,Llaca,Llactapata,Llanganuco,Llaqta,Lloqllasca,Llupachayoc,Luricocha,Machu,Mallku,Matarraju,Mechecc,Mikhuy,Milluacocha,Morochuco,Munay,Ocshapalca,Ollantaytambo,Oroccahua,Oronccoy,Oyolo,Pacamayo,Pacaycasa.Carapo,Paccharaju,Pachacamac,Pachakamaq,Pachakuteq,Pachakuti,Pachamama,Paititi,Pajaten,Palcaraju,Pallccas,Pampa,Panaka,Paqarina,Paqo,Parap,Paria,Patahuasi,Patallacta,Patibamba,Pisac,Pisco,Pongos,Pucacolpa,Pucahirca,Pucaranra,Pumatambo,Puscanturpa,Putaca,Puyupatamarca,Qawaq,Qayqa,Qochamoqo,Qollana,Qorihuayrachina,Qorimoqo,Qotupuquio,Quenuaracra,Queshque,Quillcayhuanca,Quillya,Quitaracsa,Quitaraju,Qusqu,Rajucolta,Rajutakanan,Rajutuna,Ranrahirca,Ranrapalca,Raria,Rasac,Rimarima,Riobamba,Runkuracay,Rurec,Sacsa,Sacsamarca,Saiwa,Sarapo,Sayacmarca,Sayripata,Sinakara,Sonccopa,Taripaypacha,Taulliraju,Tawantinsuyu,Taytanchis,Tiwanaku,Tocllaraju,Tsacra,Tuco,Tucubamba,Tullparaju,Tumbes,Uchuraccay,Uchuraqay,Ulta,Urihuana,Uruashraju,Vallunaraju,Vilcabamba,Wacho,Wankawillka,Wayra,Yachay,Yahuarraju,Yanamarey,Yanaqucha,Yanesha,Yerupaja"}, {name: "Quechua", i: 27, min: 6, max: 12, d: "l", m: 0, b: "Alpahuaycco,Anchihuay,Anqea,Apurimac,Arequipa,Atahuallpa,Atawalpa,Atico,Ayacucho,Ayahuanco,Ayllu,Cajamarca,Canayre,Canchacancha,Carapo,Carhuac,Carhuacatac,Cashan,Caullaraju,Caxamalca,Cayesh,Ccahuasno,Ccarhuacc,Ccopayoc,Chacchapunta,Chacraraju,Challhuamayo,Champara,Chanchan,Chekiacraju,Chillihua,Chinchey,Chontah,Chopicalqui,Chucuito,Chuito,Chullo,Chumpi,Chuncho,Chupahuacho,Chuquiapo,Chuquisaca,Churup,Cocapata,Cochabamba,Cojup,Collota,Conococha,Corihuayrachina,Cuchoquesera,Cusichaca,Haika,Hanpiq,Hatun,Haywarisqa,Huaca,Huachinga,Hualcan,Hualchancca,Huamanga,Huamashraju,Huancarhuas,Huandoy,Huantsan,Huanupampa,Huarmihuanusca,Huascaran,Huaylas,Huayllabamba,Huayrana,Huaytara,Huichajanca,Huinayhuayna,Huinche,Huinioch,Illiasca,Intipunku,Iquicha,Ishinca,Jahuacocha,Jirishanca,Juli,Jurau,Kakananpunta,Kamasqa,Karpay,Kausay,Khuya,Kuelap,Lanccochayocc,Llaca,Llactapata,Llanganuco,Llaqta,Lloqllasca,Llupachayoc,Luricocha,Machu,Mallku,Matarraju,Mechecc,Mikhuy,Milluacocha,Morochuco,Munay,Ocshapalca,Ollantaytambo,Oroccahua,Oronccoy,Oyolo,Pacamayo,Pacaycasa,Paccharaju,Pachacamac,Pachakamaq,Pachakuteq,Pachakuti,Pachamama,Paititi,Pajaten,Palcaraju,Pallccas,Pampa,Panaka,Paqarina,Paqo,Parap,Paria,Patahuasi,Patallacta,Patibamba,Pisac,Pisco,Pongos,Pucacolpa,Pucahirca,Pucaranra,Pumatambo,Puscanturpa,Putaca,Puyupatamarca,Qawaq,Qayqa,Qochamoqo,Qollana,Qorihuayrachina,Qorimoqo,Qotupuquio,Quenuaracra,Queshque,Quillcayhuanca,Quillya,Quitaracsa,Quitaraju,Qusqu,Rajucolta,Rajutakanan,Rajutuna,Ranrahirca,Ranrapalca,Raria,Rasac,Rimarima,Riobamba,Runkuracay,Rurec,Sacsa,Sacsamarca,Saiwa,Sarapo,Sayacmarca,Sayripata,Sinakara,Sonccopa,Taripaypacha,Taulliraju,Tawantinsuyu,Taytanchis,Tiwanaku,Tocllaraju,Tsacra,Tuco,Tucubamba,Tullparaju,Tumbes,Uchuraccay,Uchuraqay,Ulta,Urihuana,Uruashraju,Vallunaraju,Vilcabamba,Wacho,Wankawillka,Wayra,Yachay,Yahuarraju,Yanamarey,Yanaqucha,Yanesha,Yerupaja"},
{name: "Swahili", i: 28, min: 4, max: 9, d: "", m: 0, b: "Abim,Adjumani,Alebtong,Amolatar,Amuru,Apac,Arua,Arusha,Babati,Baragoi,Bombo,Budaka,Bugembe,Bugiri,Buikwe,Bukedea,Bukoba,Bukomansimbi,Bukungu,Buliisa,Bundibugyo,Bungoma,Busembatya,Bushenyi,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,Kabuyanda,Kabwohe,Kagadi,Kajiado,Kakinga,Kakiri,Kakuma,Kalangala,Kaliro,Kalongo,Kalungu,Kampala,Kamwenge,Kanungu,Kapchorwa,Kasese,Kasulu,Katakwi,Kayunga,Keroka,Kiambu,Kibaale,Kibaha,Kibingo,Kibwezi,Kigoma,Kihiihi,Kilifi,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,Marsabit,Masaka,Masindi,Masulita,Matugga,Mayuge,Mbale,Mbarara,Mbeya,Meru,Mitooma,Mityana,Mombasa,Morogoro,Moroto,Moyale,Moyo,Mpanda,Mpigi,Mpondwe,Mtwara,Mubende,Mukono,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"}, {name: "Swahili", i: 28, min: 4, max: 9, d: "", m: 0, b: "Abim,Adjumani,Alebtong,Amolatar,Amuru,Apac,Arua,Arusha,Babati,Baragoi,Bombo,Budaka,Bugembe,Bugiri,Buikwe,Bukedea,Bukoba,Bukomansimbi,Bukungu,Buliisa,Bundibugyo,Bungoma,Busembatya,Bushenyi,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,Kabuyanda,Kabwohe,Kagadi,Kajiado,Kakinga,Kakiri,Kakuma,Kalangala,Kaliro,Kalongo,Kalungu,Kampala,Kamwenge,Kanungu,Kapchorwa,Kasese,Kasulu,Katakwi,Kayunga,Keroka,Kiambu,Kibaale,Kibaha,Kibingo,Kibwezi,Kigoma,Kihiihi,Kilifi,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,Marsabit,Masaka,Masindi,Masulita,Matugga,Mayuge,Mbale,Mbarara,Mbeya,Meru,Mitooma,Mityana,Mombasa,Morogoro,Moroto,Moyale,Moyo,Mpanda,Mpigi,Mpondwe,Mtwara,Mubende,Mukono,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"},
{name: "Vietnamese", i: 29, min: 3, max: 12, d: "", m: 1, b: "An Giang,Anh Son,An Khe,An Nhon,Ayun Pa,Bac Giang,Bac Kan,Bac Lieu,Bac Ninh,Ba Don,Bao Loc,Ba Ria,Ba Ria-Vung Tau,Ba Thuoc,Ben Cat,Ben Tre,Bien Hoa,Bim Son,Binh Dinh,Binh Duong,Binh Long,Binh Minh,Binh Phuoc,Binh Thuan,Buon Ho,Buon Ma Thuot,Cai Lay,Ca Mau,Cam Khe,Cam Pha,Cam Ranh,Cam Thuy,Can Tho,Cao Bang,Cao Lanh,Cao Phong,Chau Doc,Chi Linh,Con Cuong,Cua Lo,Da Bac,Dak Lak,Da Lat,Da Nang,Di An,Dien Ban,Dien Bien,Dien Bien Phu,Dien Chau,Do Luong,Dong Ha,Dong Hoi,Dong Trieu,Duc Pho,Duyen Hai,Duy Tien,Gia Lai,Gia Nghia,Gia Rai,Go Cong,Ha Giang,Ha Hoa,Hai Duong,Hai Phong,Ha Long,Ha Nam,Ha Noi,Ha Tinh,Ha Trung,Hau Giang,Hoa Binh,Hoang Mai,Hoa Thanh,Ho Chi Minh,Hoi An,Hong Linh,Hong Ngu,Hue,Hung Nguyen,Hung Yen,Huong Thuy,Huong Tra,Khanh Hoa,Kien Tuong,Kim Boi,Kinh Mon,Kon Tum,Ky Anh,Ky Son,Lac Son,Lac Thuy,La Gi,Lai Chau,Lam Thao,Lang Chanh,Lang Son,Lao Cai,Long An,Long Khanh,Long My,Long Xuyen,Luong Son,Mai Chau,Mong Cai,Muong Lat,Muong Lay,My Hao,My Tho,Nam Dan,Nam Dinh,Nga Bay,Nga Nam,Nga Son,Nghe An,Nghia Dan,Nghia Lo,Nghi Loc,Nghi Son,Ngoc Lac,Nha Trang,Nhu Thanh,Nhu Xuan,Ninh Binh,Ninh Hoa,Nong Cong,Phan Rang Thap Cham,Phan Thiet,Pho Yen,Phu Ly,Phu My,Phu Ninh,Phuoc Long,Phu Tho,Phu Yen,Pleiku,Quang Binh,Quang Nam,Quang Ngai,Quang Ninh,Quang Tri,Quang Xuong,Quang Yen,Quan Hoa,Quan Son,Que Phong,Quy Chau,Quy Hop,Quynh Luu,Quy Nhon,Rach Gia,Sa Dec,Sai Gon,Sam Son,Sa Pa,Soc Trang,Song Cau,Song Cong,Son La,Son Tay,Tam Diep,Tam Ky,Tan An,Tan Chau,Tan Ky,Tan Lac,Tan Son,Tan Uyen,Tay Ninh,Thach Thanh,Thai Binh,Thai Hoa,Thai Nguyen,Thanh Chuong,Thanh Hoa,Thieu Hoa,Thuan An,Thua Thien-Hue,Thu Dau Mot,Thu Duc,Thuong Xuan,Tien Giang,Trang Bang,Tra Vinh,Trieu Son,Tu Son,Tuyen Quang,Tuy Hoa,Uong Bi,Viet Tri,Vinh,Vinh Chau,Vinh Loc,Vinh Long,Vinh Yen,Vi Thanh,Vung Tau,Yen Bai,Yen Dinh,Yen Thanh,Yen Thuy"}, {name: "Vietnamese", i: 29, min: 3, max: 12, d: "", m: 1, b: "An Giang,Anh Son,An Khe,An Nhon,Ayun Pa,Bac Giang,Bac Kan,Bac Lieu,Bac Ninh,Ba Don,Bao Loc,Ba Ria,Ba Ria-Vung Tau,Ba Thuoc,Ben Cat,Ben Tre,Bien Hoa,Bim Son,Binh Dinh,Binh Duong,Binh Long,Binh Minh,Binh Phuoc,Binh Thuan,Buon Ho,Buon Ma Thuot,Cai Lay,Ca Mau,Cam Khe,Cam Pha,Cam Ranh,Cam Thuy,Can Tho,Cao Bang,Cao Lanh,Cao Phong,Chau Doc,Chi Linh,Con Cuong,Cua Lo,Da Bac,Dak Lak,Da Lat,Da Nang,Di An,Dien Ban,Dien Bien,Dien Bien Phu,Dien Chau,Do Luong,Dong Ha,Dong Hoi,Dong Trieu,Duc Pho,Duyen Hai,Duy Tien,Gia Lai,Gia Nghia,Gia Rai,Go Cong,Ha Giang,Ha Hoa,Hai Duong,Hai Phong,Ha Long,Ha Nam,Ha Noi,Ha Tinh,Ha Trung,Hau Giang,Hoa Binh,Hoang Mai,Hoa Thanh,Ho Chi Minh,Hoi An,Hong Linh,Hong Ngu,Hue,Hung Nguyen,Hung Yen,Huong Thuy,Huong Tra,Khanh Hoa,Kien Tuong,Kim Boi,Kinh Mon,Kon Tum,Ky Anh,Ky Son,Lac Son,Lac Thuy,La Gi,Lai Chau,Lam Thao,Lang Chanh,Lang Son,Lao Cai,Long An,Long Khanh,Long My,Long Xuyen,Luong Son,Mai Chau,Mong Cai,Muong Lat,Muong Lay,My Hao,My Tho,Nam Dan,Nam Dinh,Nga Bay,Nga Nam,Nga Son,Nghe An,Nghia Dan,Nghia Lo,Nghi Loc,Nghi Son,Ngoc Lac,Nha Trang,Nhu Thanh,Nhu Xuan,Ninh Binh,Ninh Hoa,Nong Cong,Phan Rang Thap Cham,Phan Thiet,Pho Yen,Phu Ly,Phu My,Phu Ninh,Phuoc Long,Phu Tho,Phu Yen,Pleiku,Quang Binh,Quang Nam,Quang Ngai,Quang Ninh,Quang Tri,Quang Xuong,Quang Yen,Quan Hoa,Quan Son,Que Phong,Quy Chau,Quy Hop,Quynh Luu,Quy Nhon,Rach Gia,Sa Dec,Sai Gon,Sam Son,Sa Pa,Soc Trang,Song Cau,Song Cong,Son La,Son Tay,Tam Diep,Tam Ky,Tan An,Tan Chau,Tan Ky,Tan Lac,Tan Son,Tan Uyen,Tay Ninh,Thach Thanh,Thai Binh,Thai Hoa,Thai Nguyen,Thanh Chuong,Thanh Hoa,Thieu Hoa,Thuan An,Thua Thien-Hue,Thu Dau Mot,Thu Duc,Thuong Xuan,Tien Giang,Trang Bang,Tra Vinh,Trieu Son,Tu Son,Tuyen Quang,Tuy Hoa,Uong Bi,Viet Tri,Vinh,Vinh Chau,Vinh Loc,Vinh Long,Vinh Yen,Vi Thanh,Vung Tau,Yen Bai,Yen Dinh,Yen Thanh,Yen Thuy"},
{name: "Cantonese", i: 30, min: 5, max: 11, d: "", m: 0, b: "Chaiwan,Chingchung,Chinghoi,Chingsen,Chingshing,Chiunam,Chiuon,Chiuyeung,Chiyuen,Choihung,Chuehoi,Chuiman,Chungfu,Chungsan,Chunguktsuen,Dakhing,Daopo,Daumun,Dingwu,Dinpak,Donggun,Dongyuen,Duenchau,Fachau,Fanling,Fatgong,Fatshan,Fotan,Fuktien,Fumun,Funggong,Funghoi,Fungshun,Fungtei,Gamtin,Gochau,Goming,Gonghoi,Gongshing,Goyiu,Hanghau,Hangmei,Hengon,Heungchau,Heunggong,Heungkiu,Hingning,Hohfuktong,Hoichue,Hoifung,Hoiping,Hokong,Hokshan,Hoyuen,Hunghom,Hungshuikiu,Jiuling,Kamsheung,Kamwan,Kaulongtong,Keilun,Kinon,Kinsang,Kityeung,Kongmun,Kukgong,Kwaifong,Kwaihing,Kwongchau,Kwongling,Kwongming,Kwuntong,Laichikok,Laiking,Laiwan,Lamtei,Lamtin,Leitung,Leungking,Limkong,Linping,Linshan,Loding,Lokcheong,Lokfu,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,Namsha,Nganwai,Ngautaukok,Ngchuen,Ngwa,Onting,Pakwun,Paotoishan,Pingshan,Pingyuen,Poklo,Pongon,Poning,Potau,Puito,Punyue,Saiwanho,Saiyingpun,Samshing,Samshui,Samtsen,Samyuenlei,Sanfung,Sanhing,Sanhui,Sanwai,Seiwui,Shamshuipo,Shanmei,Shantau,Shauking,Shekmun,Shekpai,Sheungshui,Shingkui,Shiuhing,Shundak,Shunyi,Shupinwai,Simshing,Siuhei,Siuhong,Siukwan,Siulun,Suikai,Taihing,Taikoo,Taipo,Taishuihang,Taiwai,Taiwohau,Tinhau,Tinshuiwai,Tiukengleng,Toishan,Tongfong,Tonglowan,Tsakyoochung,Tsamgong,Tsangshing,Tseungkwano,Tsimshatsui,Tsinggong,Tsingshantsuen,Tsingwun,Tsingyi,Tsingyuen,Tsiuchau,Tsuenshekshan,Tsuenwan,Tuenmun,Tungchung,Waichap,Waichau,Waidong,Wailoi,Waishing,Waiyeung,Wanchai,Wanfau,Wanshing,Wingon,Wongpo,Wongtaisin,Woping,Wukaisha,Yano,Yaumatei,Yautong,Yenfa,Yeungchun,Yeungdong,Yeungsai,Yeungshan,Yimtin,Yingdak,Yiuping,Yongshing,Yongyuen,Yuenlong,Yuenshing,Yuetsau,Yuknam,Yunping"}, {name: "Cantonese", i: 30, min: 5, max: 11, d: "", m: 0, b: "Chaiwan,Chingchung,Chinghoi,Chingsen,Chingshing,Chiunam,Chiuon,Chiuyeung,Chiyuen,Choihung,Chuehoi,Chuiman,Chungfu,Chungsan,Chunguktsuen,Dakhing,Daopo,Daumun,Dingwu,Dinpak,Donggun,Dongyuen,Duenchau,Fachau,Fanling,Fatgong,Fatshan,Fotan,Fuktien,Fumun,Funggong,Funghoi,Fungshun,Fungtei,Gamtin,Gochau,Goming,Gonghoi,Gongshing,Goyiu,Hanghau,Hangmei,Hengon,Heungchau,Heunggong,Heungkiu,Hingning,Hohfuktong,Hoichue,Hoifung,Hoiping,Hokong,Hokshan,Hoyuen,Hunghom,Hungshuikiu,Jiuling,Kamsheung,Kamwan,Kaulongtong,Keilun,Kinon,Kinsang,Kityeung,Kongmun,Kukgong,Kwaifong,Kwaihing,Kwongchau,Kwongling,Kwongming,Kwuntong,Laichikok,Laiking,Laiwan,Lamtei,Lamtin,Leitung,Leungking,Limkong,Linping,Linshan,Loding,Lokcheong,Lokfu,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,Namsha,Nganwai,Ngautaukok,Ngchuen,Ngwa,Onting,Pakwun,Paotoishan,Pingshan,Pingyuen,Poklo,Pongon,Poning,Potau,Puito,Punyue,Saiwanho,Saiyingpun,Samshing,Samshui,Samtsen,Samyuenlei,Sanfung,Sanhing,Sanhui,Sanwai,Seiwui,Shamshuipo,Shanmei,Shantau,Shauking,Shekmun,Shekpai,Sheungshui,Shingkui,Shiuhing,Shundak,Shunyi,Shupinwai,Simshing,Siuhei,Siuhong,Siukwan,Siulun,Suikai,Taihing,Taikoo,Taipo,Taishuihang,Taiwai,Taiwohau,Tinhau,Tinshuiwai,Tiukengleng,Toishan,Tongfong,Tonglowan,Tsakyoochung,Tsamgong,Tsangshing,Tseungkwano,Tsimshatsui,Tsinggong,Tsingshantsuen,Tsingwun,Tsingyi,Tsingyuen,Tsiuchau,Tsuenshekshan,Tsuenwan,Tuenmun,Tungchung,Waichap,Waichau,Waidong,Wailoi,Waishing,Waiyeung,Wanchai,Wanfau,Wanshing,Wingon,Wongpo,Wongtaisin,Woping,Wukaisha,Yano,Yaumatei,Yautong,Yenfa,Yeungchun,Yeungdong,Yeungsai,Yeungshan,Yimtin,Yingdak,Yiuping,Yongshing,Yongyuen,Yuenlong,Yuenshing,Yuetsau,Yuknam,Yunping"},

View file

@ -223,18 +223,19 @@ function addBurgsGroup(group) {
} }
function removeBurg(id) { function removeBurg(id) {
const label = document.querySelector("#burgLabels [data-id='" + id + "']"); document.querySelector("#burgLabels [data-id='" + id + "']")?.remove();
const icon = document.querySelector("#burgIcons [data-id='" + id + "']"); document.querySelector("#burgIcons [data-id='" + id + "']")?.remove();
const anchor = document.querySelector("#anchors [data-id='" + id + "']"); document.querySelector("#anchors [data-id='" + id + "']")?.remove();
if (label) label.remove();
if (icon) icon.remove(); const cells = pack.cells;
if (anchor) anchor.remove(); const burg = pack.burgs[id];
const cells = pack.cells,
burg = pack.burgs[id];
burg.removed = true; burg.removed = true;
cells.burg[burg.cell] = 0; cells.burg[burg.cell] = 0;
const noteId = notes.findIndex(note => note.id === `burg${id}`);
if (noteId !== -1) notes.splice(noteId, 1);
if (burg.coa) { if (burg.coa) {
const coaId = "burgCOA" + id; const coaId = "burgCOA" + id;
if (byId(coaId)) byId(coaId).remove(); if (byId(coaId)) byId(coaId).remove();

View file

@ -312,10 +312,7 @@ function showElevationProfile(data, routeLen, isRiver) {
.attr("transform", "translate(" + xOffset + "," + parseInt(chartHeight + +yOffset + 20) + ")") .attr("transform", "translate(" + xOffset + "," + parseInt(chartHeight + +yOffset + 20) + ")")
.call(xAxis) .call(xAxis)
.selectAll("text") .selectAll("text")
.style("text-anchor", "center") .style("text-anchor", "center");
.attr("transform", function (d) {
return "rotate(0)"; // used to rotate labels, - anti-clockwise, + clockwise
});
chart chart
.append("g") .append("g")

View file

@ -8,9 +8,10 @@ function editRegiment(selector) {
armies.selectAll(":scope > g > g").call(d3.drag().on("drag", dragRegiment)); armies.selectAll(":scope > g > g").call(d3.drag().on("drag", dragRegiment));
elSelected = selector ? document.querySelector(selector) : d3.event.target.parentElement; // select g element elSelected = selector ? document.querySelector(selector) : d3.event.target.parentElement; // select g element
if (!pack.states[elSelected.dataset.state]) return; if (!pack.states[elSelected.dataset.state]) return;
if (!regiment()) return; if (!getRegiment()) return;
updateRegimentData(regiment()); updateRegimentData(getRegiment());
drawBase(); drawBase();
drawRotationControl();
$("#regimentEditor").dialog({ $("#regimentEditor").dialog({
title: "Edit Regiment", title: "Edit Regiment",
@ -37,8 +38,8 @@ function editRegiment(selector) {
document.getElementById("regimentRemove").addEventListener("click", removeRegiment); document.getElementById("regimentRemove").addEventListener("click", removeRegiment);
// get regiment data element // get regiment data element
function regiment() { function getRegiment() {
return pack.states[elSelected.dataset.state].military.find(r => r.i == elSelected.dataset.id); return pack.states[elSelected.dataset.state]?.military.find(r => r.i == elSelected.dataset.id);
} }
function updateRegimentData(regiment) { function updateRegimentData(regiment) {
@ -60,7 +61,7 @@ function editRegiment(selector) {
} }
function drawBase() { function drawBase() {
const reg = regiment(); const reg = getRegiment();
const clr = pack.states[elSelected.dataset.state].color; const clr = pack.states[elSelected.dataset.state].color;
const base = viewbox const base = viewbox
.insert("g", "g#armies") .insert("g", "g#armies")
@ -69,12 +70,8 @@ function editRegiment(selector) {
.attr("stroke", "#000") .attr("stroke", "#000")
.attr("cursor", "move"); .attr("cursor", "move");
base base
.on("mouseenter", () => { .on("mouseenter", () => tip("Regiment base. Drag to re-base the regiment", true))
tip("Regiment base. Drag to re-base the regiment", true); .on("mouseleave", () => tip("", true));
})
.on("mouseleave", () => {
tip("", true);
});
base base
.append("line") .append("line")
@ -92,8 +89,42 @@ function editRegiment(selector) {
.call(d3.drag().on("drag", dragBase)); .call(d3.drag().on("drag", dragBase));
} }
function drawRotationControl() {
const reg = getRegiment();
const {x, width, y, height} = elSelected.getBBox();
debug
.append("circle")
.attr("id", "rotationControl")
.attr("cx", x + width)
.attr("cy", y + height / 2)
.attr("r", 1)
.attr("opacity", 1)
.attr("fill", "yellow")
.attr("stroke-width", 0.3)
.attr("stroke", "black")
.attr("cursor", "alias")
.attr("transform", `rotate(${reg.angle || 0})`)
.attr("transform-origin", `${reg.x}px ${reg.y}px`)
.on("mouseenter", () => tip("Drag to rotate the regiment", true))
.on("mouseleave", () => tip("", true))
.call(d3.drag().on("start", rotateRegiment));
}
function rotateRegiment() {
const reg = getRegiment();
d3.event.on("drag", function () {
const {x, y} = d3.event;
const angle = rn(Math.atan2(y - reg.y, x - reg.x) * (180 / Math.PI), 2);
elSelected.setAttribute("transform", `rotate(${angle})`);
this.setAttribute("transform", `rotate(${angle})`);
reg.angle = rn(angle, 2);
});
}
function changeType() { function changeType() {
const reg = regiment(); const reg = getRegiment();
reg.n = +!reg.n; reg.n = +!reg.n;
document.getElementById("regimentType").className = reg.n ? "icon-anchor" : "icon-users"; document.getElementById("regimentType").className = reg.n ? "icon-anchor" : "icon-users";
@ -110,11 +141,11 @@ function editRegiment(selector) {
} }
function changeName() { function changeName() {
elSelected.dataset.name = regiment().name = this.value; elSelected.dataset.name = getRegiment().name = this.value;
} }
function restoreName() { function restoreName() {
const reg = regiment(), const reg = getRegiment(),
regs = pack.states[elSelected.dataset.state].military; regs = pack.states[elSelected.dataset.state].military;
const name = Military.getName(reg, regs); const name = Military.getName(reg, regs);
elSelected.dataset.name = reg.name = document.getElementById("regimentName").value = name; elSelected.dataset.name = reg.name = document.getElementById("regimentName").value = name;
@ -129,12 +160,12 @@ function editRegiment(selector) {
function changeEmblem() { function changeEmblem() {
const emblem = document.getElementById("regimentEmblem").value; const emblem = document.getElementById("regimentEmblem").value;
regiment().icon = elSelected.querySelector(".regimentIcon").innerHTML = emblem; getRegiment().icon = elSelected.querySelector(".regimentIcon").innerHTML = emblem;
} }
function changeUnit() { function changeUnit() {
const u = this.dataset.u; const u = this.dataset.u;
const reg = regiment(); const reg = getRegiment();
reg.u[u] = +this.value || 0; reg.u[u] = +this.value || 0;
reg.a = d3.sum(Object.values(reg.u)); reg.a = d3.sum(Object.values(reg.u));
elSelected.querySelector("text").innerHTML = Military.getTotal(reg); elSelected.querySelector("text").innerHTML = Military.getTotal(reg);
@ -143,7 +174,7 @@ function editRegiment(selector) {
} }
function splitRegiment() { function splitRegiment() {
const reg = regiment(), const reg = getRegiment(),
u1 = reg.u; u1 = reg.u;
const state = +elSelected.dataset.state, const state = +elSelected.dataset.state,
military = pack.states[state].military; military = pack.states[state].military;
@ -206,8 +237,7 @@ function editRegiment(selector) {
function addRegimentOnClick() { function addRegimentOnClick() {
const point = d3.mouse(this); const point = d3.mouse(this);
const cell = findCell(point[0], point[1]); const cell = findCell(point[0], point[1]);
const x = pack.cells.p[cell][0], const [x, y] = pack.cells.p[cell];
y = pack.cells.p[cell][1];
const state = +elSelected.dataset.state, const state = +elSelected.dataset.state,
military = pack.states[state].military; military = pack.states[state].military;
const i = military.length ? last(military).i + 1 : 0; const i = military.length ? last(military).i + 1 : 0;
@ -254,7 +284,7 @@ function editRegiment(selector) {
return; return;
} }
const attacker = regiment(); const attacker = getRegiment();
const defender = pack.states[regSelected.dataset.state].military.find(r => r.i == regSelected.dataset.id); const defender = pack.states[regSelected.dataset.state].military.find(r => r.i == regSelected.dataset.id);
if (!attacker.a || !defender.a) { if (!attacker.a || !defender.a) {
tip("Regiment has no troops to battle", false, "error"); tip("Regiment has no troops to battle", false, "error");
@ -322,7 +352,7 @@ function editRegiment(selector) {
return; return;
} }
const reg = regiment(); // reg to be attached const reg = getRegiment(); // reg to be attached
const sel = pack.states[newState].military.find(r => r.i == regSelected.dataset.id); // reg to attach to const sel = pack.states[newState].military.find(r => r.i == regSelected.dataset.id); // reg to attach to
for (const unit of options.military) { for (const unit of options.military) {
@ -349,11 +379,11 @@ function editRegiment(selector) {
if (index != -1) notes.splice(index, 1); if (index != -1) notes.splice(index, 1);
const s = pack.states[elSelected.dataset.state]; const s = pack.states[elSelected.dataset.state];
Military.generateNote(regiment(), s); Military.generateNote(getRegiment(), s);
} }
function editLegend() { function editLegend() {
editNotes(elSelected.id, regiment().name); editNotes(elSelected.id, getRegiment().name);
} }
function removeRegiment() { function removeRegiment() {
@ -365,7 +395,7 @@ function editRegiment(selector) {
Remove: function () { Remove: function () {
$(this).dialog("close"); $(this).dialog("close");
const military = pack.states[elSelected.dataset.state].military; const military = pack.states[elSelected.dataset.state].military;
const regIndex = military.indexOf(regiment()); const regIndex = military.indexOf(getRegiment());
if (regIndex === -1) return; if (regIndex === -1) return;
military.splice(regIndex, 1); military.splice(regIndex, 1);
@ -392,8 +422,6 @@ function editRegiment(selector) {
const size = +armies.attr("box-size"); const size = +armies.attr("box-size");
const w = reg.n ? size * 4 : size * 6; const w = reg.n ? size * 4 : size * 6;
const h = size * 2; const h = size * 2;
const x1 = x => rn(x - w / 2, 2);
const y1 = y => rn(y - size, 2);
const baseRect = this.querySelector("rect"); const baseRect = this.querySelector("rect");
const text = this.querySelector("text"); const text = this.querySelector("text");
@ -402,26 +430,37 @@ function editRegiment(selector) {
const self = elSelected === this; const self = elSelected === this;
const baseLine = viewbox.select("g#regimentBase > line"); const baseLine = viewbox.select("g#regimentBase > line");
const rotationControl = debug.select("#rotationControl");
d3.event.on("drag", function () { d3.event.on("drag", function () {
const x = (reg.x = d3.event.x), const {x, y} = d3.event;
y = (reg.y = d3.event.y); reg.x = x;
reg.y = y;
const x1 = rn(x - w / 2, 2);
const y1 = rn(y - size, 2);
baseRect.setAttribute("x", x1(x)); this.setAttribute("transform-origin", `${x}px ${y}px`);
baseRect.setAttribute("y", y1(y)); baseRect.setAttribute("x", x1);
baseRect.setAttribute("y", y1);
text.setAttribute("x", x); text.setAttribute("x", x);
text.setAttribute("y", y); text.setAttribute("y", y);
iconRect.setAttribute("x", x1(x) - h); iconRect.setAttribute("x", x1 - h);
iconRect.setAttribute("y", y1(y)); iconRect.setAttribute("y", y1);
icon.setAttribute("x", x1(x) - size); icon.setAttribute("x", x1 - size);
icon.setAttribute("y", y); icon.setAttribute("y", y);
if (self) baseLine.attr("x2", x).attr("y2", y); if (self) {
baseLine.attr("x2", x).attr("y2", y);
rotationControl
.attr("cx", x1 + w)
.attr("cy", y)
.attr("transform-origin", `${x}px ${y}px`);
}
}); });
} }
function dragBase() { function dragBase() {
const baseLine = viewbox.select("g#regimentBase > line"); const baseLine = viewbox.select("g#regimentBase > line");
const reg = regiment(); const reg = getRegiment();
d3.event.on("drag", function () { d3.event.on("drag", function () {
this.setAttribute("cx", d3.event.x); this.setAttribute("cx", d3.event.x);
@ -436,9 +475,10 @@ function editRegiment(selector) {
} }
function closeEditor() { function closeEditor() {
debug.selectAll("*").remove();
viewbox.selectAll("g#regimentBase").remove();
armies.selectAll(":scope > g").classed("draggable", false); armies.selectAll(":scope > g").classed("draggable", false);
armies.selectAll("g>g").call(d3.drag().on("drag", null)); armies.selectAll("g>g").call(d3.drag().on("drag", null));
viewbox.selectAll("g#regimentBase").remove();
document.getElementById("regimentAdd").classList.remove("pressed"); document.getElementById("regimentAdd").classList.remove("pressed");
document.getElementById("regimentAttack").classList.remove("pressed"); document.getElementById("regimentAttack").classList.remove("pressed");
document.getElementById("regimentAttach").classList.remove("pressed"); document.getElementById("regimentAttach").classList.remove("pressed");

View file

@ -336,29 +336,44 @@ function regenerateProvinces() {
} }
function regenerateBurgs() { function regenerateBurgs() {
const {cells, states} = pack; const {cells, features, burgs, states, provinces} = pack;
const lockedburgs = pack.burgs.filter(b => b.i && !b.removed && b.lock);
rankCells(); rankCells();
cells.burg = new Uint16Array(cells.i.length); // remove notes for unlocked burgs
const burgs = (pack.burgs = [0]); // clear burgs array notes = notes.filter(note => {
states.filter(s => s.i).forEach(s => (s.capital = 0)); // clear state capitals if (note.id.startsWith("burg")) {
pack.provinces.filter(p => p.i).forEach(p => (p.burg = 0)); // clear province capitals const burgId = +note.id.slice(4);
return burgs[burgId]?.lock;
}
return true;
});
const newBurgs = [0]; // new burgs array
const burgsTree = d3.quadtree(); const burgsTree = d3.quadtree();
// add locked burgs cells.burg = new Uint16Array(cells.i.length); // clear cells burg data
states.filter(s => s.i).forEach(s => (s.capital = 0)); // clear state capitals
provinces.filter(p => p.i).forEach(p => (p.burg = 0)); // clear province capitals
// readd locked burgs
const lockedburgs = burgs.filter(burg => burg.i && !burg.removed && burg.lock);
for (let j = 0; j < lockedburgs.length; j++) { for (let j = 0; j < lockedburgs.length; j++) {
const id = burgs.length;
const lockedBurg = lockedburgs[j]; const lockedBurg = lockedburgs[j];
lockedBurg.i = id; const newId = newBurgs.length;
burgs.push(lockedBurg);
const noteIndex = notes.findIndex(note => note.id === `burg${lockedBurg.i}`);
if (noteIndex !== -1) notes[noteIndex].id = `burg${newId}`;
lockedBurg.i = newId;
newBurgs.push(lockedBurg);
burgsTree.add([lockedBurg.x, lockedBurg.y]); burgsTree.add([lockedBurg.x, lockedBurg.y]);
cells.burg[lockedBurg.cell] = id; cells.burg[lockedBurg.cell] = newId;
if (lockedBurg.capital) { if (lockedBurg.capital) {
const stateId = lockedBurg.state; const stateId = lockedBurg.state;
states[stateId].capital = id; states[stateId].capital = newId;
states[stateId].center = lockedBurg.cell; states[stateId].center = lockedBurg.cell;
} }
} }
@ -371,8 +386,8 @@ function regenerateBurgs() {
existingStatesCount; existingStatesCount;
const spacing = (graphWidth + graphHeight) / 150 / (burgsCount ** 0.7 / 66); // base min distance between towns const spacing = (graphWidth + graphHeight) / 150 / (burgsCount ** 0.7 / 66); // base min distance between towns
for (let i = 0; i < sorted.length && burgs.length < burgsCount; i++) { for (let i = 0; i < sorted.length && newBurgs.length < burgsCount; i++) {
const id = burgs.length; const id = newBurgs.length;
const cell = sorted[i]; const cell = sorted[i];
const [x, y] = cells.p[cell]; const [x, y] = cells.p[cell];
@ -388,24 +403,27 @@ function regenerateBurgs() {
const culture = cells.culture[cell]; const culture = cells.culture[cell];
const name = Names.getCulture(culture); const name = Names.getCulture(culture);
burgs.push({cell, x, y, state: stateId, i: id, culture, name, capital, feature: cells.f[cell]}); newBurgs.push({cell, x, y, state: stateId, i: id, culture, name, capital, feature: cells.f[cell]});
burgsTree.add([x, y]); burgsTree.add([x, y]);
cells.burg[cell] = id; cells.burg[cell] = id;
} }
pack.burgs = newBurgs; // assign new burgs array
// add a capital at former place for states without added capitals // add a capital at former place for states without added capitals
states states
.filter(s => s.i && !s.removed && !s.capital) .filter(s => s.i && !s.removed && !s.capital)
.forEach(s => { .forEach(s => {
const burg = addBurg([cells.p[s.center][0], cells.p[s.center][1]]); // add new burg const [x, y] = cells.p[s.center];
s.capital = burg; const burgId = addBurg([x, y]);
s.center = pack.burgs[burg].cell; s.capital = burgId;
pack.burgs[burg].capital = 1; s.center = pack.burgs[burgId].cell;
pack.burgs[burg].state = s.i; pack.burgs[burgId].capital = 1;
moveBurgToGroup(burg, "cities"); pack.burgs[burgId].state = s.i;
moveBurgToGroup(burgId, "cities");
}); });
pack.features.forEach(f => { features.forEach(f => {
if (f.port) f.port = 0; // reset features ports counter if (f.port) f.port = 0; // reset features ports counter
}); });

View file

@ -3,7 +3,7 @@
function editZones() { function editZones() {
closeDialogs(); closeDialogs();
if (!layerIsOn("toggleZones")) toggleZones(); if (!layerIsOn("toggleZones")) toggleZones();
const body = document.getElementById("zonesBodySection"); const body = byId("zonesBodySection");
updateFilters(); updateFilters();
zonesEditorAddLines(); zonesEditorAddLines();
@ -20,20 +20,20 @@ function editZones() {
}); });
// add listeners // add listeners
document.getElementById("zonesFilterType").addEventListener("click", updateFilters); byId("zonesFilterType").on("click", updateFilters);
document.getElementById("zonesFilterType").addEventListener("change", filterZonesByType); byId("zonesFilterType").on("change", filterZonesByType);
document.getElementById("zonesEditorRefresh").addEventListener("click", zonesEditorAddLines); byId("zonesEditorRefresh").on("click", zonesEditorAddLines);
document.getElementById("zonesEditStyle").addEventListener("click", () => editStyle("zones")); byId("zonesEditStyle").on("click", () => editStyle("zones"));
document.getElementById("zonesLegend").addEventListener("click", toggleLegend); byId("zonesLegend").on("click", toggleLegend);
document.getElementById("zonesPercentage").addEventListener("click", togglePercentageMode); byId("zonesPercentage").on("click", togglePercentageMode);
document.getElementById("zonesManually").addEventListener("click", enterZonesManualAssignent); byId("zonesManually").on("click", enterZonesManualAssignent);
document.getElementById("zonesManuallyApply").addEventListener("click", applyZonesManualAssignent); byId("zonesManuallyApply").on("click", applyZonesManualAssignent);
document.getElementById("zonesManuallyCancel").addEventListener("click", cancelZonesManualAssignent); byId("zonesManuallyCancel").on("click", cancelZonesManualAssignent);
document.getElementById("zonesAdd").addEventListener("click", addZonesLayer); byId("zonesAdd").on("click", addZonesLayer);
document.getElementById("zonesExport").addEventListener("click", downloadZonesData); byId("zonesExport").on("click", downloadZonesData);
document.getElementById("zonesRemove").addEventListener("click", toggleEraseMode); byId("zonesRemove").on("click", toggleEraseMode);
body.addEventListener("click", function (ev) { body.on("click", function (ev) {
const el = ev.target, const el = ev.target,
cl = el.classList, cl = el.classList,
zone = el.parentNode.dataset.id; zone = el.parentNode.dataset.id;
@ -45,7 +45,7 @@ function editZones() {
if (customization) selectZone(el); if (customization) selectZone(el);
}); });
body.addEventListener("input", function (ev) { body.on("input", function (ev) {
const el = ev.target; const el = ev.target;
const zone = zones.select("#" + el.parentNode.dataset.id); const zone = zones.select("#" + el.parentNode.dataset.id);
@ -58,7 +58,7 @@ function editZones() {
const zones = Array.from(document.querySelectorAll("#zones > g")); const zones = Array.from(document.querySelectorAll("#zones > g"));
const types = unique(zones.map(zone => zone.dataset.type)); const types = unique(zones.map(zone => zone.dataset.type));
const filterSelect = document.getElementById("zonesFilterType"); const filterSelect = byId("zonesFilterType");
const typeToFilterBy = types.includes(zonesFilterType.value) ? zonesFilterType.value : "all"; const typeToFilterBy = types.includes(zonesFilterType.value) ? zonesFilterType.value : "all";
filterSelect.innerHTML = filterSelect.innerHTML =
@ -70,7 +70,7 @@ function editZones() {
function zonesEditorAddLines() { function zonesEditorAddLines() {
const unit = " " + getAreaUnit(); const unit = " " + getAreaUnit();
const typeToFilterBy = document.getElementById("zonesFilterType").value; const typeToFilterBy = byId("zonesFilterType").value;
const zones = Array.from(document.querySelectorAll("#zones > g")); const zones = Array.from(document.querySelectorAll("#zones > g"));
const filteredZones = typeToFilterBy === "all" ? zones : zones.filter(zone => zone.dataset.type === typeToFilterBy); const filteredZones = typeToFilterBy === "all" ? zones : zones.filter(zone => zone.dataset.type === typeToFilterBy);
@ -127,8 +127,8 @@ function editZones() {
zonesFooterPopulation.innerHTML = si(totalPop); zonesFooterPopulation.innerHTML = si(totalPop);
// add listeners // add listeners
body.querySelectorAll("div.states").forEach(el => el.addEventListener("mouseenter", ev => zoneHighlightOn(ev))); body.querySelectorAll("div.states").forEach(el => el.on("mouseenter", ev => zoneHighlightOn(ev)));
body.querySelectorAll("div.states").forEach(el => el.addEventListener("mouseleave", ev => zoneHighlightOff(ev))); body.querySelectorAll("div.states").forEach(el => el.on("mouseleave", ev => zoneHighlightOff(ev)));
if (body.dataset.type === "percentage") { if (body.dataset.type === "percentage") {
body.dataset.type = "absolute"; body.dataset.type = "absolute";
@ -182,7 +182,7 @@ function editZones() {
if (!layerIsOn("toggleZones")) toggleZones(); if (!layerIsOn("toggleZones")) toggleZones();
customization = 10; customization = 10;
document.querySelectorAll("#zonesBottom > *").forEach(el => (el.style.display = "none")); document.querySelectorAll("#zonesBottom > *").forEach(el => (el.style.display = "none"));
document.getElementById("zonesManuallyButtons").style.display = "inline-block"; byId("zonesManuallyButtons").style.display = "inline-block";
zonesEditor.querySelectorAll(".hide").forEach(el => el.classList.add("hidden")); zonesEditor.querySelectorAll(".hide").forEach(el => el.classList.add("hidden"));
zonesFooter.style.display = "none"; zonesFooter.style.display = "none";
@ -215,24 +215,27 @@ function editZones() {
} }
function dragZoneBrush() { function dragZoneBrush() {
const r = +zonesBrush.value; const radius = +byId("zonesBrush").value;
const eraseMode = byId("zonesRemove").classList.contains("pressed");
const landOnly = byId("zonesBrushLandOnly").checked;
const selected = body.querySelector("div.selected");
const zone = zones.select("#" + selected.dataset.id);
const base = zone.attr("id") + "_"; // id generic part
d3.event.on("drag", () => { d3.event.on("drag", () => {
if (!d3.event.dx && !d3.event.dy) return; if (!d3.event.dx && !d3.event.dy) return;
const p = d3.mouse(this); const [x, y] = d3.mouse(this);
moveCircle(p[0], p[1], r); moveCircle(x, y, radius);
const selection = r > 5 ? findAll(p[0], p[1], r) : [findCell(p[0], p[1])]; let selection = radius > 5 ? findAll(x, y, radius) : [findCell(x, y, radius)];
if (landOnly) selection = selection.filter(i => pack.cells.h[i] >= 20);
if (!selection) return; if (!selection) return;
const selected = body.querySelector("div.selected");
const zone = zones.select("#" + selected.dataset.id);
const base = zone.attr("id") + "_"; // id generic part
const dataCells = zone.attr("data-cells"); const dataCells = zone.attr("data-cells");
let cells = dataCells ? dataCells.split(",").map(i => +i) : []; let cells = dataCells ? dataCells.split(",").map(i => +i) : [];
const erase = document.getElementById("zonesRemove").classList.contains("pressed"); if (eraseMode) {
if (erase) {
// remove // remove
selection.forEach(i => { selection.forEach(i => {
const index = cells.indexOf(i); const index = cells.indexOf(i);
@ -300,7 +303,7 @@ function editZones() {
customization = 0; customization = 0;
removeCircle(); removeCircle();
document.querySelectorAll("#zonesBottom > *").forEach(el => (el.style.display = "inline-block")); document.querySelectorAll("#zonesBottom > *").forEach(el => (el.style.display = "inline-block"));
document.getElementById("zonesManuallyButtons").style.display = "none"; byId("zonesManuallyButtons").style.display = "none";
zonesEditor.querySelectorAll(".hide:not(.show)").forEach(el => el.classList.remove("hidden")); zonesEditor.querySelectorAll(".hide:not(.show)").forEach(el => el.classList.remove("hidden"));
zonesFooter.style.display = "block"; zonesFooter.style.display = "block";
@ -321,7 +324,7 @@ function editZones() {
const fill = el.getAttribute("fill"); const fill = el.getAttribute("fill");
const callback = newFill => { const callback = newFill => {
el.fill = newFill; el.fill = newFill;
document.getElementById(el.parentNode.dataset.id).setAttribute("fill", newFill); byId(el.parentNode.dataset.id).setAttribute("fill", newFill);
}; };
openPicker(fill, callback); openPicker(fill, callback);