function updateZoomText(){
if (map.getZoom() >=10){
document.getElementById("zoomalert").innerHTML = "";
return;
}
else{
// document.getElementById("cheapestinfo").innerHTML = "";
}
zoomstr = "Click the Zoom in button " + (10-map.getZoom()).toString() + " more time";
if (10-map.getZoom() > 1){
zoomstr +="s";
}
zoomstr+=" to see fuel prices";
document.getElementById("zoomalert").innerHTML = zoomstr ;
}
function getLastSelectedFuel(){
var fuel = localStorage.getItem('fuel');
if (fuel == null){
fuel = 1;
localStorage.setItem('fuel',fuel);
}
return fuel;
}
function fuelSelectChange(name){
var fuel = document.getElementById(name).value;
localStorage.setItem('fuel',fuel);
addMarkers(json_response);
updateListHtml(json_response);
}
function getFuelSelectHTML(){
var fuel = getLastSelectedFuel();
var fuelSelectHTML ="";
fuelSelectHTML += "";
fuelSelectHTML += "Normal Unleaded petrol prices (E10) ";
fuelSelectHTML += "Old-style unleaded petrol prices (E5) ";
fuelSelectHTML += "Diesel prices (B7) ";
fuelSelectHTML += "Super Diesel prices (SDV) ";
fuelSelectHTML += " ";
return fuelSelectHTML;
}
function sortStationsByFuelPrice(data, fuelIndex) {
// Extract stations as an array
let stationsArray = Object.values(data);
// Filter out non-station entries and stations where the price at the given index is not set, is -1, or is 999999
stationsArray = stationsArray.filter(station => station.fuel_prices && station.fuel_prices[fuelIndex] < 999999);
// Sort the array based on the fuel price at the given index
stationsArray.sort((a, b) => a.fuel_prices[fuelIndex] - b.fuel_prices[fuelIndex]);
return stationsArray;
}
function updateListHtml(json) {
var fuel = getLastSelectedFuel();
var priceSortedStations = sortStationsByFuelPrice(json, fuel);
var html = "
";
document.getElementById('station_list').innerHTML = html;
}
function populateStationModal(id){
modalText = "
Current prices: ";
if ((islandOnly)&&(hasIsland)){
chosenMins = json_response['islandmins'];
}
else{
chosenMins = json_response['mins'];
}
if (id['fuel_prices'][1]!=999999){
if (id['fuel_prices'][1]==chosenMins[1]){
modalText += "
Unleaded (E10): " + id['fuel_prices'][1] + "
";
}
else{
modalText += "
Unleaded (E10): " + id['fuel_prices'][1] + " (" + (id['fuel_prices'][1]-chosenMins[1]).toFixed(1) + "p more expensive)
";
}
}
if (id['fuel_prices'][2]!=999999) {
if (id['fuel_prices'][2]==chosenMins[2]){
modalText += "
Old unleaded (E5): " + id['fuel_prices'][2] + "
";
}
else{
modalText += "
Old unleaded (E5): " + id['fuel_prices'][2] + " (" + (id['fuel_prices'][2]-chosenMins[2]).toFixed(1) + "p more expensive than cheapest)
";
}
}
if (id['fuel_prices'][3]!=999999) {
if (id['fuel_prices'][3]==chosenMins[3]){
modalText += "
Diesel (B7): " + id['fuel_prices'][3] + "
";
}
else{
modalText += "
Diesel (B7): " + id['fuel_prices'][3] + " (" + (id['fuel_prices'][3]-chosenMins[3]).toFixed(1) + "p more expensive than cheapest)
";
}
}
if (id['fuel_prices'][4]!=999999) {
if (id['fuel_prices'][4]==mins[4]){
modalText += "
Super Diesel (SDV): " + id['fuel_prices'][4] + "
";
}
else{
modalText += "
Super Diesel (SDV): " + id['fuel_prices'][4] + + " (" + (id['fuel_prices'][4]-chosenMins[4]).toFixed(1) + "p more expensive than cheapest)
";
}
}
modalText += "
green = cheapest in this area ";
modalText += "
red = not cheapest in this area ";
document.getElementById("modal-body").innerHTML = modalText ;
// + minHTML;
document.getElementById("exampleModalLabel").innerHTML = "
" + id['name'] + ' - ' + id['short_address'] + " (click address to view map)";
$('#exampleModal').modal('show');
}
function toggleIslandOnly(){
if (document.getElementById('islandOnlyCheckbox').checked) {
islandOnly = true;
localStorage.setItem('islandOnly', 'true');
}
else{
islandOnly = false;
localStorage.setItem('islandOnly', 'false');
}
markersLayer.clearLayers();
addMarkers(json_response);
updateListHtml(json_response);
addNerdMode(json_response);
}
function check_to_show_island_only(data){
hasIsland = false;
for (var key in data) {
if ((key !== "mins")&&(key !== "islandmins")) {
if (data[key]['island'] == 1){
hasIsland = true;
break;
}
}
}
if (hasIsland){
document.getElementById("islandOnlyOption").innerHTML = "
Only show island stations";
if (islandOnly) {
document.getElementById("islandOnlyCheckbox").checked = true;
}
document.getElementById("islandOnlyOption").style.display = "block";
}
else{
document.getElementById("islandOnlyOption").style.display = "none";
}
}
function highlightPrice(price,count){
markers.forEach((marker, index) => {
});
}
function getPricesToColoursArr(data){
var returnArr = [];
smallest = data[0];
largest = data[data.length - 1];
var rg_delta = Math.abs(parseInt(190 / (largest - smallest)));
var current_red ;
var current_green ;
for (var i = 0; i < data.length; i++) {
this_price = data[i];
dist_from_base = this_price - smallest;
current_green = 190 - (rg_delta * dist_from_base);
current_red = rg_delta * dist_from_base;
returnArr[i] = 'rgba('+current_red+', '+current_green+',' + 120 + ', 1)';
}
returnArr[0] = 'rgba(0, 255, 0, 1)';
returnArr[data.length - 1] = 'rgba(255, 0, 0, 1)';
return returnArr;
}
function getPricesToColoursDict(data){
var returnDict = {};
smallest = data[0];
largest = data[data.length - 1];
var rg_delta = Math.abs(parseInt(190 / (largest - smallest)));
var current_red ;
var current_green ;
for (var i = 0; i < data.length; i++) {
this_price = data[i];
dist_from_base = this_price - smallest;
current_green = 190 - (rg_delta * dist_from_base);
current_red = rg_delta * dist_from_base;
returnDict[this_price] = 'rgba('+current_red+', '+current_green+',' + 120 + ', 1)';
}
returnDict[largest] = 'rgba(255, 0, 0, 1)';
returnDict[smallest] = 'rgba(0, 255, 0, 1)';
return returnDict;
}
function get_prices_dict_from_data(data) {
var x_vals = [];
var y_vals = [];
var prices_dict = {};
hasIsland = false;
for (var key in data) {
if ((key !== "mins")&&(key !== "islandmins")) {
if (data[key]['island'] == 1){
hasIsland = true;
break;
}
}
}
var selectedFuel = getLastSelectedFuel();
for (var key in data) {
if ((key !== "mins")&&(key !== "islandmins")){
if (!data[key]['island']) {
if ((islandOnly)&&(hasIsland)){
continue;
}
}
if (data[key]['fuel_prices'][selectedFuel] != 999999){
if (data[key]['fuel_prices'][selectedFuel] in prices_dict) {
prices_dict[data[key]['fuel_prices'][selectedFuel]] += 1;
}
else{
prices_dict[data[key]['fuel_prices'][selectedFuel]] = 1;
}
}
}
}
var sortedKeys = Object.keys(prices_dict).map(Number).sort((a, b) => a - b);
var keyCount = 0;
sortedKeys.forEach(key => {
keyCount += 1;
x_vals.push(key);
if (prices_dict[key] >3) {
prices_dict[key] = 4;
}
y_vals.push(prices_dict[key]);
});
return [x_vals, y_vals, keyCount, sortedKeys];
}
function addNerdMode(data){
if (typeof myChart !== 'undefined') {
myChart.destroy();
}
var fuelNames = ['','Unleaded (E10)','Old unleaded (E5)','Diesel (B7)','Super Diesel (SDV)'];
var [x_vals, y_vals, keyCount,sortedKeys] = get_prices_dict_from_data(data);
if (keyCount>2) {
var chart_data = x_vals.map((k, i) => ({x: k, y: y_vals[i]}));
var backgroundColrs = getPricesToColoursArr(sortedKeys);
var borderColor = Array(x_vals.length).fill('rgba(10,10,10, 1)');
const ctx = document.getElementById('myChart').getContext('2d');
myChart = new Chart(ctx, {
type: 'bar',
data: {
datasets: [{
label: 'Num of Stations at this price:',
data: chart_data,
backgroundColor: backgroundColrs,
borderColor: borderColor,
borderWidth: 1,
barPercentage: 1,
categoryPercentage: .9,
borderRadius: 1,
}]
},
options: {
maintainAspectRatio: false,
scales: {
x: {
type: 'category',
labels: x_vals,
grid: {
display: false // Hide horizontal grid lines if needed
},
offset: true,
title: {
display: true,
text: 'Prices',
font: {
size: 14
}
}
},
y: {
// beginAtZero: true
title: {
display: true,
text: 'Stations',
font: {
size: 14
}
},
ticks: {
callback: function(value, index, values) {
if (value === 4) {
return '3+';
}
return value;
}
},
grid: {
display: false // Hide horizontal grid lines if needed
}
}
},
plugins: {
legend: {
display: false,
},
tooltip: {
callbacks: {
title: (items) => {
if (!items.length) {
return '';
}
const item = items[0];
return `Price: ${item.label}`;
},
label: (item) => {
const count = item.raw.y;
if (count>3) {
return `Num of stations at this price: 3+`;
}
return `Num of stations at this price: ${count}`;
}
}
}
},
onClick: (event, elements) => {
if (elements.length > 0) {
const element = elements[0];
const datasetIndex = element.datasetIndex;
const index = element.index;
const dataset = myChart.data.datasets[datasetIndex];
const data = dataset.data[index];
const price = data.x;
const count = data.y;
highlightPrice(price, count);
}
}
}
});
}
}
function getPrices(){
if (map.getZoom() >= 10){
var bounds = map.getBounds();
var southWest = bounds.getSouthWest();
var northEast = bounds.getNorthEast();
var minLat = southWest.lat;
var minLong = southWest.lng;
var maxLat = northEast.lat;
var maxLong = northEast.lng;
var url = '/stationsfromgeo?minLat=' + minLat + '&maxLat=' + maxLat + '&minLong=' + minLong + '&maxLong=' + maxLong + '&fuelType=' + getLastSelectedFuel();
document.getElementById('spinner').style.display = 'block';
fetch(url)
.then(response => response.json())
.then(data => {
document.getElementById('spinner').style.display = 'none';
json_response = data;
check_to_show_island_only(json_response);
addMarkers(json_response);
listHtml = updateListHtml(json_response);
addNerdMode(json_response);
})
.catch(error => {
console.error('Error:', error);
});
}
else{
updateZoomText();
}
}
function fetchAndColorSvg(svgContent, color, callback) {
// Modify the SVG content to apply the desired color
const coloredSvg = svgContent.replace(/
gas-station-location `;
svgContent = ' ';
// Color the SVG and create the custom icon
fetchAndColorSvg(svgContent, customcolor, function(svgDataUrl) {
var customIcon = L.icon({
iconSize: [40, 30],
iconAnchor: [10, 10],
iconUrl: svgDataUrl
});
var fuelNames = ['', 'Unleaded (E10)', 'Old unleaded (E5)', 'Diesel (B7)', 'Super Diesel (SDV)'];
if ((!(islandOnly)) || ((islandOnly) && (data[key]['island'] == 1) && (hasIsland)) || (islandOnly && !hasIsland)) {
var title = chosenMins[selectedFuel] == data[key]['fuel_prices'][selectedFuel] ? data[key]['name'] + " - Cheapest for " + fuelNames[selectedFuel] + " in this area" : data[key]['name'] + ": " + (data[key]['fuel_prices'][selectedFuel] - chosenMins[selectedFuel]).toFixed(1) + "p per liter more expensive than cheapest in this area";
var zIndexOffset = chosenMins[selectedFuel] == data[key]['fuel_prices'][selectedFuel] ? 1000 : 0; // Green markers on top
var stationMarker = L.marker([data[key]['latitude'], data[key]['longitude']], {
icon: customIcon,
title: title,
zIndexOffset: zIndexOffset
}).addTo(markersLayer);
markers.push(stationMarker);
(function(key) {
stationMarker.on('click', function(e) {
populateStationModal(data[key]);
});
})(key);
}
});
}
}
}
}
function initMap(inlat,inlong,zoom = 13) {
map = L.map('map').setView([inlat, inlong], zoom);
markersLayer = new L.LayerGroup().addTo(map);
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 30,
attribution: '© OpenStreetMap '
}).addTo(map);
var titleControl = L.control({ position: 'bottomright' });
var title="You can drag this map, and click +/- to zoom Hover over a marker to see more info Click a marker for more info Click this box to hide it";
titleControl.onAdd = function(map) {
var div = L.DomUtil.create('div', 'map-title');
div.innerHTML = '' + title + ' ';
div.style.backgroundColor = 'white';
div.style.padding = '5px';
div.style.borderRadius = '5px';
div.style.boxShadow = '0 0 15px rgba(0,0,0,0.2)';
div.style.cursor = 'pointer'; // Add cursor pointer to indicate it's clickable
div.onclick = function() {
removeTitleControl(); // Call the function to remove the control when clicked
};
return div;
};
titleControl.addTo(map);
var titleControlRef = titleControl;
getPrices();
map.on('zoomend', function(e) {
markersLayer.clearLayers();
updateZoomText();
getPrices();
});
map.on('moveend', function(e) {
markersLayer.clearLayers();
center = map.getCenter();
getPrices();
check_to_show_island_only(json_response);
});
function removeTitleControl() {
if (titleControlRef) {
map.removeControl(titleControlRef);
titleControlRef = null; // Clear the reference
}
}
}