diff --git a/Controllers/BuildingController.cs b/Controllers/BuildingController.cs index 891bad8..bd7a230 100644 --- a/Controllers/BuildingController.cs +++ b/Controllers/BuildingController.cs @@ -111,6 +111,11 @@ int FuzzScore(Building building) [Authorize(Roles = "Admin")] public async Task Post(Building building) { + if (building is DinningCourt dinningCourt) + { + // Handle DinningCourt-specific initialization if necessary + } + // Prepare the Geocoding API request string url = $"https://maps.googleapis.com/maps/api/geocode/json?address={building.Address}&key={_googleApiKey}"; @@ -254,35 +259,138 @@ private class BuildingOutline public List Coordinates { get; set; } = new List(); } - [HttpGet("filterByType")] - public async Task> GetByType( + /// + /// Filters buildings by type and specific criteria, including room-level attributes for Housing. + /// + /// The type of building (e.g., Housing, DinningCourt). + /// A JSON object containing filtering criteria. + /// A filtered list of buildings. + [HttpGet("filter")] + public async Task>> Filter( [FromQuery] string type, - [FromQuery] string? query = null) + [FromQuery] string? criteria) { - // Ensure type is valid - if (type != nameof(DinningCourt) && type != nameof(Housing)) + if (string.IsNullOrEmpty(type)) { - return null; + return BadRequest("Building type is required."); } - // MongoDB filter for BuildingType - var filter = Builders.Filter.Eq("buildingType", type); + // Parse criteria JSON into a dictionary + Dictionary? filters = null; + if (!string.IsNullOrEmpty(criteria)) + { + try + { + filters = Newtonsoft.Json.JsonConvert.DeserializeObject>(criteria); + } + catch + { + return BadRequest("Invalid criteria format."); + } + } - // Fetch buildings of the given type - var buildings = await _buildings.Find(filter).ToListAsync(); + // Base filter for building type + var typeFilter = Builders.Filter.Eq("buildingType", type); + var filter = typeFilter; - if (!string.IsNullOrEmpty(query)) + // Add additional filters based on criteria + if (filters != null) { - int FuzzScore(Building building) + foreach (var filterKey in filters.Keys) { - return building.Name == null ? 0 : Fuzz.Ratio(query, building.Name); + switch (filterKey.ToLower()) + { + // Filters specific to Housing + case "pianonum": + if (type == nameof(Housing)) + filter &= Builders.Filter.Gte("pianoNum", Convert.ToInt32(filters[filterKey])); + break; + + case "kitchennum": + if (type == nameof(Housing)) + filter &= Builders.Filter.Gte("kitchenNum", Convert.ToInt32(filters[filterKey])); + break; + + case "havedinningcourt": + if (type == nameof(Housing)) + filter &= Builders.Filter.Eq("haveDinningCourt", Convert.ToBoolean(filters[filterKey])); + break; + + case "haveboilermarket": + if (type == nameof(Housing)) + filter &= Builders.Filter.Eq("haveBoilerMarket", Convert.ToBoolean(filters[filterKey])); + break; + + case "studyspacenum": + if (type == nameof(Housing)) + filter &= Builders.Filter.Gte("studySpaceNum", Convert.ToInt32(filters[filterKey])); + break; + + // Room-specific filters for Housing + // case "roomcapacity": + // if (type == nameof(Housing)) + // filter &= Builders.Filter.ElemMatch(h => h.Rooms, r => r.Capacity >= Convert.ToInt32(filters[filterKey])); + // break; + + // case "roomcost": + // if (type == nameof(Housing)) + // filter &= Builders.Filter.ElemMatch(h => h.Rooms, r => r.Cost <= Convert.ToDecimal(filters[filterKey])); + // break; + + // case "roomfeatures": + // if (type == nameof(Housing)) + // filter &= Builders.Filter.ElemMatch(h => h.Rooms, r => r.Features.Contains(filters[filterKey]?.ToString() ?? "")); + // break; + + // case "roomhousingrate": + // if (type == nameof(Housing)) + // filter &= Builders.Filter.ElemMatch(h => h.Rooms, r => r.HousingRate >= Convert.ToDouble(filters[filterKey])); + // break; + + // case "roomissharedbathroom": + // if (type == nameof(Housing)) + // filter &= Builders.Filter.ElemMatch(h => h.Rooms, r => r.IsSharedBathroom == Convert.ToBoolean(filters[filterKey])); + // break; + + // Filters specific to DinningCourt + case "acceptsswipes": + if (type == nameof(DinningCourt)) + filter &= Builders.Filter.Eq("acceptsSwipes", Convert.ToBoolean(filters[filterKey])); + break; + + case "acceptsdiningdollars": + if (type == nameof(DinningCourt)) + filter &= Builders.Filter.Eq("acceptsDiningDollars", Convert.ToBoolean(filters[filterKey])); + break; + + case "acceptsboilerexpress": + if (type == nameof(DinningCourt)) + filter &= Builders.Filter.Eq("acceptsBoilerExpress", Convert.ToBoolean(filters[filterKey])); + break; + + case "stabiloptions": + if (type == nameof(DinningCourt)) + filter &= Builders.Filter.AnyEq("stableOptions", filters[filterKey]?.ToString()); + break; + + case "busyhours": + if (type == nameof(DinningCourt)) + filter &= Builders.Filter.AnyEq("busyHours", filters[filterKey]?.ToString()); + break; + + default: + // Ignore unknown filters + break; + } } - - buildings.Sort((b1, b2) => FuzzScore(b2).CompareTo(FuzzScore(b1))); } - return buildings; + // Query the database + var buildings = await _buildings.Find(filter).ToListAsync(); + + return Ok(buildings); } + } } \ No newline at end of file diff --git a/Entities/DinningCourt.cs b/Entities/DinningCourt.cs index 93580f9..6d1f01f 100644 --- a/Entities/DinningCourt.cs +++ b/Entities/DinningCourt.cs @@ -2,28 +2,29 @@ namespace SimpleWebAppReact.Entities; using MongoDB.Bson; using MongoDB.Bson.Serialization.Attributes; /// -/// Class structure matches 1-1 with Building Table in database +/// Class structure matches 1-1 with the Building table in the database /// public class DinningCourt : Building { - // food options always available at the court (ex/ salad bar, la fonda, deli bar) + // Food options always available at the court (e.g., salad bar, la fonda, deli bar) [BsonElement("stableOptions"), BsonRepresentation(BsonType.Array)] - public Array? StableOptions { get; set; } + public List StableOptions { get; set; } + - // whether or not swipes are accepted + // Whether or not meal swipes are accepted [BsonElement("acceptsSwipes"), BsonRepresentation(BsonType.Boolean)] public bool? AcceptsSwipes { get; set; } - // an array of hours when the location is busiest (strings?) + // An array of hours when the location is busiest [BsonElement("busyHours"), BsonRepresentation(BsonType.Array)] - public bool? BusyHours { get; set; } + public List BusyHours { get; set; } = new(); - // whether or not dining dollars are accepted + // Whether or not dining dollars are accepted [BsonElement("acceptsDiningDollars"), BsonRepresentation(BsonType.Boolean)] public bool? AcceptsDiningDollars { get; set; } - // whether or not boilerExpress is accepted + // Whether or not BoilerExpress is accepted [BsonElement("acceptsBoilerExpress"), BsonRepresentation(BsonType.Boolean)] public bool? AcceptsBoilerExpress { get; set; } -} \ No newline at end of file +} diff --git a/Entities/Housing.cs b/Entities/Housing.cs index 5349ca3..23fdc30 100644 --- a/Entities/Housing.cs +++ b/Entities/Housing.cs @@ -1,9 +1,14 @@ namespace SimpleWebAppReact.Entities; using MongoDB.Bson; using MongoDB.Bson.Serialization.Attributes; +using System.Collections.Generic; + +/// +/// Represents a housing building with specific attributes. +/// public class Housing : Building { - //Store a list of room objects, each object store attributes such as cost, capacity, features, etc. + // List of room objects, each storing attributes such as cost, capacity, and features [BsonElement("rooms")] public List Rooms { get; set; } = new List(); @@ -11,7 +16,7 @@ public class Housing : Building public int PianoNum { get; set; } [BsonElement("kitchenNum"), BsonRepresentation(BsonType.Int32)] - public int KitchenNum { get; set; } + public int KitchenNum { get; set; } [BsonElement("haveDinningCourt"), BsonRepresentation(BsonType.Boolean)] public bool HaveDinningCourt { get; set; } @@ -21,5 +26,5 @@ public class Housing : Building [BsonElement("studySpaceNum"), BsonRepresentation(BsonType.Int32)] public int StudySpaceNum { get; set; } - -} \ No newline at end of file + +} diff --git a/Entities/Room.cs b/Entities/Room.cs index af66605..16f59fb 100644 --- a/Entities/Room.cs +++ b/Entities/Room.cs @@ -2,8 +2,14 @@ using MongoDB.Bson.Serialization.Attributes; public class Room { - public string? Type { get; set; } - public int Capacity { get; set; } + [BsonElement("capacity"), BsonRepresentation(BsonType.Int32)] + public int Capacity { get; set; } + + [BsonElement("features")] + public List Features { get; set; } = new List(); + + [BsonElement("cost"), BsonRepresentation(BsonType.Decimal128)] + public decimal Cost { get; set; } public double HousingRate {get; set; }