# -*- coding: utf-8 -*-
"""用 OSRM（OpenStreetMap 路由）算「小区 -> 网点」的驾车实际行驶距离与时间，写入 geodb.json 的 drive 字段。"""
import io, json, time, urllib.request

GEO = r"D:\workbbbbbb\build\geodb.json"
BASE = 'https://router.project-osrm.org/table/v1/driving/'
CHUNK = 80
SLEEP = 1.2

OPENER = urllib.request.build_opener(urllib.request.ProxyHandler({}))


def fetch(coords):
    cs = ';'.join('%.6f,%.6f' % (a[0], a[1]) for a in coords)
    dst = ';'.join(str(i) for i in range(1, len(coords)))
    url = (BASE + cs + '?sources=0&destinations=' + dst +
           '&annotations=distance,duration')
    req = urllib.request.Request(url, headers={'User-Agent': 'paiban-tool/1.0'})
    with OPENER.open(req, timeout=45) as r:
        return json.loads(r.read().decode('utf-8'))


def main():
    db = json.load(io.open(GEO, encoding='utf-8'))
    homes = db['homes']
    orgs = db['orgs']
    print('homes=%d orgs=%d' % (len(homes), len(orgs)))

    drive = {}
    driveMin = {}
    found = 0
    miss = 0
    reqs = 0
    for hi, h in enumerate(homes):
        hc = (h['lng'], h['lat'])
        dm = {}
        dn = {}
        for i in range(0, len(orgs), CHUNK):
            part = orgs[i:i + CHUNK]
            coords = [hc] + [(o['lng'], o['lat']) for o in part]
            try:
                js = fetch(coords)
            except Exception as e:
                print('  REQ FAIL home=%s part=%d %s' % (h['n'], i, e))
                miss += len(part)
                time.sleep(3)
                continue
            reqs += 1
            dist = (js.get('distances') or [[None]])[0]
            dur = (js.get('durations') or [[None]])[0]
            # sources=0、destinations=1..N 时，返回矩阵只有 N 列，第 k 列就是 coords[k+1]
            for k, o in enumerate(part):
                d = dist[k] if k < len(dist) else None
                t = dur[k] if k < len(dur) else None
                if d is None:
                    miss += 1
                    continue
                dm[o['c']] = round(d / 1000.0, 1)
                if t is not None:
                    dn[o['c']] = int(round(t / 60.0))
                found += 1
            time.sleep(SLEEP)
        drive[h['n']] = dm
        driveMin[h['n']] = dn
        print('  home %d/%d %s -> %d 条' % (hi + 1, len(homes), h['n'], len(dm)))

    db['drive'] = drive
    db['driveMin'] = driveMin
    db['driveMeta'] = {
        'source': 'OSRM /table/v1/driving（OpenStreetMap 路网，驾车实际路径）',
        'requests': reqs,
        'pairs': found,
        'miss': miss,
        'builtAt': time.strftime('%Y-%m-%d %H:%M:%S'),
    }
    io.open(GEO, 'w', encoding='utf-8').write(
        json.dumps(db, ensure_ascii=False, separators=(',', ':')))
    print('DONE pairs=%d miss=%d reqs=%d' % (found, miss, reqs))
    # 抽查
    for nm in ['桦枫居', '孙银刚']:
        pass
    hm = '桦枫居'
    if hm in drive:
        for code in ['T710950000', 'T710630000']:
            print('  %s -> %s = %s km / %s min' % (hm, code, drive[hm].get(code), driveMin[hm].get(code)))


main()
