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 ""
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 ""
노드 이름을 관리하기 위한 기본 클래스. 기본적인 이름 구성 요소를 정의하고 관리합니다. 이 클래스는 하위 클래스에서 확장하여 특정 목적에 맞게 사용할 수 있습니다.
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) 설정 파일이 제공되면 해당 파일에서 설정을 로드함
254 def get_padding_num(self): 255 """ 256 패딩 숫자 가져오기 257 258 Returns: 259 패딩 숫자 260 """ 261 return self._paddingNum
패딩 숫자 가져오기
Returns: 패딩 숫자
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
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
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의 사전 정의 값 리스트, 존재하지 않으면 빈 리스트
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
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에 해당하는 문자열
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
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에 해당하는 문자열
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: 조합된 이름 문자열
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: 실제 이름 부분 문자열
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: 실제 이름이 제외된 이름 문자열
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 등)
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", ...}
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")
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: 한국어 설명 문자열 (예: "팔_왼쪽_팔")
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
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: 수정된 이름 문자열
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: 수정된 이름 문자열
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: 수정된 이름 문자열
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: 수정된 이름 문자열
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: 패딩된 문자열
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: 패딩이 적용된 이름 문자열
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: 인덱스 패딩 자릿수
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: 인덱스가 증가된 이름 문자열
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)
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: 인덱스 기준으로 정렬된 이름 배열
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: 인덱스가 제외된 이름 문자열
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: 미러링된 이름 문자열
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: 구분자가 변경된 이름 문자열
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: 수정된 이름 문자열
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: 수정된 이름 문자열
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)
1050 def load_default_config(self): 1051 """ 1052 기본 설정 로드 (현재는 아무 작업도 수행하지 않음) 1053 1054 Returns: 1055 항상 True 반환 (기본 설정은 __init__에서 이미 설정됨) 1056 """ 1057 # 이 메소드는 현재 __init__에서 설정한 기본값을 그대로 사용하므로 1058 # 아무 작업도 수행하지 않습니다. 1059 return True
기본 설정 로드 (현재는 아무 작업도 수행하지 않음)
Returns: 항상 True 반환 (기본 설정은 __init__에서 이미 설정됨)