root/locations/json_to_struct.py

import json
# Download this url as query.json:
# https://query.wikidata.org/#SELECT%20%3Fitem%20%3FitemLabel%20%3Flocation%20%3Felevation%20%3FcountryLabel%20%3Ftzoffset%20%3Ftztype%0AWHERE%0A%7B%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%3Fitem%20p%3AP31%20%3Fstatement0.%0A%20%20%20%20%20%20%20%20%3Fstatement0%20%28ps%3AP31%2F%28wdt%3AP279%2a%29%29%20wd%3AQ1549591.%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20UNION%0A%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%3Fitem%20p%3AP31%20%3Fstatement1.%0A%20%20%20%20%20%20%20%20%3Fstatement1%20%28ps%3AP31%2F%28wdt%3AP279%2a%29%29%20wd%3AQ174844.%0A%20%20%20%20%20%20%7D%0A%20%20%0A%20%20%23%20%3Fitem%20wdt%3AP31%20wd%3AQ1549591.%0A%20%20%3Fitem%20wdt%3AP625%20%3Flocation.%0A%20%20%3Fitem%20wdt%3AP2044%20%3Felevation.%0A%20%20%3Fitem%20wdt%3AP17%20%3Fcountry.%0A%20%20%0A%20%20OPTIONAL%20%7B%0A%20%20%3Fitem%20p%3AP421%20%3Ftimezone.%0A%20%20%20%20OPTIONAL%20%7B%0A%20%20%3Ftimezone%20pq%3AP1264%20%3Ftztype.%0A%20%20%20%20%20%20%7D%0A%20%20%3Ftimezone%20ps%3AP421%20%3Ftimezonevalue.%20%0A%20%20%3Ftimezonevalue%20wdt%3AP2907%20%3Ftzoffset.%0A%20%20%7D%20%20OPTIONAL%20%7B%0A%20%20%20%20%3Fitem%20wdt%3AP131%20%3Fparent.%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%3Fparent%20p%3AP421%20%3Ftimezone.%0AOPTIONAL%20%7B%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%3Ftimezone%20pq%3AP1264%20%3Ftztype.%0A%20%20%7D%0A%20%20%20%20%3Ftimezone%20ps%3AP421%20%3Ftimezonevalue.%20%0A%20%20%20%20%3Ftimezonevalue%20wdt%3AP2907%20%3Ftzoffset.%0A%20%20%7D%0A%20%20OPTIONAL%20%7B%0A%20%20%20%20%3Fitem%20wdt%3AP131%20%3Fparent1.%0A%20%20%20%20%3Fparent1%20wdt%3AP131%20%3Fparent2.%0A%20%20%20%20%3Fparent2%20p%3AP421%20%3Ftimezone.%0A%20%20%20%20OPTIONAL%20%7B%0A%20%20%20%20%3Ftimezone%20pq%3AP1264%20%3Ftztype.%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%3Ftimezone%20ps%3AP421%20%3Ftimezonevalue.%20%0A%20%20%20%20%3Ftimezonevalue%20wdt%3AP2907%20%3Ftzoffset.%0A%20%20%7D%0A%20%20OPTIONAL%20%7B%0A%20%20%20%20%3Fitem%20wdt%3AP131%20%3Fparent1.%0A%20%20%20%20%3Fparent1%20wdt%3AP131%20%3Fparent2.%0A%20%20%20%20%3Fparent2%20wdt%3AP131%20%3Fparent3.%0A%20%20%20%20%3Fparent3%20p%3AP421%20%3Ftimezone.%0A%20%20%20%20OPTIONAL%20%7B%0A%20%20%20%20%3Ftimezone%20pq%3AP1264%20%3Ftztype.%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%3Ftimezone%20ps%3AP421%20%3Ftimezonevalue.%20%0A%20%20%20%20%3Ftimezonevalue%20wdt%3AP2907%20%3Ftzoffset.%0A%20%20%7D%0A%20%20%20%20OPTIONAL%20%7B%0A%20%20%20%20%3Fitem%20wdt%3AP131%20%3Fparent1.%0A%20%20%20%20%3Fparent1%20wdt%3AP131%20%3Fparent2.%0A%20%20%20%20%3Fparent2%20wdt%3AP131%20%3Fparent3.%0A%20%20%20%20%20%20%3Fparent3%20wdt%3AP131%20%3Fparent4.%0A%20%20%20%20%3Fparent4%20p%3AP421%20%3Ftimezone.%0A%20%20%20%20OPTIONAL%20%7B%0A%20%20%20%20%3Ftimezone%20pq%3AP1264%20%3Ftztype.%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%3Ftimezone%20ps%3AP421%20%3Ftimezonevalue.%20%0A%20%20%20%20%3Ftimezonevalue%20wdt%3AP2907%20%3Ftzoffset.%0A%20%20%7D%0A%20%20%20%20%20%20OPTIONAL%20%7B%0A%20%20%20%20%3Fitem%20wdt%3AP131%20%3Fparent1.%0A%20%20%20%20%3Fparent1%20wdt%3AP131%20%3Fparent2.%0A%20%20%20%20%3Fparent2%20wdt%3AP131%20%3Fparent3.%0A%20%20%20%20%3Fparent3%20wdt%3AP131%20%3Fparent4.%20%20%20%20%0A%20%20%20%20%3Fparent4%20wdt%3AP131%20%3Fparent5.%0A%20%20%20%20%3Fparent5%20p%3AP421%20%3Ftimezone.%0A%20%20%20%20OPTIONAL%20%7B%0A%20%20%20%20%3Ftimezone%20pq%3AP1264%20%3Ftztype.%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%3Ftimezone%20ps%3AP421%20%3Ftimezonevalue.%20%0A%20%20%20%20%3Ftimezonevalue%20wdt%3AP2907%20%3Ftzoffset.%0A%20%20%7D%0A%20%20%20%20%20%20%20%20OPTIONAL%20%7B%0A%20%20%20%20%3Fitem%20wdt%3AP131%20%3Fparent1.%0A%20%20%20%20%3Fparent1%20wdt%3AP131%20%3Fparent2.%0A%20%20%20%20%3Fparent2%20wdt%3AP131%20%3Fparent3.%0A%20%20%20%20%3Fparent3%20wdt%3AP131%20%3Fparent4.%20%20%20%20%0A%20%20%20%20%3Fparent4%20wdt%3AP131%20%3Fparent5.%0A%20%20%20%20%3Fparent5%20wdt%3AP131%20%3Fparent6.%0A%20%20%20%20%3Fparent6%20p%3AP421%20%3Ftimezone.%0A%20%20%20%20OPTIONAL%20%7B%0A%20%20%20%20%3Ftimezone%20pq%3AP1264%20%3Ftztype.%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%3Ftimezone%20ps%3AP421%20%3Ftimezonevalue.%20%0A%20%20%20%20%3Ftimezonevalue%20wdt%3AP2907%20%3Ftzoffset.%0A%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20OPTIONAL%20%7B%0A%20%20%20%20%3Fitem%20wdt%3AP131%20%3Fparent1.%0A%20%20%20%20%3Fparent1%20wdt%3AP131%20%3Fparent2.%0A%20%20%20%20%3Fparent2%20wdt%3AP131%20%3Fparent3.%0A%20%20%20%20%3Fparent3%20wdt%3AP131%20%3Fparent4.%20%20%20%20%0A%20%20%20%20%3Fparent4%20wdt%3AP131%20%3Fparent5.%0A%20%20%20%20%3Fparent5%20wdt%3AP131%20%3Fparent6.%0A%20%20%20%20%3Fparent6%20wdt%3AP131%20%3Fparent7.%0A%20%20%20%20%3Fparent7%20p%3AP421%20%3Ftimezone.%0A%20%20%20%20OPTIONAL%20%7B%0A%20%20%20%20%3Ftimezone%20pq%3AP1264%20%3Ftztype.%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%3Ftimezone%20ps%3AP421%20%3Ftimezonevalue.%20%0A%20%20%20%20%3Ftimezonevalue%20wdt%3AP2907%20%3Ftzoffset.%0A%20%20%7D%0A%20%20SERVICE%20wikibase%3Alabel%20%7B%20bd%3AserviceParam%20wikibase%3Alanguage%20%22en%2C%5BAUTO_LANGUAGE%5D%2Cmul%22.%20%7D%0A%7D

times = {
    'http://www.wikidata.org/entity/Q28195998': 'd', # Palestine Summer Time
    'http://www.wikidata.org/entity/Q21034628': 's', # Palestine Standard Time
    'http://www.wikidata.org/entity/Q10860882': 's', # winter time
    'http://www.wikidata.org/entity/Q1777301': 's',  # Standard Time
    'http://www.wikidata.org/entity/Q1311': 's',     # winter
    'http://www.wikidata.org/entity/Q1313': 'd',     # summer
    'http://www.wikidata.org/entity/Q36669': 'd',    # daylight saving time
    'http://www.wikidata.org/entity/Q161278': 'd'    # European Summer Time
}

def set_timezone(obj, value):
    if not 'tzoffset' in value:
        return obj
    tztype = times[value['tztype']] if ('tztype' in value) and (value['tztype'] in times) else '?'
    if tztype == 'd':
        obj['dtzoffset'] = value['tzoffset']
    elif tztype == 's':
        obj['stzoffset'] = value['tzoffset']
    else:
        # just guess
        if 'stzoffset' in obj and obj['stzoffset'] <= value['tzoffset']:
            obj['dtzoffset'] = value['tzoffset']
        else:
            obj['stzoffset'] = value['tzoffset']
        # print("UNKNOWN TIMEZONE TYPE {}".format(value))
    return obj

def main():
    dict = {}
    same_name = {}
    out = []
    with open("query.json") as json_file:
        data = json.load(json_file)
        # {"item":"http://www.wikidata.org/entity/Q62","itemLabel":"San Francisco","location":"Point(-122.416388888 37.7775)","elevation":"52"}
        for value in data:
            # TODO fix elevation
            key = value['item']
            if not key in dict:
                set_timezone(value, value)
                dict[key] = value
            else:
                new_value = dict[key]
                set_timezone(new_value, value)
                dict[key] = new_value
                
        # print(dict)
        # manual fixes for cities that are twice in the same country
        # TODO fix the () ones, I'm too lazy
        # Glendale (United States of America) http://www.wikidata.org/entity/Q485716 http://www.wikidata.org/entity/Q51682
        # dict['http://www.wikidata.org/entity/Q485716']['itemLabel'] = 'Glendale (CA)'
        # dict['http://www.wikidata.org/entity/Q51682']['itemLabel'] = 'Glendale (AZ)'
        # Naga (Philippines) http://www.wikidata.org/entity/Q316197 http://www.wikidata.org/entity/Q2207
        dict['http://www.wikidata.org/entity/Q316197']['itemLabel'] = 'Naga (Cebu)'
        dict['http://www.wikidata.org/entity/Q2207']['itemLabel'] = 'Naga (Camarines Sur)'
        # Springfield (United States of America) http://www.wikidata.org/entity/Q28515 http://www.wikidata.org/entity/Q135615
        dict['http://www.wikidata.org/entity/Q28515']['itemLabel'] = 'Springfield (IL)'
        dict['http://www.wikidata.org/entity/Q135615']['itemLabel'] = 'Springfield (MO)'
        dict['http://www.wikidata.org/entity/Q49158']['itemLabel'] = 'Springfield (MA)'
        # Jian (People's Republic of China) http://www.wikidata.org/entity/Q1016720 http://www.wikidata.org/entity/Q363262
        dict['http://www.wikidata.org/entity/Q1016720']['itemLabel'] = 'Ji\'an (Tonghua)'
        dict['http://www.wikidata.org/entity/Q363262']['itemLabel'] = 'Ji\'an (Jiangxi)'
        # Jubail (Saudi Arabia) http://www.wikidata.org/entity/Q12185424 http://www.wikidata.org/entity/Q27430
        dict['http://www.wikidata.org/entity/Q12185424']['itemLabel'] = 'Jubail (Al-Ahsa)'
        dict['http://www.wikidata.org/entity/Q27430']['itemLabel'] = 'Jubail'
        # Aurora (United States of America) http://www.wikidata.org/entity/Q22595 http://www.wikidata.org/entity/Q49246
        # dict['http://www.wikidata.org/entity/Q22595']['itemLabel'] = ' ()'
        # dict['http://www.wikidata.org/entity/Q49246']['itemLabel'] = ' ()'
        # Rochester (United States of America) http://www.wikidata.org/entity/Q49218 http://www.wikidata.org/entity/Q486479
        # dict['http://www.wikidata.org/entity/Q49218']['itemLabel'] =  ' ()'
        # dict['http://www.wikidata.org/entity/Q486479']['itemLabel'] = ' ()'
        # Columbia (United States of America) http://www.wikidata.org/entity/Q59670 http://www.wikidata.org/entity/Q397905
        # dict['http://www.wikidata.org/entity/Q59670']['itemLabel'] =  ' ()'
        # dict['http://www.wikidata.org/entity/Q397905']['itemLabel'] = ' ()'
        # San Cristóbal (Venezuela) http://www.wikidata.org/entity/Q167974 http://www.wikidata.org/entity/Q820235
        dict['http://www.wikidata.org/entity/Q167974']['itemLabel'] = 'San Cristóbal (Cárdenas)'
        dict['http://www.wikidata.org/entity/Q820235']['itemLabel'] = 'San Cristóbal'
        # Kansas City (United States of America) http://www.wikidata.org/entity/Q41819 http://www.wikidata.org/entity/Q486472
        # dict['http://www.wikidata.org/entity/Q41819']['itemLabel'] = ' ()'
        # dict['http://www.wikidata.org/entity/Q486472']['itemLabel'] = ' ()'
        # Columbus (United States of America) http://www.wikidata.org/entity/Q16567 http://www.wikidata.org/entity/Q239870
        # dict['http://www.wikidata.org/entity/Q16567']['itemLabel'] =  ' ()'
        # dict['http://www.wikidata.org/entity/Q239870']['itemLabel'] = ' ()'
        # Alvorada (Brazil) http://www.wikidata.org/entity/Q22060164 http://www.wikidata.org/entity/Q449593
        dict['http://www.wikidata.org/entity/Q22060164']['itemLabel'] = 'Alvorada (Tocantins)' # TODO remove, not big 8k pop
        dict['http://www.wikidata.org/entity/Q449593']['itemLabel'] = 'Alvorada'
        # Matamoros (Mexico) http://www.wikidata.org/entity/Q738353 http://www.wikidata.org/entity/Q984646
        dict['http://www.wikidata.org/entity/Q738353']['itemLabel'] = 'Matamoros (Tamaulipas)'
        dict['http://www.wikidata.org/entity/Q984646']['itemLabel'] = 'Matamoros (Coahuila)'
        # Richmond (United States of America) http://www.wikidata.org/entity/Q43421 http://www.wikidata.org/entity/Q495377
        # dict['http://www.wikidata.org/entity/Q43421']['itemLabel'] =  ' ()'
        # dict['http://www.wikidata.org/entity/Q495377']['itemLabel'] = ' ()'
        # Talisay (Philippines) http://www.wikidata.org/entity/Q316500 http://www.wikidata.org/entity/Q1027120
        dict['http://www.wikidata.org/entity/Q316500']['itemLabel'] =  'Talisay (Cebu)'
        dict['http://www.wikidata.org/entity/Q1027120']['itemLabel'] = 'Talisay'
        # Saint-Denis (France) http://www.wikidata.org/entity/Q47045 http://www.wikidata.org/entity/Q160506
        dict['http://www.wikidata.org/entity/Q47045']['itemLabel'] =  'Saint-Denis (Réunion)'
        dict['http://www.wikidata.org/entity/Q160506']['itemLabel'] = 'Saint-Denis (Île-de-France)'
        # Pasadena (United States of America) http://www.wikidata.org/entity/Q51695 http://www.wikidata.org/entity/Q485176
        # dict['http://www.wikidata.org/entity/Q51695']['itemLabel'] =  ' ()'
        # dict['http://www.wikidata.org/entity/Q485176']['itemLabel'] = ' ()'
        # San Fernando (Philippines) http://www.wikidata.org/entity/Q55740 http://www.wikidata.org/entity/Q40584
        dict['http://www.wikidata.org/entity/Q55740']['itemLabel'] = 'San Fernando (Pampanga)'
        dict['http://www.wikidata.org/entity/Q40584']['itemLabel'] = 'San Fernando (La Union)'  

        #
        # timezone missing
        #
        dict['http://www.wikidata.org/entity/Q214485']['stzoffset'] = 3.0
        dict['http://www.wikidata.org/entity/Q214485']['dtzoffset'] = 3.0
        
        # sort out double labels
        for key in dict:
            value = dict[key]
            label = value['itemLabel']
            country = value['countryLabel']
            if label in same_name:
                other_key = same_name[label]
                label = "{} ({})".format(label, country)
                dict[key]['itemLabel'] = label
                other = dict[other_key]
                if country == other['countryLabel']:
                    # print("---- {} {} {}".format(label, key, other_key))
                    pass
                if not 'appended_country_label' in other:
                    other_label = "{} ({})".format(other['itemLabel'], other['countryLabel'])
                    dict[other_key]['itemLabel'] = other_label
                    dict[other_key]['appended_country_label'] = True
                    # print("double, append the country: {}".format(label))
                else:
                    # print("tripple+, append the country: {}".format(label))
                    pass
            same_name[label] = key              

        # print the actual stuff
        for key in dict:
            value = dict[key]
            id = key[len('http://www.wikidata.org/entity/'):]
            label = value['itemLabel']
            country = value['countryLabel']
            if key in same_name:
                label = "{} ({})".format(label, country)
                print("double, append the country: {}".format(label))
                
            coords = value['location'][len("Point("):-1].split(' ')
            y = coords[0]
            x = coords[1]
            elevation = value['elevation']
            # dtzoffset = 'Some({})'.format(float(value['dtzoffset'])) if 'dtzoffset' in value else 'None'
            # tzoffset = 'Some({})'.format(float(value['stzoffset'])) if 'stzoffset' in value else 'None'
            dtzoffset = '{}'.format(float(value['dtzoffset'])) if 'dtzoffset' in value else 'None'
            tzoffset = '{}'.format(float(value['stzoffset'])) if 'stzoffset' in value else 'None'	    
            if dtzoffset == 'None' and tzoffset != 'None':
                dtzoffset = tzoffset

            out.append('Location {{label: "{}", id: "{}", coords:({},{}), elevation:{}, dtzoffset: {}, tzoffset: {} }},'.format(label, id, y, x, float(elevation), dtzoffset, tzoffset))
        out = sorted(out)
        for line in out:
            print(line)

main()