# -*- coding: utf-8 -*-
"""M2 Bab 3: membandingkan rute dan area layanan QGIS dengan pgRouting memakai titik awal dan akhir yang SAMA (tepat di simpul).
Penulis: Badar Mubarok Yogaswara. Syarat: m2_03b_pgrouting.sql sudah dijalankan; variabel PGHOST, PGPORT, PGUSER, PGDATABASE terisi.
Pemakaian: python-qgis.bat m2_03c_silang_jaringan.py <folder paket-m2>"""
import os
import sys
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
import _inisialisasi  # noqa: F401
import processing
import psycopg2
from qgis.core import QgsVectorLayer

paket = sys.argv[1]
con = psycopg2.connect(dbname=os.environ["PGDATABASE"])
cur = con.cursor()


def simpul(vid):
    cur.execute("SELECT ST_X(geom), ST_Y(geom) FROM kph.jalan_simpul WHERE id = %s", (vid,))
    x, y = cur.fetchone()
    return "%.3f,%.3f [EPSG:32749]" % (x, y)


jalan_buka = QgsVectorLayer(os.path.join(paket, "Jalan.gpkg|layername=Jalan|subset=status<>'ditutup'"), "j", "ogr")
a, b = simpul(5), simpul(24)                       # simpul terdekat Pos Jaga 1 dan Pos Jaga 4 (lihat keluaran 03b)


def qgis_rute(strategi):
    return processing.run("native:shortestpathpointtopoint", {
        "INPUT": jalan_buka, "STRATEGY": strategi, "DIRECTION_FIELD": "", "VALUE_FORWARD": "", "VALUE_BACKWARD": "", "VALUE_BOTH": "",
        "DEFAULT_DIRECTION": 2, "SPEED_FIELD": "kecepatan_kmj", "DEFAULT_SPEED": 20, "TOLERANCE": 0,
        "START_POINT": a, "END_POINT": b, "OUTPUT": "memory:"})["TRAVEL_COST"]


cur.execute("""SELECT MAX(agg_cost) FROM pgr_dijkstra('SELECT id, source, target, panjang_m AS cost FROM kph.jalan_ruas WHERE status <> ''ditutup''', 5, 24, false)""")
pg_m = cur.fetchone()[0]
cur.execute("""SELECT MAX(agg_cost) FROM pgr_dijkstra('SELECT id, source, target, waktu_dtk AS cost FROM kph.jalan_ruas WHERE status <> ''ditutup''', 5, 24, false)""")
pg_dtk = cur.fetchone()[0]
q_m, q_jam = qgis_rute(0), qgis_rute(1)
print("terpendek : QGIS %.2f m | pgRouting %.2f m | selisih %.4f" % (q_m, pg_m, abs(q_m - pg_m)))
print("tercepat  : QGIS %.3f menit | pgRouting %.3f menit" % (q_jam * 60, pg_dtk / 60))

# area layanan: simpul persimpangan yang terjangkau
cur.execute("SELECT ST_X(geom), ST_Y(geom), id FROM kph.jalan_simpul")
persimpangan = {(round(x, 1), round(y, 1)): i for x, y, i in cur.fetchall()}
cur.execute("SELECT ST_X(geom), ST_Y(geom) FROM kph.jalan_simpul WHERE id = 11")
kx, ky = cur.fetchone()
for batas in (500, 1000):
    h = processing.run("native:serviceareafrompoint", {
        "INPUT": jalan_buka, "STRATEGY": 0, "DIRECTION_FIELD": "", "VALUE_FORWARD": "", "VALUE_BACKWARD": "", "VALUE_BOTH": "",
        "DEFAULT_DIRECTION": 2, "SPEED_FIELD": "", "DEFAULT_SPEED": 50, "TOLERANCE": 0, "START_POINT": "%.3f,%.3f [EPSG:32749]" % (kx, ky),
        "TRAVEL_COST": batas, "INCLUDE_BOUNDS": True, "OUTPUT": "memory:"})["OUTPUT"]
    dalam = set()
    for f in h.getFeatures():
        if f["type"] == "within":
            g = f.geometry()
            for p in (g.asMultiPoint() if g.isMultipart() else [g.asPoint()]):
                k = (round(p.x(), 1), round(p.y(), 1))
                if k in persimpangan:
                    dalam.add(persimpangan[k])
    cur.execute("""SELECT COUNT(*) FROM pgr_drivingDistance('SELECT id, source, target, panjang_m AS cost FROM kph.jalan_ruas WHERE status <> ''ditutup''', 11, %s::float, false)""", (batas,))
    print("area layanan %4d m: persimpangan terjangkau QGIS %d | pgRouting %d" % (batas, len(dalam), cur.fetchone()[0]))
