From c36e80933718e6c2826ef6f7bd9efa59c0bee1e7 Mon Sep 17 00:00:00 2001 From: "Mirar (Pontus Hagland)" <pike@sort.mirar.org> Date: Thu, 18 May 2000 10:27:50 +0200 Subject: [PATCH] first checkin; some geographical support Rev: lib/modules/Geography.pmod/Countries.pmod:1.1 Rev: lib/modules/Geography.pmod/Position.pike:1.1 --- lib/modules/Geography.pmod/Countries.pmod | 408 ++++++++++++++++++++++ lib/modules/Geography.pmod/Position.pike | 170 +++++++++ 2 files changed, 578 insertions(+) create mode 100644 lib/modules/Geography.pmod/Countries.pmod create mode 100644 lib/modules/Geography.pmod/Position.pike diff --git a/lib/modules/Geography.pmod/Countries.pmod b/lib/modules/Geography.pmod/Countries.pmod new file mode 100644 index 0000000000..950496f517 --- /dev/null +++ b/lib/modules/Geography.pmod/Countries.pmod @@ -0,0 +1,408 @@ +array(Country) countries= +({ + Country("AD","Andorra"), + Country("AE","United Arab Emirates"), + Country("AF","Afghanistan"), + Country("AG","Antigua and Barbuda"), + Country("AI","Anguilla"), + Country("AL","Albania"), + Country("AM","Armenia"), + Country("AN","Netherlands Antilles"), + Country("AO","Angola"), + Country("AQ","Antarctica"), + Country("AR","Argentina"), + Country("AS","American Samoa"), + Country("AT","Austria"), + Country("AU","Australia"), + Country("AW","Aruba"), + Country("AZ","Azerbaijan"), + Country("BA","Bosnia and Herzegovina"), + Country("BB","Barbados"), + Country("BD","Bangladesh"), + Country("BE","Belgium"), + Country("BF","Burkina Faso"), + Country("BG","Bulgaria"), + Country("BH","Bahrain"), + Country("BI","Burundi"), + Country("BJ","Benin"), + Country("BM","Bermuda"), + Country("BN","Brunei Darussalam"), + Country("BO","Bolivia"), + Country("BR","Brazil"), + Country("BS","Bahamas"), + Country("BT","Bhutan"), + Country("BV","Bouvet Island"), + Country("BW","Botswana"), + Country("BY","Belarus"), + Country("BZ","Belize"), + Country("CA","Canada"), + Country("CC","Cocos Islands",(["aka":({"Keeling Islands"})])), + Country("CF","Central African Republic"), + Country("CG","Congo"), + Country("CH","Switzerland"), + Country("CI","Cote D'Ivoire",(["aka":({"Ivory Coast"})])), + Country("CK","Cook Islands"), + Country("CL","Chile"), + Country("CM","Cameroon"), + Country("CN","China"), + Country("CO","Colombia"), + Country("CR","Costa Rica"), + Country("CS","Czechoslovakia",(["former":1])), + Country("CU","Cuba"), + Country("CV","Cape Verde"), + Country("CX","Christmas Island"), + Country("CY","Cyprus"), + Country("CZ","Czech Republic"), + Country("DE","Germany"), + Country("DJ","Djibouti"), + Country("DK","Denmark"), + Country("DM","Dominica"), + Country("DO","Dominican Republic"), + Country("DZ","Algeria"), + Country("EC","Ecuador"), + Country("EE","Estonia"), + Country("EG","Egypt"), + Country("EH","Western Sahara"), + Country("ER","Eritrea"), + Country("ES","Spain"), + Country("ET","Ethiopia"), + Country("FI","Finland"), + Country("FJ","Fiji"), + Country("FK","Falkland Islands",(["aka":({"Malvinas"})])), + Country("FM","Micronesia"), + Country("FO","Faroe Islands"), + Country("FR","France"), + Country("FX","France, Metropolitan"), + Country("GA","Gabon"), + Country("GB","United Kingdom",(["aka":({"Great Britain"})])), + Country("GD","Grenada"), + Country("GE","Georgia"), + Country("GF","French Guiana"), + Country("GH","Ghana"), + Country("GI","Gibraltar"), + Country("GL","Greenland"), + Country("GM","Gambia"), + Country("GN","Guinea"), + Country("GP","Guadeloupe"), + Country("GQ","Equatorial Guinea"), + Country("GR","Greece"), + Country("GS","S. Georgia and S. Sandwich Isls."), + Country("GT","Guatemala"), + Country("GU","Guam"), + Country("GW","Guinea-Bissau"), + Country("GY","Guyana"), + Country("HK","Hong Kong"), + Country("HM","Heard and McDonald Islands"), + Country("HN","Honduras"), + Country("HR","Croatia",(["aka":({"Hrvatska"})])), + Country("HT","Haiti"), + Country("HU","Hungary"), + Country("ID","Indonesia"), + Country("IE","Ireland"), + Country("IL","Israel"), + Country("IN","India"), + Country("IO","British Indian Ocean Territory"), + Country("IQ","Iraq"), + Country("IR","Iran"), + Country("IS","Iceland"), + Country("IT","Italy"), + Country("JM","Jamaica"), + Country("JO","Jordan"), + Country("JP","Japan"), + Country("KE","Kenya"), + Country("KG","Kyrgyzstan"), + Country("KH","Cambodia"), + Country("KI","Kiribati"), + Country("KM","Comoros"), + Country("KN","Saint Kitts and Nevis"), + Country("KP","North Korea"), + Country("KR","South Korea"), + Country("KW","Kuwait"), + Country("KY","Cayman Islands"), + Country("KZ","Kazakhstan"), + Country("LA","Laos"), + Country("LB","Lebanon"), + Country("LC","Saint Lucia"), + Country("LI","Liechtenstein"), + Country("LK","Sri Lanka"), + Country("LR","Liberia"), + Country("LS","Lesotho"), + Country("LT","Lithuania"), + Country("LU","Luxembourg"), + Country("LV","Latvia"), + Country("LY","Libya"), + Country("MA","Morocco"), + Country("MC","Monaco"), + Country("MD","Moldova"), + Country("MG","Madagascar"), + Country("MH","Marshall Islands"), + Country("MK","Macedonia"), + Country("ML","Mali"), + Country("MM","Myanmar"), + Country("MN","Mongolia"), + Country("MO","Macau"), + Country("MP","Northern Mariana Islands"), + Country("MQ","Martinique"), + Country("MR","Mauritania"), + Country("MS","Montserrat"), + Country("MT","Malta"), + Country("MU","Mauritius"), + Country("MV","Maldives"), + Country("MW","Malawi"), + Country("MX","Mexico"), + Country("MY","Malaysia"), + Country("MZ","Mozambique"), + Country("NA","Namibia"), + Country("NC","New Caledonia"), + Country("NE","Niger"), + Country("NF","Norfolk Island"), + Country("NG","Nigeria"), + Country("NI","Nicaragua"), + Country("NL","Netherlands"), + Country("NO","Norway"), + Country("NP","Nepal"), + Country("NR","Nauru"), + Country("NT","Neutral Zone"), + Country("NU","Niue"), + Country("NZ","New Zealand (Aotearoa)"), + Country("OM","Oman"), + Country("PA","Panama"), + Country("PE","Peru"), + Country("PF","French Polynesia"), + Country("PG","Papua New Guinea"), + Country("PH","Philippines"), + Country("PK","Pakistan"), + Country("PL","Poland"), + Country("PM","St. Pierre and Miquelon"), + Country("PN","Pitcairn"), + Country("PR","Puerto Rico"), + Country("PT","Portugal"), + Country("PW","Palau"), + Country("PY","Paraguay"), + Country("QA","Qatar"), + Country("RE","Reunion"), + Country("RO","Romania"), + Country("RU","Russian Federation"), + Country("RW","Rwanda"), + Country("SA","Saudi Arabia"), + Country("Sb","Solomon Islands"), + Country("SC","Seychelles"), + Country("SD","Sudan"), + Country("SE","Sweden"), + Country("SG","Singapore"), + Country("SH","St. Helena"), + Country("SI","Slovenia"), + Country("SJ","Svalbard and Jan Mayen Islands"), + Country("SK","Slovak Republic"), + Country("SL","Sierra Leone"), + Country("SM","San Marino"), + Country("SN","Senegal"), + Country("SO","Somalia"), + Country("SR","Suriname"), + Country("ST","Sao Tome and Principe"), + Country("SU","USSR",(["former":1])), + Country("SV","El Salvador"), + Country("SY","Syria"), + Country("SZ","Swaziland"), + Country("TC","Turks and Caicos Islands"), + Country("TD","Chad"), + Country("TF","French Southern Territories"), + Country("TG","Togo"), + Country("TH","Thailand"), + Country("TJ","Tajikistan"), + Country("TK","Tokelau"), + Country("TM","Turkmenistan"), + Country("TN","Tunisia"), + Country("TO","Tonga"), + Country("TP","East Timor"), + Country("TR","Turkey"), + Country("TT","Trinidad and Tobago"), + Country("TV","Tuvalu"), + Country("TW","Taiwan"), + Country("TZ","Tanzania"), + Country("UA","Ukraine"), + Country("UG","Uganda"), + Country("UM","US Minor Outlying Islands"), + Country("US","United States"), + Country("UY","Uruguay"), + Country("UZ","Uzbekistan"), + Country("VA","Vatican City State (Holy See)"), + Country("VC","Saint Vincent and the Grenadines"), + Country("VE","Venezuela"), + Country("VG","Virgin Islands (British)"), + Country("VI","Virgin Islands (U.S.)"), + Country("VN","Viet Nam"), + Country("VU","Vanuatu"), + Country("WF","Wallis and Futuna Islands"), + Country("WS","Samoa"), + Country("YE","Yemen"), + Country("YT","Mayotte"), + Country("YU","Yugoslavia"), + Country("ZA","South Africa"), + Country("ZM","Zambia"), + Country("ZR","Zaire"), + Country("ZW","Zimbabwe"), +}); + +//! module Geographical +//! submodule Countries +//! subclass Country + +class Country +{ +//! variable string iso2 +//! ISO 2-character code aka domain name + + string iso2; // iso-2-character-code aka domain name + +//! variable string name +//! variable array(string) aka +//! Country name and as-known-as, if any + + string name; + array(string) aka=({}); + +//! variable int former +//! Flag that is set if this isn't a country anymore +//! (Like USSR.) + + int former=0; + + void create(string _iso2,string _name,mapping opts) + { + iso2=_iso2; + name=_name; + if (opts) + { + foreach ( (array)opts, [string what,string val]) + ::`[]=(what,val); + } + } + +//! method string cast("string") +//! It is possible to cast a country to a string, +//! which will be the same as performing +//! <tt>country->name;</tt>. + + string cast(string to) + { + if (to[..5]=="string") return name; + error("can't cast to %O\n",to); + } + + string _sprintf(int t) + { + if (t=='O') + return "Country("+name+")"; + return 0; + } + +} + +//! module Geographical +//! submodule Countries + +//! constant array(Country) countries +//! All known countries. + +//! method Country from_domain(string domain) +//! Look up a country from a domain name. +//! Returns zero if the domain doesn't map +//! to a country. Note that there are some +//! valid domains that doesn't: +//! <dl compact> +//! <dt>INT <dd>International +//! <dt>MIL <dd>US Military +//! <dt>NET <dd>Network +//! <dt>ORG <dd>Non-Profit Organization +//! <dt>ARPA <dd>Old style Arpanet +//! <dt>NATO <dd>Nato field +//! </dl> +//! +//! And that USA has three domains, Great Britain two: +//! <dl compact> +//! <dt>COM <dd>US Commercial +//! <dt>EDU <dd>US Educational +//! <dt>GOV <dd>US Government +//! <dt>GB <dd>Great Britain (UK) +//! <dt>UK <dd>United Kingdom +//! </dl> + + +static private mapping _from_domain=0; + +Country from_domain(string domain) +{ + if (!_from_domain) + { + _from_domain=mkmapping(countries->iso2,countries); + _from_domain|= + (["COM":_from_domain->US, + "EDU":_from_domain->US, + "MIL":_from_domain->US, + "UK":_from_domain->GB, + ]); + } + return _from_domain[upper_case(domain)]; +} + +//! method Country from_domain(string name) +//! Look up a country from its name or aka. +//! The search is case-insensitive but +//! regards whitespace and interpunctation. + +static private mapping _from_name=0; + +Country from_name(string name) +{ + if (!_from_name) + { + _from_name= + `+(@map( countries, + lambda(Country c) + { + if (c->aka && sizeof(c->aka)) + return + ([lower_case(c->name):c])+ + (mapping)map( + c->aka, + lambda(string n) + { + return ({lower_case(n),c}); + }); + else + return ([lower_case(c->name):c]); + })); + } + return _from_name[lower_case(name)]; +} + +//! method mixed `[](string what) +//! method mixed `->(string what) +//! Convenience function for getting a country +//! the name-space way; it looks up whatever it +//! is in the name- and domain-space and +//! returns that country if possible: +//! +//! <pre> +//! > Geographical.Countries.se; +//! Result: Country(Sweden) +//! > Geographical.Countries.djibouti; +//! Result: Country(Djibouti) +//! > Geographical.Countries.com; +//! Result: Country(United States) +//! > Geographical.Countries.wallis_and_futuna_islands->iso2; +//! Result: "WF" +//! </pre> + +Country|function(string:Country)|array(Country)|program + `->(string what) +{ + return + ::`[](what) || + from_domain(what)|| + from_name(what)|| + from_name(replace(what,"_"," ")); +} + +function `[] =`->; diff --git a/lib/modules/Geography.pmod/Position.pike b/lib/modules/Geography.pmod/Position.pike new file mode 100644 index 0000000000..ec360f278b --- /dev/null +++ b/lib/modules/Geography.pmod/Position.pike @@ -0,0 +1,170 @@ +//! +//! module Geographical +//! class Position +//! This class contains a geographical position, +//! ie a point on the earths surface. +//! + +//! variable float lat +//! variable float long +//! Longitude (W--E) and latitude (N--S) of the position, +//! float value in degrees. +//! Positive number is north and east, respectively. +//! Negative number is south and west, respectively. + + +float lat; // latitude in degrees (N--S) +float long; // longitude in degrees (W--E) + +//! method void create(float lat,float long) +//! method void create(string lat,string long) +//! method void create(string both) +//! Constructor for this class. +//! If feeded with strings, it will perform +//! a dwim scan on the strings. If they +//! fails to be understood, there will be an exception. + +void create(int|float|string _lat,void|int|float|string _long) +{ + if (stringp(_lat)) + { + if (zero_type(_long)) + { + string tmp; + if (sscanf(_lat,"%sN %s",tmp,_long)==2) _long=tmp+"N"; + else if (sscanf(_lat,"%sS %s",tmp,_long)==2) _long=tmp+"N"; + else if (sscanf(_lat,"%s %s",tmp,_long)==2) _long=tmp; + } + _lat=dwim(_lat,"NS"); + if (stringp(_lat)) + error("Failed to understand latitude %O\n",lat); + } + if (stringp(_long)) + { + _long=dwim(_long,"EW"); + if (stringp(_long)) + error("Failed to understand longitude %O\n",long); + } + lat=(float)_lat; + long=(float)_long; +} + +float|string dwim(string what,string direction) +{ + float d,m,s; + string dir=0; + int neg=0; +#define DIV "%*[ \t\r\n'`�\"]" + + if (sscanf(what,"-%s",what)) neg=1; + + what=upper_case(what); + + sscanf(what,"%f"DIV"%f"DIV"%f"DIV"%["+direction+"]",d,m,s,dir)==7 || + sscanf(what,"%f"DIV"%f"DIV "%["+direction+"]",d,m, dir)==5 || + sscanf(what,"%f"DIV "%["+direction+"]",d, dir); + + if (dir==direction[1..1]) neg=!neg; + + d+=m/60+s/3600; + return neg?-d:d; +} + +//! method string latitude(void|int n) +//! method string longitude(void|int n) +//! Returns the nicely formatted latitude +//! or longitude. +//! <pre> +//! n format +//! - 17�42.19'N 42�22.2'W +//! 1 17.703�N 42.37�W +//! 2 17�42.18'N 42�22.2'W +//! 3 17�42'10.4"N 42�22'12"W +//! -1 17.703 -42.37 +//! </pre> + +string prettyprint(float what,int n,string directions) +{ + if (what<0) what=-what,directions=directions[1..]; + else directions=directions[..0]; + + switch (n) + { + case -1: return sprintf("%.5g",what); + case 1: + return sprintf("%.5g�%s",what,directions); + case 3: + return sprintf("%d�%d'%.3g\"%s", + (int)floor(what),(int)floor(60*(what-floor(what))), + 3600*(what-floor(60*what)/60), + directions); + default: + return sprintf("%d�%.5g'%s", + (int)floor(what),60*(what-floor(what)), + directions); + } +} + +string latitude(void|int n) +{ + return prettyprint(lat,n,"NS"); +} + +string longitude(void|int n) +{ + return prettyprint(long,n,"EW"); +} + + +//! method array cast("array") +//! It is possible to cast the position to an array, +//! <tt>({float lat,float long})</tt>. + +string|array cast(string to) +{ + if (to[..4]=="array") + return ({lat,long}); + + if (to[..5]=="string") + return latitude()+" "+longitude(); + + error("can't cast to %O\n",to); +} + +//! method int __hash() +//! method int `==(Position pos) +//! method int `<(Position pos) +//! method int `>(Position pos) +//! These exist solely for purpose of detecting +//! equal positions, for instance when used as keys in mappings. + +int __hash() +{ + return (int)(lat*3600000+long*3600000); +} + +int `==(object pos) +{ + return (pos->lat==lat && pos->long==long); +} + +int `<(object pos) +{ + if (pos->lat>lat) return 1; + else if (pos->lat==lat && pos->long>long) return 1; + return 0; +} + +int `>(object pos) +{ + if (pos->lat<lat) return 1; + else if (pos->lat==lat && pos->long<long) return 1; + return 0; +} + +string _sprintf(int t) +{ + if (t=='O') + return "Position("+longitude()+", "+latitude()+")"; + return 0; +} -- GitLab