PageSourceSearch

https://www.rayama.cz/wp-content/plugins/roadbook-generator/assets/planner/region-router.js?ver=0.1.0

js rayama.cz collected 2026-09-24 14:21:28 UTC 6,659 bytes, 206 lines download raw bytes

1/* assets/planner/region-router.js */
2(function () {
3  "use strict";
4
5  function num(v) {
6    const n = Number(v);
7    return Number.isFinite(n) ? n : null;
8  }
9
10  function inBbox(lat, lng, b) {
11    if (!b) return false;
12    const minLat = num(b.minLat), maxLat = num(b.maxLat);
13    const minLng = num(b.minLng), maxLng = num(b.maxLng);
14    if (minLat === null || maxLat === null || minLng === null || maxLng === null) return false;
15    return lat >= minLat && lat <= maxLat && lng >= minLng && lng <= maxLng;
16  }
17
18  // Robustní detekce:
19  // 1) preferuj FINISH (nejčastější očekávání)
20  // 2) pak START
21  // 3) pak centroid (fallback)
22  // 4) a jako pojistka: pokud centroid nevychází, zkus "any-point match"
23  function detect(points, defaultRegion, regionBounds) {
24  try {
25    const fallback = (defaultRegion || "cee").toString();
26    const bounds = (regionBounds && typeof regionBounds === "object") ? regionBounds : {};
27    const keys = Object.keys(bounds);
28
29    if (!Array.isArray(points) || points.length < 1 || keys.length < 1) return fallback;
30
31    // --- helpers ---
32    function getLatLng(p) {
33      if (!p) return null;
34      const lat = num(p.lat);
35      const lng = num((p.lng !== undefined) ? p.lng : p.lon);
36      if (lat === null || lng === null) return null;
37      return { lat, lng };
38    }
39
40    function bboxNums(b) {
41      if (!b) return null;
42      const minLat = num(b.minLat), maxLat = num(b.maxLat);
43      const minLng = num(b.minLng), maxLng = num(b.maxLng);
44      if (minLat === null || maxLat === null || minLng === null || maxLng === null) return null;
45      return { minLat, maxLat, minLng, maxLng };
46    }
47
48    function marginInside(lat, lng, bb) {
49      // vrací >=0 pouze když je bod uvnitř; čím vyšší, tím víc "uvnitř"
50      if (lat < bb.minLat || lat > bb.maxLat || lng < bb.minLng || lng > bb.maxLng) return -1;
51      return Math.min(
52        lat - bb.minLat,
53        bb.maxLat - lat,
54        lng - bb.minLng,
55        bb.maxLng - lng
56      );
57    }
58
59    function distToBbox(lat, lng, bb) {
60      // vzdálenost bodu k obdélníku (0 pokud uvnitř)
61      const dLat = (lat < bb.minLat) ? (bb.minLat - lat) : (lat > bb.maxLat ? (lat - bb.maxLat) : 0);
62      const dLng = (lng < bb.minLng) ? (bb.minLng - lng) : (lng > bb.maxLng ? (lng - bb.maxLng) : 0);
63      return Math.hypot(dLat, dLng);
64    }
65
66    // normalizuj body
67    const pts = [];
68    for (const p of points) {
69      const ll = getLatLng(p);
70      if (ll) pts.push(ll);
71    }
72    if (!pts.length) return fallback;
73
74    // referenční bod: START = první validní bod
75    const start = pts[0];
76    const finish = pts[pts.length - 1];
77
78    // předpočítej bbox čísla
79    const bboxMap = {};
80    for (const slug of keys) {
81      const bb = bboxNums(bounds[slug]);
82      if (bb) bboxMap[String(slug)] = bb;
83    }
84    const slugs = Object.keys(bboxMap);
85    if (!slugs.length) return fallback;
86
87    // --- scoring ---
88    // váhy: START a FINISH mají větší váhu než VIA
89    // (nepřepíná to chaoticky při přidání VIA)
90    const scores = {};
91    const bestMargin = {};
92
93    function addVote(slug, weight, margin) {
94      scores[slug] = (scores[slug] || 0) + weight;
95      const m = (margin > 0 ? margin : 0);
96      bestMargin[slug] = Math.max(bestMargin[slug] || 0, m);
97      // malé zvýhodnění "hloubky uvnitř" (aby v překryvu nevyhrál region jen pořadím)
98      scores[slug] += m * 0.01;
99    }
100
101    // START (váha 3)
102    for (const slug of slugs) {
103      const bb = bboxMap[slug];
104      const m = marginInside(start.lat, start.lng, bb);
105      if (m >= 0) addVote(slug, 3, m);
106    }
107
108    // FINISH (váha 3)
109    if (finish && (finish.lat !== start.lat || finish.lng !== start.lng)) {
110      for (const slug of slugs) {
111        const bb = bboxMap[slug];
112        const m = marginInside(finish.lat, finish.lng, bb);
113        if (m >= 0) addVote(slug, 3, m);
114      }
115    }
116
117    // VIA body (váha 1)
118    if (pts.length > 2) {
119      for (let i = 1; i < pts.length - 1; i++) {
120        const p = pts[i];
121        for (const slug of slugs) {
122          const bb = bboxMap[slug];
123          const m = marginInside(p.lat, p.lng, bb);
124          if (m >= 0) addVote(slug, 1, m);
125        }
126      }
127    }
128
129    // 1) pokud máme alespoň jeden hit, vyber nejlepší score
130    let bestSlug = null;
131    let bestScore = -Infinity;
132    for (const slug of slugs) {
133      const s = (scores[slug] !== undefined) ? scores[slug] : -Infinity;
134      if (s > bestScore) {
135        bestScore = s;
136        bestSlug = slug;
137      }
138    }
139    if (bestSlug && Number.isFinite(bestScore) && bestScore > -Infinity) {
140      // pokud vůbec nebyl žádný bod uvnitř žádného bboxu, score zůstane -Infinity
141      if (scores[bestSlug] !== undefined) return bestSlug;
142    }
143
144    // 2) pojistka proti "hluchému místu": vyber nejbližší bbox podle START
145    let nearest = null;
146    let nearestD = Infinity;
147    for (const slug of slugs) {
148      const d = distToBbox(start.lat, start.lng, bboxMap[slug]);
149      if (d < nearestD) {
150        nearestD = d;
151        nearest = slug;
152      }
153    }
154    return nearest || fallback;
155  } catch (e) {
156    return (defaultRegion || "cee").toString();
157  }
158}
159
160function detectWithMeta(points, defaultRegion, regionBounds) {
161  const primary = detect(points, defaultRegion, regionBounds);
162
163  // zjisti, zda je START uvnitř alespoň jednoho bboxu
164  let inCoverage = false;
165  let start = null;
166
167  if (Array.isArray(points) && points.length) {
168    for (const p of points) {
169      if (!p) continue;
170      const lat = num(p.lat);
171      const lng = num((p.lng !== undefined) ? p.lng : p.lon);
172      if (lat !== null && lng !== null) {
173        start = { lat, lng };
174        break;
175      }
176    }
177  }
178
179  if (start) {
180    for (const slug in regionBounds) {
181      const b = regionBounds[slug];
182      const minLat = num(b.minLat), maxLat = num(b.maxLat);
183      const minLng = num(b.minLng), maxLng = num(b.maxLng);
184      if (
185        minLat !== null && maxLat !== null &&
186        minLng !== null && maxLng !== null &&
187        start.lat >= minLat && start.lat <= maxLat &&
188        start.lng >= minLng && start.lng <= maxLng
189      ) {
190        inCoverage = true;
191        break;
192      }
193    }
194  }
195
196  return {
197    primary: primary,
198    inCoverage: inCoverage
199  };
200}
201
202  window.RBG_REGION_ROUTER = window.RBG_REGION_ROUTER || {};
203  window.RBG_REGION_ROUTER.detect = detect;
204  window.RBG_REGION_ROUTER.detectWithMeta = detectWithMeta;
205
206})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.