@@ -934,13 +934,19 @@ func (e *Engine) loopSpecial() {
934934 overlay .UpdateStatus ("⭐ 특수 강화 완료!\n [%s] +%d" , itemName , result .FinalLevel )
935935 e .telem .TrySend ()
936936 return // 목표 달성 → 종료
937- } else {
937+ } else if result . Destroyed {
938938 // 파괴됨 → 다시 특수 아이템 찾기
939939 fmt .Printf ("💥 강화 중 파괴됨 (최종 레벨: +%d) → 다시 특수 아이템 찾기\n " , result .FinalLevel )
940940 overlay .UpdateStatus ("💥 특수 파괴됨\n 다시 특수 찾는 중..." )
941941 e .telem .TrySend ()
942942 time .Sleep (time .Duration (e .cfg .TrashDelay * float64 (time .Second )))
943943 continue // 루프 계속 → 특수 아이템 다시 찾기
944+ } else {
945+ // 골드 부족 또는 사용자 중지 → 종료 (무한 루프 방지)
946+ fmt .Printf ("⚠️ 강화 중단됨 (레벨: +%d) → 종료\n " , result .FinalLevel )
947+ overlay .UpdateStatus ("⚠️ 강화 중단\n [%s] +%d" , itemName , result .FinalLevel )
948+ e .telem .TrySend ()
949+ return
944950 }
945951 } else {
946952 // 강화 목표 없으면 (보관만) 바로 종료
@@ -954,14 +960,23 @@ func (e *Engine) loopSpecial() {
954960 // 4. 쓰레기/일반/미판별이면 /판매로 새 아이템 받기 (v3 변경점)
955961 // "none"도 포함: 타입 판별 실패 시 계속 강화하면 안되므로 판매 처리
956962 if state .ItemType == "trash" || state .ItemType == "normal" || state .ItemType == "unknown" || state .ItemType == "none" {
963+ // 현재 레벨 추출
964+ saleLevel := e .ExtractCurrentLevel (state )
965+
966+ // 레벨 0은 판매 불가 → /강화 재시도 필요
967+ if saleLevel == 0 {
968+ fmt .Printf (" ⚠️ +0 상태 → 판매 불가, 강화 재시도\n " )
969+ overlay .UpdateStatus ("⭐ 특수 아이템 뽑기\n ⚠️ +0 판매 불가\n 강화 재시도..." )
970+ time .Sleep (time .Duration (e .cfg .TrashDelay * float64 (time .Second )))
971+ continue
972+ }
973+
957974 e .telem .RecordFarmingWithItem (itemName , state .ItemType )
958975 e .sessionStats .trashCount ++
959976 displayName := itemName
960977 if displayName == "" {
961978 displayName = GetItemTypeLabel (state .ItemType )
962979 }
963- // 현재 레벨 추출 (판매 통계용)
964- saleLevel := e .ExtractCurrentLevel (state )
965980 overlay .UpdateStatus ("⭐ 특수 아이템 뽑기\n 쓰레기: %d회\n 🗑️ %s\n \n 📋 판단: %s → 판매" , e .sessionStats .trashCount , displayName , GetItemTypeLabel (state .ItemType ))
966981 fmt .Printf (" 🗑️ [%s] → /판매\n " , displayName )
967982
@@ -978,10 +993,19 @@ func (e *Engine) loopSpecial() {
978993 }
979994
980995 // 5. 예상치 못한 타입 - 안전하게 판매 처리 (무한 강화 방지)
981- fmt .Printf (" ❓ 예상치 못한 아이템 타입: [%s] - 판매 처리\n " , state .ItemType )
982- overlay .UpdateStatus ("⭐ 특수 아이템 뽑기\n ❓ 타입 불명 → 판매" )
983996 // 현재 레벨 추출 (판매 통계용)
984997 unknownSaleLevel := e .ExtractCurrentLevel (state )
998+
999+ // 레벨 0은 판매 불가 → /강화 재시도 필요
1000+ if unknownSaleLevel == 0 {
1001+ fmt .Printf (" ⚠️ +0 상태 → 판매 불가, 강화 재시도\n " )
1002+ overlay .UpdateStatus ("⭐ 특수 아이템 뽑기\n ⚠️ +0 판매 불가\n 강화 재시도..." )
1003+ time .Sleep (time .Duration (e .cfg .TrashDelay * float64 (time .Second )))
1004+ continue
1005+ }
1006+
1007+ fmt .Printf (" ❓ 예상치 못한 아이템 타입: [%s] - 판매 처리\n " , state .ItemType )
1008+ overlay .UpdateStatus ("⭐ 특수 아이템 뽑기\n ❓ 타입 불명 → 판매" )
9851009 e .sendCommand ("/판매" )
9861010 // 판매 응답 대기
9871011 unknownSaleText := e .readChatTextWaitForChange (5 * time .Second )
@@ -2158,10 +2182,8 @@ func (e *Engine) showSettings(reader *bufio.Reader) {
21582182 fmt .Printf ("2. 중간 속도: %.1f초\n " , e .cfg .MidDelay )
21592183 fmt .Printf ("3. 고강 속도: %.1f초\n " , e .cfg .HighDelay )
21602184 fmt .Printf ("4. 좌표 고정: %v\n " , e .cfg .LockXY )
2161- fmt .Printf ("5. 골드 채굴 목표: +%d\n " , e .cfg .GoldMineTarget )
2162- fmt .Printf ("6. 배틀 역배 레벨차: %d\n " , e .cfg .BattleLevelDiff )
2163- fmt .Printf ("7. 배틀 쿨다운: %.1f초\n " , e .cfg .BattleCooldown )
2164- fmt .Printf ("8. 배틀 최소 골드: %dG\n " , e .cfg .BattleMinGold )
2185+ fmt .Printf ("5. 배틀 역배 레벨차: %d\n " , e .cfg .BattleLevelDiff )
2186+ fmt .Printf ("6. 배틀 쿨다운: %.1f초\n " , e .cfg .BattleCooldown )
21652187 fmt .Println ("0. 돌아가기" )
21662188 fmt .Print ("선택: " )
21672189
@@ -2191,29 +2213,17 @@ func (e *Engine) showSettings(reader *bufio.Reader) {
21912213 e .cfg .LockXY = ! e .cfg .LockXY
21922214 fmt .Printf ("좌표 고정: %v\n " , e .cfg .LockXY )
21932215 case "5" :
2194- fmt .Print ("골드 채굴 목표 레벨 (1-20): " )
2195- val , _ := reader .ReadString ('\n' )
2196- if v , err := strconv .Atoi (strings .TrimSpace (val )); err == nil && v >= 1 && v <= 20 {
2197- e .cfg .GoldMineTarget = v
2198- }
2199- case "6" :
22002216 fmt .Print ("배틀 역배 레벨차 (1-20): " )
22012217 val , _ := reader .ReadString ('\n' )
22022218 if v , err := strconv .Atoi (strings .TrimSpace (val )); err == nil && v >= 1 && v <= 20 {
22032219 e .cfg .BattleLevelDiff = v
22042220 }
2205- case "7 " :
2221+ case "6 " :
22062222 fmt .Print ("배틀 쿨다운 (초): " )
22072223 val , _ := reader .ReadString ('\n' )
22082224 if v , err := strconv .ParseFloat (strings .TrimSpace (val ), 64 ); err == nil && v > 0 {
22092225 e .cfg .BattleCooldown = v
22102226 }
2211- case "8" :
2212- fmt .Print ("배틀 최소 골드: " )
2213- val , _ := reader .ReadString ('\n' )
2214- if v , err := strconv .Atoi (strings .TrimSpace (val )); err == nil && v >= 0 {
2215- e .cfg .BattleMinGold = v
2216- }
22172227 case "0" :
22182228 e .cfg .Save ()
22192229 return
@@ -2315,14 +2325,32 @@ func (e *Engine) showMyProfile() {
23152325 fmt .Println ()
23162326 fmt .Println ("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" )
23172327
2328+ // 아이템 타입 분석
2329+ itemType := "normal"
2330+ if profile .SwordName != "" {
2331+ itemType = DetermineItemType (profile .SwordName )
2332+ }
2333+ itemTypeKr := map [string ]string {"normal" : "일반" , "special" : "특수" , "trash" : "쓰레기" }[itemType ]
2334+ if itemTypeKr == "" {
2335+ itemTypeKr = "일반"
2336+ }
2337+
23182338 // 1. 내 검 정보
23192339 fmt .Println ("⚔️ 내 검 정보" )
23202340 fmt .Printf (" 이름: %s\n " , profile .Name )
23212341 if profile .SwordName != "" {
2322- fmt .Printf (" 보유 검: [+%d] %s\n " , profile .Level , profile .SwordName )
2342+ fmt .Printf (" 보유 검: [+%d] %s (%s) \n " , profile .Level , profile .SwordName , itemTypeKr )
23232343 } else {
23242344 fmt .Printf (" 보유 검: +%d\n " , profile .Level )
23252345 }
2346+ // 최고 기록 표시
2347+ if profile .BestLevel > 0 {
2348+ if profile .BestSword != "" {
2349+ fmt .Printf (" 최고 기록: [+%d] %s\n " , profile .BestLevel , profile .BestSword )
2350+ } else {
2351+ fmt .Printf (" 최고 기록: +%d\n " , profile .BestLevel )
2352+ }
2353+ }
23262354 fmt .Printf (" 전적: %d승 %d패\n " , profile .Wins , profile .Losses )
23272355 if profile .Gold > 0 {
23282356 fmt .Printf (" 보유 골드: %sG\n " , FormatGold (profile .Gold ))
@@ -2333,23 +2361,57 @@ func (e *Engine) showMyProfile() {
23332361 fmt .Println ("💰 예상 판매가" )
23342362 price := GetSwordPrice (profile .Level )
23352363 if price != nil {
2336- fmt .Printf (" 최소: %sG\n " , FormatGold (price .MinPrice ))
2337- fmt .Printf (" 평균: %sG\n " , FormatGold (price .AvgPrice ))
2338- fmt .Printf (" 최대: %sG\n " , FormatGold (price .MaxPrice ))
2364+ fmt .Printf (" 현재 +%d강: %sG (최소 %sG ~ 최대 %sG)\n " ,
2365+ profile .Level , FormatGold (price .AvgPrice ), FormatGold (price .MinPrice ), FormatGold (price .MaxPrice ))
23392366 } else {
23402367 fmt .Println (" 데이터 없음" )
23412368 }
23422369 fmt .Println ()
23432370
2344- // 3. 강화 확률표
2371+ // 3. 최적 판매 추천 (서버 API 활용)
2372+ fmt .Println ("🎯 최적 판매 추천" )
2373+ optimalLevel , optSource := GetOptimalSellLevel (profile .Gold )
2374+ fmt .Printf (" 전체 최적: +%d강 (%s)\n " , optimalLevel , optSource )
2375+
2376+ // 타입별 최적 레벨
2377+ typeOptLevel , isDefault := GetOptimalLevelByType (itemType )
2378+ if isDefault {
2379+ fmt .Printf (" %s 검 최적: +%d강 (기본값)\n " , itemTypeKr , typeOptLevel )
2380+ } else {
2381+ fmt .Printf (" %s 검 최적: +%d강 (실측 데이터)\n " , itemTypeKr , typeOptLevel )
2382+ }
2383+
2384+ // 현재 레벨과 최적 레벨 비교 추천
2385+ if profile .Level < typeOptLevel {
2386+ nextPrice := GetSwordPrice (typeOptLevel )
2387+ if nextPrice != nil && price != nil {
2388+ profit := nextPrice .AvgPrice - price .AvgPrice
2389+ fmt .Printf (" 💡 +%d강까지 강화 추천 (예상 추가 수익: +%sG)\n " , typeOptLevel , FormatGold (profit ))
2390+ } else {
2391+ fmt .Printf (" 💡 +%d강까지 강화 추천\n " , typeOptLevel )
2392+ }
2393+ } else if profile .Level == typeOptLevel {
2394+ fmt .Println (" ✅ 현재 최적 판매 레벨입니다!" )
2395+ } else {
2396+ fmt .Printf (" ⚠️ 최적 레벨(+%d) 초과 - 리스크 관리 필요\n " , typeOptLevel )
2397+ }
2398+ fmt .Println ()
2399+
2400+ // 4. 레벨별 효율 분석 (GPM 테이블)
2401+ PrintLevelEfficiencyTable (profile .Level , itemType )
2402+
2403+ // 5. 강화 확률표
23452404 PrintEnhanceRateTable (profile .Level )
23462405
2347- // 4 . 목표별 성공 확률
2406+ // 6 . 목표별 성공 확률
23482407 PrintTargetSuccessChance (profile .Level )
23492408
2350- // 5 . 역배 기대값
2409+ // 7 . 역배 기대값
23512410 PrintUpsetAnalysis (profile .Level , profile .Gold )
23522411
2412+ // 8. 추천 액션 요약
2413+ PrintRecommendedActions (profile .Level , profile .Gold , itemType , typeOptLevel )
2414+
23532415 fmt .Println ()
23542416 fmt .Println ("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" )
23552417 fmt .Println ()
0 commit comments