1 parent
ebdbee71db
commit
f748330a1b
6 files changed
+26454
-32
No files matched your search
@@ -598,6 +598,8 @@ function openCheckpointModal(mode, data = null) {
|
|||||||
it.item_time || "",
|
it.item_time || "",
|
||||||
it.duration || 1,
|
it.duration || 1,
|
||||||
it.expense_context || "local",
|
it.expense_context || "local",
|
||||||
|
it.lat || "",
|
||||||
|
it.lng || "",
|
||||||
);
|
);
|
||||||
visibleCount++;
|
visibleCount++;
|
||||||
}
|
}
|
||||||
@@ -792,49 +794,128 @@ function addCpExpenseLine(
|
|||||||
itemTime = "",
|
itemTime = "",
|
||||||
itemDur = 1,
|
itemDur = 1,
|
||||||
expenseContext = "local",
|
expenseContext = "local",
|
||||||
|
itemLat = "",
|
||||||
|
itemLng = "",
|
||||||
) {
|
) {
|
||||||
const container = document.getElementById("cpExpensesContainer");
|
const container = document.getElementById("cpExpensesContainer");
|
||||||
const div = document.createElement("div");
|
const div = document.createElement("div");
|
||||||
div.className = "hol-form-row";
|
div.className = "hol-form-row";
|
||||||
const isChecked = isPaid == 1 ? "checked" : "";
|
const isChecked = isPaid == 1 ? "checked" : "";
|
||||||
|
|
||||||
// 💡 Nouveaux types (Les valeurs à 0 par défaut pour les visites gratuites)
|
const pinBtnStyle =
|
||||||
let defaultAmount = amount;
|
itemLat && itemLng
|
||||||
if (category === "visit_free" && amount === "") defaultAmount = "0.00";
|
? "background:var(--success);color:white;border-color:var(--success);"
|
||||||
|
: "";
|
||||||
|
|
||||||
div.innerHTML = `
|
div.innerHTML = `
|
||||||
<div class="hol-form-inner">
|
<div class="hol-form-inner">
|
||||||
<select name="items[cat][]" class="pf-input hol-form-select" style="width:55px; padding:6px; font-size:1.1rem;" title="Catégorie">
|
<select name="items[cat][]" class="pf-input hol-form-select">
|
||||||
<option value="accommodation" ${category === "accommodation" ? "selected" : ""}>🏨</option>
|
<option value="accommodation" ${category === "accommodation" ? "selected" : ""}>🏨</option>
|
||||||
<option value="transport" ${category === "transport" ? "selected" : ""}>🚗</option>
|
<option value="transport" ${category === "transport" ? "selected" : ""}>🚗</option>
|
||||||
<option value="food" ${category === "food" ? "selected" : ""}>🍽️</option>
|
|
||||||
<option value="activity" ${category === "activity" ? "selected" : ""}>🎫</option>
|
<option value="activity" ${category === "activity" ? "selected" : ""}>🎫</option>
|
||||||
<option value="visit_free" ${category === "visit_free" ? "selected" : ""}>🏞️</option>
|
|
||||||
<option value="other" ${category === "other" ? "selected" : ""}>🛍️</option>
|
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<input type="hidden" name="items[context][]" value="${expenseContext}">
|
<input type="hidden" name="items[context][]" value="${expenseContext}">
|
||||||
<input type="text" name="items[name][]" class="pf-input hol-form-text" placeholder="Description (Ex: Musée, Restaurant...)" value="${name}">
|
<input type="text" name="items[name][]" class="pf-input hol-form-text" placeholder="${tr("hdl_js_ph_expense_name")}" value="${name}">
|
||||||
<input type="number" step="0.01" name="items[amount][]" class="pf-input hol-form-number" placeholder="0.00" value="${defaultAmount}">
|
|
||||||
|
<button type="button" class="btn-icon-action" style="width:28px;height:28px;display:flex;align-items:center;justify-content:center;border:1px solid var(--border-light);border-radius:6px;${pinBtnStyle}" onclick="toggleItemSearch(this)" title="Adresse précise">📍</button>
|
||||||
|
|
||||||
|
<input type="number" step="0.01" name="items[amount][]" class="pf-input hol-form-number" placeholder="0.00" value="${amount}">
|
||||||
|
|
||||||
<label class="hol-form-paid-label" title="${tr("hdl_paid")}">
|
<label class="hol-form-paid-label" title="${tr("hdl_paid")}">
|
||||||
<input type="checkbox" ${isChecked} onchange="this.nextElementSibling.value = this.checked ? 1 : 0" style="accent-color:var(--success); width:16px; height:16px;">
|
<input type="checkbox" ${isChecked} onchange="this.nextElementSibling.value = this.checked ? 1 : 0">
|
||||||
<input type="hidden" name="items[paid][]" value="${isPaid}">
|
<input type="hidden" name="items[paid][]" value="${isPaid}">
|
||||||
<span class="hol-form-paid-text" style="display:none;">${tr("hdl_paid")}</span>
|
<span class="hol-form-paid-text">${tr("hdl_paid")}</span>
|
||||||
</label>
|
</label>
|
||||||
<button type="button" class="btn-icon-action delete btn-remove-expense" onclick="this.parentElement.parentElement.remove()" title="${tr("btn_delete")}">🗑️</button>
|
<button type="button" class="btn-icon-action delete btn-remove-expense" onclick="this.parentElement.parentElement.remove()" title="${tr("btn_delete")}">🗑️</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="hol-form-subrow" style="padding-left:0; margin-top:4px;">
|
|
||||||
<input type="text" name="items[notes][]" class="pf-input hol-form-notes-input hol-form-notes-full" placeholder="🔗 Réservation ou notes..." value="${notes}" style="margin-left:0; width:100%; border-radius:6px;">
|
<div class="hol-item-search-box" style="display:none; padding: 10px; background: var(--bg-subtle); border-radius: 8px; margin-top: 6px; width: 100%;">
|
||||||
|
<div style="display:flex; gap:10px;">
|
||||||
|
<input type="text" class="pf-input item-search-input" placeholder="Chercher une adresse..." onkeypress="if(event.key === 'Enter') { searchItemPlace(this); return false; }">
|
||||||
|
<button type="button" class="pf-btn btn-secondary" onclick="searchItemPlace(this)">🔍</button>
|
||||||
|
</div>
|
||||||
|
<div class="item-search-results" style="margin-top:10px; max-height:150px; overflow-y:auto;"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="hol-form-subrow">
|
||||||
|
<input type="text" name="items[notes][]" class="pf-input hol-form-notes-input hol-form-notes-full" placeholder="${tr("hdl_ph_notes")}" value="${notes}">
|
||||||
</div>
|
</div>
|
||||||
<input type="hidden" name="items[id][]" value="${itemId}">
|
<input type="hidden" name="items[id][]" value="${itemId}">
|
||||||
<input type="hidden" name="items[date][]" value="${itemDate}">
|
<input type="hidden" name="items[date][]" value="${itemDate}">
|
||||||
<input type="hidden" name="items[time][]" value="${itemTime}">
|
<input type="hidden" name="items[time][]" value="${itemTime}">
|
||||||
<input type="hidden" name="items[duration][]" value="${itemDur}">
|
<input type="hidden" name="items[duration][]" value="${itemDur}">
|
||||||
|
<input type="hidden" name="items[lat][]" value="${itemLat}">
|
||||||
|
<input type="hidden" name="items[lng][]" value="${itemLng}">
|
||||||
`;
|
`;
|
||||||
container.appendChild(div);
|
container.appendChild(div);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function toggleItemSearch(btn) {
|
||||||
|
const searchBox = btn
|
||||||
|
.closest(".hol-form-row")
|
||||||
|
.querySelector(".hol-item-search-box");
|
||||||
|
searchBox.style.display =
|
||||||
|
searchBox.style.display === "none" ? "block" : "none";
|
||||||
|
}
|
||||||
|
|
||||||
|
function searchItemPlace(btn) {
|
||||||
|
const container = btn.closest(".hol-item-search-box");
|
||||||
|
const input = container.querySelector(".item-search-input");
|
||||||
|
const resultsDiv = container.querySelector(".item-search-results");
|
||||||
|
const q = input.value.trim();
|
||||||
|
if (q.length < 3) return;
|
||||||
|
|
||||||
|
resultsDiv.innerHTML = `<span style="color:#64748b; font-size:0.85rem;">Recherche en cours...</span>`;
|
||||||
|
|
||||||
|
fetch(
|
||||||
|
"/modules/holidays/includes/api/geocode.php?limit=5&q=" +
|
||||||
|
encodeURIComponent(q),
|
||||||
|
)
|
||||||
|
.then((res) => res.json())
|
||||||
|
.then((data) => {
|
||||||
|
resultsDiv.innerHTML = "";
|
||||||
|
if (data.error || !data.results || data.results.length === 0) {
|
||||||
|
resultsDiv.innerHTML = `<span style="color:#ef4444; font-size:0.85rem;">Aucun résultat</span>`;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
data.results.forEach((place) => {
|
||||||
|
const b = document.createElement("button");
|
||||||
|
b.type = "button";
|
||||||
|
b.className = "pf-btn btn-secondary";
|
||||||
|
b.style.textAlign = "left";
|
||||||
|
b.style.padding = "8px";
|
||||||
|
b.style.marginBottom = "4px";
|
||||||
|
b.style.width = "100%";
|
||||||
|
b.innerText = "📍 " + place.display_name;
|
||||||
|
b.onclick = () =>
|
||||||
|
selectItemPlace(container, place.lat, place.lng, place.display_name);
|
||||||
|
resultsDiv.appendChild(b);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
resultsDiv.innerHTML = `<span style="color:#ef4444; font-size:0.85rem;">Erreur de connexion</span>`;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function selectItemPlace(container, lat, lng, displayName) {
|
||||||
|
const row = container.closest(".hol-form-row");
|
||||||
|
row.querySelector('input[name="items[lat][]"]').value = lat;
|
||||||
|
row.querySelector('input[name="items[lng][]"]').value = lng;
|
||||||
|
|
||||||
|
const notesInput = row.querySelector('input[name="items[notes][]"]');
|
||||||
|
if (notesInput.value === "") {
|
||||||
|
notesInput.value = displayName;
|
||||||
|
}
|
||||||
|
|
||||||
|
container.style.display = "none";
|
||||||
|
const pinBtn = row.querySelector('button[title="Adresse précise"]');
|
||||||
|
if (pinBtn) {
|
||||||
|
pinBtn.style.background = "var(--success)";
|
||||||
|
pinBtn.style.color = "white";
|
||||||
|
pinBtn.style.borderColor = "var(--success)";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function deleteCheckpoint() {
|
function deleteCheckpoint() {
|
||||||
if (!confirm(tr("hdl_js_confirm_del_step"))) return;
|
if (!confirm(tr("hdl_js_confirm_del_step"))) return;
|
||||||
const form = document.getElementById("formCheckpoint");
|
const form = document.getElementById("formCheckpoint");
|
||||||
|
|||||||
@@ -170,7 +170,11 @@ if ($holiday_id > 0 && !empty($location_name)) {
|
|||||||
$dur = !empty($_POST['items']['duration'][$i]) ? (int)$_POST['items']['duration'][$i] : 1;
|
$dur = !empty($_POST['items']['duration'][$i]) ? (int)$_POST['items']['duration'][$i] : 1;
|
||||||
$context = !empty($_POST['items']['context'][$i]) ? $_POST['items']['context'][$i] : 'local';
|
$context = !empty($_POST['items']['context'][$i]) ? $_POST['items']['context'][$i] : 'local';
|
||||||
|
|
||||||
$stmt->execute([$holiday_id, $cat, $name, $amount, $paid, $location_name, $lat, $lng, $target_order, $note, $date, $time, $step_start, $step_end, $dur, $step_type, $context]);
|
// Récupération des coordonnées spécifiques à l'activité (ou fallback sur l'étape)
|
||||||
|
$itemLat = !empty($_POST['items']['lat'][$i]) ? (float)$_POST['items']['lat'][$i] : $lat;
|
||||||
|
$itemLng = !empty($_POST['items']['lng'][$i]) ? (float)$_POST['items']['lng'][$i] : $lng;
|
||||||
|
|
||||||
|
$stmt->execute([$holiday_id, $cat, $name, $amount, $paid, $location_name, $itemLat, $itemLng, $target_order, $note, $date, $time, $step_start, $step_end, $dur, $step_type, $context]);
|
||||||
$validItemsCount++;
|
$validItemsCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -292,15 +292,32 @@ $pctSaved = $cost > 0 ? min(100 - $pctPaid, ($saved / $cost) * 100) : 0;
|
|||||||
if ($it['name'] === 'PF_TECHNICAL_POINT') continue;
|
if ($it['name'] === 'PF_TECHNICAL_POINT') continue;
|
||||||
$visibleItemsCount++;
|
$visibleItemsCount++;
|
||||||
$icon = match($it['category']) { 'transport' => '🚗', 'accommodation' => '🏨', 'activity' => '🎫', default => '🏷️' };
|
$icon = match($it['category']) { 'transport' => '🚗', 'accommodation' => '🏨', 'activity' => '🎫', default => '🏷️' };
|
||||||
|
|
||||||
|
// On vérifie si l'activité possède ses propres coordonnées GPS
|
||||||
|
$hasCustomGps = (!empty($it['lat']) && !empty($it['lng']) && ((float)$it['lat'] !== (float)$step['lat'] || (float)$it['lng'] !== (float)$step['lng']));
|
||||||
?>
|
?>
|
||||||
<div class="hol-expense-wrapper">
|
<div class="hol-expense-wrapper">
|
||||||
<div class="hol-expense-main">
|
<div class="hol-expense-main">
|
||||||
<span class="hol-expense-name"><?= $icon ?> <?= htmlspecialchars($it['name']) ?></span>
|
<span class="hol-expense-name">
|
||||||
|
<?= $icon ?>
|
||||||
|
<?php if ($hasCustomGps): ?>
|
||||||
|
<span onclick="openGpsModal(<?= $it['lat'] ?>, <?= $it['lng'] ?>)" style="cursor:pointer; color:var(--primary); text-decoration:underline; font-weight:600;" title="Y aller (GPS)">
|
||||||
|
<?= htmlspecialchars($it['name']) ?>
|
||||||
|
</span>
|
||||||
|
<?php else: ?>
|
||||||
|
<?= htmlspecialchars($it['name']) ?>
|
||||||
|
<?php endif; ?>
|
||||||
|
</span>
|
||||||
<span>
|
<span>
|
||||||
<strong class="hol-expense-amount"><?= number_format($it['amount'], 2, ',', ' ') ?> €</strong>
|
<strong class="hol-expense-amount"><?= number_format($it['amount'], 2, ',', ' ') ?> €</strong>
|
||||||
<span class="<?= $it['is_paid'] ? 'status-paid' : 'status-pending' ?>" title="<?= $it['is_paid'] ? tr('hdl_paid') : tr('hdl_to_pay') ?>"><?= $it['is_paid'] ? '✓' : '⏳' ?></span>
|
<span class="<?= $it['is_paid'] ? 'status-paid' : 'status-pending' ?>" title="<?= $it['is_paid'] ? tr('hdl_paid') : tr('hdl_to_pay') ?>"><?= $it['is_paid'] ? '✓' : '⏳' ?></span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
<?php if (!empty($it['notes'])): ?>
|
||||||
|
<div class="hol-expense-note" style="font-size: 0.75rem; color: var(--text-muted); margin-top: 2px;">
|
||||||
|
<?= htmlspecialchars($it['notes']) ?>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
|
|
||||||
|
|||||||
+5
-15
@@ -26,33 +26,23 @@ $stops = $params['stops'];
|
|||||||
$fuelL100 = (float)($params['fuel_l100'] ?? 7);
|
$fuelL100 = (float)($params['fuel_l100'] ?? 7);
|
||||||
$fuelPrice= (float)($params['fuel_price'] ?? 1.85);
|
$fuelPrice= (float)($params['fuel_price'] ?? 1.85);
|
||||||
|
|
||||||
// --- Load databases ---
|
// --- Load pre-indexed PHP database ---
|
||||||
$tollsPath = __DIR__ . '/data/tolls.json';
|
$tollsDataPath = __DIR__ . '/data/tolls.data.php';
|
||||||
$gpsPath = __DIR__ . '/data/toll_gps.json';
|
$gpsPath = __DIR__ . '/data/toll_gps.json';
|
||||||
|
|
||||||
if (!file_exists($tollsPath)) {
|
if (!file_exists($tollsDataPath)) {
|
||||||
echo json_encode(['ok' => false, 'error' => 'Base de péages introuvable']);
|
echo json_encode(['ok' => false, 'error' => 'Base de péages introuvable']);
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
$tollsRaw = json_decode(file_get_contents($tollsPath), true);
|
// Grâce à OPcache, le fichier est exécuté et stocké en RAM partagée
|
||||||
$tollData = $tollsRaw['data'] ?? [];
|
$tollIndex = require $tollsDataPath;
|
||||||
|
|
||||||
$gpsData = [];
|
$gpsData = [];
|
||||||
if (file_exists($gpsPath)) {
|
if (file_exists($gpsPath)) {
|
||||||
$gpsData = json_decode(file_get_contents($gpsPath), true) ?? [];
|
$gpsData = json_decode(file_get_contents($gpsPath), true) ?? [];
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Build lookup index: [op][entry][exit] => c1_price ---
|
|
||||||
$tollIndex = [];
|
|
||||||
foreach ($tollData as $row) {
|
|
||||||
$op = $row['op'];
|
|
||||||
$e = $row['e'];
|
|
||||||
$x = $row['x'];
|
|
||||||
$c1 = (float)$row['c1'];
|
|
||||||
$tollIndex[$op][$e][$x] = $c1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- Helper: great-circle distance (km) ---
|
// --- Helper: great-circle distance (km) ---
|
||||||
function haversine(float $lat1, float $lng1, float $lat2, float $lng2): float {
|
function haversine(float $lat1, float $lng1, float $lat2, float $lng2): float {
|
||||||
$R = 6371.0;
|
$R = 6371.0;
|
||||||
|
|||||||
File diff suppressed because it is too large.
Load diff
@@ -1 +0,0 @@
|
|||||||
{"generated":"2026-02-01","stats":{"APRR":20964,"AREA":674,"COFIROUTE":1296,"SANEF":1620,"SAPN":126},"data":[{"op":"APRR","e":"ALLAINES","x":"AMBERIEU","c1":58.2,"c2":89.1,"c3":143.0,"c4":190.7,"c5":32.8},{"op":"APRR","e":"ALLAINES","x":"ARLAY","c1":52.3,"c2":80.9,"c3":131.7,"c4":173.9,"c5":29.1},{"op":"APRR","e":"ALLAINES","x":"AUXERRE NORD","c1":30.1,"c2":45.5,"c3":75.3,"c4":96.7,"c5":15.6},{"op":"APRR","e":"ALLAINES","x":"AUXERRE SUD","c1":30.1,"c2":45.5,"c3":75.3,"c4":96.7,"c5":15.6},{"op":"APRR","e":"ALLAINES","x":"AVALLON","c1":34.3,"c2":52.2,"c3":86.3,"c4":112.4,"c5":18.5},{"op":"APRR","e":"ALLAINES","x":"BALAN","c1":59.1,"c2":91.2,"c3":145.8,"c4":194.0,"c5":33.4},{"op":"APRR","e":"ALLAINES","x":"BAUME-LES-DAMES","c1":55.4,"c2":85.6,"c3":138.1,"c4":184.1,"c5":31.3},{"op":"APRR","e":"ALLAINES","x":"BEAUNE NORD","c1":42.8,"c2":66.0,"c3":107.1,"c4":140.1,"c5":23.6},{"op":"APRR","e":"ALLAINES","x":"BEAUNE SUD","c1":44.1,"c2":67.5,"c3":109.7,"c4":144.2,"c5":24.2},{"op":"APRR","e":"ALLAINES","x":"BEAUPONT","c1":55.6,"c2":86.1,"c3":139.6,"c4":185.5,"c5":31.6},{"op":"APRR","e":"ALLAINES","x":"BEAUREPAIRE","c1":53.5,"c2":82.6,"c3":133.8,"c4":178.4,"c5":29.8},{"op":"APRR","e":"ALLAINES","x":"BELLEVILLE S/SAONE","c1":53.6,"c2":82.5,"c3":132.4,"c4":176.0,"c5":29.8},{"op":"APRR","e":"ALLAINES","x":"BERSAILLIN","c1":52.1,"c2":79.4,"c3":130.2,"c4":172.2,"c5":29.0},{"op":"APRR","e":"ALLAINES","x":"BESANCON EST","c1":52.6,"c2":82.0,"c3":132.6,"c4":176.7,"c5":29.6},{"op":"APRR","e":"ALLAINES","x":"BESANCON NORD","c1":52.6,"c2":80.9,"c3":131.0,"c4":173.7,"c5":29.2},{"op":"APRR","e":"ALLAINES","x":"BESANCON OUEST","c1":52.6,"c2":80.3,"c3":130.5,"c4":172.6,"c5":29.1},{"op":"APRR","e":"ALLAINES","x":"BEYNOST","c1":61.6,"c2":95.3,"c3":152.0,"c4":203.0,"c5":35.4},{"op":"APRR","e":"ALLAINES","x":"BIERRE-LES-SEMUR","c1":36.4,"c2":55.1,"c3":90.9,"c4":118.7,"c5":19.7},{"op":"APRR","e":"ALLAINES","x":"BOURG NORD","c1":53.8,"c2":83.0,"c3":132.6,"c4":176.7,"c5":30.2},{"op":"APRR","e":"ALLAINES","x":"BOURG SUD","c1":55.1,"c2":85.3,"c3":136.7,"c4":181.9,"c5":31.6},{"op":"APRR","e":"ALLAINES","x":"BULGNEVILLE","c1":47.1,"c2":72.3,"c3":116.4,"c4":155.0,"c5":25.8},{"op":"APRR","e":"ALLAINES","x":"CHALON CENTRE","c1":46.5,"c2":71.7,"c3":114.7,"c4":151.6,"c5":25.5},{"op":"APRR","e":"ALLAINES","x":"CHALON NORD","c1":46.5,"c2":71.7,"c3":114.7,"c4":151.6,"c5":25.5},{"op":"APRR","e":"ALLAINES","x":"CHALON SUD","c1":46.5,"c2":71.7,"c3":114.7,"c4":151.6,"c5":25.5},{"op":"APRR","e":"ALLAINES","x":"CHATENOIS","c1":47.7,"c2":73.0,"c3":118.2,"c4":157.0,"c5":26.4},{"op":"APRR","e":"ALLAINES","x":"CHATILLON-LABORDE","c1":33.4,"c2":50.8,"c3":83.2,"c4":108.1,"c5":18.0},{"op":"APRR","e":"ALLAINES","x":"CHAUMONT-SEMOUTIERS","c1":40.1,"c2":61.1,"c3":100.1,"c4":131.6,"c5":21.7},{"op":"APRR","e":"ALLAINES","x":"CHOISEY","c1":48.9,"c2":74.6,"c3":121.6,"c4":160.9,"c5":26.9},{"op":"APRR","e":"ALLAINES","x":"COLOMBEY-LES-BELLES","c1":50.5,"c2":76.9,"c3":124.6,"c4":166.7,"c5":27.7},{"op":"APRR","e":"ALLAINES","x":"COMBRONDE","c1":32.5,"c2":50.8,"c3":79.2,"c4":106.8,"c5":19.4},{"op":"APRR","e":"ALLAINES","x":"COURTENAY","c1":25.6,"c2":38.6,"c3":64.4,"c4":81.7,"c5":13.1},{"op":"APRR","e":"ALLAINES","x":"DIJON SUD","c1":46.7,"c2":72.1,"c3":116.0,"c4":153.2,"c5":25.6},{"op":"APRR","e":"ALLAINES","x":"DIJON-ARC S/TILLE","c1":48.4,"c2":74.5,"c3":119.9,"c4":158.6,"c5":26.7},{"op":"APRR","e":"ALLAINES","x":"DIJON-CRIMOLOIS","c1":47.7,"c2":72.7,"c3":118.7,"c4":156.0,"c5":26.4},{"op":"APRR","e":"ALLAINES","x":"DOLE","c1":48.9,"c2":74.6,"c3":121.6,"c4":160.9,"c5":26.9},{"op":"APRR","e":"ALLAINES","x":"FEILLENS","c1":51.2,"c2":79.0,"c3":127.7,"c4":169.8,"c5":28.9},{"op":"APRR","e":"ALLAINES","x":"FLEURY-EN-BIERE","c1":32.0,"c2":48.7,"c3":79.6,"c4":102.6,"c5":16.9},{"op":"APRR","e":"ALLAINES","x":"FONTAINEBLEAU","c1":29.3,"c2":44.3,"c3":73.4,"c4":93.2,"c5":15.3},{"op":"APRR","e":"ALLAINES","x":"FORET DE TRONCAIS","c1":24.8,"c2":39.6,"c3":60.2,"c4":79.6,"c5":15.1},{"op":"APRR","e":"ALLAINES","x":"FORGES","c1":31.0,"c2":46.5,"c3":76.6,"c4":99.2,"c5":15.9},{"op":"APRR","e":"ALLAINES","x":"GANNAT","c1":32.2,"c2":50.7,"c3":78.4,"c4":106.1,"c5":19.3},{"op":"APRR","e":"ALLAINES","x":"GENDREY","c1":50.0,"c2":76.9,"c3":125.1,"c4":166.3,"c5":28.0},{"op":"APRR","e":"ALLAINES","x":"GERZAT-VILLE","c1":34.1,"c2":53.7,"c3":82.8,"c4":110.4,"c5":20.5},{"op":"APRR","e":"ALLAINES","x":"GROISSIAT","c1":62.0,"c2":95.9,"c3":154.1,"c4":205.8,"c5":35.6},{"op":"APRR","e":"ALLAINES","x":"GYE","c1":52.8,"c2":80.2,"c3":128.9,"c4":172.1,"c5":29.0},{"op":"APRR","e":"ALLAINES","x":"JOIGNY","c1":27.3,"c2":41.0,"c3":67.9,"c4":86.8,"c5":14.1},{"op":"APRR","e":"ALLAINES","x":"L ISLE-S/LE-DOUBS","c1":57.0,"c2":87.9,"c3":141.6,"c4":188.7,"c5":32.1},{"op":"APRR","e":"ALLAINES","x":"LA BOISSE","c1":63.1,"c2":97.6,"c3":156.2,"c4":208.8,"c5":36.2},{"op":"APRR","e":"ALLAINES","x":"LA BOISSE - MONTLUEL","c1":60.7,"c2":93.3,"c3":147.1,"c4":195.9,"c5":34.6},{"op":"APRR","e":"ALLAINES","x":"LA COTIERE","c1":61.5,"c2":Line truncated
|
|
||||||
Reference in new issue
Block a user