public async Task <IActionResult> Index(int id, [Bind("FacilityID,FacilityName,NumberOfClientsUsingWeightRoom,NumberOfClientsUsingCardioRoom," + "NumberOfClientsUsingStretchRoom,IsOpenDoorRequested,DoorOpened,DoorCloseTimer,IsCameraScanSuccessful, IsWithin10m")] Facility facilityView ) // { // Get the default gym for a user and set it to be the Id for the gym being edited var user = await _userManager.GetUserAsync(User); if (user.Id == null) { return(NotFound()); } id = user.DefaultGym; // Variable facility is the database values, facilityView, binds data from the view to post to DB var facility = await _facilityContext.Facilities.FindAsync(id); var facilityDetails = await _facilityContext.UsersInGymDetails.ToListAsync(); UsersInGymDetail currentFacilityDetail = new UsersInGymDetail(); var currentFacilityDetailDb = await _facilityContext.UsersInGymDetails.Where(f => f.UniqueEntryID == user.Id).FirstOrDefaultAsync(); var allGymUserRecords = await _facilityContext.UsersOutofGymDetails.Where(f => f.UniqueEntryID == user.Id).FirstOrDefaultAsync(); bool enteredGym = false; if (id != facility.FacilityID || id != facilityView.FacilityID) { return(NotFound()); } if (!ModelState.IsValid) { return(RedirectToAction(nameof(Index))); } if (ModelState.IsValid) { try { // maybe make is open door requested a user property // if door open is requested from the view by clicking the button, then run the below logic to test if user is authorized and also apply crowdsensing functions enteredGym = await DetermineEnterOrExitGym(facilityView, user, facility, facilityDetails, currentFacilityDetail, currentFacilityDetailDb, enteredGym, allGymUserRecords); } catch (DbUpdateConcurrencyException e) { if (!FacilityExists(facility.FacilityID)) { return(NotFound()); } else { _logger.LogInformation(e.Message); } } // if the user has logged in successfully and not logged workout, then send to questionnaire TODO: for now, later will use AJAX to post questionaire here, and have option to later log in workout return((user.AccessGrantedToFacility) && (!user.HasLoggedWorkoutToday) ? RedirectToAction("LogWorkout", "Facilities", new { id = user.DefaultGym }) : RedirectToAction(nameof(Index))); } return(View(facility)); }
public async Task <IActionResult> Index(int?id) { // Get the default gym for a user and set it to be the Id for the gym being edited var user = await _userManager.GetUserAsync(User); ViewBag.EstimatedNumberInGym = 0; ViewBag.IsOpenDoorRequested = false; ViewBag.DefaultLat = user.TestLat; ViewBag.DefaultLong = user.TestLong; // if user does not exist return not found, if id is null, send to login page if (user.Id == null) { return(NotFound()); } id = user.DefaultGym; // set the ID to be current user's default gym if (id == null) { return(RedirectToPage("/Identity/Account/Login")); } // if (!user.isVerifiedUser) return RedirectToPage("/Identity/Account/Login"); var facility = await _facilityContext.Facilities.FindAsync(id); var facilityDetails = await _facilityContext.UsersInGymDetails.ToListAsync(); UsersInGymDetail = await _facilityContext.UsersInGymDetails.Where(f => f.UniqueEntryID == user.Id).FirstOrDefaultAsync(); if (facility == null) { return(NotFound()); // ensure facility exists } // if there is a user in gym, retreive facial recognition results from the database if (UsersInGymDetail != null) { ViewBag.IsSmiling = _facilityContext.UsersInGymDetails.Where(o => o.UniqueEntryID == user.Id).FirstOrDefault().IsSmiling; ViewBag.Gender = _facilityContext.UsersInGymDetails.Where(o => o.UniqueEntryID == user.Id).FirstOrDefault().Gender; ViewBag.AgeRangeLow = _facilityContext.UsersInGymDetails.Where(o => o.UniqueEntryID == user.Id).FirstOrDefault().AgeRangeLow; ViewBag.AgeRangeHigh = _facilityContext.UsersInGymDetails.Where(o => o.UniqueEntryID == user.Id).FirstOrDefault().AgeRangeHigh; } // Calculations for estimated time // get estimated time to check submitted to the db for the user submitting DateTime estimatedTimeToCheck = _facilityContext.UsersOutofGymDetails.Where(o => o.UniqueEntryID == user.Id).FirstOrDefault().EstimatedTimeToCheck; DateTime estimatedExitTimeCurrentUser = DateTime.Now; // default to false for access ViewBag.AccessGrantedToFacility = false; // door open status depends on database value ViewBag.DoorOpened = facility.DoorOpened; // Decide to increase or decrease the estimated numbers in gym // if there are entries get the estimated exit time estimatedExitTimeCurrentUser = GetEstimatedNumberOfGymUsers(facilityDetails, estimatedTimeToCheck, estimatedExitTimeCurrentUser); // access denied message is normally true // if time since the date where user was denied, is more than 5 seconds, then access denied msg received is not received so present the access denial ViewBag.AccessDeniedMsgRecieved = true; if (DateTime.Now <= (user.TimeAccessDenied.AddSeconds(10))) { ViewBag.AccessDeniedMsgRecieved = false; } // TODO: Logic for conditonally displaying if current time after last workout logged then send to log workout, and inside gym //if (DateTime.Now > user.TimeLoggedWorkout && user.IsInsideGym) // return RedirectToAction("LogWorkout", "Facilities", new { id = user.DefaultGym }); return(View(facility)); }
// Face detection method private async Task FacialRecognitionScan(ApplicationUser user, UsersInGymDetail currentFacilityDetail) { // initialize similarity threshold for accepting face match, source and target img. // S3 bucket img, dynamically selected based on user currently logged in. float similarityThreshold = 70F; string photo = $"{user.FirstName}_{user.Id}.jpg"; String targetImage = $"{user.FirstName}_{user.Id}_Target.jpg"; try { // create image objects Image imageSource = new Image() { S3Object = new S3Object() { Name = photo, Bucket = bucket }, }; Image imageTarget = new Image() { S3Object = new S3Object() { Name = targetImage, Bucket = bucket }, }; // create a compare face request object CompareFacesRequest compareFacesRequest = new CompareFacesRequest() { SourceImage = imageSource, TargetImage = imageTarget, SimilarityThreshold = similarityThreshold }; // detect face features of img scanned CompareFacesResponse compareFacesResponse = await AmazonRekognition.CompareFacesAsync(compareFacesRequest); // Display results foreach (CompareFacesMatch match in compareFacesResponse.FaceMatches) { ComparedFace face = match.Face; // if confidence for similarity is over 90 then grant access if (match.Similarity > 90) { // if there is a match set scan success user.IsCameraScanSuccessful = true; } else { ViewBag.MatchResult = "Facial Match Failed!"; } } } catch (Exception e) { _logger.LogInformation(e.Message); } // now add get facial details to display in the view. DetectFacesRequest detectFacesRequest = new DetectFacesRequest() { Image = new Image() { S3Object = new S3Object() { Name = targetImage, Bucket = bucket }, }, // "DEFAULT": BoundingBox, Confidence, Landmarks, Pose, and Quality. Attributes = new List <String>() { "ALL" } }; try { DetectFacesResponse detectFacesResponse = await AmazonRekognition.DetectFacesAsync(detectFacesRequest); bool hasAll = detectFacesRequest.Attributes.Contains("ALL"); foreach (FaceDetail face in detectFacesResponse.FaceDetails) { // if the face found has all attributes within a Detect Face object then save these values to the database. if (hasAll) { currentFacilityDetail.IsSmiling = face.Smile.Value; currentFacilityDetail.Gender = face.Gender.Value.ToString(); currentFacilityDetail.AgeRangeLow = face.AgeRange.Low; currentFacilityDetail.AgeRangeHigh = face.AgeRange.High; } } } catch (Exception e) { _logger.LogInformation(e.Message); } }
private async Task LeaveGym(Facility facilityView, ApplicationUser user, Facility facility, List <UsersInGymDetail> facilityDetails, UsersInGymDetail currentFacilityDetailDb) { user.IsInsideGym = false; // if it is not 0 then we can decrement to avoid negatives if (facility.NumberOfClientsInGym != 0) { facility.NumberOfClientsInGym--; } // adjust all variables to update the user to a left gym status if (user.WillUseWeightsRoom) { facility.NumberOfClientsUsingWeightRoom--; user.WillUseWeightsRoom = false; } if (user.WillUseCardioRoom && facility.NumberOfClientsUsingCardioRoom != 0) { facility.NumberOfClientsUsingCardioRoom--; user.WillUseCardioRoom = false; } if (user.WillUseStretchRoom && facility.NumberOfClientsUsingStretchRoom != 0) { facility.NumberOfClientsUsingStretchRoom--; user.WillUseWeightsRoom = false; } // if there are entries for facilities, loop through all the facilities, remove the entry which is stamped with the current user entry if (facilityDetails.Count() > 0) { _facilityContext.UsersInGymDetails.Remove(currentFacilityDetailDb); } facilityView.IsCameraScanSuccessful = false; user.IsWithin10m = false; user.IsCameraScanSuccessful = false; user.AccessGrantedToFacility = false; // delete detected image from S3 bucket try { string keyName = $"{user.FirstName}_{user.Id}.jpg"; var deleteObjectRequest = new Amazon.S3.Model.DeleteObjectRequest { BucketName = bucket, Key = keyName }; await S3Client.DeleteObjectAsync(deleteObjectRequest); } catch (AmazonS3Exception e) { _logger.LogInformation(e.Message); } catch (Exception e) { _logger.LogInformation(e.Message); } }
// Method that applies action based on whether user is entering or exiting the gym private async Task <bool> DetermineEnterOrExitGym(Facility facilityView, ApplicationUser user, Facility facility, List <UsersInGymDetail> facilityDetails, UsersInGymDetail currentFacilityDetail, UsersInGymDetail currentFacilityDetailDb, bool enteredGym, UsersOutOfGymDetails allGymUserRecords) { if (facilityView.IsOpenDoorRequested) { // perform facial recognition scan if not inside the gym if (!user.IsInsideGym) { await FacialRecognitionScan(user, currentFacilityDetail); } // Location scan (results from HERE API using javascript) is passed to this POST Action Method // when the checkbox's value is checked we assign user.IsWithin10m as true, // satisfying the first requirement to gaining access to the facility if (facilityView.IsWithin10m) { user.IsWithin10m = true; } // if camera scan and location check is true, and user is not in the gym, then we open the door, and access granted is true if (user.IsWithin10m && user.IsCameraScanSuccessful && !user.IsInsideGym) { user.AccessGrantedToFacility = true; ViewBag.AccessGrantedToFacility = true; } // if camera scan is not successful else if (!facilityView.IsCameraScanSuccessful && !user.IsWithin10m) { user.AccessGrantedToFacility = false; } if (user.AccessGrantedToFacility) { facility.DoorOpened = true; // if the user is not in the gym, then say this user is not in the gym, and increase object values as required. if (!user.IsInsideGym) { facility.NumberOfClientsInGym++; user.IsInsideGym = true; user.TimeAccessGranted = DateTime.Now; currentFacilityDetail.TimeAccessGranted = DateTime.Now; currentFacilityDetail.FirstName = user.FirstName; currentFacilityDetail.UniqueEntryID = user.Id; currentFacilityDetail.FacilityID = facility.FacilityID; enteredGym = true; // TODO: Use AJAX to async send to and from the client at the same time } // <--------------------------------- LEAVE GYM ----------------------------------------------------------- // if the user is already in the gym, when button is pushed then make reset all access to false, and decrement the number of ppl in the gym by 1 else if (user.IsInsideGym) { await LeaveGym(facilityView, user, facility, facilityDetails, currentFacilityDetailDb); } } // end access granted else if (!user.AccessGrantedToFacility) { ViewBag.AccessDeniedMsgRecieved = false; user.TimeAccessDenied = DateTime.Now; } // if door has been opened and user is authorised if (facility.DoorOpened && user.AccessGrantedToFacility) { // log the time granted, and wait 5 seconds. System.Threading.Thread.Sleep(5000); } // When 5 second timer finishes, we close the door again automatically facility.IsOpenDoorRequested = false; ViewBag.IsOpenDoorRequested = false; facility.DoorOpened = false; _facilityContext.Update(facility); // if we are entering gym, use the new facility object, if we are leaving, use the facility detail using Db values. if (enteredGym) { _facilityContext.Update(currentFacilityDetail); } // after a facility exist, then we can update facility to avoid foreign key constraint? await _facilityContext.SaveChangesAsync(); await _userManager.UpdateAsync(user); } return(enteredGym); }