<commit_before>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using QCF.Contest.Contracts.Coordination;
using QCF.Contest.Contracts.GameElements;
using QCF.Contest.Contracts.Moves;

namespace QCF.GameEngine.Analysis
{
	//non directed graph with edges added in both directions 
	public class GameGraph
    {
        private readonly List<FieldCoordinate> endCoordinatesForBottomPlayer = new List<FieldCoordinate>();
        private readonly List<FieldCoordinate> endCoordinatesForTopPlayer    = new List<FieldCoordinate>();

		public IList<Node> Graph { get; } = new List<Node>();
		public IDictionary<FieldCoordinate, Node> GraphDictionary { get; } = new Dictionary<FieldCoordinate, Node>();

	    private FieldCoordinate bottomPlayerPosition;
	    private FieldCoordinate topPlayerPosition;
		
        public GameGraph()
        {
            InitEndCoordinates();
        }

        public GameGraph InitGraph()
        {
            return InitialGraphCreator.CreateInitialGameGraph(this);
        }

        private void InitEndCoordinates()
        {
	        for (var xCoord = XField.A; xCoord <= XField.I; xCoord++)
	        {
				endCoordinatesForBottomPlayer.Add(new FieldCoordinate(xCoord, YField.Nine));
				endCoordinatesForTopPlayer.Add(new FieldCoordinate(xCoord, YField.One));
			}            
        }

        public Node GetNodeForCoordinate(FieldCoordinate coordinate)
        {
            return GraphDictionary[coordinate];
        }

        public void RemoveNode(FieldCoordinate coordinate)
        {
	        var nodeToRemove = GetNodeForCoordinate(coordinate);
	        Graph.Remove(nodeToRemove);          
        }

        public GameGraph ApplyWallsAndPlayers(BoardState boardState)
        {
            foreach (var wall in boardState.PlacedWalls)
            {
               ApplyWall(wall);
            }

	        bottomPlayerPosition = boardState.BottomPlayer.Position;
	        topPlayerPosition = boardState.TopPlayer.Position;

			// TODO: addSpezialEdges if players are neighbours

            return this;
        }

	    private void ApplyWall(Wall wall)
	    {
			var topleftNode     = GetNodeForCoordinate(wall.TopLeft);
			var bottomleftNode  = GetNodeForCoordinate(wall.TopLeft.GetBottom());
			var topRightNode    = GetNodeForCoordinate(wall.TopLeft.GetRight());
			var bottomRightNode = GetNodeForCoordinate(wall.TopLeft.GetBottom().GetRight());

			if (wall.Orientation == WallOrientation.Horizontal)
			{
				topleftNode.Neighbors.Remove(bottomleftNode);
				topRightNode.Neighbors.Remove(bottomRightNode);
				bottomleftNode.Neighbors.Remove(topleftNode);
				bottomRightNode.Neighbors.Remove(topRightNode);
			}
			else
			{
				topleftNode.Neighbors.Remove(topRightNode);
				topRightNode.Neighbors.Remove(topleftNode);
				bottomleftNode.Neighbors.Remove(bottomRightNode);
				bottomRightNode.Neighbors.Remove(bottomleftNode);
			}
		}

        private bool TraverseGraph(Node startNode, IEnumerable<FieldCoordinate> targetCoords)
        {
            foreach (var targetCoord in targetCoords)
            {
                var stack = new Stack<Node>();
                stack.Push(startNode);
                startNode.Visited = true;

                while (stack.Count != 0)
                {
                    var nextNode = stack.Peek();
                    if (nextNode.Coordinate.Equals(targetCoord))
                    {
                        ClearVisitStatusForNodes();
                        return true;
                    }

                    var child = nextNode.Neighbors.FirstOrDefault(n => !n.Visited);
                    if (child == null)
                    {
                        stack.Pop();
                    }
                    else
                    {
                        child.Visited = true;
                        stack.Push(child);
                    }
                }

                ClearVisitStatusForNodes();
            }
            return false;
        }

        private void ClearVisitStatusForNodes()
        {
            foreach (var node in Graph)
                node.Visited = false;
        }

	    public bool ValidateWallMove(WallMove wallMove)
	    {				
			ApplyWall(wallMove.PlacedWall);

			// TODO: Check for spezial edges
					
			return TraverseGraph(GetNodeForCoordinate(topPlayerPosition),    endCoordinatesForTopPlayer) &&
				   TraverseGraph(GetNodeForCoordinate(bottomPlayerPosition), endCoordinatesForBottomPlayer);			
	    }

	    private bool ValidateFigureMove(FigureMove move)
	    {
			var sourceCoordinate = move.PlayerAtMove.PlayerType == PlayerType.BottomPlayer 
										? bottomPlayerPosition 
										: topPlayerPosition;

		    var targetCoordinate = move.NewPosition;

		    var sourceNode = GetNodeForCoordinate(sourceCoordinate);
		    var targetNode = GetNodeForCoordinate(targetCoordinate);

			return sourceNode.Neighbors.Contains(targetNode);
	    }

	    public bool ValidateMove(Move move)
	    {
			if (move is FigureMove)
				return ValidateFigureMove((FigureMove)move);
			else if (move is WallMove)
				return ValidateWallMove((WallMove) move);
			else			
				throw new ArgumentException();					    
	    }

        public override string ToString()
        {
            var builder = new StringBuilder();
            foreach (var node in Graph)
            {
                var elements = "";
                node.Neighbors.ForEach(value => elements += value + ",");
                builder.AppendLine($"{node.Coordinate}: {elements}");
            }

            return builder.ToString();
        }
    }
}<commit_msg>slight code cleanup<commit_after>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using QCF.Contest.Contracts.Coordination;
using QCF.Contest.Contracts.GameElements;
using QCF.Contest.Contracts.Moves;

namespace QCF.GameEngine.Analysis
{
	//non directed graph with edges added in both directions 
	public class GameGraph
    {
        private readonly List<FieldCoordinate> endCoordinatesForBottomPlayer = new List<FieldCoordinate>();
        private readonly List<FieldCoordinate> endCoordinatesForTopPlayer    = new List<FieldCoordinate>();

		public IList<Node> Graph { get; } = new List<Node>();
		public IDictionary<FieldCoordinate, Node> GraphDictionary { get; } = new Dictionary<FieldCoordinate, Node>();

	    private FieldCoordinate bottomPlayerPosition;
	    private FieldCoordinate topPlayerPosition;
		
        public GameGraph()
        {
            InitEndCoordinates();
        }

        public GameGraph InitGraph()
        {
            return InitialGraphCreator.CreateInitialGameGraph(this);
        }

        private void InitEndCoordinates()
        {
	        for (var xCoord = XField.A; xCoord <= XField.I; xCoord++)
	        {
				endCoordinatesForBottomPlayer.Add(new FieldCoordinate(xCoord, YField.Nine));
				endCoordinatesForTopPlayer.Add(new FieldCoordinate(xCoord, YField.One));
			}            
        }

        public Node GetNodeForCoordinate(FieldCoordinate coordinate)
        {
            return GraphDictionary[coordinate];
        }

        public void RemoveNode(FieldCoordinate coordinate)
        {
	        var nodeToRemove = GetNodeForCoordinate(coordinate);
	        Graph.Remove(nodeToRemove);          
        }

        public GameGraph ApplyWallsAndPlayers(BoardState boardState)
        {
            foreach (var wall in boardState.PlacedWalls)
            {
               ApplyWall(wall);
            }

	        bottomPlayerPosition = boardState.BottomPlayer.Position;
	        topPlayerPosition = boardState.TopPlayer.Position;

			// TODO: addSpezialEdges if players are neighbours

            return this;
        }

	    private void ApplyWall(Wall wall)
	    {
			var topleftNode     = GetNodeForCoordinate(wall.TopLeft);
			var bottomleftNode  = GetNodeForCoordinate(wall.TopLeft.GetBottom());
			var topRightNode    = GetNodeForCoordinate(wall.TopLeft.GetRight());
			var bottomRightNode = GetNodeForCoordinate(wall.TopLeft.GetBottom().GetRight());

			if (wall.Orientation == WallOrientation.Horizontal)
			{
				topleftNode.Neighbors.Remove(bottomleftNode);
				topRightNode.Neighbors.Remove(bottomRightNode);
				bottomleftNode.Neighbors.Remove(topleftNode);
				bottomRightNode.Neighbors.Remove(topRightNode);
			}
			else
			{
				topleftNode.Neighbors.Remove(topRightNode);
				topRightNode.Neighbors.Remove(topleftNode);
				bottomleftNode.Neighbors.Remove(bottomRightNode);
				bottomRightNode.Neighbors.Remove(bottomleftNode);
			}
		}

        private bool TraverseGraph(Node startNode, IEnumerable<FieldCoordinate> targetCoords)
        {
            foreach (var targetCoord in targetCoords)
            {
                var stack = new Stack<Node>();
                stack.Push(startNode);
                startNode.Visited = true;

                while (stack.Count != 0)
                {
                    var nextNode = stack.Peek();
                    if (nextNode.Coordinate.Equals(targetCoord))
                    {
                        ClearVisitStatusForNodes();
                        return true;
                    }

                    var child = nextNode.Neighbors.FirstOrDefault(n => !n.Visited);
                    if (child == null)
                    {
                        stack.Pop();
                    }
                    else
                    {
                        child.Visited = true;
                        stack.Push(child);
                    }
                }

                ClearVisitStatusForNodes();
            }
            return false;
        }

        private void ClearVisitStatusForNodes()
        {
            foreach (var node in Graph)
                node.Visited = false;
        }

	    public bool ValidateWallMove(WallMove wallMove)
	    {				
			ApplyWall(wallMove.PlacedWall);

			// TODO: Check for spezial edges
					
			return TraverseGraph(GetNodeForCoordinate(topPlayerPosition),    endCoordinatesForTopPlayer) &&
				   TraverseGraph(GetNodeForCoordinate(bottomPlayerPosition), endCoordinatesForBottomPlayer);			
	    }

	    private bool ValidateFigureMove(FigureMove move)
	    {
			var sourceCoordinate = move.PlayerAtMove.PlayerType == PlayerType.BottomPlayer 
										? bottomPlayerPosition 
										: topPlayerPosition;

		    var targetCoordinate = move.NewPosition;

		    var sourceNode = GetNodeForCoordinate(sourceCoordinate);
		    var targetNode = GetNodeForCoordinate(targetCoordinate);

			return sourceNode.Neighbors.Contains(targetNode);
	    }

	    public bool ValidateMove(Move move)
	    {
			if (move is FigureMove)
				return ValidateFigureMove((FigureMove)move);

			if (move is WallMove)
				return ValidateWallMove((WallMove) move);
					
			throw new ArgumentException();					    
	    }

        public override string ToString()
        {
            var builder = new StringBuilder();
            foreach (var node in Graph)
            {
                var elements = "";
                node.Neighbors.ForEach(value => elements += value + ",");
                builder.AppendLine($"{node.Coordinate}: {elements}");
            }

            return builder.ToString();
        }
    }
}
{'fraction_non_alphanumeric': 0.08178108923186092, 'fraction_numerical': 0.00017739932588256165, 'mean_word_length': 2.1086297215329473, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1691851', 'n_tokens_mistral': 3295, 'n_tokens_neox': 2864, 'n_words': 564}