pyjallib.naming

Naming 모듈 - 이름 규칙 관리 및 적용 기능 제공 NamePart 객체를 기반으로 조직화된 이름 생성 및 분석 기능 구현

   1#!/usr/bin/env python
   2# -*- coding: utf-8 -*-
   3
   4"""
   5Naming 모듈 - 이름 규칙 관리 및 적용 기능 제공
   6NamePart 객체를 기반으로 조직화된 이름 생성 및 분석 기능 구현
   7"""
   8
   9import os
  10import re
  11from dataclasses import dataclass
  12from typing import List, Dict, Any, Optional, Union, Tuple
  13
  14# NamePart와 NamingConfig 임포트
  15from pyjallib.namePart import NamePart, NamePartType
  16from pyjallib.namingConfig import NamingConfig
  17
  18class Naming:
  19    """
  20    노드 이름을 관리하기 위한 기본 클래스.
  21    기본적인 이름 구성 요소를 정의하고 관리합니다.
  22    이 클래스는 하위 클래스에서 확장하여 특정 목적에 맞게 사용할 수 있습니다.
  23    """
  24    
  25    def __init__(self, configPath=None):
  26        """
  27        클래스 초기화 및 기본 설정값 정의
  28        
  29        Args:
  30            configPath: 설정 파일 경로 (기본값: None)
  31                        설정 파일이 제공되면 해당 파일에서 설정을 로드함
  32        """
  33        # 기본 설정값
  34        self._paddingNum = 2
  35        self._configPath = configPath
  36        
  37        # 기본 namePart 초기화 (각 부분에 사전 정의 값 직접 설정)
  38        self._nameParts = []
  39        
  40        # Prefix 부분 (PREFIX 타입)
  41        prefixPart = NamePart("Prefix", NamePartType.PREFIX, ["Pr"], ["Prefix"])
  42        
  43        # RealName 부분 (REALNAME 타입)
  44        realNamePart = NamePart("RealName", NamePartType.REALNAME, [], [])
  45        
  46        # Index 부분 (INDEX 타입)
  47        indexPart = NamePart("Index", NamePartType.INDEX, [], [])
  48        
  49        # Suffix 부분 (SUFFIX 타입)
  50        suffixPart = NamePart("Suffix", NamePartType.SUFFIX, ["Su"], ["Suffix"])
  51        
  52        # 기본 순서대로 설정
  53        self._nameParts = [prefixPart, realNamePart, indexPart, suffixPart]
  54        
  55        # 설정 파일이 제공된 경우 로드
  56        if configPath:
  57            self.load_from_config_file(configPath)
  58        else:
  59            # 기본 JSON 설정 파일 로드 시도
  60            self.load_default_config()
  61
  62    # ---- String 관련 메소드들 (내부 사용 헬퍼 메소드) ----
  63    
  64    def _split_into_string_and_digit(self, inStr):
  65        """
  66        문자열을 문자부분과 숫자부분으로 분리
  67        
  68        Args:
  69            inStr: 분리할 문자열
  70            
  71        Returns:
  72            튜플 (문자부분, 숫자부분)
  73        """
  74        match = re.match(r'^(.*?)(\d*)$', inStr)
  75        if match:
  76            return match.group(1), match.group(2)
  77        return inStr, ""
  78
  79    def _compare_string(self, inStr1, inStr2):
  80        """
  81        대소문자 구분 없이 문자열 비교
  82        
  83        Args:
  84            inStr1: 첫 번째 문자열
  85            inStr2: 두 번째 문자열
  86            
  87        Returns:
  88            비교 결과 (inStr1 < inStr2: 음수, inStr1 == inStr2: 0, inStr1 > inStr2: 양수)
  89        """
  90        # Python에서는 대소문자 구분 없는 비교를 위해 lower() 메서드 사용
  91        if inStr1.lower() < inStr2.lower():
  92            return -1
  93        elif inStr1.lower() > inStr2.lower():
  94            return 1
  95        return 0
  96
  97    def _sort_by_alphabet(self, inArray):
  98        """
  99        배열 내 문자열을 알파벳 순으로 정렬
 100        
 101        Args:
 102            inArray: 정렬할 배열
 103            
 104        Returns:
 105            정렬된 배열
 106        """
 107        # Python의 sorted 함수와 lambda를 사용하여 대소문자 구분 없이 정렬
 108        return sorted(inArray, key=lambda x: x.lower())
 109
 110    def _get_filtering_char(self, inStr):
 111        """
 112        문자열에서 사용된 구분자 문자 찾기
 113        
 114        Args:
 115            inStr: 확인할 문자열
 116            
 117        Returns:
 118            구분자 문자 (' ' 또는 '_' 또는 '')
 119        """
 120        if ' ' in inStr:
 121            return ' '
 122        if '_' in inStr:
 123            return '_'
 124        return ''
 125
 126    def _filter_by_filtering_char(self, inStr):
 127        """
 128        구분자 문자로 문자열 분할
 129        
 130        Args:
 131            inStr: 분할할 문자열
 132            
 133        Returns:
 134            분할된 문자열 리스트
 135        """
 136        filChar = self._get_filtering_char(inStr)
 137        
 138        if not filChar:
 139            return [inStr]
 140            
 141        # 빈 문자열 제거하며 분할
 142        return [part for part in inStr.split(filChar) if part]
 143
 144    def _filter_by_upper_case(self, inStr):
 145        """
 146        대문자로 시작하는 부분을 기준으로 문자열 분할
 147        
 148        Args:
 149            inStr: 분할할 문자열
 150            
 151        Returns:
 152            분할된 문자열 리스트
 153        """
 154        if not inStr:
 155            return []
 156            
 157        result = []
 158        currentPart = inStr[0]
 159        
 160        for i in range(1, len(inStr)):
 161            if inStr[i].isupper():
 162                result.append(currentPart)
 163                currentPart = inStr[i]
 164            else:
 165                currentPart += inStr[i]
 166                
 167        if currentPart:
 168            result.append(currentPart)
 169            
 170        return result
 171
 172    def _has_digit(self, inStr):
 173        """
 174        문자열에 숫자가 포함되어 있는지 확인
 175        
 176        Args:
 177            inStr: 확인할 문자열
 178            
 179        Returns:
 180            숫자가 포함되어 있으면 True, 아니면 False
 181        """
 182        return any(char.isdigit() for char in inStr)
 183
 184    def _split_to_array(self, inStr):
 185        """
 186        문자열을 구분자 또는 대문자로 분할하고 숫자 부분도 분리
 187        
 188        Args:
 189            inStr: 분할할 문자열
 190            
 191        Returns:
 192            분할된 문자열 리스트
 193        """
 194        filChar = self._get_filtering_char(inStr)
 195        
 196        if not filChar:
 197            # 구분자가 없을 경우 대문자로 분할
 198            resultArray = self._filter_by_upper_case(inStr)
 199            tempArray = []
 200            
 201            for item in resultArray:
 202                if self._has_digit(item):
 203                    stringPart, digitPart = self._split_into_string_and_digit(item)
 204                    if stringPart:
 205                        tempArray.append(stringPart)
 206                    if digitPart:
 207                        tempArray.append(digitPart)
 208                else:
 209                    tempArray.append(item)
 210                    
 211            return tempArray
 212        else:
 213            # 구분자가 있을 경우 구분자로 분할
 214            return self._filter_by_filtering_char(inStr)
 215
 216    def _remove_empty_string_in_array(self, inArray):
 217        """
 218        배열에서 빈 문자열 제거
 219        
 220        Args:
 221            inArray: 처리할 배열
 222            
 223        Returns:
 224            빈 문자열이 제거된 배열
 225        """
 226        return [item for item in inArray if item]
 227
 228    def _combine(self, inArray, inFilChar=" "):
 229        """
 230        문자열 배열을 하나의 문자열로 결합
 231        
 232        Args:
 233            inArray: 결합할 문자열 배열
 234            filChar: 구분자 (기본값: 공백)
 235            
 236        Returns:
 237            결합된 문자열
 238        """
 239        refinedArray = self._remove_empty_string_in_array(inArray)
 240        
 241        if not refinedArray:
 242            return ""
 243            
 244        if len(refinedArray) == 1:
 245            return refinedArray[0]
 246            
 247        return inFilChar.join(refinedArray)
 248
 249    # ---- Name 관련 메서드들 ----
 250    
 251    # 사전 정의 값 편집 메서드 제거 (namingConfig를 통해서만 변경 가능)
 252
 253    def get_padding_num(self):
 254        """
 255        패딩 숫자 가져오기
 256        
 257        Returns:
 258            패딩 숫자
 259        """
 260        return self._paddingNum
 261
 262    def get_name_part(self, inNamePartName):
 263        """
 264        namePart 이름으로 NamePart 객체 가져오기
 265        
 266        Args:
 267            namePart: 가져올 NamePart의 이름 ("Prefix", "RealName", "Suffix", "Index" 등)
 268            
 269        Returns:
 270            해당 NamePart 객체, 존재하지 않으면 None
 271        """
 272        for part in self._nameParts:
 273            if part.get_name() == inNamePartName:
 274                return part
 275        return None
 276     
 277    def get_name_part_index(self, inNamePartName):
 278        """
 279        namePart 이름으로 인덱스 가져오기
 280        
 281        Args:
 282            namePart: 가져올 NamePart의 이름 ("Prefix", "RealName", "Suffix", "Index" 등)
 283            
 284        Returns:
 285            해당 NamePart의 인덱스, 존재하지 않으면 -1
 286        """
 287        for i, part in enumerate(self._nameParts):
 288            if part.get_name() == inNamePartName:
 289                return i
 290        return -1
 291
 292    def get_name_part_predefined_values(self, inNamePartName):
 293        """
 294        namePart의 사전 정의 값 가져오기
 295        
 296        Args:
 297            namePart: 가져올 NamePart의 이름 ("Prefix", "RealName", "Suffix", "Index" 등)
 298            
 299        Returns:
 300            해당 NamePart의 사전 정의 값 리스트, 존재하지 않으면 빈 리스트
 301        """
 302        partObj = self.get_name_part(inNamePartName)
 303        if partObj:
 304            return partObj.get_predefined_values()
 305        return []
 306    
 307    def is_in_name_part_predefined_values(self, inNamePartName, inStr):
 308        """
 309        지정된 namePart에 해당하는 부분이 문자열에 포함되어 있는지 확인
 310        
 311        Args:
 312            namePart: 확인할 namePart 이름 ("Base", "Type", "Side" 등)
 313            inStr: 확인할 문자열
 314            
 315        Returns:
 316            포함되어 있으면 True, 아니면 False
 317        """
 318        partObj = self.get_name_part(inNamePartName)
 319        if not partObj:
 320            return False
 321        
 322        partType = partObj.get_type()
 323        if not partType:
 324            return False
 325            
 326        partValues = partObj.get_predefined_values()
 327        
 328        if partType == NamePartType.PREFIX or partType == NamePartType.SUFFIX:
 329            return any(item in inStr for item in partValues)
 330        
 331        return False
 332
 333    def get_name_part_value_by_description(self, inNamePartName, inDescription):
 334        """
 335        지정된 namePart에 해당하는 부분을 문자열에서 추출
 336        
 337        Args:
 338            namePart: 추출할 namePart 이름 ("Base", "Type", "Side" 등)
 339            inDescription: predefined value에서 찾기위한 description 문자열
 340            
 341        Returns:
 342            지정된 namePart에 해당하는 문자열
 343        """
 344        partObj = self.get_name_part(inNamePartName)
 345        if not partObj:
 346            return ""
 347        
 348        partType = partObj.get_type()
 349        if not partType:
 350            return ""
 351            
 352        partValues = partObj.get_predefined_values()
 353        
 354        if partType == NamePartType.PREFIX or partType == NamePartType.SUFFIX:
 355            try:
 356                foundIndex = partObj._descriptions.index(inDescription)
 357                return partValues[foundIndex]
 358            except ValueError:
 359                # Description not found in the list
 360                return ""
 361
 362    def pick_name(self, inNamePartName, inStr):
 363        nameArray = self._split_to_array(inStr)
 364        returnStr = ""
 365        
 366        # namePart 문자열 목록 가져오기
 367        partObj = self.get_name_part(inNamePartName)
 368        if not partObj:
 369            return returnStr
 370        
 371        partType = partObj.get_type()
 372        if not partType:
 373            return returnStr
 374            
 375        partValues = partObj.get_predefined_values()
 376        if partType != NamePartType.INDEX and partType != NamePartType.REALNAME and not partValues:
 377            return returnStr
 378        
 379        if partType == NamePartType.PREFIX:
 380            for item in nameArray:
 381                if item in partValues:
 382                    returnStr = item
 383                    break
 384        
 385        if partType == NamePartType.SUFFIX:
 386            for i in range(len(nameArray) - 1, -1, -1):
 387                if nameArray[i] in partValues:
 388                    returnStr = nameArray[i]
 389                    break
 390                
 391        if partType == NamePartType.INDEX:
 392            if self.get_name_part_index("Index") > self.get_name_part_index("RealName"):
 393                for i in range(len(nameArray) - 1, -1, -1):
 394                    if nameArray[i].isdigit():
 395                        returnStr = nameArray[i]
 396                        break
 397            else:
 398                for item in nameArray:
 399                    if item.isdigit():
 400                        returnStr = item
 401                        break
 402        
 403        return returnStr
 404        
 405    def get_name(self, inNamePartName, inStr):
 406        """
 407        지정된 namePart에 해당하는 부분을 문자열에서 추출
 408        
 409        Args:
 410            namePart: 추출할 namePart 이름 ("Base", "Type", "Side" 등)
 411            inStr: 처리할 문자열
 412            
 413        Returns:
 414            지정된 namePart에 해당하는 문자열
 415        """
 416        nameArray = self._split_to_array(inStr)
 417        returnStr = ""
 418        
 419        partType = self.get_name_part(inNamePartName).get_type()
 420        
 421        foundName = self.pick_name(inNamePartName, inStr)
 422        if foundName == "":
 423            return returnStr
 424        partIndex = self.get_name_part_index(inNamePartName)
 425        foundIndex = nameArray.index(foundName)
 426        
 427        if partType == NamePartType.PREFIX:
 428            if foundIndex >= 0:
 429                prevNameParts = self._nameParts[:partIndex]
 430                prevNames = [self.pick_name(part.get_name(), inStr) for part in prevNameParts]
 431                prevNamesInNameArray = nameArray[:foundIndex]
 432                for prevName in prevNames:
 433                    if prevName in prevNamesInNameArray:
 434                        prevNamesInNameArray.remove(prevName)
 435                if len(prevNamesInNameArray) == 0 :
 436                    returnStr = foundName
 437        
 438        if partType == NamePartType.SUFFIX:
 439            if foundIndex >= 0:
 440                nextNameParts = self._nameParts[partIndex + 1:]
 441                nextNames = [self.pick_name(part.get_name(), inStr) for part in nextNameParts]
 442                nextNamesInNameArray = nameArray[foundIndex + 1:]
 443                for nextName in nextNames:
 444                    if nextName in nextNamesInNameArray:
 445                        nextNamesInNameArray.remove(nextName)
 446                if len(nextNamesInNameArray) == 0 :
 447                    returnStr = foundName
 448        
 449        if partType == NamePartType.INDEX:
 450            returnStr = self.pick_name(inNamePartName, inStr)
 451                
 452        return returnStr
 453    
 454    def combine(self, inPartsDict={}, inFilChar=" "):
 455        """
 456        namingConfig에서 정의된 nameParts와 그 순서에 따라 이름 부분들을 조합하여 완전한 이름 생성
 457        
 458        Args:
 459            parts_dict: namePart 이름과 값의 딕셔너리 (예: {"Base": "b", "Type": "P", "Side": "L"})
 460            inFilChar: 구분자 문자 (기본값: " ")
 461            
 462        Returns:
 463            조합된 이름 문자열
 464        """
 465        # 결과 배열 초기화 (빈 문자열로)
 466        combinedNameArray = [""] * len(self._nameParts)
 467        
 468        # 각 namePart에 대해
 469        for i, part in enumerate(self._nameParts):
 470            partName = part.get_name()
 471            # 딕셔너리에서 해당 부분의 값 가져오기 (없으면 빈 문자열 사용)
 472            if partName in inPartsDict:
 473                combinedNameArray[i] = inPartsDict[partName]
 474                
 475        # 배열을 문자열로 결합
 476        newName = self._combine(combinedNameArray, inFilChar)
 477        newName = self.set_index_padding_num(newName)
 478        return newName
 479    
 480    def get_RealName(self, inStr):
 481        """
 482        문자열에서 실제 이름 부분 추출
 483        
 484        Args:
 485            inStr: 처리할 문자열
 486            
 487        Returns:
 488            실제 이름 부분 문자열
 489        """
 490        filChar = self._get_filtering_char(inStr)
 491        nameArray = self._split_to_array(inStr)
 492        
 493        # 모든 nameParts 중 RealName이 아닌 것들의 값을 수집
 494        nonRealNameArray = []
 495        for part in self._nameParts:
 496            partName = part.get_name()
 497            partType = part.get_type()
 498            if partType != NamePartType.REALNAME:
 499                foundName = self.get_name(partName, inStr)
 500                nonRealNameArray.append(foundName)
 501        
 502        for item in nonRealNameArray:
 503            if item in nameArray:
 504                nameArray.remove(item)
 505                
 506        # 구분자로 결합
 507        return self._combine(nameArray, filChar)
 508
 509    def get_non_RealName(self, inStr):
 510        """
 511        실제 이름 부분을 제외한 이름 가져오기
 512        
 513        Args:
 514            inStr: 처리할 이름 문자열
 515            
 516        Returns:
 517            실제 이름이 제외된 이름 문자열
 518        """
 519        filChar = self._get_filtering_char(inStr)
 520        
 521        # 모든 nameParts 중 RealName이 아닌 것들의 값을 수집
 522        nonRealNameArray = []
 523        for part in self._nameParts:
 524            partName = part.get_name()
 525            partType = part.get_type()
 526            if partType != NamePartType.REALNAME:
 527                foundName = self.get_name(partName, inStr)
 528                nonRealNameArray.append(foundName)
 529        
 530        return self._combine(nonRealNameArray, filChar)
 531                
 532    def convert_name_to_array(self, inStr):
 533        """
 534        문자열 이름을 이름 부분 배열로 변환
 535        
 536        Args:
 537            inStr: 변환할 이름 문자열
 538            
 539        Returns:
 540            이름 부분 배열 (Base, Type, Side, FrontBack, RealName, Index, Nub 등)
 541        """
 542        returnArray = [""] * len(self._nameParts)
 543        
 544        # 각 namePart에 대해 처리
 545        for i, part in enumerate(self._nameParts):
 546            partName = part.get_name()
 547            
 548            # 특수 케이스인 RealName은 마지막에 처리하기 위해 저장
 549            if partName == "RealName":
 550                realNameIndex = i
 551                continue
 552                
 553            # get_name 메소드를 사용하여 해당 부분 추출
 554            partValue = self.get_name(partName, inStr)
 555            returnArray[i] = partValue
 556        
 557        # 마지막으로 RealName 처리 (다른 모든 부분을 찾은 후에 수행해야 함)
 558        if 'realNameIndex' in locals():
 559            realNameStr = self.get_RealName(inStr)
 560            returnArray[realNameIndex] = realNameStr
 561        
 562        return returnArray
 563    
 564    def convert_to_dictionary(self, inStr):
 565        """
 566        문자열 이름을 이름 부분 딕셔너리로 변환
 567        
 568        Args:
 569            inStr: 변환할 이름 문자열
 570            
 571        Returns:
 572            이름 부분 딕셔너리 (키: namePart 이름, 값: 추출된 값)
 573            예: {"Base": "b", "Type": "P", "Side": "L", "RealName": "Arm", ...}
 574        """
 575        returnDict = {}
 576        
 577        # 각 namePart에 대해 처리
 578        for part in self._nameParts:
 579            partName = part.get_name()
 580            
 581            # 특수 케이스인 RealName은 마지막에 처리하기 위해 저장
 582            if partName == "RealName":
 583                continue
 584                
 585            # get_name 메소드를 사용하여 해당 부분 추출
 586            partValue = self.get_name(partName, inStr)
 587            returnDict[partName] = partValue
 588        
 589        # 마지막으로 RealName 처리 (다른 모든 부분을 찾은 후에 수행해야 함)
 590        realNameStr = self.get_RealName(inStr)
 591        returnDict["RealName"] = realNameStr
 592        
 593        return returnDict
 594    
 595    def convert_to_description(self, inStr):
 596        """
 597        문자열 이름을 설명으로 변환
 598        
 599        Args:
 600            inStr: 변환할 이름 문자열
 601            
 602        Returns:
 603            설명 문자열 (예: "b_P_L_Arm")
 604        """
 605        nameDic = self.convert_to_dictionary(inStr)
 606        descriptionDic = {}
 607        filteringChar = self._get_filtering_char(inStr)
 608        descName = inStr
 609        if nameDic:
 610            for namePartName, value in nameDic.items():
 611                namePart = self.get_name_part(namePartName)
 612                desc = namePart.get_description_by_value(value)
 613
 614                if desc == "" and value != "":
 615                    desc = value
 616
 617                descriptionDic[namePartName] = desc # Store in dictionary for later use
 618
 619            descName = self.combine(descriptionDic, filteringChar)
 620        
 621        return descName
 622    
 623    def convert_to_korean_description(self, inStr):
 624        """
 625        문자열 이름을 한국어 설명으로 변환
 626        
 627        Args:
 628            inStr: 변환할 이름 문자열
 629            
 630        Returns:
 631            한국어 설명 문자열 (예: "팔_왼쪽_팔")
 632        """
 633        nameDic = self.convert_to_dictionary(inStr)
 634        korDescDic = {}
 635        filteringChar = self._get_filtering_char(inStr)
 636        korDescName = inStr
 637        if nameDic:
 638            for namePartName, value in nameDic.items():
 639                namePart = self.get_name_part(namePartName)
 640                desc = namePart.get_description_by_value(value)
 641                korDesc = namePart.get_korean_description_by_value(value)
 642
 643                if korDesc == "" and desc != "":
 644                    korDesc = desc
 645
 646                korDescDic[namePartName] = korDesc # Store in dictionary for later use
 647
 648            korDescName = self.combine(korDescDic, filteringChar)
 649        
 650        return korDescName
 651    
 652    def has_name_part(self, inPart, inStr):
 653        """
 654        문자열에 특정 namePart가 포함되어 있는지 확인
 655        
 656        Args:
 657            inPart: 확인할 namePart 이름 ("Base", "Type", "Side", "FrontBack", "RealName", "Index")
 658            inStr: 확인할 문자열
 659            
 660        Returns:
 661            포함되어 있으면 True, 아니면 False
 662        """
 663        return self.get_name(inPart, inStr) != ""
 664    
 665    def add_prefix_to_name_part(self, inPart, inStr, inPrefix):
 666        """
 667        이름의 특정 부분에 접두사 추가
 668        
 669        Args:
 670            inPart: 수정할 부분 ("Base", "Type", "Side", "FrontBack", "RealName", "Index")
 671            inStr: 처리할 이름 문자열
 672            inPrefix: 추가할 접두사
 673            
 674        Returns:
 675            수정된 이름 문자열
 676        """
 677        returnStr = inStr
 678        
 679        if inPrefix:
 680            filChar = self._get_filtering_char(inStr)
 681            nameArray = self.convert_name_to_array(inStr)
 682            partIndex = self.get_name_part_index(inPart)
 683                
 684            nameArray[partIndex] = inPrefix + nameArray[partIndex]
 685                    
 686            returnStr = self._combine(nameArray, filChar)
 687                
 688        return returnStr
 689    
 690    def add_suffix_to_name_part(self, inPart, inStr, inSuffix):
 691        """
 692        이름의 특정 부분에 접미사 추가
 693        
 694        Args:
 695            inPart: 수정할 부분 ("Base", "Type", "Side", "FrontBack", "RealName", "Index")
 696            inStr: 처리할 이름 문자열
 697            inSuffix: 추가할 접미사
 698            
 699        Returns:
 700            수정된 이름 문자열
 701        """
 702        returnStr = inStr
 703        
 704        if inSuffix:
 705            filChar = self._get_filtering_char(inStr)
 706            nameArray = self.convert_name_to_array(inStr)
 707            partIndex = self.get_name_part_index(inPart)
 708                
 709            nameArray[partIndex] = nameArray[partIndex] + inSuffix
 710                    
 711            returnStr = self._combine(nameArray, filChar)
 712                
 713        return returnStr
 714
 715    def add_prefix_to_real_name(self, inStr, inPrefix):
 716        """
 717        실제 이름 부분에 접두사 추가
 718        
 719        Args:
 720            inStr: 처리할 이름 문자열
 721            inPrefix: 추가할 접두사
 722            
 723        Returns:
 724            수정된 이름 문자열
 725        """
 726        return self.add_prefix_to_name_part("RealName", inStr, inPrefix)
 727
 728    def add_suffix_to_real_name(self, inStr, inSuffix):
 729        """
 730        실제 이름 부분에 접미사 추가
 731        
 732        Args:
 733            inStr: 처리할 이름 문자열
 734            inSuffix: 추가할 접미사
 735            
 736        Returns:
 737            수정된 이름 문자열
 738        """
 739        return self.add_suffix_to_name_part("RealName", inStr, inSuffix)
 740    
 741    def convert_digit_into_padding_string(self, inDigit, inPaddingNum=None):
 742        """
 743        숫자를 패딩된 문자열로 변환
 744        
 745        Args:
 746            inDigit: 변환할 숫자 또는 숫자 문자열
 747            inPaddingNum: 패딩 자릿수 (기본값: 클래스의 _paddingNum)
 748            
 749        Returns:
 750            패딩된 문자열
 751        """
 752        if inPaddingNum is None:
 753            inPaddingNum = self._paddingNum
 754            
 755        digitNum = 0
 756        
 757        if isinstance(inDigit, int):
 758            digitNum = inDigit
 759        elif isinstance(inDigit, str):
 760            if inDigit.isdigit():
 761                digitNum = int(inDigit)
 762                
 763        # Python의 문자열 포맷팅을 사용하여 패딩
 764        return f"{digitNum:0{inPaddingNum}d}"
 765
 766    def set_index_padding_num(self, inStr, inPaddingNum=None):
 767        """
 768        이름의 인덱스 부분 패딩 설정
 769        
 770        Args:
 771            inStr: 처리할 이름 문자열
 772            inPaddingNum: 설정할 패딩 자릿수 (기본값: 클래스의 _paddingNum)
 773            
 774        Returns:
 775            패딩이 적용된 이름 문자열
 776        """
 777        if inPaddingNum is None:
 778            inPaddingNum = self._paddingNum
 779            
 780        filChar = self._get_filtering_char(inStr)
 781        nameArray = self.convert_name_to_array(inStr)
 782        indexIndex = self.get_name_part_index("Index")
 783        indexStr = self.get_name("Index", inStr)
 784        
 785        if indexStr:
 786            indexStr = self.convert_digit_into_padding_string(indexStr, inPaddingNum)
 787            nameArray[indexIndex] = indexStr
 788            
 789        return self._combine(nameArray, filChar)
 790
 791    def get_index_padding_num(self, inStr):
 792        """
 793        이름의 인덱스 부분 패딩 자릿수 가져오기
 794        
 795        Args:
 796            inStr: 처리할 이름 문자열
 797            
 798        Returns:
 799            인덱스 패딩 자릿수
 800        """
 801        indexVal = self.get_name("Index", inStr)
 802        
 803        if indexVal:
 804            return len(indexVal)
 805            
 806        return 1
 807
 808    def increase_index(self, inStr, inAmount):
 809        """
 810        이름의 인덱스 부분 값 증가
 811        
 812        Args:
 813            inStr: 처리할 이름 문자열
 814            inAmount: 증가시킬 값
 815            
 816        Returns:
 817            인덱스가 증가된 이름 문자열
 818        """
 819        newName = inStr
 820        filChar = self._get_filtering_char(inStr)
 821        nameArray = self.convert_name_to_array(inStr)
 822        indexIndex = self.get_name_part_index("Index")
 823        
 824        if indexIndex >= 0:
 825            indexStr = ""
 826            indexPaddingNum = self._paddingNum
 827            indexNum = -99999
 828            
 829            if not nameArray[indexIndex]:
 830                indexNum = -1
 831            else:
 832                try:
 833                    indexNum = int(nameArray[indexIndex])
 834                    indexPaddingNum = len(nameArray[indexIndex])
 835                except ValueError:
 836                    pass
 837            
 838            indexNum += inAmount
 839            
 840            if indexNum < 0:
 841                indexNum = 0
 842            
 843            # Python의 문자열 포맷팅을 사용하여 패딩
 844            indexStr = f"{indexNum:0{indexPaddingNum}d}"
 845            nameArray[indexIndex] = indexStr
 846            newName = self._combine(nameArray, filChar)
 847            newName = self.set_index_padding_num(newName)
 848            
 849        return newName
 850
 851    def get_index_as_digit(self, inStr):
 852        """
 853        이름의 인덱스를 숫자로 변환
 854        
 855        Args:
 856            inStr: 변환할 이름 문자열
 857            
 858        Returns:
 859            숫자로 변환된 인덱스 (넙이 있으면 -1, 인덱스가 없으면 False)
 860        """
 861        indexStr = self.get_name("Index", inStr)
 862            
 863        if indexStr:
 864            try:
 865                return int(indexStr)
 866            except ValueError:
 867                pass
 868                
 869        return False
 870
 871    def sort_by_index(self, inNameArray):
 872        """
 873        이름 배열을 인덱스 기준으로 정렬
 874        
 875        Args:
 876            inNameArray: 정렬할 이름 배열
 877            
 878        Returns:
 879            인덱스 기준으로 정렬된 이름 배열
 880        """
 881        if not inNameArray:
 882            return []
 883            
 884        # 정렬을 위한 보조 클래스 정의
 885        @dataclass
 886        class IndexSorting:
 887            oriIndex: int
 888            newIndex: int
 889                
 890        # 각 이름의 인덱스를 추출하여 정렬 정보 생성
 891        structArray = []
 892        
 893        for i, name in enumerate(inNameArray):
 894            tempIndex = self.get_index_as_digit(name)
 895            
 896            if tempIndex is False:
 897                structArray.append(IndexSorting(i, 0))
 898            else:
 899                structArray.append(IndexSorting(i, tempIndex))
 900                
 901        # 인덱스 기준으로 정렬
 902        structArray.sort(key=lambda x: x.newIndex)
 903        
 904        # 정렬된 순서로 결과 배열 생성
 905        sortedNameArray = []
 906        for struct in structArray:
 907            sortedNameArray.append(inNameArray[struct.oriIndex])
 908            
 909        return sortedNameArray
 910    
 911    def get_string(self, inStr):
 912        """
 913        인덱스 부분을 제외한 이름 문자열 가져오기
 914        
 915        Args:
 916            inStr: 처리할 이름 문자열
 917            
 918        Returns:
 919            인덱스가 제외된 이름 문자열
 920        """
 921        filChar = self._get_filtering_char(inStr)
 922        nameArray = self.convert_name_to_array(inStr)
 923        indexOrder = self.get_name_part_index("Index")
 924        
 925        # 인덱스 부분 제거
 926        returnNameArray = nameArray.copy()
 927        returnNameArray[indexOrder] = ""
 928        
 929        return self._combine(returnNameArray, filChar)
 930
 931    def gen_mirroring_name(self, inStr):
 932        """
 933        미러링된 이름 생성 (측면 또는 앞/뒤 변경)
 934        
 935        이름에서 Side와 FrontBack namePart를 자동으로 검색하고,
 936        발견된 값의 semanticmapping weight와 가장 차이가 큰 값으로 교체합니다.
 937        
 938        Args:
 939            inStr: 처리할 이름 문자열
 940            
 941        Returns:
 942            미러링된 이름 문자열
 943        """
 944        nameArray = self.convert_name_to_array(inStr)
 945            
 946        for part in self._nameParts:
 947            partName = part.get_name()
 948            partType = part.get_type()
 949            if (partType != NamePartType.REALNAME or partType != NamePartType.INDEX) and part.is_direction():
 950                partIndex = self.get_name_part_index(partName)
 951                foundName = self.get_name(partName, inStr)
 952                opositeName = part.get_most_different_weight_value(foundName)
 953                if opositeName and foundName != opositeName:
 954                    nameArray[partIndex] = opositeName
 955        
 956        returnName = self._combine(nameArray, self._get_filtering_char(inStr))
 957        
 958        return returnName
 959
 960    def replace_filtering_char(self, inStr, inNewFilChar):
 961        """
 962        이름의 구분자 문자 변경
 963        
 964        Args:
 965            inStr: 처리할 이름 문자열
 966            inNewFilChar: 새 구분자 문자
 967            
 968        Returns:
 969            구분자가 변경된 이름 문자열
 970        """
 971        nameArray = self.convert_name_to_array(inStr)
 972        return self._combine(nameArray, inNewFilChar)
 973
 974    def replace_name_part(self, inPart, inStr, inNewName):
 975        """
 976        이름의 특정 부분을 새 이름으로 변경
 977        
 978        Args:
 979            inPart: 수정할 부분 ("Base", "Type", "Side", "FrontBack", "RealName", "Index")
 980            inStr: 처리할 이름 문자열
 981            inNewName: 새 이름
 982        
 983        Returns:
 984            수정된 이름 문자열
 985        """
 986        nameArray = self.convert_name_to_array(inStr)
 987        partIndex = self.get_name_part_index(inPart)
 988        
 989        if partIndex >= 0:
 990            nameArray[partIndex] = inNewName
 991        
 992        newName = self._combine(nameArray, self._get_filtering_char(inStr))
 993        newName = self.set_index_padding_num(newName)
 994        
 995        return newName
 996
 997    def remove_name_part(self, inPart, inStr):
 998        """
 999        이름의 특정 부분 제거
1000        
1001        Args:
1002            inPart: 제거할 부분 ("Base", "Type", "Side", "FrontBack", "RealName", "Index")
1003            inStr: 처리할 이름 문자열
1004            
1005        Returns:
1006            수정된 이름 문자열
1007        """
1008        nameArray = self.convert_name_to_array(inStr)
1009        partIndex = self.get_name_part_index(inPart)
1010        
1011        if partIndex >= 0:
1012            nameArray[partIndex] = ""
1013            
1014        newName = self._combine(nameArray, self._get_filtering_char(inStr))
1015        newName = self.set_index_padding_num(newName)
1016        
1017        return newName
1018
1019    def load_from_config_file(self, configPath=None):
1020        """
1021        설정 파일에서 설정 로드
1022        
1023        Args:
1024            configPath: 설정 파일 경로 (기본값: self._configPath)
1025            
1026        Returns:
1027            로드 성공 여부 (True/False)
1028        """
1029        # 경로가 없으면 인스턴스 생성 시 설정된 경로 사용
1030        if not configPath:
1031            configPath = self._configPath
1032            
1033        if not configPath:
1034            print("설정 파일 경로가 제공되지 않았습니다.")
1035            return False
1036            
1037        # NamingConfig 인스턴스 생성 및 설정 로드
1038        config = NamingConfig()
1039        if config.load(configPath):
1040            # 설정을 Naming 인스턴스에 적용
1041            result = config.apply_to_naming(self)
1042            if result:
1043                self._configPath = configPath  # 성공적으로 로드한 경로 저장
1044            return result
1045        else:
1046            print(f"설정 파일 로드 실패: {configPath}")
1047            return False
1048    
1049    def load_default_config(self):
1050        """
1051        기본 설정 로드 (현재는 아무 작업도 수행하지 않음)
1052        
1053        Returns:
1054            항상 True 반환 (기본 설정은 __init__에서 이미 설정됨)
1055        """
1056        # 이 메소드는 현재 __init__에서 설정한 기본값을 그대로 사용하므로
1057        # 아무 작업도 수행하지 않습니다.
1058        return True
1059
1060    def get_config_path(self):
1061        """
1062        현재 설정 파일 경로 가져오기
1063        
1064        Returns:
1065            설정 파일 경로 (없으면 빈 문자열)
1066        """
1067        return self._configPath or ""
class Naming:
  19class Naming:
  20    """
  21    노드 이름을 관리하기 위한 기본 클래스.
  22    기본적인 이름 구성 요소를 정의하고 관리합니다.
  23    이 클래스는 하위 클래스에서 확장하여 특정 목적에 맞게 사용할 수 있습니다.
  24    """
  25    
  26    def __init__(self, configPath=None):
  27        """
  28        클래스 초기화 및 기본 설정값 정의
  29        
  30        Args:
  31            configPath: 설정 파일 경로 (기본값: None)
  32                        설정 파일이 제공되면 해당 파일에서 설정을 로드함
  33        """
  34        # 기본 설정값
  35        self._paddingNum = 2
  36        self._configPath = configPath
  37        
  38        # 기본 namePart 초기화 (각 부분에 사전 정의 값 직접 설정)
  39        self._nameParts = []
  40        
  41        # Prefix 부분 (PREFIX 타입)
  42        prefixPart = NamePart("Prefix", NamePartType.PREFIX, ["Pr"], ["Prefix"])
  43        
  44        # RealName 부분 (REALNAME 타입)
  45        realNamePart = NamePart("RealName", NamePartType.REALNAME, [], [])
  46        
  47        # Index 부분 (INDEX 타입)
  48        indexPart = NamePart("Index", NamePartType.INDEX, [], [])
  49        
  50        # Suffix 부분 (SUFFIX 타입)
  51        suffixPart = NamePart("Suffix", NamePartType.SUFFIX, ["Su"], ["Suffix"])
  52        
  53        # 기본 순서대로 설정
  54        self._nameParts = [prefixPart, realNamePart, indexPart, suffixPart]
  55        
  56        # 설정 파일이 제공된 경우 로드
  57        if configPath:
  58            self.load_from_config_file(configPath)
  59        else:
  60            # 기본 JSON 설정 파일 로드 시도
  61            self.load_default_config()
  62
  63    # ---- String 관련 메소드들 (내부 사용 헬퍼 메소드) ----
  64    
  65    def _split_into_string_and_digit(self, inStr):
  66        """
  67        문자열을 문자부분과 숫자부분으로 분리
  68        
  69        Args:
  70            inStr: 분리할 문자열
  71            
  72        Returns:
  73            튜플 (문자부분, 숫자부분)
  74        """
  75        match = re.match(r'^(.*?)(\d*)$', inStr)
  76        if match:
  77            return match.group(1), match.group(2)
  78        return inStr, ""
  79
  80    def _compare_string(self, inStr1, inStr2):
  81        """
  82        대소문자 구분 없이 문자열 비교
  83        
  84        Args:
  85            inStr1: 첫 번째 문자열
  86            inStr2: 두 번째 문자열
  87            
  88        Returns:
  89            비교 결과 (inStr1 < inStr2: 음수, inStr1 == inStr2: 0, inStr1 > inStr2: 양수)
  90        """
  91        # Python에서는 대소문자 구분 없는 비교를 위해 lower() 메서드 사용
  92        if inStr1.lower() < inStr2.lower():
  93            return -1
  94        elif inStr1.lower() > inStr2.lower():
  95            return 1
  96        return 0
  97
  98    def _sort_by_alphabet(self, inArray):
  99        """
 100        배열 내 문자열을 알파벳 순으로 정렬
 101        
 102        Args:
 103            inArray: 정렬할 배열
 104            
 105        Returns:
 106            정렬된 배열
 107        """
 108        # Python의 sorted 함수와 lambda를 사용하여 대소문자 구분 없이 정렬
 109        return sorted(inArray, key=lambda x: x.lower())
 110
 111    def _get_filtering_char(self, inStr):
 112        """
 113        문자열에서 사용된 구분자 문자 찾기
 114        
 115        Args:
 116            inStr: 확인할 문자열
 117            
 118        Returns:
 119            구분자 문자 (' ' 또는 '_' 또는 '')
 120        """
 121        if ' ' in inStr:
 122            return ' '
 123        if '_' in inStr:
 124            return '_'
 125        return ''
 126
 127    def _filter_by_filtering_char(self, inStr):
 128        """
 129        구분자 문자로 문자열 분할
 130        
 131        Args:
 132            inStr: 분할할 문자열
 133            
 134        Returns:
 135            분할된 문자열 리스트
 136        """
 137        filChar = self._get_filtering_char(inStr)
 138        
 139        if not filChar:
 140            return [inStr]
 141            
 142        # 빈 문자열 제거하며 분할
 143        return [part for part in inStr.split(filChar) if part]
 144
 145    def _filter_by_upper_case(self, inStr):
 146        """
 147        대문자로 시작하는 부분을 기준으로 문자열 분할
 148        
 149        Args:
 150            inStr: 분할할 문자열
 151            
 152        Returns:
 153            분할된 문자열 리스트
 154        """
 155        if not inStr:
 156            return []
 157            
 158        result = []
 159        currentPart = inStr[0]
 160        
 161        for i in range(1, len(inStr)):
 162            if inStr[i].isupper():
 163                result.append(currentPart)
 164                currentPart = inStr[i]
 165            else:
 166                currentPart += inStr[i]
 167                
 168        if currentPart:
 169            result.append(currentPart)
 170            
 171        return result
 172
 173    def _has_digit(self, inStr):
 174        """
 175        문자열에 숫자가 포함되어 있는지 확인
 176        
 177        Args:
 178            inStr: 확인할 문자열
 179            
 180        Returns:
 181            숫자가 포함되어 있으면 True, 아니면 False
 182        """
 183        return any(char.isdigit() for char in inStr)
 184
 185    def _split_to_array(self, inStr):
 186        """
 187        문자열을 구분자 또는 대문자로 분할하고 숫자 부분도 분리
 188        
 189        Args:
 190            inStr: 분할할 문자열
 191            
 192        Returns:
 193            분할된 문자열 리스트
 194        """
 195        filChar = self._get_filtering_char(inStr)
 196        
 197        if not filChar:
 198            # 구분자가 없을 경우 대문자로 분할
 199            resultArray = self._filter_by_upper_case(inStr)
 200            tempArray = []
 201            
 202            for item in resultArray:
 203                if self._has_digit(item):
 204                    stringPart, digitPart = self._split_into_string_and_digit(item)
 205                    if stringPart:
 206                        tempArray.append(stringPart)
 207                    if digitPart:
 208                        tempArray.append(digitPart)
 209                else:
 210                    tempArray.append(item)
 211                    
 212            return tempArray
 213        else:
 214            # 구분자가 있을 경우 구분자로 분할
 215            return self._filter_by_filtering_char(inStr)
 216
 217    def _remove_empty_string_in_array(self, inArray):
 218        """
 219        배열에서 빈 문자열 제거
 220        
 221        Args:
 222            inArray: 처리할 배열
 223            
 224        Returns:
 225            빈 문자열이 제거된 배열
 226        """
 227        return [item for item in inArray if item]
 228
 229    def _combine(self, inArray, inFilChar=" "):
 230        """
 231        문자열 배열을 하나의 문자열로 결합
 232        
 233        Args:
 234            inArray: 결합할 문자열 배열
 235            filChar: 구분자 (기본값: 공백)
 236            
 237        Returns:
 238            결합된 문자열
 239        """
 240        refinedArray = self._remove_empty_string_in_array(inArray)
 241        
 242        if not refinedArray:
 243            return ""
 244            
 245        if len(refinedArray) == 1:
 246            return refinedArray[0]
 247            
 248        return inFilChar.join(refinedArray)
 249
 250    # ---- Name 관련 메서드들 ----
 251    
 252    # 사전 정의 값 편집 메서드 제거 (namingConfig를 통해서만 변경 가능)
 253
 254    def get_padding_num(self):
 255        """
 256        패딩 숫자 가져오기
 257        
 258        Returns:
 259            패딩 숫자
 260        """
 261        return self._paddingNum
 262
 263    def get_name_part(self, inNamePartName):
 264        """
 265        namePart 이름으로 NamePart 객체 가져오기
 266        
 267        Args:
 268            namePart: 가져올 NamePart의 이름 ("Prefix", "RealName", "Suffix", "Index" 등)
 269            
 270        Returns:
 271            해당 NamePart 객체, 존재하지 않으면 None
 272        """
 273        for part in self._nameParts:
 274            if part.get_name() == inNamePartName:
 275                return part
 276        return None
 277     
 278    def get_name_part_index(self, inNamePartName):
 279        """
 280        namePart 이름으로 인덱스 가져오기
 281        
 282        Args:
 283            namePart: 가져올 NamePart의 이름 ("Prefix", "RealName", "Suffix", "Index" 등)
 284            
 285        Returns:
 286            해당 NamePart의 인덱스, 존재하지 않으면 -1
 287        """
 288        for i, part in enumerate(self._nameParts):
 289            if part.get_name() == inNamePartName:
 290                return i
 291        return -1
 292
 293    def get_name_part_predefined_values(self, inNamePartName):
 294        """
 295        namePart의 사전 정의 값 가져오기
 296        
 297        Args:
 298            namePart: 가져올 NamePart의 이름 ("Prefix", "RealName", "Suffix", "Index" 등)
 299            
 300        Returns:
 301            해당 NamePart의 사전 정의 값 리스트, 존재하지 않으면 빈 리스트
 302        """
 303        partObj = self.get_name_part(inNamePartName)
 304        if partObj:
 305            return partObj.get_predefined_values()
 306        return []
 307    
 308    def is_in_name_part_predefined_values(self, inNamePartName, inStr):
 309        """
 310        지정된 namePart에 해당하는 부분이 문자열에 포함되어 있는지 확인
 311        
 312        Args:
 313            namePart: 확인할 namePart 이름 ("Base", "Type", "Side" 등)
 314            inStr: 확인할 문자열
 315            
 316        Returns:
 317            포함되어 있으면 True, 아니면 False
 318        """
 319        partObj = self.get_name_part(inNamePartName)
 320        if not partObj:
 321            return False
 322        
 323        partType = partObj.get_type()
 324        if not partType:
 325            return False
 326            
 327        partValues = partObj.get_predefined_values()
 328        
 329        if partType == NamePartType.PREFIX or partType == NamePartType.SUFFIX:
 330            return any(item in inStr for item in partValues)
 331        
 332        return False
 333
 334    def get_name_part_value_by_description(self, inNamePartName, inDescription):
 335        """
 336        지정된 namePart에 해당하는 부분을 문자열에서 추출
 337        
 338        Args:
 339            namePart: 추출할 namePart 이름 ("Base", "Type", "Side" 등)
 340            inDescription: predefined value에서 찾기위한 description 문자열
 341            
 342        Returns:
 343            지정된 namePart에 해당하는 문자열
 344        """
 345        partObj = self.get_name_part(inNamePartName)
 346        if not partObj:
 347            return ""
 348        
 349        partType = partObj.get_type()
 350        if not partType:
 351            return ""
 352            
 353        partValues = partObj.get_predefined_values()
 354        
 355        if partType == NamePartType.PREFIX or partType == NamePartType.SUFFIX:
 356            try:
 357                foundIndex = partObj._descriptions.index(inDescription)
 358                return partValues[foundIndex]
 359            except ValueError:
 360                # Description not found in the list
 361                return ""
 362
 363    def pick_name(self, inNamePartName, inStr):
 364        nameArray = self._split_to_array(inStr)
 365        returnStr = ""
 366        
 367        # namePart 문자열 목록 가져오기
 368        partObj = self.get_name_part(inNamePartName)
 369        if not partObj:
 370            return returnStr
 371        
 372        partType = partObj.get_type()
 373        if not partType:
 374            return returnStr
 375            
 376        partValues = partObj.get_predefined_values()
 377        if partType != NamePartType.INDEX and partType != NamePartType.REALNAME and not partValues:
 378            return returnStr
 379        
 380        if partType == NamePartType.PREFIX:
 381            for item in nameArray:
 382                if item in partValues:
 383                    returnStr = item
 384                    break
 385        
 386        if partType == NamePartType.SUFFIX:
 387            for i in range(len(nameArray) - 1, -1, -1):
 388                if nameArray[i] in partValues:
 389                    returnStr = nameArray[i]
 390                    break
 391                
 392        if partType == NamePartType.INDEX:
 393            if self.get_name_part_index("Index") > self.get_name_part_index("RealName"):
 394                for i in range(len(nameArray) - 1, -1, -1):
 395                    if nameArray[i].isdigit():
 396                        returnStr = nameArray[i]
 397                        break
 398            else:
 399                for item in nameArray:
 400                    if item.isdigit():
 401                        returnStr = item
 402                        break
 403        
 404        return returnStr
 405        
 406    def get_name(self, inNamePartName, inStr):
 407        """
 408        지정된 namePart에 해당하는 부분을 문자열에서 추출
 409        
 410        Args:
 411            namePart: 추출할 namePart 이름 ("Base", "Type", "Side" 등)
 412            inStr: 처리할 문자열
 413            
 414        Returns:
 415            지정된 namePart에 해당하는 문자열
 416        """
 417        nameArray = self._split_to_array(inStr)
 418        returnStr = ""
 419        
 420        partType = self.get_name_part(inNamePartName).get_type()
 421        
 422        foundName = self.pick_name(inNamePartName, inStr)
 423        if foundName == "":
 424            return returnStr
 425        partIndex = self.get_name_part_index(inNamePartName)
 426        foundIndex = nameArray.index(foundName)
 427        
 428        if partType == NamePartType.PREFIX:
 429            if foundIndex >= 0:
 430                prevNameParts = self._nameParts[:partIndex]
 431                prevNames = [self.pick_name(part.get_name(), inStr) for part in prevNameParts]
 432                prevNamesInNameArray = nameArray[:foundIndex]
 433                for prevName in prevNames:
 434                    if prevName in prevNamesInNameArray:
 435                        prevNamesInNameArray.remove(prevName)
 436                if len(prevNamesInNameArray) == 0 :
 437                    returnStr = foundName
 438        
 439        if partType == NamePartType.SUFFIX:
 440            if foundIndex >= 0:
 441                nextNameParts = self._nameParts[partIndex + 1:]
 442                nextNames = [self.pick_name(part.get_name(), inStr) for part in nextNameParts]
 443                nextNamesInNameArray = nameArray[foundIndex + 1:]
 444                for nextName in nextNames:
 445                    if nextName in nextNamesInNameArray:
 446                        nextNamesInNameArray.remove(nextName)
 447                if len(nextNamesInNameArray) == 0 :
 448                    returnStr = foundName
 449        
 450        if partType == NamePartType.INDEX:
 451            returnStr = self.pick_name(inNamePartName, inStr)
 452                
 453        return returnStr
 454    
 455    def combine(self, inPartsDict={}, inFilChar=" "):
 456        """
 457        namingConfig에서 정의된 nameParts와 그 순서에 따라 이름 부분들을 조합하여 완전한 이름 생성
 458        
 459        Args:
 460            parts_dict: namePart 이름과 값의 딕셔너리 (예: {"Base": "b", "Type": "P", "Side": "L"})
 461            inFilChar: 구분자 문자 (기본값: " ")
 462            
 463        Returns:
 464            조합된 이름 문자열
 465        """
 466        # 결과 배열 초기화 (빈 문자열로)
 467        combinedNameArray = [""] * len(self._nameParts)
 468        
 469        # 각 namePart에 대해
 470        for i, part in enumerate(self._nameParts):
 471            partName = part.get_name()
 472            # 딕셔너리에서 해당 부분의 값 가져오기 (없으면 빈 문자열 사용)
 473            if partName in inPartsDict:
 474                combinedNameArray[i] = inPartsDict[partName]
 475                
 476        # 배열을 문자열로 결합
 477        newName = self._combine(combinedNameArray, inFilChar)
 478        newName = self.set_index_padding_num(newName)
 479        return newName
 480    
 481    def get_RealName(self, inStr):
 482        """
 483        문자열에서 실제 이름 부분 추출
 484        
 485        Args:
 486            inStr: 처리할 문자열
 487            
 488        Returns:
 489            실제 이름 부분 문자열
 490        """
 491        filChar = self._get_filtering_char(inStr)
 492        nameArray = self._split_to_array(inStr)
 493        
 494        # 모든 nameParts 중 RealName이 아닌 것들의 값을 수집
 495        nonRealNameArray = []
 496        for part in self._nameParts:
 497            partName = part.get_name()
 498            partType = part.get_type()
 499            if partType != NamePartType.REALNAME:
 500                foundName = self.get_name(partName, inStr)
 501                nonRealNameArray.append(foundName)
 502        
 503        for item in nonRealNameArray:
 504            if item in nameArray:
 505                nameArray.remove(item)
 506                
 507        # 구분자로 결합
 508        return self._combine(nameArray, filChar)
 509
 510    def get_non_RealName(self, inStr):
 511        """
 512        실제 이름 부분을 제외한 이름 가져오기
 513        
 514        Args:
 515            inStr: 처리할 이름 문자열
 516            
 517        Returns:
 518            실제 이름이 제외된 이름 문자열
 519        """
 520        filChar = self._get_filtering_char(inStr)
 521        
 522        # 모든 nameParts 중 RealName이 아닌 것들의 값을 수집
 523        nonRealNameArray = []
 524        for part in self._nameParts:
 525            partName = part.get_name()
 526            partType = part.get_type()
 527            if partType != NamePartType.REALNAME:
 528                foundName = self.get_name(partName, inStr)
 529                nonRealNameArray.append(foundName)
 530        
 531        return self._combine(nonRealNameArray, filChar)
 532                
 533    def convert_name_to_array(self, inStr):
 534        """
 535        문자열 이름을 이름 부분 배열로 변환
 536        
 537        Args:
 538            inStr: 변환할 이름 문자열
 539            
 540        Returns:
 541            이름 부분 배열 (Base, Type, Side, FrontBack, RealName, Index, Nub 등)
 542        """
 543        returnArray = [""] * len(self._nameParts)
 544        
 545        # 각 namePart에 대해 처리
 546        for i, part in enumerate(self._nameParts):
 547            partName = part.get_name()
 548            
 549            # 특수 케이스인 RealName은 마지막에 처리하기 위해 저장
 550            if partName == "RealName":
 551                realNameIndex = i
 552                continue
 553                
 554            # get_name 메소드를 사용하여 해당 부분 추출
 555            partValue = self.get_name(partName, inStr)
 556            returnArray[i] = partValue
 557        
 558        # 마지막으로 RealName 처리 (다른 모든 부분을 찾은 후에 수행해야 함)
 559        if 'realNameIndex' in locals():
 560            realNameStr = self.get_RealName(inStr)
 561            returnArray[realNameIndex] = realNameStr
 562        
 563        return returnArray
 564    
 565    def convert_to_dictionary(self, inStr):
 566        """
 567        문자열 이름을 이름 부분 딕셔너리로 변환
 568        
 569        Args:
 570            inStr: 변환할 이름 문자열
 571            
 572        Returns:
 573            이름 부분 딕셔너리 (키: namePart 이름, 값: 추출된 값)
 574            예: {"Base": "b", "Type": "P", "Side": "L", "RealName": "Arm", ...}
 575        """
 576        returnDict = {}
 577        
 578        # 각 namePart에 대해 처리
 579        for part in self._nameParts:
 580            partName = part.get_name()
 581            
 582            # 특수 케이스인 RealName은 마지막에 처리하기 위해 저장
 583            if partName == "RealName":
 584                continue
 585                
 586            # get_name 메소드를 사용하여 해당 부분 추출
 587            partValue = self.get_name(partName, inStr)
 588            returnDict[partName] = partValue
 589        
 590        # 마지막으로 RealName 처리 (다른 모든 부분을 찾은 후에 수행해야 함)
 591        realNameStr = self.get_RealName(inStr)
 592        returnDict["RealName"] = realNameStr
 593        
 594        return returnDict
 595    
 596    def convert_to_description(self, inStr):
 597        """
 598        문자열 이름을 설명으로 변환
 599        
 600        Args:
 601            inStr: 변환할 이름 문자열
 602            
 603        Returns:
 604            설명 문자열 (예: "b_P_L_Arm")
 605        """
 606        nameDic = self.convert_to_dictionary(inStr)
 607        descriptionDic = {}
 608        filteringChar = self._get_filtering_char(inStr)
 609        descName = inStr
 610        if nameDic:
 611            for namePartName, value in nameDic.items():
 612                namePart = self.get_name_part(namePartName)
 613                desc = namePart.get_description_by_value(value)
 614
 615                if desc == "" and value != "":
 616                    desc = value
 617
 618                descriptionDic[namePartName] = desc # Store in dictionary for later use
 619
 620            descName = self.combine(descriptionDic, filteringChar)
 621        
 622        return descName
 623    
 624    def convert_to_korean_description(self, inStr):
 625        """
 626        문자열 이름을 한국어 설명으로 변환
 627        
 628        Args:
 629            inStr: 변환할 이름 문자열
 630            
 631        Returns:
 632            한국어 설명 문자열 (예: "팔_왼쪽_팔")
 633        """
 634        nameDic = self.convert_to_dictionary(inStr)
 635        korDescDic = {}
 636        filteringChar = self._get_filtering_char(inStr)
 637        korDescName = inStr
 638        if nameDic:
 639            for namePartName, value in nameDic.items():
 640                namePart = self.get_name_part(namePartName)
 641                desc = namePart.get_description_by_value(value)
 642                korDesc = namePart.get_korean_description_by_value(value)
 643
 644                if korDesc == "" and desc != "":
 645                    korDesc = desc
 646
 647                korDescDic[namePartName] = korDesc # Store in dictionary for later use
 648
 649            korDescName = self.combine(korDescDic, filteringChar)
 650        
 651        return korDescName
 652    
 653    def has_name_part(self, inPart, inStr):
 654        """
 655        문자열에 특정 namePart가 포함되어 있는지 확인
 656        
 657        Args:
 658            inPart: 확인할 namePart 이름 ("Base", "Type", "Side", "FrontBack", "RealName", "Index")
 659            inStr: 확인할 문자열
 660            
 661        Returns:
 662            포함되어 있으면 True, 아니면 False
 663        """
 664        return self.get_name(inPart, inStr) != ""
 665    
 666    def add_prefix_to_name_part(self, inPart, inStr, inPrefix):
 667        """
 668        이름의 특정 부분에 접두사 추가
 669        
 670        Args:
 671            inPart: 수정할 부분 ("Base", "Type", "Side", "FrontBack", "RealName", "Index")
 672            inStr: 처리할 이름 문자열
 673            inPrefix: 추가할 접두사
 674            
 675        Returns:
 676            수정된 이름 문자열
 677        """
 678        returnStr = inStr
 679        
 680        if inPrefix:
 681            filChar = self._get_filtering_char(inStr)
 682            nameArray = self.convert_name_to_array(inStr)
 683            partIndex = self.get_name_part_index(inPart)
 684                
 685            nameArray[partIndex] = inPrefix + nameArray[partIndex]
 686                    
 687            returnStr = self._combine(nameArray, filChar)
 688                
 689        return returnStr
 690    
 691    def add_suffix_to_name_part(self, inPart, inStr, inSuffix):
 692        """
 693        이름의 특정 부분에 접미사 추가
 694        
 695        Args:
 696            inPart: 수정할 부분 ("Base", "Type", "Side", "FrontBack", "RealName", "Index")
 697            inStr: 처리할 이름 문자열
 698            inSuffix: 추가할 접미사
 699            
 700        Returns:
 701            수정된 이름 문자열
 702        """
 703        returnStr = inStr
 704        
 705        if inSuffix:
 706            filChar = self._get_filtering_char(inStr)
 707            nameArray = self.convert_name_to_array(inStr)
 708            partIndex = self.get_name_part_index(inPart)
 709                
 710            nameArray[partIndex] = nameArray[partIndex] + inSuffix
 711                    
 712            returnStr = self._combine(nameArray, filChar)
 713                
 714        return returnStr
 715
 716    def add_prefix_to_real_name(self, inStr, inPrefix):
 717        """
 718        실제 이름 부분에 접두사 추가
 719        
 720        Args:
 721            inStr: 처리할 이름 문자열
 722            inPrefix: 추가할 접두사
 723            
 724        Returns:
 725            수정된 이름 문자열
 726        """
 727        return self.add_prefix_to_name_part("RealName", inStr, inPrefix)
 728
 729    def add_suffix_to_real_name(self, inStr, inSuffix):
 730        """
 731        실제 이름 부분에 접미사 추가
 732        
 733        Args:
 734            inStr: 처리할 이름 문자열
 735            inSuffix: 추가할 접미사
 736            
 737        Returns:
 738            수정된 이름 문자열
 739        """
 740        return self.add_suffix_to_name_part("RealName", inStr, inSuffix)
 741    
 742    def convert_digit_into_padding_string(self, inDigit, inPaddingNum=None):
 743        """
 744        숫자를 패딩된 문자열로 변환
 745        
 746        Args:
 747            inDigit: 변환할 숫자 또는 숫자 문자열
 748            inPaddingNum: 패딩 자릿수 (기본값: 클래스의 _paddingNum)
 749            
 750        Returns:
 751            패딩된 문자열
 752        """
 753        if inPaddingNum is None:
 754            inPaddingNum = self._paddingNum
 755            
 756        digitNum = 0
 757        
 758        if isinstance(inDigit, int):
 759            digitNum = inDigit
 760        elif isinstance(inDigit, str):
 761            if inDigit.isdigit():
 762                digitNum = int(inDigit)
 763                
 764        # Python의 문자열 포맷팅을 사용하여 패딩
 765        return f"{digitNum:0{inPaddingNum}d}"
 766
 767    def set_index_padding_num(self, inStr, inPaddingNum=None):
 768        """
 769        이름의 인덱스 부분 패딩 설정
 770        
 771        Args:
 772            inStr: 처리할 이름 문자열
 773            inPaddingNum: 설정할 패딩 자릿수 (기본값: 클래스의 _paddingNum)
 774            
 775        Returns:
 776            패딩이 적용된 이름 문자열
 777        """
 778        if inPaddingNum is None:
 779            inPaddingNum = self._paddingNum
 780            
 781        filChar = self._get_filtering_char(inStr)
 782        nameArray = self.convert_name_to_array(inStr)
 783        indexIndex = self.get_name_part_index("Index")
 784        indexStr = self.get_name("Index", inStr)
 785        
 786        if indexStr:
 787            indexStr = self.convert_digit_into_padding_string(indexStr, inPaddingNum)
 788            nameArray[indexIndex] = indexStr
 789            
 790        return self._combine(nameArray, filChar)
 791
 792    def get_index_padding_num(self, inStr):
 793        """
 794        이름의 인덱스 부분 패딩 자릿수 가져오기
 795        
 796        Args:
 797            inStr: 처리할 이름 문자열
 798            
 799        Returns:
 800            인덱스 패딩 자릿수
 801        """
 802        indexVal = self.get_name("Index", inStr)
 803        
 804        if indexVal:
 805            return len(indexVal)
 806            
 807        return 1
 808
 809    def increase_index(self, inStr, inAmount):
 810        """
 811        이름의 인덱스 부분 값 증가
 812        
 813        Args:
 814            inStr: 처리할 이름 문자열
 815            inAmount: 증가시킬 값
 816            
 817        Returns:
 818            인덱스가 증가된 이름 문자열
 819        """
 820        newName = inStr
 821        filChar = self._get_filtering_char(inStr)
 822        nameArray = self.convert_name_to_array(inStr)
 823        indexIndex = self.get_name_part_index("Index")
 824        
 825        if indexIndex >= 0:
 826            indexStr = ""
 827            indexPaddingNum = self._paddingNum
 828            indexNum = -99999
 829            
 830            if not nameArray[indexIndex]:
 831                indexNum = -1
 832            else:
 833                try:
 834                    indexNum = int(nameArray[indexIndex])
 835                    indexPaddingNum = len(nameArray[indexIndex])
 836                except ValueError:
 837                    pass
 838            
 839            indexNum += inAmount
 840            
 841            if indexNum < 0:
 842                indexNum = 0
 843            
 844            # Python의 문자열 포맷팅을 사용하여 패딩
 845            indexStr = f"{indexNum:0{indexPaddingNum}d}"
 846            nameArray[indexIndex] = indexStr
 847            newName = self._combine(nameArray, filChar)
 848            newName = self.set_index_padding_num(newName)
 849            
 850        return newName
 851
 852    def get_index_as_digit(self, inStr):
 853        """
 854        이름의 인덱스를 숫자로 변환
 855        
 856        Args:
 857            inStr: 변환할 이름 문자열
 858            
 859        Returns:
 860            숫자로 변환된 인덱스 (넙이 있으면 -1, 인덱스가 없으면 False)
 861        """
 862        indexStr = self.get_name("Index", inStr)
 863            
 864        if indexStr:
 865            try:
 866                return int(indexStr)
 867            except ValueError:
 868                pass
 869                
 870        return False
 871
 872    def sort_by_index(self, inNameArray):
 873        """
 874        이름 배열을 인덱스 기준으로 정렬
 875        
 876        Args:
 877            inNameArray: 정렬할 이름 배열
 878            
 879        Returns:
 880            인덱스 기준으로 정렬된 이름 배열
 881        """
 882        if not inNameArray:
 883            return []
 884            
 885        # 정렬을 위한 보조 클래스 정의
 886        @dataclass
 887        class IndexSorting:
 888            oriIndex: int
 889            newIndex: int
 890                
 891        # 각 이름의 인덱스를 추출하여 정렬 정보 생성
 892        structArray = []
 893        
 894        for i, name in enumerate(inNameArray):
 895            tempIndex = self.get_index_as_digit(name)
 896            
 897            if tempIndex is False:
 898                structArray.append(IndexSorting(i, 0))
 899            else:
 900                structArray.append(IndexSorting(i, tempIndex))
 901                
 902        # 인덱스 기준으로 정렬
 903        structArray.sort(key=lambda x: x.newIndex)
 904        
 905        # 정렬된 순서로 결과 배열 생성
 906        sortedNameArray = []
 907        for struct in structArray:
 908            sortedNameArray.append(inNameArray[struct.oriIndex])
 909            
 910        return sortedNameArray
 911    
 912    def get_string(self, inStr):
 913        """
 914        인덱스 부분을 제외한 이름 문자열 가져오기
 915        
 916        Args:
 917            inStr: 처리할 이름 문자열
 918            
 919        Returns:
 920            인덱스가 제외된 이름 문자열
 921        """
 922        filChar = self._get_filtering_char(inStr)
 923        nameArray = self.convert_name_to_array(inStr)
 924        indexOrder = self.get_name_part_index("Index")
 925        
 926        # 인덱스 부분 제거
 927        returnNameArray = nameArray.copy()
 928        returnNameArray[indexOrder] = ""
 929        
 930        return self._combine(returnNameArray, filChar)
 931
 932    def gen_mirroring_name(self, inStr):
 933        """
 934        미러링된 이름 생성 (측면 또는 앞/뒤 변경)
 935        
 936        이름에서 Side와 FrontBack namePart를 자동으로 검색하고,
 937        발견된 값의 semanticmapping weight와 가장 차이가 큰 값으로 교체합니다.
 938        
 939        Args:
 940            inStr: 처리할 이름 문자열
 941            
 942        Returns:
 943            미러링된 이름 문자열
 944        """
 945        nameArray = self.convert_name_to_array(inStr)
 946            
 947        for part in self._nameParts:
 948            partName = part.get_name()
 949            partType = part.get_type()
 950            if (partType != NamePartType.REALNAME or partType != NamePartType.INDEX) and part.is_direction():
 951                partIndex = self.get_name_part_index(partName)
 952                foundName = self.get_name(partName, inStr)
 953                opositeName = part.get_most_different_weight_value(foundName)
 954                if opositeName and foundName != opositeName:
 955                    nameArray[partIndex] = opositeName
 956        
 957        returnName = self._combine(nameArray, self._get_filtering_char(inStr))
 958        
 959        return returnName
 960
 961    def replace_filtering_char(self, inStr, inNewFilChar):
 962        """
 963        이름의 구분자 문자 변경
 964        
 965        Args:
 966            inStr: 처리할 이름 문자열
 967            inNewFilChar: 새 구분자 문자
 968            
 969        Returns:
 970            구분자가 변경된 이름 문자열
 971        """
 972        nameArray = self.convert_name_to_array(inStr)
 973        return self._combine(nameArray, inNewFilChar)
 974
 975    def replace_name_part(self, inPart, inStr, inNewName):
 976        """
 977        이름의 특정 부분을 새 이름으로 변경
 978        
 979        Args:
 980            inPart: 수정할 부분 ("Base", "Type", "Side", "FrontBack", "RealName", "Index")
 981            inStr: 처리할 이름 문자열
 982            inNewName: 새 이름
 983        
 984        Returns:
 985            수정된 이름 문자열
 986        """
 987        nameArray = self.convert_name_to_array(inStr)
 988        partIndex = self.get_name_part_index(inPart)
 989        
 990        if partIndex >= 0:
 991            nameArray[partIndex] = inNewName
 992        
 993        newName = self._combine(nameArray, self._get_filtering_char(inStr))
 994        newName = self.set_index_padding_num(newName)
 995        
 996        return newName
 997
 998    def remove_name_part(self, inPart, inStr):
 999        """
1000        이름의 특정 부분 제거
1001        
1002        Args:
1003            inPart: 제거할 부분 ("Base", "Type", "Side", "FrontBack", "RealName", "Index")
1004            inStr: 처리할 이름 문자열
1005            
1006        Returns:
1007            수정된 이름 문자열
1008        """
1009        nameArray = self.convert_name_to_array(inStr)
1010        partIndex = self.get_name_part_index(inPart)
1011        
1012        if partIndex >= 0:
1013            nameArray[partIndex] = ""
1014            
1015        newName = self._combine(nameArray, self._get_filtering_char(inStr))
1016        newName = self.set_index_padding_num(newName)
1017        
1018        return newName
1019
1020    def load_from_config_file(self, configPath=None):
1021        """
1022        설정 파일에서 설정 로드
1023        
1024        Args:
1025            configPath: 설정 파일 경로 (기본값: self._configPath)
1026            
1027        Returns:
1028            로드 성공 여부 (True/False)
1029        """
1030        # 경로가 없으면 인스턴스 생성 시 설정된 경로 사용
1031        if not configPath:
1032            configPath = self._configPath
1033            
1034        if not configPath:
1035            print("설정 파일 경로가 제공되지 않았습니다.")
1036            return False
1037            
1038        # NamingConfig 인스턴스 생성 및 설정 로드
1039        config = NamingConfig()
1040        if config.load(configPath):
1041            # 설정을 Naming 인스턴스에 적용
1042            result = config.apply_to_naming(self)
1043            if result:
1044                self._configPath = configPath  # 성공적으로 로드한 경로 저장
1045            return result
1046        else:
1047            print(f"설정 파일 로드 실패: {configPath}")
1048            return False
1049    
1050    def load_default_config(self):
1051        """
1052        기본 설정 로드 (현재는 아무 작업도 수행하지 않음)
1053        
1054        Returns:
1055            항상 True 반환 (기본 설정은 __init__에서 이미 설정됨)
1056        """
1057        # 이 메소드는 현재 __init__에서 설정한 기본값을 그대로 사용하므로
1058        # 아무 작업도 수행하지 않습니다.
1059        return True
1060
1061    def get_config_path(self):
1062        """
1063        현재 설정 파일 경로 가져오기
1064        
1065        Returns:
1066            설정 파일 경로 (없으면 빈 문자열)
1067        """
1068        return self._configPath or ""

노드 이름을 관리하기 위한 기본 클래스. 기본적인 이름 구성 요소를 정의하고 관리합니다. 이 클래스는 하위 클래스에서 확장하여 특정 목적에 맞게 사용할 수 있습니다.

Naming(configPath=None)
26    def __init__(self, configPath=None):
27        """
28        클래스 초기화 및 기본 설정값 정의
29        
30        Args:
31            configPath: 설정 파일 경로 (기본값: None)
32                        설정 파일이 제공되면 해당 파일에서 설정을 로드함
33        """
34        # 기본 설정값
35        self._paddingNum = 2
36        self._configPath = configPath
37        
38        # 기본 namePart 초기화 (각 부분에 사전 정의 값 직접 설정)
39        self._nameParts = []
40        
41        # Prefix 부분 (PREFIX 타입)
42        prefixPart = NamePart("Prefix", NamePartType.PREFIX, ["Pr"], ["Prefix"])
43        
44        # RealName 부분 (REALNAME 타입)
45        realNamePart = NamePart("RealName", NamePartType.REALNAME, [], [])
46        
47        # Index 부분 (INDEX 타입)
48        indexPart = NamePart("Index", NamePartType.INDEX, [], [])
49        
50        # Suffix 부분 (SUFFIX 타입)
51        suffixPart = NamePart("Suffix", NamePartType.SUFFIX, ["Su"], ["Suffix"])
52        
53        # 기본 순서대로 설정
54        self._nameParts = [prefixPart, realNamePart, indexPart, suffixPart]
55        
56        # 설정 파일이 제공된 경우 로드
57        if configPath:
58            self.load_from_config_file(configPath)
59        else:
60            # 기본 JSON 설정 파일 로드 시도
61            self.load_default_config()

클래스 초기화 및 기본 설정값 정의

Args: configPath: 설정 파일 경로 (기본값: None) 설정 파일이 제공되면 해당 파일에서 설정을 로드함

def get_padding_num(self):
254    def get_padding_num(self):
255        """
256        패딩 숫자 가져오기
257        
258        Returns:
259            패딩 숫자
260        """
261        return self._paddingNum

패딩 숫자 가져오기

Returns: 패딩 숫자

def get_name_part(self, inNamePartName):
263    def get_name_part(self, inNamePartName):
264        """
265        namePart 이름으로 NamePart 객체 가져오기
266        
267        Args:
268            namePart: 가져올 NamePart의 이름 ("Prefix", "RealName", "Suffix", "Index" 등)
269            
270        Returns:
271            해당 NamePart 객체, 존재하지 않으면 None
272        """
273        for part in self._nameParts:
274            if part.get_name() == inNamePartName:
275                return part
276        return None

namePart 이름으로 NamePart 객체 가져오기

Args: namePart: 가져올 NamePart의 이름 ("Prefix", "RealName", "Suffix", "Index" 등)

Returns: 해당 NamePart 객체, 존재하지 않으면 None

def get_name_part_index(self, inNamePartName):
278    def get_name_part_index(self, inNamePartName):
279        """
280        namePart 이름으로 인덱스 가져오기
281        
282        Args:
283            namePart: 가져올 NamePart의 이름 ("Prefix", "RealName", "Suffix", "Index" 등)
284            
285        Returns:
286            해당 NamePart의 인덱스, 존재하지 않으면 -1
287        """
288        for i, part in enumerate(self._nameParts):
289            if part.get_name() == inNamePartName:
290                return i
291        return -1

namePart 이름으로 인덱스 가져오기

Args: namePart: 가져올 NamePart의 이름 ("Prefix", "RealName", "Suffix", "Index" 등)

Returns: 해당 NamePart의 인덱스, 존재하지 않으면 -1

def get_name_part_predefined_values(self, inNamePartName):
293    def get_name_part_predefined_values(self, inNamePartName):
294        """
295        namePart의 사전 정의 값 가져오기
296        
297        Args:
298            namePart: 가져올 NamePart의 이름 ("Prefix", "RealName", "Suffix", "Index" 등)
299            
300        Returns:
301            해당 NamePart의 사전 정의 값 리스트, 존재하지 않으면 빈 리스트
302        """
303        partObj = self.get_name_part(inNamePartName)
304        if partObj:
305            return partObj.get_predefined_values()
306        return []

namePart의 사전 정의 값 가져오기

Args: namePart: 가져올 NamePart의 이름 ("Prefix", "RealName", "Suffix", "Index" 등)

Returns: 해당 NamePart의 사전 정의 값 리스트, 존재하지 않으면 빈 리스트

def is_in_name_part_predefined_values(self, inNamePartName, inStr):
308    def is_in_name_part_predefined_values(self, inNamePartName, inStr):
309        """
310        지정된 namePart에 해당하는 부분이 문자열에 포함되어 있는지 확인
311        
312        Args:
313            namePart: 확인할 namePart 이름 ("Base", "Type", "Side" 등)
314            inStr: 확인할 문자열
315            
316        Returns:
317            포함되어 있으면 True, 아니면 False
318        """
319        partObj = self.get_name_part(inNamePartName)
320        if not partObj:
321            return False
322        
323        partType = partObj.get_type()
324        if not partType:
325            return False
326            
327        partValues = partObj.get_predefined_values()
328        
329        if partType == NamePartType.PREFIX or partType == NamePartType.SUFFIX:
330            return any(item in inStr for item in partValues)
331        
332        return False

지정된 namePart에 해당하는 부분이 문자열에 포함되어 있는지 확인

Args: namePart: 확인할 namePart 이름 ("Base", "Type", "Side" 등) inStr: 확인할 문자열

Returns: 포함되어 있으면 True, 아니면 False

def get_name_part_value_by_description(self, inNamePartName, inDescription):
334    def get_name_part_value_by_description(self, inNamePartName, inDescription):
335        """
336        지정된 namePart에 해당하는 부분을 문자열에서 추출
337        
338        Args:
339            namePart: 추출할 namePart 이름 ("Base", "Type", "Side" 등)
340            inDescription: predefined value에서 찾기위한 description 문자열
341            
342        Returns:
343            지정된 namePart에 해당하는 문자열
344        """
345        partObj = self.get_name_part(inNamePartName)
346        if not partObj:
347            return ""
348        
349        partType = partObj.get_type()
350        if not partType:
351            return ""
352            
353        partValues = partObj.get_predefined_values()
354        
355        if partType == NamePartType.PREFIX or partType == NamePartType.SUFFIX:
356            try:
357                foundIndex = partObj._descriptions.index(inDescription)
358                return partValues[foundIndex]
359            except ValueError:
360                # Description not found in the list
361                return ""

지정된 namePart에 해당하는 부분을 문자열에서 추출

Args: namePart: 추출할 namePart 이름 ("Base", "Type", "Side" 등) inDescription: predefined value에서 찾기위한 description 문자열

Returns: 지정된 namePart에 해당하는 문자열

def pick_name(self, inNamePartName, inStr):
363    def pick_name(self, inNamePartName, inStr):
364        nameArray = self._split_to_array(inStr)
365        returnStr = ""
366        
367        # namePart 문자열 목록 가져오기
368        partObj = self.get_name_part(inNamePartName)
369        if not partObj:
370            return returnStr
371        
372        partType = partObj.get_type()
373        if not partType:
374            return returnStr
375            
376        partValues = partObj.get_predefined_values()
377        if partType != NamePartType.INDEX and partType != NamePartType.REALNAME and not partValues:
378            return returnStr
379        
380        if partType == NamePartType.PREFIX:
381            for item in nameArray:
382                if item in partValues:
383                    returnStr = item
384                    break
385        
386        if partType == NamePartType.SUFFIX:
387            for i in range(len(nameArray) - 1, -1, -1):
388                if nameArray[i] in partValues:
389                    returnStr = nameArray[i]
390                    break
391                
392        if partType == NamePartType.INDEX:
393            if self.get_name_part_index("Index") > self.get_name_part_index("RealName"):
394                for i in range(len(nameArray) - 1, -1, -1):
395                    if nameArray[i].isdigit():
396                        returnStr = nameArray[i]
397                        break
398            else:
399                for item in nameArray:
400                    if item.isdigit():
401                        returnStr = item
402                        break
403        
404        return returnStr
def get_name(self, inNamePartName, inStr):
406    def get_name(self, inNamePartName, inStr):
407        """
408        지정된 namePart에 해당하는 부분을 문자열에서 추출
409        
410        Args:
411            namePart: 추출할 namePart 이름 ("Base", "Type", "Side" 등)
412            inStr: 처리할 문자열
413            
414        Returns:
415            지정된 namePart에 해당하는 문자열
416        """
417        nameArray = self._split_to_array(inStr)
418        returnStr = ""
419        
420        partType = self.get_name_part(inNamePartName).get_type()
421        
422        foundName = self.pick_name(inNamePartName, inStr)
423        if foundName == "":
424            return returnStr
425        partIndex = self.get_name_part_index(inNamePartName)
426        foundIndex = nameArray.index(foundName)
427        
428        if partType == NamePartType.PREFIX:
429            if foundIndex >= 0:
430                prevNameParts = self._nameParts[:partIndex]
431                prevNames = [self.pick_name(part.get_name(), inStr) for part in prevNameParts]
432                prevNamesInNameArray = nameArray[:foundIndex]
433                for prevName in prevNames:
434                    if prevName in prevNamesInNameArray:
435                        prevNamesInNameArray.remove(prevName)
436                if len(prevNamesInNameArray) == 0 :
437                    returnStr = foundName
438        
439        if partType == NamePartType.SUFFIX:
440            if foundIndex >= 0:
441                nextNameParts = self._nameParts[partIndex + 1:]
442                nextNames = [self.pick_name(part.get_name(), inStr) for part in nextNameParts]
443                nextNamesInNameArray = nameArray[foundIndex + 1:]
444                for nextName in nextNames:
445                    if nextName in nextNamesInNameArray:
446                        nextNamesInNameArray.remove(nextName)
447                if len(nextNamesInNameArray) == 0 :
448                    returnStr = foundName
449        
450        if partType == NamePartType.INDEX:
451            returnStr = self.pick_name(inNamePartName, inStr)
452                
453        return returnStr

지정된 namePart에 해당하는 부분을 문자열에서 추출

Args: namePart: 추출할 namePart 이름 ("Base", "Type", "Side" 등) inStr: 처리할 문자열

Returns: 지정된 namePart에 해당하는 문자열

def combine(self, inPartsDict={}, inFilChar=' '):
455    def combine(self, inPartsDict={}, inFilChar=" "):
456        """
457        namingConfig에서 정의된 nameParts와 그 순서에 따라 이름 부분들을 조합하여 완전한 이름 생성
458        
459        Args:
460            parts_dict: namePart 이름과 값의 딕셔너리 (예: {"Base": "b", "Type": "P", "Side": "L"})
461            inFilChar: 구분자 문자 (기본값: " ")
462            
463        Returns:
464            조합된 이름 문자열
465        """
466        # 결과 배열 초기화 (빈 문자열로)
467        combinedNameArray = [""] * len(self._nameParts)
468        
469        # 각 namePart에 대해
470        for i, part in enumerate(self._nameParts):
471            partName = part.get_name()
472            # 딕셔너리에서 해당 부분의 값 가져오기 (없으면 빈 문자열 사용)
473            if partName in inPartsDict:
474                combinedNameArray[i] = inPartsDict[partName]
475                
476        # 배열을 문자열로 결합
477        newName = self._combine(combinedNameArray, inFilChar)
478        newName = self.set_index_padding_num(newName)
479        return newName

namingConfig에서 정의된 nameParts와 그 순서에 따라 이름 부분들을 조합하여 완전한 이름 생성

Args: parts_dict: namePart 이름과 값의 딕셔너리 (예: {"Base": "b", "Type": "P", "Side": "L"}) inFilChar: 구분자 문자 (기본값: " ")

Returns: 조합된 이름 문자열

def get_RealName(self, inStr):
481    def get_RealName(self, inStr):
482        """
483        문자열에서 실제 이름 부분 추출
484        
485        Args:
486            inStr: 처리할 문자열
487            
488        Returns:
489            실제 이름 부분 문자열
490        """
491        filChar = self._get_filtering_char(inStr)
492        nameArray = self._split_to_array(inStr)
493        
494        # 모든 nameParts 중 RealName이 아닌 것들의 값을 수집
495        nonRealNameArray = []
496        for part in self._nameParts:
497            partName = part.get_name()
498            partType = part.get_type()
499            if partType != NamePartType.REALNAME:
500                foundName = self.get_name(partName, inStr)
501                nonRealNameArray.append(foundName)
502        
503        for item in nonRealNameArray:
504            if item in nameArray:
505                nameArray.remove(item)
506                
507        # 구분자로 결합
508        return self._combine(nameArray, filChar)

문자열에서 실제 이름 부분 추출

Args: inStr: 처리할 문자열

Returns: 실제 이름 부분 문자열

def get_non_RealName(self, inStr):
510    def get_non_RealName(self, inStr):
511        """
512        실제 이름 부분을 제외한 이름 가져오기
513        
514        Args:
515            inStr: 처리할 이름 문자열
516            
517        Returns:
518            실제 이름이 제외된 이름 문자열
519        """
520        filChar = self._get_filtering_char(inStr)
521        
522        # 모든 nameParts 중 RealName이 아닌 것들의 값을 수집
523        nonRealNameArray = []
524        for part in self._nameParts:
525            partName = part.get_name()
526            partType = part.get_type()
527            if partType != NamePartType.REALNAME:
528                foundName = self.get_name(partName, inStr)
529                nonRealNameArray.append(foundName)
530        
531        return self._combine(nonRealNameArray, filChar)

실제 이름 부분을 제외한 이름 가져오기

Args: inStr: 처리할 이름 문자열

Returns: 실제 이름이 제외된 이름 문자열

def convert_name_to_array(self, inStr):
533    def convert_name_to_array(self, inStr):
534        """
535        문자열 이름을 이름 부분 배열로 변환
536        
537        Args:
538            inStr: 변환할 이름 문자열
539            
540        Returns:
541            이름 부분 배열 (Base, Type, Side, FrontBack, RealName, Index, Nub 등)
542        """
543        returnArray = [""] * len(self._nameParts)
544        
545        # 각 namePart에 대해 처리
546        for i, part in enumerate(self._nameParts):
547            partName = part.get_name()
548            
549            # 특수 케이스인 RealName은 마지막에 처리하기 위해 저장
550            if partName == "RealName":
551                realNameIndex = i
552                continue
553                
554            # get_name 메소드를 사용하여 해당 부분 추출
555            partValue = self.get_name(partName, inStr)
556            returnArray[i] = partValue
557        
558        # 마지막으로 RealName 처리 (다른 모든 부분을 찾은 후에 수행해야 함)
559        if 'realNameIndex' in locals():
560            realNameStr = self.get_RealName(inStr)
561            returnArray[realNameIndex] = realNameStr
562        
563        return returnArray

문자열 이름을 이름 부분 배열로 변환

Args: inStr: 변환할 이름 문자열

Returns: 이름 부분 배열 (Base, Type, Side, FrontBack, RealName, Index, Nub 등)

def convert_to_dictionary(self, inStr):
565    def convert_to_dictionary(self, inStr):
566        """
567        문자열 이름을 이름 부분 딕셔너리로 변환
568        
569        Args:
570            inStr: 변환할 이름 문자열
571            
572        Returns:
573            이름 부분 딕셔너리 (키: namePart 이름, 값: 추출된 값)
574            예: {"Base": "b", "Type": "P", "Side": "L", "RealName": "Arm", ...}
575        """
576        returnDict = {}
577        
578        # 각 namePart에 대해 처리
579        for part in self._nameParts:
580            partName = part.get_name()
581            
582            # 특수 케이스인 RealName은 마지막에 처리하기 위해 저장
583            if partName == "RealName":
584                continue
585                
586            # get_name 메소드를 사용하여 해당 부분 추출
587            partValue = self.get_name(partName, inStr)
588            returnDict[partName] = partValue
589        
590        # 마지막으로 RealName 처리 (다른 모든 부분을 찾은 후에 수행해야 함)
591        realNameStr = self.get_RealName(inStr)
592        returnDict["RealName"] = realNameStr
593        
594        return returnDict

문자열 이름을 이름 부분 딕셔너리로 변환

Args: inStr: 변환할 이름 문자열

Returns: 이름 부분 딕셔너리 (키: namePart 이름, 값: 추출된 값) 예: {"Base": "b", "Type": "P", "Side": "L", "RealName": "Arm", ...}

def convert_to_description(self, inStr):
596    def convert_to_description(self, inStr):
597        """
598        문자열 이름을 설명으로 변환
599        
600        Args:
601            inStr: 변환할 이름 문자열
602            
603        Returns:
604            설명 문자열 (예: "b_P_L_Arm")
605        """
606        nameDic = self.convert_to_dictionary(inStr)
607        descriptionDic = {}
608        filteringChar = self._get_filtering_char(inStr)
609        descName = inStr
610        if nameDic:
611            for namePartName, value in nameDic.items():
612                namePart = self.get_name_part(namePartName)
613                desc = namePart.get_description_by_value(value)
614
615                if desc == "" and value != "":
616                    desc = value
617
618                descriptionDic[namePartName] = desc # Store in dictionary for later use
619
620            descName = self.combine(descriptionDic, filteringChar)
621        
622        return descName

문자열 이름을 설명으로 변환

Args: inStr: 변환할 이름 문자열

Returns: 설명 문자열 (예: "b_P_L_Arm")

def convert_to_korean_description(self, inStr):
624    def convert_to_korean_description(self, inStr):
625        """
626        문자열 이름을 한국어 설명으로 변환
627        
628        Args:
629            inStr: 변환할 이름 문자열
630            
631        Returns:
632            한국어 설명 문자열 (예: "팔_왼쪽_팔")
633        """
634        nameDic = self.convert_to_dictionary(inStr)
635        korDescDic = {}
636        filteringChar = self._get_filtering_char(inStr)
637        korDescName = inStr
638        if nameDic:
639            for namePartName, value in nameDic.items():
640                namePart = self.get_name_part(namePartName)
641                desc = namePart.get_description_by_value(value)
642                korDesc = namePart.get_korean_description_by_value(value)
643
644                if korDesc == "" and desc != "":
645                    korDesc = desc
646
647                korDescDic[namePartName] = korDesc # Store in dictionary for later use
648
649            korDescName = self.combine(korDescDic, filteringChar)
650        
651        return korDescName

문자열 이름을 한국어 설명으로 변환

Args: inStr: 변환할 이름 문자열

Returns: 한국어 설명 문자열 (예: "팔_왼쪽_팔")

def has_name_part(self, inPart, inStr):
653    def has_name_part(self, inPart, inStr):
654        """
655        문자열에 특정 namePart가 포함되어 있는지 확인
656        
657        Args:
658            inPart: 확인할 namePart 이름 ("Base", "Type", "Side", "FrontBack", "RealName", "Index")
659            inStr: 확인할 문자열
660            
661        Returns:
662            포함되어 있으면 True, 아니면 False
663        """
664        return self.get_name(inPart, inStr) != ""

문자열에 특정 namePart가 포함되어 있는지 확인

Args: inPart: 확인할 namePart 이름 ("Base", "Type", "Side", "FrontBack", "RealName", "Index") inStr: 확인할 문자열

Returns: 포함되어 있으면 True, 아니면 False

def add_prefix_to_name_part(self, inPart, inStr, inPrefix):
666    def add_prefix_to_name_part(self, inPart, inStr, inPrefix):
667        """
668        이름의 특정 부분에 접두사 추가
669        
670        Args:
671            inPart: 수정할 부분 ("Base", "Type", "Side", "FrontBack", "RealName", "Index")
672            inStr: 처리할 이름 문자열
673            inPrefix: 추가할 접두사
674            
675        Returns:
676            수정된 이름 문자열
677        """
678        returnStr = inStr
679        
680        if inPrefix:
681            filChar = self._get_filtering_char(inStr)
682            nameArray = self.convert_name_to_array(inStr)
683            partIndex = self.get_name_part_index(inPart)
684                
685            nameArray[partIndex] = inPrefix + nameArray[partIndex]
686                    
687            returnStr = self._combine(nameArray, filChar)
688                
689        return returnStr

이름의 특정 부분에 접두사 추가

Args: inPart: 수정할 부분 ("Base", "Type", "Side", "FrontBack", "RealName", "Index") inStr: 처리할 이름 문자열 inPrefix: 추가할 접두사

Returns: 수정된 이름 문자열

def add_suffix_to_name_part(self, inPart, inStr, inSuffix):
691    def add_suffix_to_name_part(self, inPart, inStr, inSuffix):
692        """
693        이름의 특정 부분에 접미사 추가
694        
695        Args:
696            inPart: 수정할 부분 ("Base", "Type", "Side", "FrontBack", "RealName", "Index")
697            inStr: 처리할 이름 문자열
698            inSuffix: 추가할 접미사
699            
700        Returns:
701            수정된 이름 문자열
702        """
703        returnStr = inStr
704        
705        if inSuffix:
706            filChar = self._get_filtering_char(inStr)
707            nameArray = self.convert_name_to_array(inStr)
708            partIndex = self.get_name_part_index(inPart)
709                
710            nameArray[partIndex] = nameArray[partIndex] + inSuffix
711                    
712            returnStr = self._combine(nameArray, filChar)
713                
714        return returnStr

이름의 특정 부분에 접미사 추가

Args: inPart: 수정할 부분 ("Base", "Type", "Side", "FrontBack", "RealName", "Index") inStr: 처리할 이름 문자열 inSuffix: 추가할 접미사

Returns: 수정된 이름 문자열

def add_prefix_to_real_name(self, inStr, inPrefix):
716    def add_prefix_to_real_name(self, inStr, inPrefix):
717        """
718        실제 이름 부분에 접두사 추가
719        
720        Args:
721            inStr: 처리할 이름 문자열
722            inPrefix: 추가할 접두사
723            
724        Returns:
725            수정된 이름 문자열
726        """
727        return self.add_prefix_to_name_part("RealName", inStr, inPrefix)

실제 이름 부분에 접두사 추가

Args: inStr: 처리할 이름 문자열 inPrefix: 추가할 접두사

Returns: 수정된 이름 문자열

def add_suffix_to_real_name(self, inStr, inSuffix):
729    def add_suffix_to_real_name(self, inStr, inSuffix):
730        """
731        실제 이름 부분에 접미사 추가
732        
733        Args:
734            inStr: 처리할 이름 문자열
735            inSuffix: 추가할 접미사
736            
737        Returns:
738            수정된 이름 문자열
739        """
740        return self.add_suffix_to_name_part("RealName", inStr, inSuffix)

실제 이름 부분에 접미사 추가

Args: inStr: 처리할 이름 문자열 inSuffix: 추가할 접미사

Returns: 수정된 이름 문자열

def convert_digit_into_padding_string(self, inDigit, inPaddingNum=None):
742    def convert_digit_into_padding_string(self, inDigit, inPaddingNum=None):
743        """
744        숫자를 패딩된 문자열로 변환
745        
746        Args:
747            inDigit: 변환할 숫자 또는 숫자 문자열
748            inPaddingNum: 패딩 자릿수 (기본값: 클래스의 _paddingNum)
749            
750        Returns:
751            패딩된 문자열
752        """
753        if inPaddingNum is None:
754            inPaddingNum = self._paddingNum
755            
756        digitNum = 0
757        
758        if isinstance(inDigit, int):
759            digitNum = inDigit
760        elif isinstance(inDigit, str):
761            if inDigit.isdigit():
762                digitNum = int(inDigit)
763                
764        # Python의 문자열 포맷팅을 사용하여 패딩
765        return f"{digitNum:0{inPaddingNum}d}"

숫자를 패딩된 문자열로 변환

Args: inDigit: 변환할 숫자 또는 숫자 문자열 inPaddingNum: 패딩 자릿수 (기본값: 클래스의 _paddingNum)

Returns: 패딩된 문자열

def set_index_padding_num(self, inStr, inPaddingNum=None):
767    def set_index_padding_num(self, inStr, inPaddingNum=None):
768        """
769        이름의 인덱스 부분 패딩 설정
770        
771        Args:
772            inStr: 처리할 이름 문자열
773            inPaddingNum: 설정할 패딩 자릿수 (기본값: 클래스의 _paddingNum)
774            
775        Returns:
776            패딩이 적용된 이름 문자열
777        """
778        if inPaddingNum is None:
779            inPaddingNum = self._paddingNum
780            
781        filChar = self._get_filtering_char(inStr)
782        nameArray = self.convert_name_to_array(inStr)
783        indexIndex = self.get_name_part_index("Index")
784        indexStr = self.get_name("Index", inStr)
785        
786        if indexStr:
787            indexStr = self.convert_digit_into_padding_string(indexStr, inPaddingNum)
788            nameArray[indexIndex] = indexStr
789            
790        return self._combine(nameArray, filChar)

이름의 인덱스 부분 패딩 설정

Args: inStr: 처리할 이름 문자열 inPaddingNum: 설정할 패딩 자릿수 (기본값: 클래스의 _paddingNum)

Returns: 패딩이 적용된 이름 문자열

def get_index_padding_num(self, inStr):
792    def get_index_padding_num(self, inStr):
793        """
794        이름의 인덱스 부분 패딩 자릿수 가져오기
795        
796        Args:
797            inStr: 처리할 이름 문자열
798            
799        Returns:
800            인덱스 패딩 자릿수
801        """
802        indexVal = self.get_name("Index", inStr)
803        
804        if indexVal:
805            return len(indexVal)
806            
807        return 1

이름의 인덱스 부분 패딩 자릿수 가져오기

Args: inStr: 처리할 이름 문자열

Returns: 인덱스 패딩 자릿수

def increase_index(self, inStr, inAmount):
809    def increase_index(self, inStr, inAmount):
810        """
811        이름의 인덱스 부분 값 증가
812        
813        Args:
814            inStr: 처리할 이름 문자열
815            inAmount: 증가시킬 값
816            
817        Returns:
818            인덱스가 증가된 이름 문자열
819        """
820        newName = inStr
821        filChar = self._get_filtering_char(inStr)
822        nameArray = self.convert_name_to_array(inStr)
823        indexIndex = self.get_name_part_index("Index")
824        
825        if indexIndex >= 0:
826            indexStr = ""
827            indexPaddingNum = self._paddingNum
828            indexNum = -99999
829            
830            if not nameArray[indexIndex]:
831                indexNum = -1
832            else:
833                try:
834                    indexNum = int(nameArray[indexIndex])
835                    indexPaddingNum = len(nameArray[indexIndex])
836                except ValueError:
837                    pass
838            
839            indexNum += inAmount
840            
841            if indexNum < 0:
842                indexNum = 0
843            
844            # Python의 문자열 포맷팅을 사용하여 패딩
845            indexStr = f"{indexNum:0{indexPaddingNum}d}"
846            nameArray[indexIndex] = indexStr
847            newName = self._combine(nameArray, filChar)
848            newName = self.set_index_padding_num(newName)
849            
850        return newName

이름의 인덱스 부분 값 증가

Args: inStr: 처리할 이름 문자열 inAmount: 증가시킬 값

Returns: 인덱스가 증가된 이름 문자열

def get_index_as_digit(self, inStr):
852    def get_index_as_digit(self, inStr):
853        """
854        이름의 인덱스를 숫자로 변환
855        
856        Args:
857            inStr: 변환할 이름 문자열
858            
859        Returns:
860            숫자로 변환된 인덱스 (넙이 있으면 -1, 인덱스가 없으면 False)
861        """
862        indexStr = self.get_name("Index", inStr)
863            
864        if indexStr:
865            try:
866                return int(indexStr)
867            except ValueError:
868                pass
869                
870        return False

이름의 인덱스를 숫자로 변환

Args: inStr: 변환할 이름 문자열

Returns: 숫자로 변환된 인덱스 (넙이 있으면 -1, 인덱스가 없으면 False)

def sort_by_index(self, inNameArray):
872    def sort_by_index(self, inNameArray):
873        """
874        이름 배열을 인덱스 기준으로 정렬
875        
876        Args:
877            inNameArray: 정렬할 이름 배열
878            
879        Returns:
880            인덱스 기준으로 정렬된 이름 배열
881        """
882        if not inNameArray:
883            return []
884            
885        # 정렬을 위한 보조 클래스 정의
886        @dataclass
887        class IndexSorting:
888            oriIndex: int
889            newIndex: int
890                
891        # 각 이름의 인덱스를 추출하여 정렬 정보 생성
892        structArray = []
893        
894        for i, name in enumerate(inNameArray):
895            tempIndex = self.get_index_as_digit(name)
896            
897            if tempIndex is False:
898                structArray.append(IndexSorting(i, 0))
899            else:
900                structArray.append(IndexSorting(i, tempIndex))
901                
902        # 인덱스 기준으로 정렬
903        structArray.sort(key=lambda x: x.newIndex)
904        
905        # 정렬된 순서로 결과 배열 생성
906        sortedNameArray = []
907        for struct in structArray:
908            sortedNameArray.append(inNameArray[struct.oriIndex])
909            
910        return sortedNameArray

이름 배열을 인덱스 기준으로 정렬

Args: inNameArray: 정렬할 이름 배열

Returns: 인덱스 기준으로 정렬된 이름 배열

def get_string(self, inStr):
912    def get_string(self, inStr):
913        """
914        인덱스 부분을 제외한 이름 문자열 가져오기
915        
916        Args:
917            inStr: 처리할 이름 문자열
918            
919        Returns:
920            인덱스가 제외된 이름 문자열
921        """
922        filChar = self._get_filtering_char(inStr)
923        nameArray = self.convert_name_to_array(inStr)
924        indexOrder = self.get_name_part_index("Index")
925        
926        # 인덱스 부분 제거
927        returnNameArray = nameArray.copy()
928        returnNameArray[indexOrder] = ""
929        
930        return self._combine(returnNameArray, filChar)

인덱스 부분을 제외한 이름 문자열 가져오기

Args: inStr: 처리할 이름 문자열

Returns: 인덱스가 제외된 이름 문자열

def gen_mirroring_name(self, inStr):
932    def gen_mirroring_name(self, inStr):
933        """
934        미러링된 이름 생성 (측면 또는 앞/뒤 변경)
935        
936        이름에서 Side와 FrontBack namePart를 자동으로 검색하고,
937        발견된 값의 semanticmapping weight와 가장 차이가 큰 값으로 교체합니다.
938        
939        Args:
940            inStr: 처리할 이름 문자열
941            
942        Returns:
943            미러링된 이름 문자열
944        """
945        nameArray = self.convert_name_to_array(inStr)
946            
947        for part in self._nameParts:
948            partName = part.get_name()
949            partType = part.get_type()
950            if (partType != NamePartType.REALNAME or partType != NamePartType.INDEX) and part.is_direction():
951                partIndex = self.get_name_part_index(partName)
952                foundName = self.get_name(partName, inStr)
953                opositeName = part.get_most_different_weight_value(foundName)
954                if opositeName and foundName != opositeName:
955                    nameArray[partIndex] = opositeName
956        
957        returnName = self._combine(nameArray, self._get_filtering_char(inStr))
958        
959        return returnName

미러링된 이름 생성 (측면 또는 앞/뒤 변경)

이름에서 Side와 FrontBack namePart를 자동으로 검색하고, 발견된 값의 semanticmapping weight와 가장 차이가 큰 값으로 교체합니다.

Args: inStr: 처리할 이름 문자열

Returns: 미러링된 이름 문자열

def replace_filtering_char(self, inStr, inNewFilChar):
961    def replace_filtering_char(self, inStr, inNewFilChar):
962        """
963        이름의 구분자 문자 변경
964        
965        Args:
966            inStr: 처리할 이름 문자열
967            inNewFilChar: 새 구분자 문자
968            
969        Returns:
970            구분자가 변경된 이름 문자열
971        """
972        nameArray = self.convert_name_to_array(inStr)
973        return self._combine(nameArray, inNewFilChar)

이름의 구분자 문자 변경

Args: inStr: 처리할 이름 문자열 inNewFilChar: 새 구분자 문자

Returns: 구분자가 변경된 이름 문자열

def replace_name_part(self, inPart, inStr, inNewName):
975    def replace_name_part(self, inPart, inStr, inNewName):
976        """
977        이름의 특정 부분을 새 이름으로 변경
978        
979        Args:
980            inPart: 수정할 부분 ("Base", "Type", "Side", "FrontBack", "RealName", "Index")
981            inStr: 처리할 이름 문자열
982            inNewName: 새 이름
983        
984        Returns:
985            수정된 이름 문자열
986        """
987        nameArray = self.convert_name_to_array(inStr)
988        partIndex = self.get_name_part_index(inPart)
989        
990        if partIndex >= 0:
991            nameArray[partIndex] = inNewName
992        
993        newName = self._combine(nameArray, self._get_filtering_char(inStr))
994        newName = self.set_index_padding_num(newName)
995        
996        return newName

이름의 특정 부분을 새 이름으로 변경

Args: inPart: 수정할 부분 ("Base", "Type", "Side", "FrontBack", "RealName", "Index") inStr: 처리할 이름 문자열 inNewName: 새 이름

Returns: 수정된 이름 문자열

def remove_name_part(self, inPart, inStr):
 998    def remove_name_part(self, inPart, inStr):
 999        """
1000        이름의 특정 부분 제거
1001        
1002        Args:
1003            inPart: 제거할 부분 ("Base", "Type", "Side", "FrontBack", "RealName", "Index")
1004            inStr: 처리할 이름 문자열
1005            
1006        Returns:
1007            수정된 이름 문자열
1008        """
1009        nameArray = self.convert_name_to_array(inStr)
1010        partIndex = self.get_name_part_index(inPart)
1011        
1012        if partIndex >= 0:
1013            nameArray[partIndex] = ""
1014            
1015        newName = self._combine(nameArray, self._get_filtering_char(inStr))
1016        newName = self.set_index_padding_num(newName)
1017        
1018        return newName

이름의 특정 부분 제거

Args: inPart: 제거할 부분 ("Base", "Type", "Side", "FrontBack", "RealName", "Index") inStr: 처리할 이름 문자열

Returns: 수정된 이름 문자열

def load_from_config_file(self, configPath=None):
1020    def load_from_config_file(self, configPath=None):
1021        """
1022        설정 파일에서 설정 로드
1023        
1024        Args:
1025            configPath: 설정 파일 경로 (기본값: self._configPath)
1026            
1027        Returns:
1028            로드 성공 여부 (True/False)
1029        """
1030        # 경로가 없으면 인스턴스 생성 시 설정된 경로 사용
1031        if not configPath:
1032            configPath = self._configPath
1033            
1034        if not configPath:
1035            print("설정 파일 경로가 제공되지 않았습니다.")
1036            return False
1037            
1038        # NamingConfig 인스턴스 생성 및 설정 로드
1039        config = NamingConfig()
1040        if config.load(configPath):
1041            # 설정을 Naming 인스턴스에 적용
1042            result = config.apply_to_naming(self)
1043            if result:
1044                self._configPath = configPath  # 성공적으로 로드한 경로 저장
1045            return result
1046        else:
1047            print(f"설정 파일 로드 실패: {configPath}")
1048            return False

설정 파일에서 설정 로드

Args: configPath: 설정 파일 경로 (기본값: self._configPath)

Returns: 로드 성공 여부 (True/False)

def load_default_config(self):
1050    def load_default_config(self):
1051        """
1052        기본 설정 로드 (현재는 아무 작업도 수행하지 않음)
1053        
1054        Returns:
1055            항상 True 반환 (기본 설정은 __init__에서 이미 설정됨)
1056        """
1057        # 이 메소드는 현재 __init__에서 설정한 기본값을 그대로 사용하므로
1058        # 아무 작업도 수행하지 않습니다.
1059        return True

기본 설정 로드 (현재는 아무 작업도 수행하지 않음)

Returns: 항상 True 반환 (기본 설정은 __init__에서 이미 설정됨)

def get_config_path(self):
1061    def get_config_path(self):
1062        """
1063        현재 설정 파일 경로 가져오기
1064        
1065        Returns:
1066            설정 파일 경로 (없으면 빈 문자열)
1067        """
1068        return self._configPath or ""

현재 설정 파일 경로 가져오기

Returns: 설정 파일 경로 (없으면 빈 문자열)