public void Checkout() { if (customerInfo == null) // no previous transactions { if (customerRegistrationInfo == null) // unregistered customer { IgniteDataAccess.CreateNewTransaction(ItemGiveaway.ItemId, ItemGiveaway.ProductQty, IgniteDataAccess.UNREGISTERED_CUSTOMERID); } else { IgniteDataAccess.CreateNewTransaction(ItemGiveaway.ItemId, ItemGiveaway.ProductQty, customerRegistrationInfo.CustomerFaceHash); } } else { IgniteDataAccess.CreateNewTransaction(ItemGiveaway.ItemId, ItemGiveaway.ProductQty, customerInfo.CustomerFaceHash); } // TODO: report transaction success status // Prepare for the next customer UpdateCustomer(null); ItemGiveaway.Reset(IgniteDataServices.GetLocatedProduct(), 1); TotalItems = 1; IsWarningNoCheckout = false; }
public async Task SignIn() { try { // 1. Try to identify the person await customerFace.DetectFacesAsync(); await customerFace.IdentifyFacesAsync(); // TODO: consider looping over identified persons to find matching DB record customerInfo = new CustomerRegistrationInfo(); customerInfo.CustomerFaceHash = customerFace.IdentifiedPersons.First().Person.PersonId.ToString(); customerInfo.CustomerName = customerFace.IdentifiedPersons.First().Person.Name; // 2. Try to obtain customer info from DB CustomerInfo dbCustomerInfo = IgniteDataAccess.GetCustomerInfo(customerInfo.CustomerFaceHash); customerInfo.RegistrationDate = dbCustomerInfo.PreviousVisitDate; // 3. Update status StatusText = $"Welcome, {customerInfo.CustomerName}!"; StatusTextColor = Util.ToBrush("green"); PauseCamera?.Invoke(this, EventArgs.Empty); } catch (Exception) { customerInfo = null; StatusText = "Please try again."; StatusTextColor = Util.ToBrush("red"); ResumeCamera?.Invoke(this, EventArgs.Empty); } }
private async Task ProcessCameraCapture(ImageAnalyzer e) { if (this.isEngagingCustomer) { this.isProcessingPhoto = false; return; } if (e == null) { this.allowSendingOffMsg = false; this.ViewModel.Update(DemoScreenState.NoFace); this.isProcessingPhoto = false; return; } await e.DetectFacesAsync(); if (e.DetectedFaces.Any()) { await e.IdentifyFacesAsync(); bool recognized = false; if (e.IdentifiedPersons.Any()) { var candidate = e.IdentifiedPersons.First().Person; // Check if this is a registered customer, who made purchases, before recognizing CustomerInfo ci = IgniteDataAccess.GetCustomerInfo(candidate.PersonId.ToString()); if (ci != null) { recognized = true; await EngageRecognizedCustomer(ci); } } if (!recognized) { await EngageUnrecognized(); } } // else CameraControl captured a face, but ImageAnalyzer cannot detect any - no change of state in this case this.isProcessingPhoto = false; }
private CustomerRegistrationInfo customerRegistrationInfo; // obtained form registration UI public void UpdateCustomer(CustomerRegistrationInfo info) { customerRegistrationInfo = info; if (info != null && info.CustomerName.Length > 0) { customerInfo = IgniteDataAccess.GetCustomerInfo(info.CustomerFaceHash); if (customerInfo == null) // first visit { IsRecognized = true; IsUnrecognized = false; CustomerName = info.CustomerName; VisitDateStr = ""; PreviousPurchase = ""; RecommendedActions = IgniteDataServices.GetRecommendedActions(customerInfo); IsWarningNoCheckout = true; // we want to avoid having registered customers without transactions } else // second visit { IsRecognized = true; IsUnrecognized = false; CustomerName = customerInfo.CustomerName; VisitDateStr = customerInfo.PreviousVisitDate.ToString("MM/dd/yyyy"); PreviousPurchase = ProductCatalog.Instance.GetProductById(customerInfo.SourceItemId).ItemDescription; RecommendedActions = IgniteDataServices.GetRecommendedActions(customerInfo); } } else { customerInfo = null; IsRecognized = false; IsUnrecognized = true; CustomerName = ""; VisitDateStr = ""; PreviousPurchase = ""; RecommendedActions = ""; } }
private void OnTestBackendFlyoutOpened(object sender, object e) { try { // Run DB tests var customers = IgniteDataAccess.GetCustomers(); string testGetCustomers = (customers != null) ? customers.Count.ToString() : "FAIL"; string unregCustomerGuid = "00000000-0000-0000-0000-000000000000"; bool createCustomerRes = IgniteDataAccess.CreateCustomerRecord(unregCustomerGuid, "UNREGISTERED"); string testCreateCustomerRecord = createCustomerRes ? "OK" : "FAIL"; bool createNewTransactionRes = IgniteDataAccess.CreateNewTransaction(11110, 1, unregCustomerGuid); string testCreateNewTransaction = createNewTransactionRes ? "OK" : "FAIL"; var customerInfo = IgniteDataAccess.GetCustomerInfo(unregCustomerGuid); string testGetCustomerInfo = (customerInfo?.CustomerName == "UNREGISTERED" && customerInfo?.SourceItemId == 11110) ? "OK" : "FAIL"; var inventoryStats = IgniteDataAccess.GetInventoryStats(); string testGetInventoryStats = "FAIL"; foreach (InventoryItemStats iist in inventoryStats) { if (iist.ItemId == 11110) { testGetInventoryStats = iist.RemainingInventory.ToString(); } } this.backendTestResultTextBox.Text = $"GetCustomers.Count: {testGetCustomers}\n" + $"CreateCutomerRecord: {testCreateCustomerRecord}\n" + $"CreateNewTransaction: {testCreateNewTransaction}\n" + $"GetCustomerInfo: {testGetCustomerInfo}\n" + $"GetInventoryStats.RemainingInventory: {testGetInventoryStats}"; } catch (Exception ex) { this.backendTestResultTextBox.Text = $"Exception: {ex.Message}"; } }
public async Task Register() { IsRegistrationEnabled = false; try { IEnumerable <PersonGroup> PersonGroups = null; int i = 3; //retry count // 1. Select group // If the group is full, another one needs to added manually with alphabetically preceeding name do { PersonGroups = await FaceServiceHelper.ListPersonGroupsAsync(SettingsHelper.Instance.WorkspaceKey); if (PersonGroups.Count() > 0) { CurrentPersonGroup = PersonGroups.OrderBy(pg => pg.Name).First(); } // Do not forget to create a persons group if there is not one else { await FaceServiceHelper.CreatePersonGroupAsync(Guid.NewGuid().ToString(), "DefaultGroup", SettingsHelper.Instance.WorkspaceKey); } i--; } while (PersonGroups.Count() < 1 && i >= 0); // 2. Create a person in that group CurrentPerson = await FaceServiceHelper.CreatePersonAsync(this.CurrentPersonGroup.PersonGroupId, FullName); // 3. Add face to that person CurrentFace = await FaceServiceHelper.AddPersonFaceFromStreamAsync( CurrentPersonGroup.PersonGroupId, CurrentPerson.PersonId, imageStreamCallback : customerFace.GetImageStreamCallback, userData : customerFace.LocalImagePath, targetFaceRect : null); // 4. Train model await FaceServiceHelper.TrainPersonGroupAsync(CurrentPersonGroup.PersonGroupId); bool trainingSucceeded = false; bool recordAdded = false; while (true) { TrainingStatus trainingStatus = await FaceServiceHelper.GetPersonGroupTrainingStatusAsync(CurrentPersonGroup.PersonGroupId); if (trainingStatus.Status == TrainingStatusType.Succeeded) { trainingSucceeded = true; break; } else if (trainingStatus.Status == TrainingStatusType.Failed) { break; } await Task.Delay(100); } // 5. Add record to the database if (trainingSucceeded) { customerInfo = new CustomerRegistrationInfo { CustomerFaceHash = CurrentPerson.PersonId.ToString(), CustomerName = FullName, RegistrationDate = DateTime.Now }; recordAdded = IgniteDataAccess.CreateCustomerRecord(customerInfo.CustomerFaceHash, customerInfo.CustomerName); } // 6. Update status if (trainingSucceeded && recordAdded) { StatusText = "Success!"; StatusTextColor = Util.ToBrush("green"); } else { customerInfo = null; IsRegistrationEnabled = true; StatusText = "Please try again later"; StatusTextColor = Util.ToBrush("red"); ResumeCamera?.Invoke(this, EventArgs.Empty); } } catch (Exception) { customerInfo = null; IsRegistrationEnabled = true; StatusText = "Please try again"; StatusTextColor = Util.ToBrush("red"); ResumeCamera?.Invoke(this, EventArgs.Empty); } }
public void Update() { try { var stats = IgniteDataAccess.GetInventoryStats(); var registrations = IgniteDataAccess.GetCustomers(); DateTime todayStart = DateTime.Now.Date; int customersTodayQty = (from r in registrations where r.RegistrationDate > todayStart select r).Count(); CustomersToday = $"{customersTodayQty} new customers registered today"; DateTime lastHrStart = DateTime.Now.AddHours(-1); int customersLastHrQty = (from r in registrations where r.RegistrationDate > lastHrStart select r).Count(); CustomersLastHr = $"{customersLastHrQty} new customers registered past hour"; int leftProdId = ProductCatalog.Instance.LeftProduct.ItemId; int rightProdId = ProductCatalog.Instance.RightProduct.ItemId; string leftProdHName = ProductCatalog.Instance.LeftProduct.ProductHierarchyName; string rightProdHName = ProductCatalog.Instance.RightProduct.ProductHierarchyName; int leftProductSoldTodayQty = (from i in stats where i.ProductHierarchyName == leftProdHName select i.TodayQtySold).Sum(); LeftProductSoldToday = $"{leftProductSoldTodayQty} {leftProdHName} sold today"; int rightProductSoldTodayQty = (from i in stats where i.ProductHierarchyName == rightProdHName select i.TodayQtySold).Sum(); RightProductSoldToday = $"{rightProductSoldTodayQty} {rightProdHName} sold today"; int leftProductSoldLastHrQty = (from i in stats where i.ProductHierarchyName == leftProdHName select i.LastHrQtySold).Sum(); LeftProductSoldLastHr = $"{leftProductSoldLastHrQty} {leftProdHName} sold past hour"; int rightProductSoldLastHrQty = (from i in stats where i.ProductHierarchyName == rightProdHName select i.LastHrQtySold).Sum(); RightProductSoldLastHr = $"{rightProductSoldLastHrQty} {rightProdHName} sold past hour"; int leftProductOnFloorQty = (from i in stats where i.ProductHierarchyName == leftProdHName select i.RemainingInventory).Sum(); LeftProductOnFloor = $"{leftProductOnFloorQty} {leftProdHName} in stock on floor"; int rightProductOnFloorQty = (from i in stats where i.ProductHierarchyName == rightProdHName select i.RemainingInventory).Sum(); RightProductOnFloor = $"{rightProductOnFloorQty} {rightProdHName} in stock on floor"; int leftProductInWarehouseQty = 100; // steady supply :) LeftProductInWarehouse = $"{leftProductInWarehouseQty} {leftProdHName} in stock in warehouse"; int rightProductInWarehouseQty = 100; RightProductInWarehouse = $"{rightProductInWarehouseQty} {rightProdHName} in stock in warehouse"; SeriesSales = new List <ChartPointRecord>(); SeriesSales.Add(new ChartPointRecord { Label = $"{leftProdHName} sold today -", Value = leftProductSoldTodayQty, Id = 1 }); SeriesSales.Add(new ChartPointRecord { Label = $"{rightProdHName} sold today -", Value = rightProductSoldTodayQty, Id = 2 }); SeriesSales.Add(new ChartPointRecord { Label = $"{leftProdHName} sold past hour -", Value = leftProductSoldLastHrQty, Id = 3 }); SeriesSales.Add(new ChartPointRecord { Label = $"{rightProdHName} sold past hour -", Value = rightProductSoldLastHrQty, Id = 4 }); SeriesInventory = new List <ChartPointRecord>(); SeriesInventory.Add(new ChartPointRecord { Label = $"{leftProdHName} in stock on floor -", Value = leftProductOnFloorQty, Id = 1 }); SeriesInventory.Add(new ChartPointRecord { Label = $"{rightProdHName} in stock on floor -", Value = rightProductOnFloorQty, Id = 2 }); SeriesInventory.Add(new ChartPointRecord { Label = $"{leftProdHName} in stock in warehouse -", Value = leftProductInWarehouseQty, Id = 3 }); SeriesInventory.Add(new ChartPointRecord { Label = $"{rightProdHName} in stock in warehouse -", Value = rightProductInWarehouseQty, Id = 4 }); SeriesRegistrations = new List <ChartPointRecord>(); SeriesRegistrations.Add(new ChartPointRecord { Label = "registered today -", Value = customersTodayQty, Id = 1 }); SeriesRegistrations.Add(new ChartPointRecord { Label = "registered past hour -", Value = customersLastHrQty, Id = 2 }); // Prepare last 8 hours of arrival data labeled by local time hour string seriesId = SettingsHelper.Instance.CustomerCounterSourceId; var arrivals = IgniteDataAccess.GetArrivalCounts(seriesId, 8); SeriesArrivals = new List <ChartPointRecord>(); int id = 0; foreach (Arrival a in arrivals) { // Label arrivals by the start of their time interval (i.e. arrival at 10:30AM gets labeled by 10AM) DateTime dt = (a.ArrivalDate + new TimeSpan(a.ArrivalHour, 0, 0)).ToLocalTime(); // Use only today's data if (dt.Date == DateTime.Now.Date) { id++; SeriesArrivals.Add(new ChartPointRecord { Label = dt.ToString("htt"), Value = a.Arrivals, Id = id }); } } // Make sure that we have at least one data point if (SeriesArrivals.Count == 0) { DateTime dt = (DateTime.UtcNow).ToLocalTime(); SeriesArrivals.Add(new ChartPointRecord { Label = dt.ToString("htt"), Value = 0, Id = 1 }); } //OnPropertyChanged(null); } catch (Exception ex) { Debug.Write($"Insights Page Update exception: {ex.Message}"); } }