<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Walk Score Calculator</title>
    <style>
        .container {
            max-width: 600px;
            margin: 50px auto;
            text-align: center;
            font-family: Arial, sans-serif;
            padding: 20px;
            border: 1px solid #ddd;
            border-radius: 8px;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
        }

        h1 {
            color: #333;
        }

        input {
            padding: 10px;
            font-size: 16px;
            width: 70%;
            border: 1px solid #ccc;
            border-radius: 4px;
        }

        button {
            padding: 10px 20px;
            font-size: 16px;
            margin-left: 10px;
            cursor: pointer;
            background-color: #28a745;
            color: white;
            border: none;
            border-radius: 4px;
        }

        button:hover {
            background-color: #218838;
        }

        #result {
            margin-top: 20px;
            font-size: 18px;
            text-align: left;
        }

        iframe {
            margin-top: 20px;
            border: 1px solid #ccc;
            border-radius: 4px;
        }

        small a {
            color: #007bff;
            text-decoration: none;
        }

        small a:hover {
            text-decoration: underline;
        }

        .loading {
            color: #555;
        }

        .error {
            color: red;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>Walk Score Calculator</h1>
        <input type="text" id="address" placeholder="Enter address" size="50" />
        <button id="calculate">Calculate Walk Score</button>
        <div id="result"></div>
    </div>

    <script>
        document.getElementById('calculate').addEventListener('click', () => {
            const address = document.getElementById('address').value.trim();
            const resultDiv = document.getElementById('result');

            if (!address) {
                resultDiv.innerHTML = '<p class="error">Please enter a valid address.</p>';
                return;
            }

            resultDiv.innerHTML = '<p class="loading">Calculating Walk Score...</p>';

            geocodeAddress(address)
                .then(coords => {
                    if (coords) {
                        fetchAmenities(coords.lat, coords.lon)
                            .then(amenities => {
                                const score = calculateWalkScore(amenities);
                                displayResult(score, amenities, coords);
                            })
                            .catch(err => {
                                console.error(err);
                                resultDiv.innerHTML = '<p class="error">Error fetching amenities.</p>';
                            });
                    } else {
                        resultDiv.innerHTML = '<p class="error">Address not found.</p>';
                    }
                })
                .catch(err => {
                    console.error(err);
                    resultDiv.innerHTML = '<p class="error">Error during geocoding.</p>';
                });
        });

        /
         * Geocode the address to get latitude and longitude using Nominatim.
         * @param {string} address - The address to geocode.
         * @returns {Promise<Object|null>} - An object with lat and lon or null if not found.
         */
        async function geocodeAddress(address) {
            const url = https://nominatim.openstreetmap.org/search?format=json&q=${encodeURIComponent(address)};

            try {
                const response = await fetch(url, { headers: { 'Accept-Language': 'en' } });
                const data = await response.json();

                if (data && data.length > 0) {
                    return { lat: data[0].lat, lon: data[0].lon };
                } else {
                    return null;
                }
            } catch (error) {
                console.error('Geocoding Error:', error);
                return null;
            }
        }

        /**
         * Fetch nearby amenities using Overpass API.
         * @param {string} lat - Latitude of the location.
         * @param {string} lon - Longitude of the location.
         * @param {number} radius - Search radius in meters.
         * @returns {Promise<Array>} - An array of amenities.
         */
        async function fetchAmenities(lat, lon, radius = 1000) {
            // Define the amenities to search for
            const amenities = [
                'school',
                'park',
                'hospital',
                'supermarket',
                'bank',
                'cafe',
                'restaurant',
                'library',
                'pharmacy',
                'post_office'
            ];

            // Construct Overpass QL query
            const query = <br/>[out:json];<br/>(<br/> node["amenity"~"${amenities.join('|')}"](around:${radius},${lat},${lon});<br/> way["amenity"~"${amenities.join('|')}"](around:${radius},${lat},${lon});<br/> relation["amenity"~"${amenities.join('|')}"](around:${radius},${lat},${lon});<br/>);<br/>out center;<br/>;

            const url = https://overpass-api.de/api/interpreter?data=${encodeURIComponent(query)};

            try {
                const response = await fetch(url);
                const data = await response.json();

                return data.elements;
            } catch (error) {
                console.error('Overpass API Error:', error);
                return [];
            }
        }

        /
         * Calculate a basic walk score based on the number of amenities.
         * @param {Array} amenities - Array of amenity objects.
         * @returns {number} - Walk score between 0 and 100.
         */
        function calculateWalkScore(amenities) {
            const maxAmenities = 50; // Arbitrary cap to prevent score from exceeding 100
            const scorePerAmenity = 2; // 50 amenities * 2 = 100

            const uniqueAmenities = new Set(amenities.map(a => a.tags.amenity));
            const diversityBonus = uniqueAmenities.size * 0.5; // Encourage diversity

            let score = amenities.length * scorePerAmenity + diversityBonus;
            score = Math.min(score, 100); // Cap the score at 100

            return Math.round(score);
        }

        /**
         * Display the walk score and related information.
         * @param {number} score - The calculated walk score.
         * @param {Array} amenities - Array of amenities.
         * @param {Object} coords - Latitude and longitude.
         */
        function displayResult(score, amenities, coords) {
            const resultDiv = document.getElementById('result');
            const numAmenities = amenities.length;
            const uniqueAmenities = new Set(amenities.map(a => a.tags.amenity));

            resultDiv.innerHTML = <br/>&lt;p&gt;&lt;strong&gt;Walk Score:&lt;/strong&gt; ${score} / 100&lt;/p&gt;<br/>&lt;p&gt;&lt;strong&gt;Number of Nearby Amenities:&lt;/strong&gt; ${numAmenities}&lt;/p&gt;<br/>&lt;p&gt;&lt;strong&gt;Amenity Types:&lt;/strong&gt; ${[...uniqueAmenities].join(', ')}&lt;/p&gt;<br/>&lt;p&gt;&lt;strong&gt;Location:&lt;/strong&gt; Latitude ${coords.lat}, Longitude ${coords.lon}&lt;/p&gt;<br/>&lt;iframe<br/> width="100%"<br/> height="300"<br/> frameborder="0"<br/> scrolling="no"<br/> marginheight="0"<br/> marginwidth="0"<br/> src="https://www.openstreetmap.org/export/embed.html?bbox=${(coords.lon - 0.01).toFixed(5)},${(coords.lat - 0.01).toFixed(5)},${(coords.lon + 0.01).toFixed(5)},${(coords.lat + 0.01).toFixed(5)}&layer=mapnik&marker=${coords.lat},${coords.lon}"&gt;<br/>&lt;/iframe&gt;<br/>&lt;br/&gt;<br/>&lt;small&gt;&lt;a href="https://www.openstreetmap.org/?mlat=${coords.lat}&mlon=${coords.lon}#map=15/${coords.lat}/${coords.lon}" target="_blank"&gt;View Larger Map&lt;/a&gt;&lt;/small&gt;<br/>;
        }
    </script>
</body>
</html>