@@ -62,6 +62,19 @@ type Engine struct {
6262 // v2: 세션 분석 및 알림
6363 session * analysis.SessionTracker
6464 alerts * analysis.AlertEngine
65+
66+ // 세션 통계 (종료 시 출력용)
67+ sessionStats struct {
68+ startGold int
69+ endGold int
70+ trashCount int
71+ hiddenCount int
72+ enhanceSuccess int
73+ enhanceHold int
74+ enhanceDestroy int
75+ cycleTimeSum float64 // 사이클 시간 합계 (초)
76+ cycleGoldSum int // 사이클 수익 합계
77+ }
6578}
6679
6780// NewEngine 엔진 생성
@@ -255,6 +268,17 @@ func (e *Engine) setupAndRun() {
255268 e .totalGold = 0
256269 e .startTime = time .Now ()
257270
271+ // 세션 통계 초기화
272+ e .sessionStats .startGold = e .readCurrentGold ()
273+ e .sessionStats .endGold = 0
274+ e .sessionStats .trashCount = 0
275+ e .sessionStats .hiddenCount = 0
276+ e .sessionStats .enhanceSuccess = 0
277+ e .sessionStats .enhanceHold = 0
278+ e .sessionStats .enhanceDestroy = 0
279+ e .sessionStats .cycleTimeSum = 0
280+ e .sessionStats .cycleGoldSum = 0
281+
258282 // 타이머 설정 (시간 제한이 있는 경우)
259283 if e .duration > 0 {
260284 e .stopTimer = time .AfterFunc (e .duration , func () {
@@ -283,15 +307,13 @@ func (e *Engine) setupAndRun() {
283307 time .Sleep (500 * time .Millisecond )
284308 overlay .HideAll ()
285309
286- // 종료 시 통계 출력 및 텔레메트리 전송
287- elapsed := time .Since (e .startTime )
288- fmt .Println ()
289- fmt .Println ("=== 매크로 종료 ===" )
290- fmt .Printf ("⏱️ 실행 시간: %s\n " , formatDuration (elapsed ))
291- fmt .Printf ("🔄 총 사이클: %d회\n " , e .cycleCount )
292- if e .totalGold > 0 {
293- fmt .Printf ("💰 총 수익: %dG\n " , e .totalGold )
294- }
310+ // 종료 시 현재 골드 읽기
311+ e .sessionStats .endGold = e .readCurrentGold ()
312+
313+ // 상세 통계 출력
314+ e .printSessionStats ()
315+
316+ // 텔레메트리 전송
295317 fmt .Println ("📤 통계 전송 중..." )
296318 e .telem .Flush ()
297319 fmt .Println ("✅ 완료!" )
@@ -311,6 +333,97 @@ func formatDuration(d time.Duration) string {
311333 return fmt .Sprintf ("%d초" , s )
312334}
313335
336+ // printSessionStats 세션 종료 시 상세 통계 출력
337+ func (e * Engine ) printSessionStats () {
338+ elapsed := time .Since (e .startTime )
339+ elapsedSec := elapsed .Seconds ()
340+
341+ // 골드 변화 계산
342+ goldDiff := e .sessionStats .endGold - e .sessionStats .startGold
343+ if e .sessionStats .startGold <= 0 {
344+ goldDiff = e .totalGold // 시작 골드를 못 읽었으면 누적 수익 사용
345+ }
346+
347+ // 시간당 골드 계산
348+ goldPerHour := 0
349+ if elapsedSec > 0 {
350+ goldPerHour = int (float64 (goldDiff ) / elapsedSec * 3600 )
351+ }
352+
353+ // 사이클 평균 계산
354+ avgCycleTime := 0.0
355+ avgCycleGold := 0
356+ if e .cycleCount > 0 {
357+ avgCycleTime = e .sessionStats .cycleTimeSum / float64 (e .cycleCount )
358+ avgCycleGold = e .sessionStats .cycleGoldSum / e .cycleCount
359+ }
360+
361+ // 골드 부호
362+ goldSign := "+"
363+ if goldDiff < 0 {
364+ goldSign = ""
365+ }
366+ gphSign := "+"
367+ if goldPerHour < 0 {
368+ gphSign = ""
369+ }
370+
371+ fmt .Println ()
372+ fmt .Println ("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" )
373+ fmt .Printf (" 📊 세션 통계 (%s)\n " , formatDuration (elapsed ))
374+ fmt .Println ("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" )
375+
376+ // 파밍 통계
377+ if e .sessionStats .trashCount > 0 || e .sessionStats .hiddenCount > 0 {
378+ fmt .Printf (" 🎣 트래시 판매: %d회\n " , e .sessionStats .trashCount )
379+ fmt .Printf (" ⭐ 히든 발견: %d회\n " , e .sessionStats .hiddenCount )
380+ }
381+
382+ // 강화 통계
383+ enhanceTotal := e .sessionStats .enhanceSuccess + e .sessionStats .enhanceHold + e .sessionStats .enhanceDestroy
384+ if enhanceTotal > 0 {
385+ fmt .Printf (" ✅ 강화 성공: %d회\n " , e .sessionStats .enhanceSuccess )
386+ fmt .Printf (" ⏸️ 강화 유지: %d회\n " , e .sessionStats .enhanceHold )
387+ fmt .Printf (" 💥 강화 파괴: %d회\n " , e .sessionStats .enhanceDestroy )
388+ }
389+
390+ // 배틀 통계
391+ if e .battleWins > 0 || e .battleLosses > 0 {
392+ winRate := 0.0
393+ if e .battleWins + e .battleLosses > 0 {
394+ winRate = float64 (e .battleWins ) / float64 (e .battleWins + e .battleLosses ) * 100
395+ }
396+ fmt .Printf (" ⚔️ 배틀 전적: %d승 %d패 (%.1f%%)\n " , e .battleWins , e .battleLosses , winRate )
397+ }
398+
399+ fmt .Println ("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" )
400+
401+ // 골드 통계
402+ if e .sessionStats .startGold > 0 && e .sessionStats .endGold > 0 {
403+ fmt .Printf (" 💰 골드 변화: %sG → %sG (%s%sG)\n " ,
404+ FormatGold (e .sessionStats .startGold ),
405+ FormatGold (e .sessionStats .endGold ),
406+ goldSign , FormatGold (goldDiff ))
407+ } else if e .totalGold != 0 {
408+ fmt .Printf (" 💰 총 수익: %s%sG\n " , goldSign , FormatGold (goldDiff ))
409+ }
410+
411+ fmt .Printf (" 📈 시간당 골드: %s%sG/h\n " , gphSign , FormatGold (goldPerHour ))
412+
413+ // 사이클 통계
414+ if e .cycleCount > 0 {
415+ avgGoldSign := "+"
416+ if avgCycleGold < 0 {
417+ avgGoldSign = ""
418+ }
419+ fmt .Printf (" 🔄 완료 사이클: %d회 (평균 %.0f초, %s%sG/사이클)\n " ,
420+ e .cycleCount , avgCycleTime , avgGoldSign , FormatGold (avgCycleGold ))
421+ }
422+
423+ fmt .Println ("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" )
424+ fmt .Println ()
425+ }
426+
314427func (e * Engine ) loopEnhance () {
315428 for e .running {
316429 if e .checkStop () {
@@ -368,13 +481,15 @@ func (e *Engine) loopHidden() {
368481 e .telem .RecordFarmingWithItem (itemName , "hidden" )
369482 e .telem .RecordSword ()
370483 e .telem .TrySend ()
484+ e .sessionStats .hiddenCount ++
371485 return
372486 }
373487
374488 // 트래시면 판매
375489 if state .ItemType == "trash" || state .ItemType == "normal" {
376490 // v2 텔레메트리
377491 e .telem .RecordFarmingWithItem (itemName , state .ItemType )
492+ e .sessionStats .trashCount ++
378493 e .sendCommand ("/판매" )
379494 time .Sleep (500 * time .Millisecond )
380495 }
@@ -428,6 +543,10 @@ func (e *Engine) loopGoldMine() {
428543 e .telem .RecordGoldChange (endGold )
429544 e .telem .TrySend ()
430545
546+ // 세션 통계 업데이트
547+ e .sessionStats .cycleTimeSum += cycleTime .Seconds ()
548+ e .sessionStats .cycleGoldSum += goldEarned
549+
431550 // 사이클 완료 상태 업데이트
432551 overlay .UpdateStatus ("💰 골드 채굴 #%d ✅\n %s +%d → %+sG\n 누적: %sG" , e .cycleCount , itemName , finalLevel , FormatGold (goldEarned ), FormatGold (e .totalGold ))
433552
@@ -589,11 +708,13 @@ func (e *Engine) farmUntilHiddenWithName() (string, bool) {
589708 if state .ItemType == "hidden" {
590709 // v2 텔레메트리
591710 e .telem .RecordFarmingWithItem (itemName , "hidden" )
711+ e .sessionStats .hiddenCount ++
592712 return itemName , true
593713 }
594714 if state .ItemType == "trash" || state .ItemType == "normal" {
595715 // v2 텔레메트리
596716 e .telem .RecordFarmingWithItem (itemName , state .ItemType )
717+ e .sessionStats .trashCount ++
597718 e .sendCommand ("/판매" )
598719 time .Sleep (300 * time .Millisecond )
599720 }
@@ -630,13 +751,16 @@ func (e *Engine) enhanceToTargetWithLevel() (int, bool) {
630751 currentLevel ++
631752 fmt .Printf (" ✅ +%d 성공\n " , currentLevel )
632753 e .telem .RecordEnhance (currentLevel - 1 , "success" )
754+ e .sessionStats .enhanceSuccess ++
633755 case "destroy" :
634756 fmt .Println (" 💥 파괴!" )
635757 e .telem .RecordEnhance (currentLevel , "destroy" )
758+ e .sessionStats .enhanceDestroy ++
636759 return currentLevel , false
637760 case "hold" :
638761 fmt .Printf (" ⏸️ +%d 유지\n " , currentLevel )
639762 e .telem .RecordEnhance (currentLevel , "hold" )
763+ e .sessionStats .enhanceHold ++
640764 }
641765 }
642766
0 commit comments