private void CreatePlayersLayout(RadDiagram diagram, HudDragCanvas dgCanvas, ReplayerViewModel viewModel)
        {
            var seats = (int)CurrentCapacity;

            var positionProvider = ServiceLocator.Current.GetInstance <IPositionProvider>(ReplayerPokerSite.ToString());

            var labelPositions = positionProvider.Positions[seats];
            var hasHoleCards   = viewModel.CurrentGame.Players.Any(x => x.hasHoleCards);
            var cardsCount     = hasHoleCards ? viewModel.CurrentGame.Players.Where(x => x.hasHoleCards).Max(x => x.HoleCards.Count) : 2;

            for (var i = 0; i < seats; i++)
            {
                var player = viewModel.PlayersCollection[i];
                var label  = CreatePlayerLabel(player);

                label.X = labelPositions[i, 0];
                label.Y = labelPositions[i, 1];

                PlaceCardLabels(diagram, label, cardsCount);

                player.ChipsContainer.ChipsShape.X = predefinedChipsPositions[seats][i, 0];
                player.ChipsContainer.ChipsShape.Y = predefinedChipsPositions[seats][i, 1];

                AddPotPlayerLabel(diagram, viewModel.PlayersCollection[i], predefinedChipsPositions[seats][i, 0], predefinedChipsPositions[seats][i, 1]);

                diagram.AddShape(label);
                diagram.AddShape(player.ChipsContainer.ChipsShape);
            }
        }
        private void ClearHUD(HudDragCanvas dgCanvas)
        {
            foreach (var panel in dgCanvas.Children.OfType <FrameworkElement>().ToList())
            {
                dgCanvas.Children.Remove(panel);
            }

            dgCanvas.UpdateLayout();
            EmptySeats.Clear();
        }
        private void SaveHUDPositions(HudDragCanvas dgCanvas, ReplayerViewModel viewModel)
        {
            var layout = hudLayoutsService.GetLayout(viewModel.LayoutName);

            if (layout == null)
            {
                LogProvider.Log.Warn($"Failed to save HUD positions. Could not find layout '{viewModel.LayoutName}'");
                return;
            }

            try
            {
                var hudLayoutContract = new HudLayoutContract
                {
                    LayoutName   = viewModel.LayoutName,
                    GameType     = EnumGameType.CashHoldem,
                    PokerSite    = ReplayerPokerSite,
                    TableType    = layout.TableType,
                    HudPositions = new List <HudPositionContract>()
                };

                // clone is needed
                var toolViewModels = dgCanvas.Children.OfType <FrameworkElement>()
                                     .Where(x => x != null && (x.DataContext is IHudNonPopupToolViewModel))
                                     .Select(x => x.DataContext as HudBaseToolViewModel)
                                     .Concat(EmptySeats
                                             .SelectMany(x => x.Tools)
                                             .OfType <IHudNonPopupToolViewModel>()
                                             .Cast <HudBaseToolViewModel>());

                foreach (var toolViewModel in toolViewModels)
                {
                    var seatNumber = toolViewModel.Parent != null ? toolViewModel.Parent.Seat : 1;

                    var xPos = toolViewModel.OffsetX ?? toolViewModel.Position.X;
                    var yPos = toolViewModel.OffsetY ?? toolViewModel.Position.Y;

                    hudLayoutContract.HudPositions.Add(new HudPositionContract
                    {
                        Id         = toolViewModel.Id,
                        Position   = new Point(xPos, yPos),
                        SeatNumber = seatNumber
                    });
                }

                hudLayoutsService.Save(hudLayoutContract);
            }
            catch (Exception e)
            {
                LogProvider.Log.Error(this, "Failed to save HUD positions in replayer.", e);
            }
        }
        public void ConfigureTable(RadDiagram diagram, HudDragCanvas dgCanvas, ReplayerViewModel viewModel)
        {
            try
            {
                if (viewModel == null || viewModel.CurrentGame == null)
                {
                    LogProvider.Log.Info("Cannot find handHistory");
                    return;
                }

                CurrentCapacity = GetTableSize(viewModel);

                CreateTable(diagram);
                CreatePlayersLayout(diagram, dgCanvas, viewModel);
                CreateCurrentPotValueLabel(diagram, viewModel);
                CreateTotalPotValueLabel(diagram, viewModel);
                PlaceTableCardPanels(diagram, viewModel);
                InitializeHUD(dgCanvas, viewModel);
            }
            catch (Exception e)
            {
                LogProvider.Log.Error(this, "ReplayerTable: Cannot configure table", e);
            }
        }
        private void RotateHUD(bool clockwise, EnumTableType tableType, HudDragCanvas dgCanvas)
        {
            try
            {
                var tableSize = (int)tableType;

                var toolsBySeats = dgCanvas.Children.OfType <FrameworkElement>()
                                   .Where(x => x != null && (x.DataContext is IHudNonPopupToolViewModel))
                                   .Select(x => new
                {
                    Tool  = x.DataContext as HudBaseToolViewModel,
                    Panel = x
                })
                                   .Concat(EmptySeats
                                           .SelectMany(x => x.Tools)
                                           .OfType <IHudNonPopupToolViewModel>()
                                           .Cast <HudBaseToolViewModel>()
                                           .Select(x => new
                {
                    Tool  = x as HudBaseToolViewModel,
                    Panel = (FrameworkElement)null
                }))
                                   .GroupBy(x => x.Tool.Parent.Seat)
                                   .ToDictionary(x => x.Key, x => x.ToArray());

                var toolsById = toolsBySeats.Values
                                .SelectMany(x => x)
                                .GroupBy(x => x.Tool.Id, x => new
                {
                    OffsetX = x.Tool.OffsetX ?? x.Tool.Position.X,
                    OffsetY = x.Tool.OffsetY ?? x.Tool.Position.Y,
                    x.Tool.Parent.Seat
                })
                                .ToDictionary(x => x.Key, x => x.GroupBy(p => p.Seat).ToDictionary(p => p.Key, p => p.FirstOrDefault()));

                for (var seat = 1; seat <= tableSize; seat++)
                {
                    var newSeat = clockwise ? seat + 1 : seat - 1;

                    if (newSeat > tableSize)
                    {
                        newSeat = 1;
                    }
                    else if (newSeat < 1)
                    {
                        newSeat = tableSize;
                    }

                    var nonPopupTools = toolsBySeats[seat];

                    foreach (var nonPopupTool in nonPopupTools)
                    {
                        if (!toolsById.ContainsKey(nonPopupTool.Tool.Id) ||
                            !toolsById[nonPopupTool.Tool.Id].ContainsKey(newSeat))
                        {
                            continue;
                        }

                        var newOffsets = toolsById[nonPopupTool.Tool.Id][newSeat];

                        if (newOffsets == null)
                        {
                            continue;
                        }

                        nonPopupTool.Tool.OffsetX = newOffsets.OffsetX;
                        nonPopupTool.Tool.OffsetY = newOffsets.OffsetY;

                        if (nonPopupTool.Panel == null)
                        {
                            continue;
                        }

                        Canvas.SetLeft(nonPopupTool.Panel, newOffsets.OffsetX);
                        Canvas.SetTop(nonPopupTool.Panel, newOffsets.OffsetY);
                    }
                }
            }
            catch (Exception e)
            {
                LogProvider.Log.Error(this, "Failed to rotate HUD positions in replayer.", e);
            }
        }
        private void LoadHUD(HudDragCanvas dgCanvas, ReplayerViewModel viewModel, HudLayoutInfoV2 activeLayout)
        {
            var seats = (int)CurrentCapacity;

            var hudPanelService = ServiceLocator.Current.GetInstance <IHudPanelService>(ReplayerPokerSite.ToString());

            var nonToolLayoutStats = activeLayout
                                     .HudPlayerTypes
                                     .SelectMany(x => x.Stats)
                                     .Select(x => x.Stat)
                                     .Concat(activeLayout
                                             .HudBumperStickerTypes
                                             .SelectMany(x => x.Stats)
                                             .Select(x => x.Stat))
                                     .Concat(new[] { Stat.TotalHands })
                                     .Distinct()
                                     .ToArray();

            var hudElements = new List <HudElementViewModel>();

            var hudElementCreator = ServiceLocator.Current.GetInstance <IHudElementViewModelCreator>();

            var hudElementCreationInfo = new HudElementViewModelCreationInfo
            {
                GameType      = EnumGameType.CashHoldem,
                HudLayoutInfo = activeLayout,
                PokerSite     = ReplayerPokerSite
            };

            for (var i = 0; i < seats; i++)
            {
                var replayerPlayer = viewModel.PlayersCollection[i];

                hudElementCreationInfo.SeatNumber = i + 1;

                if ((int)activeLayout.TableType < hudElementCreationInfo.SeatNumber)
                {
                    continue;
                }

                var hudElement = hudElementCreator.Create(hudElementCreationInfo);

                if (string.IsNullOrEmpty(replayerPlayer.Name))
                {
                    if (hudElement != null)
                    {
                        EmptySeats.Add(hudElement);
                    }
                    continue;
                }

                var player = dataService.GetPlayer(replayerPlayer.Name, viewModel.CurrentHand.PokersiteId);

                if (player == null)
                {
                    if (hudElement != null)
                    {
                        EmptySeats.Add(hudElement);
                    }
                    continue;
                }

                if (hudElement == null ||
                    !playerIndicators.TryGetValue(replayerPlayer.Name, out HudIndicators playerData))
                {
                    continue;
                }

                hudElement.PlayerId   = player.PlayerId;
                hudElement.PlayerName = replayerPlayer.Name;
                hudElement.TotalHands = playerData.TotalHands;

                var playerNotes = dataService.GetPlayerNotes(player.PlayerId);
                hudElement.NoteToolTip       = NoteBuilder.BuildNote(playerNotes);
                hudElement.IsXRayNoteVisible = playerNotes.Any(x => x.IsAutoNote);

                var graphTools = hudElement.Tools.OfType <HudGraphViewModel>().ToArray();

                foreach (var graphTool in graphTools)
                {
                    graphTool.StatSessionCollection = new ReactiveList <decimal>();
                }

                var heatMapTools = hudElement.Tools.OfType <HudHeatMapViewModel>()
                                   .Concat(hudElement.Tools.OfType <HudGaugeIndicatorViewModel>()
                                           .SelectMany(x => x.GroupedStats)
                                           .SelectMany(x => x.Stats)
                                           .Where(x => x.HeatMapViewModel != null)
                                           .Select(x => x.HeatMapViewModel))
                                   .ToArray();

                heatMapTools.ForEach(x =>
                {
                    var heatMapKey = playerData.HeatMaps.Keys
                                     .ToArray()
                                     .FirstOrDefault(p => p.Stat == x.BaseStat.Stat);

                    if (heatMapKey != null)
                    {
                        x.HeatMap = playerData.HeatMaps[heatMapKey];
                    }
                });

                var gaugeIndicatorTools = hudElement.Tools.OfType <HudGaugeIndicatorViewModel>().ToArray();

                hudElement.SessionMoneyWonCollection = new ObservableCollection <decimal>();

                var activeLayoutHudStats = hudElement.ToolsStatInfoCollection
                                           .Concat(heatMapTools.Select(x => x.BaseStat))
                                           .Concat(gaugeIndicatorTools.Select(x => x.BaseStat))
                                           .ToList();

                var extraStats = (from nonToolLayoutStat in nonToolLayoutStats
                                  join activateLayoutHudStat in activeLayoutHudStats on nonToolLayoutStat equals activateLayoutHudStat.Stat into grouped
                                  from extraStat in grouped.DefaultIfEmpty()
                                  where extraStat == null
                                  select new StatInfo
                {
                    Stat = nonToolLayoutStat
                }).ToArray();

                activeLayoutHudStats.AddRange(extraStats);

                StatsProvider.UpdateStats(activeLayoutHudStats);

                foreach (var statInfo in activeLayoutHudStats)
                {
                    var propertyName = StatsProvider.GetStatProperyName(statInfo.Stat);

                    if (!string.IsNullOrEmpty(propertyName))
                    {
                        if (playerData.TotalHands < statInfo.MinSample)
                        {
                            statInfo.IsNotVisible = true;
                        }

                        statInfo.AssignStatInfoValues(playerData, propertyName);
                    }
                    else if (!(statInfo is StatInfoBreak) && statInfo.Stat != Stat.PlayerInfoIcon)
                    {
                        continue;
                    }
                }

                hudElement.StatInfoCollection = activeLayoutHudStats;

                var isNoteIconSet = false;

                foreach (var toolViewModel in hudElement.Tools.Where(x => x is IHudNonPopupToolViewModel).ToArray())
                {
                    if (!isNoteIconSet && toolViewModel is HudPlainStatBoxViewModel && !(toolViewModel is HudFourStatsBoxViewModel))
                    {
                        (toolViewModel as HudPlainStatBoxViewModel).IsNoteIconEnabled = true;
                        isNoteIconSet = true;
                    }

                    var panel = hudPanelService.Create(toolViewModel);

                    if (panel != null)
                    {
                        dgCanvas.Children.Add(panel);

                        Canvas.SetLeft(panel, toolViewModel.Position.X);
                        Canvas.SetTop(panel, toolViewModel.Position.Y);
                    }
                }

                hudElements.Add(hudElement);
            }

            hudLayoutsService.SetPlayerTypeIcon(hudElements, activeLayout);
        }
        private async void InitializeHUD(HudDragCanvas dgCanvas, ReplayerViewModel viewModel)
        {
            var gameNumber = viewModel.CurrentHand.GameNumber;
            var pokerSite  = viewModel.CurrentHand.PokersiteId;

            ClearHUD(dgCanvas);

            viewModel.IsLoadingHUD = true;

            var seats = (int)CurrentCapacity;

            var tableType = (EnumTableType)viewModel.CurrentGame.GameDescription.SeatType.MaxPlayers;

            // need to add DriveHUDReplayer to sites, add provider, panel service etc.
            var activeLayout = hudLayoutsService.GetActiveLayout(ReplayerPokerSite,
                                                                 tableType,
                                                                 EnumGameType.CashHoldem);

            viewModel.LayoutName        = activeLayout.Name;
            viewModel.LayoutsCollection = new ObservableCollection <string>(hudLayoutsService.GetAvailableLayouts(tableType));
            viewModel.LoadLayoutCommand = new RelayCommand(obj =>
            {
                try
                {
                    var layoutName = obj?.ToString();

                    if (string.IsNullOrWhiteSpace(layoutName))
                    {
                        return;
                    }

                    viewModel.LayoutName = layoutName;

                    var layout = hudLayoutsService.GetLayout(layoutName);

                    var layoutHeatMapStats = new HashSet <Stat>(layout.GetHeatMapStats());

                    // there are no loaded heat map stats
                    if (layoutHeatMapStats.Count > 0 &&
                        layoutHeatMapStats.Any(x => !heatMapStats.Contains(x)))
                    {
                        viewModel.IsLoadingHUD = true;
                        playerIndicators.Clear();
                        LoadIndicators(seats, viewModel, layoutHeatMapStats);
                        heatMapStats           = layoutHeatMapStats;
                        viewModel.IsLoadingHUD = false;
                    }

                    ClearHUD(dgCanvas);
                    LoadHUD(dgCanvas, viewModel, layout);

                    hudLayoutsService.SetActiveLayout(layout, ReplayerPokerSite, EnumGameType.CashHoldem, tableType);
                }
                catch (Exception e)
                {
                    LogProvider.Log.Error(this, "Failed to load layout", e);
                }
            });

            viewModel.SaveHUDPositionsCommand = new RelayCommand(obj => SaveHUDPositions(dgCanvas, viewModel));
            viewModel.RotateHUDToLeftCommand  = new RelayCommand(() => RotateHUD(false, tableType, dgCanvas));
            viewModel.RotateHUDToRightCommand = new RelayCommand(() => RotateHUD(true, tableType, dgCanvas));

            heatMapStats = new HashSet <Stat>(activeLayout.GetHeatMapStats());

            await Task.Run(() => LoadIndicators(seats, viewModel, heatMapStats));

            if (gameNumber != viewModel.CurrentHand.GameNumber ||
                pokerSite != viewModel.CurrentHand.PokersiteId)
            {
                return;
            }

            LoadHUD(dgCanvas, viewModel, activeLayout);

            viewModel.IsLoadingHUD = false;
        }