Files
caliverse_server/ServerCore/Pattern/HeirerchyNode.cs
2025-05-01 07:20:41 +09:00

302 lines
7.2 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace ServerCore;
//=============================================================================================
// 계층적으로 노드를 관리할 수 있는 기능을 제공하는 제네릭 클래스 이다.
//
// author : kangms
//
//=============================================================================================
public interface IHeirerchy<T>
{
// 찾으려고 하는 값의 IHeirerchy<T> 를 찾는다.
IHeirerchy<T>? findHeirerchy(T toFind);
// DepthNo 0 일경우 Root 이고 자식 계층이 추가될 경우 1 증가 된다.
Int32 getDepthNo();
// 부모 계층을 수동으로 설정 한다.
void setParent(IHeirerchy<T> parent);
IHeirerchy<T>? getParent();
// 현재의 계층에 자식 노드을 추가 한다.
IHeirerchy<T> addChildNode(IHeirerchy<T> child);
// 현재의 계층에 자식 노드 목록을 반환 한다.
List<IHeirerchy<T>> getChilds();
// 현재 노드에 값을 설정 한다.
void setValue(T value);
// 현재 노드의 값을 반환 한다.
T getValue();
// 현재 계층 부터 부모의 Root 계층 까지 해당 T 타입인지 체크 한다.
bool isUpperHeirerchy(T toCheck);
// 현재 계층 부터 자식의 Leaf 계층 까지 해당 T 타입인지 체크 한다.
bool isLowerHeirerchy(T toCheck);
// 현재 노드가 Root 인가?
bool isRoot();
// 현재 노드가 최하위 노드 인가?
bool isLeaf();
bool isEqual(T value);
// 현재 노드에서 자식 노드 계층의 모든 노드값의 체크해서 성공 & 실패 노드 목록을 반환 한다.
bool onCheckValue(ref HashSet<T> successedNodes, ref List<IHeirerchy<T>> failedNodes);
// 하위 노드 목록을 채워준다.
void fillupLowers(ref List<T> lowers);
}
public class HeirerchyNode<T> : IHeirerchy<T>
{
private T m_value;
private IHeirerchy<T>? m_parent;
private List<IHeirerchy<T>> m_childs = new();
private Int32 m_depth_no = 0;
public HeirerchyNode(T value)
{
m_value = value;
}
public HeirerchyNode(T value, IHeirerchy<T> parent)
{
m_value = value;
setParent(parent);
}
public virtual bool onCheckValue(ref HashSet<T> successedNodes
, ref List<IHeirerchy<T>> failedNodes)
{
var is_success = true;
foreach (var heirerchy_node in getChilds())
{
var value = heirerchy_node.getValue();
if (true == successedNodes.Contains(value))
{
failedNodes.Add(heirerchy_node);
is_success = false;
continue;
}
successedNodes.Add(value);
if (false == heirerchy_node.onCheckValue(ref successedNodes, ref failedNodes))
{
failedNodes.Add(heirerchy_node);
is_success = false;
continue;
}
}
return is_success;
}
public static IHeirerchy<T>? findByTraveral(IHeirerchy<T> root, T toFind)
{
if (true == root.isEqual(toFind))
{
return root;
}
foreach (var heirerchy_node in root.getChilds())
{
var found_heirerchy = heirerchy_node.findHeirerchy(toFind);
if (null != found_heirerchy)
{
return found_heirerchy;
}
}
return null;
}
public IHeirerchy<T>? findHeirerchy(T toFind)
{
if (true == isEqual(toFind))
{
return this;
}
foreach (var heirerchy_node in getChilds())
{
var found_heirerchy = heirerchy_node.findHeirerchy(toFind);
if (null != found_heirerchy)
{
return found_heirerchy;
}
}
return null;
}
public IHeirerchy<T> newAndAddChildNode<THeirerchy>(T childValue) where THeirerchy : IHeirerchy<T>, new()
{
if (m_childs == null)
{
m_childs = new List<IHeirerchy<T>>();
}
var to_add_child_node = new THeirerchy();
to_add_child_node.setValue(childValue);
return addChildNode(to_add_child_node);
}
public IHeirerchy<T> addChildNode(IHeirerchy<T> childNode)
{
if (m_childs == null)
{
m_childs = new List<IHeirerchy<T>>();
}
m_childs.Add(childNode);
childNode.setParent(this);
return childNode;
}
public static IHeirerchy<T>? newAndAddChildNodeOfParent<THeirerchy>(IHeirerchy<T> root, T parentValue, T toAddChildValue) where THeirerchy : IHeirerchy<T>, new()
{
var found_parent_heirerchy = findByTraveral(root, parentValue);
if (null == found_parent_heirerchy)
{
return null;
}
var found_node = found_parent_heirerchy as HeirerchyNode<T>;
if (null == found_node)
{
return null;
}
return found_node.newAndAddChildNode<THeirerchy>(toAddChildValue);
}
public List<IHeirerchy<T>> getChilds()
{
return m_childs == null ? (new List<IHeirerchy<T>>()) : m_childs;
}
public IHeirerchy<T> getFirstChildNode()
{
return m_childs.First();
}
public IHeirerchy<T> getLastChildNode()
{
return m_childs.Last();
}
public IHeirerchy<T>? getChildNodeByIndex(Int32 index)
{
if (m_childs.Count <= index)
{
return null;
}
return m_childs[index];
}
public virtual bool isUpperHeirerchy(T toCheck)
{
if (true == isEqual(toCheck))
{
return true;
}
var parent = getParent();
if (null != parent)
{
if (true == parent.isUpperHeirerchy(toCheck))
{
return true;
}
}
return false;
}
public virtual bool isLowerHeirerchy(T toCheck)
{
if (true == isEqual(toCheck))
{
return true;
}
foreach (var child_node in getChilds())
{
if (true == child_node.isLowerHeirerchy(toCheck))
{
return true;
}
}
return false;
}
// 하위 노드들 얻기
public virtual void fillupLowers(ref List<T> lowers)
{
foreach (var child_node in getChilds())
{
lowers.Add(child_node.getValue());
}
}
public bool isRoot()
{
return getParent() == null;
}
public bool isLeaf()
{
return getChilds().Count <= 0;
}
public void setValue(T value)
{
m_value = value;
}
public T getValue()
{
return m_value;
}
public bool isEqual(T value)
{
return m_value?.Equals(value) ?? false;
}
public void setDepthNo(Int32 depthNo)
{
m_depth_no = depthNo;
}
public Int32 getDepthNo()
{
return m_depth_no;
}
public void setParent(IHeirerchy<T> parent)
{
m_parent = parent;
var depth_no = parent.getDepthNo() + 1;
setDepthNo(depth_no);
}
public IHeirerchy<T>? getParent()
{
return m_parent;
}
}