예제 #1
0
        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;
        }
예제 #2
0
        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);
            }
        }
예제 #3
0
        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;
        }
예제 #4
0
        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}";
            }
        }
예제 #6
0
        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}");
            }
        }