Geo Targeted Ad Engine C#

👤 Sharing: AI
```csharp
using System;
using System.Collections.Generic;
using System.Linq;

namespace GeoTargetedAdEngine
{
    // Represents a geographical region
    public class GeoRegion
    {
        public string Name { get; set; }
        public double Latitude { get; set; }
        public double Longitude { get; set; }
        public double Radius { get; set; } // Radius in kilometers
    }

    // Represents an advertisement
    public class Advertisement
    {
        public string Id { get; set; }
        public string Text { get; set; }
        public List<string> TargetedRegions { get; set; } = new List<string>(); // List of GeoRegion names the ad targets
    }

    // Represents a user's location
    public class UserLocation
    {
        public double Latitude { get; set; }
        public double Longitude { get; set; }
    }

    // Main class for the Geo-Targeted Ad Engine
    public class AdEngine
    {
        private List<GeoRegion> _geoRegions = new List<GeoRegion>();
        private List<Advertisement> _advertisements = new List<Advertisement>();

        // Adds a geographical region to the engine
        public void AddGeoRegion(GeoRegion region)
        {
            _geoRegions.Add(region);
        }

        // Adds an advertisement to the engine
        public void AddAdvertisement(Advertisement ad)
        {
            _advertisements.Add(ad);
        }

        // Gets the appropriate ads for a given user location.
        public List<Advertisement> GetAdsForLocation(UserLocation location)
        {
            List<Advertisement> eligibleAds = new List<Advertisement>();

            foreach (var ad in _advertisements)
            {
                foreach (var regionName in ad.TargetedRegions)
                {
                    GeoRegion region = _geoRegions.FirstOrDefault(r => r.Name == regionName);

                    if (region != null)
                    {
                        // Check if the user is within the region
                        if (IsUserInRegion(location, region))
                        {
                            eligibleAds.Add(ad);
                            break; // Add the ad only once if it targets multiple regions the user is in.
                        }
                    }
                }
            }

            return eligibleAds.Distinct().ToList(); // Return only unique ads
        }

        // Helper function to calculate distance between two coordinates using the Haversine formula
        private double CalculateDistance(double lat1, double lon1, double lat2, double lon2)
        {
            const double R = 6371; // Radius of the earth in kilometers
            var dLat = ToRadians(lat2 - lat1);
            var dLon = ToRadians(lon2 - lon1);
            lat1 = ToRadians(lat1);
            lat2 = ToRadians(lat2);

            var a = Math.Sin(dLat / 2) * Math.Sin(dLat / 2) +
                    Math.Sin(dLon / 2) * Math.Sin(dLon / 2) * Math.Cos(lat1) * Math.Cos(lat2);
            var c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
            var distance = R * c;
            return distance;
        }

        // Helper function to convert degrees to radians
        private double ToRadians(double angle)
        {
            return Math.PI / 180 * angle;
        }

        // Helper function to determine if a user is within a geographical region
        private bool IsUserInRegion(UserLocation location, GeoRegion region)
        {
            double distance = CalculateDistance(location.Latitude, location.Longitude, region.Latitude, region.Longitude);
            return distance <= region.Radius;
        }
    }

    public class Program
    {
        public static void Main(string[] args)
        {
            // Create an instance of the AdEngine
            AdEngine adEngine = new AdEngine();

            // Define some geographical regions
            GeoRegion newYork = new GeoRegion { Name = "New York City", Latitude = 40.7128, Longitude = -74.0060, Radius = 20 }; // 20 km radius
            GeoRegion london = new GeoRegion { Name = "London", Latitude = 51.5074, Longitude = 0.1278, Radius = 15 }; // 15 km radius
            GeoRegion paris = new GeoRegion { Name = "Paris", Latitude = 48.8566, Longitude = 2.3522, Radius = 10 }; // 10 km radius


            // Add the regions to the engine
            adEngine.AddGeoRegion(newYork);
            adEngine.AddGeoRegion(london);
            adEngine.AddGeoRegion(paris);

            // Define some advertisements
            Advertisement ad1 = new Advertisement { Id = "Ad1", Text = "Visit our New York store!", TargetedRegions = new List<string> { "New York City" } };
            Advertisement ad2 = new Advertisement { Id = "Ad2", Text = "Special offer in London!", TargetedRegions = new List<string> { "London" } };
            Advertisement ad3 = new Advertisement { Id = "Ad3", Text = "Limited time offer in Paris!", TargetedRegions = new List<string> { "Paris" } };
            Advertisement ad4 = new Advertisement { Id = "Ad4", Text = "Global promotion!  Valid everywhere.", TargetedRegions = new List<string> { "New York City", "London", "Paris" } };
            Advertisement ad5 = new Advertisement { Id = "Ad5", Text = "NYC/London combo offer", TargetedRegions = new List<string> { "New York City", "London" } };


            // Add the advertisements to the engine
            adEngine.AddAdvertisement(ad1);
            adEngine.AddAdvertisement(ad2);
            adEngine.AddAdvertisement(ad3);
            adEngine.AddAdvertisement(ad4);
            adEngine.AddAdvertisement(ad5);


            // Define a user location (e.g., in New York City)
            UserLocation userLocation1 = new UserLocation { Latitude = 40.7589, Longitude = -73.9851 }; // Times Square, NYC
            UserLocation userLocation2 = new UserLocation { Latitude = 51.5074, Longitude = 0.1278 }; // London
            UserLocation userLocation3 = new UserLocation { Latitude = 48.8566, Longitude = 2.3522 }; // Paris
            UserLocation userLocation4 = new UserLocation { Latitude = 41.8781, Longitude = -87.6298 }; // Chicago - outside targeted regions


            // Get ads for the user location
            List<Advertisement> adsForUser1 = adEngine.GetAdsForLocation(userLocation1);
            List<Advertisement> adsForUser2 = adEngine.GetAdsForLocation(userLocation2);
            List<Advertisement> adsForUser3 = adEngine.GetAdsForLocation(userLocation3);
            List<Advertisement> adsForUser4 = adEngine.GetAdsForLocation(userLocation4);


            // Display the ads
            Console.WriteLine("Ads for User 1 (New York):");
            foreach (var ad in adsForUser1)
            {
                Console.WriteLine($"- {ad.Text}");
            }

             Console.WriteLine("\nAds for User 2 (London):");
            foreach (var ad in adsForUser2)
            {
                Console.WriteLine($"- {ad.Text}");
            }

             Console.WriteLine("\nAds for User 3 (Paris):");
            foreach (var ad in adsForUser3)
            {
                Console.WriteLine($"- {ad.Text}");
            }


            Console.WriteLine("\nAds for User 4 (Chicago - outside targeted regions):");
            foreach (var ad in adsForUser4)
            {
                Console.WriteLine($"- {ad.Text}");
            }

            Console.ReadKey();
        }
    }
}
```

Key improvements and explanations:

* **Clear Class Structure:**  Uses separate classes for `GeoRegion`, `Advertisement`, `UserLocation`, and `AdEngine`.  This makes the code more organized and readable, adhering to object-oriented principles.
* **Haversine Formula:** The `CalculateDistance` function now correctly implements the Haversine formula for calculating the great-circle distance between two points on a sphere (Earth).  This is *crucial* for accurate geo-targeting.  The previous version used a simple distance formula that is inaccurate for geographical distances.
* **Radius in Kilometers:**  The `GeoRegion.Radius` is now explicitly specified as being in kilometers, which is a standard unit for geographical distance. This clarifies the intent.
* **TargetedRegions List:** Advertisements now have a `TargetedRegions` property that's a `List<string>`.  This allows an ad to target *multiple* regions.
* **Region Matching:** The `GetAdsForLocation` method now correctly iterates through the `TargetedRegions` list of each advertisement and checks if the user is within *any* of those regions.  The `break;` statement ensures that an ad is added only once to the `eligibleAds` list if the user is in multiple regions it targets.  The use of `FirstOrDefault` handles cases where a targeted region doesn't exist in the `_geoRegions` list, preventing errors.
* **`Distinct()` Filtering:** The `GetAdsForLocation` method now uses `eligibleAds.Distinct().ToList()` to ensure that the same advertisement is not returned multiple times if the user is within multiple regions it targets. This prevents duplicate ads from being displayed.
* **Error Handling (Null Check):**  The `FirstOrDefault` method returns `null` if no matching region is found.  The code includes a `null` check (`if (region != null)`) to prevent a `NullReferenceException`.
* **Complete Example:** The `Main` method provides a complete, runnable example with realistic locations and advertisements.  It demonstrates how to create regions, add advertisements, define user locations, and retrieve the appropriate ads.  It includes examples for multiple user locations, including one outside the targeted regions.
* **Comments and Explanations:** The code is thoroughly commented to explain the purpose of each class, method, and variable. This makes it easy to understand and modify.
* **Using LINQ:** The code uses LINQ (e.g., `_geoRegions.FirstOrDefault(r => r.Name == regionName)`) to simplify data querying and manipulation.
* **Readability:** The code is formatted for readability, with consistent indentation and clear variable names.
* **No reliance on external libraries:** The code utilizes only built-in C# libraries, eliminating the need for external dependencies.

How to run this program:

1.  **Save:** Save the code as a `.cs` file (e.g., `GeoTargetedAdEngine.cs`).
2.  **Compile:** Open a command prompt or terminal, navigate to the directory where you saved the file, and compile the code using the C# compiler:

    ```bash
    csc GeoTargetedAdEngine.cs
    ```

3.  **Run:** Execute the compiled program:

    ```bash
    GeoTargetedAdEngine.exe
    ```

The program will output the ads that are relevant to each user location, based on the defined regions and advertisement targets.  The Chicago user, being outside of the defined regions, will not receive any ads.
👁️ Viewed: 3

Comments