/* |-------------------------------------------------------------------------- | Metadata |-------------------------------------------------------------------------- | | Name: | - Progress | | Purpose: | - Manage, monitor, and report task progress through standardized | lifecycle-aware progress tracking. | | Guideline: | - Use "countable" type when progress can be measured using current | and target numeric values. | - Use "uncountable" type when progress is activity-based and cannot | be represented by a completion percentage. | - Always provide a valid lifecycle state before executing the utility. | - Provide "current" and "target" values for countable progress | tracking operations. | - Provide a non-empty "placeholder" value for uncountable progress | tracking operations. | - Use returned payload data for CLI rendering, status reporting, | and workflow monitoring. | - Check the returned status and code before consuming payload data. | | Example: | - ObrimProgress( | "countable", | map[string]any{ | "state": "running", | "current": 45, | "target": 100, | }, | ) | | - ObrimProgress( | "uncountable", | map[string]any{ | "state": "running", | "placeholder": "Processing records...", | }, | ) | | - result := ObrimProgress( | "countable", | map[string]any{ | "state": "completed", | "current": 100, | "target": 100, | }, | ) | |-------------------------------------------------------------------------- */ /* |-------------------------------------------------------------------------- | Credit |-------------------------------------------------------------------------- | | Contributor: | - Rajon Ahmed | - Blockonite | |-------------------------------------------------------------------------- */ package progress import ( "fmt" "math" "strings" "sync" ) const ( obrimProgressTypeCountable = "countable" obrimProgressTypeUncountable = "uncountable" obrimProgressStateStarted = "started" obrimProgressStateRunning = "running" obrimProgressStateCompleted = "completed" obrimProgressStateCanceled = "canceled" ObrimProgressCodeSuccessStarted = "SUCCESS_PROGRESS_STARTED" ObrimProgressCodeSuccessRunning = "SUCCESS_PROGRESS_RUNNING" ObrimProgressCodeSuccessCompleted = "SUCCESS_PROGRESS_COMPLETED" ObrimProgressCodeSuccessCanceled = "SUCCESS_PROGRESS_CANCELED" ObrimProgressCodeFailedMisconfigured = "FAILED_PROGRESS_MISCONFIGURED" obrimProgressVisualLength = 20 ) // obrimProgressStateMutex prevents state corruption during rapid updates. var obrimProgressStateMutex sync.Mutex // ObrimProgressCountablePayload defines countable progress payload data. type ObrimProgressCountablePayload struct { State string `json:"state"` Current int `json:"current"` Target int `json:"target"` Percentage int `json:"percentage"` Message string `json:"message"` Visual string `json:"visual"` } // ObrimProgressUncountablePayload defines uncountable progress payload data. type ObrimProgressUncountablePayload struct { State string `json:"state"` Placeholder string `json:"placeholder"` Message string `json:"message"` Visual string `json:"visual"` } // ObrimProgress manages lifecycle-aware countable and uncountable progress tracking operations. func ObrimProgress(progressType string, config map[string]any) map[string]any { obrimProgressStateMutex.Lock() defer obrimProgressStateMutex.Unlock() if !obrimProgressValidate(progressType, config) { return obrimProgressBuildResponse( false, ObrimProgressCodeFailedMisconfigured, nil, ) } code := obrimProgressHandleState(config["state"].(string)) switch progressType { case obrimProgressTypeCountable: return obrimProgressCountable(config, code) case obrimProgressTypeUncountable: return obrimProgressUncountable(config, code) } return obrimProgressBuildResponse( false, ObrimProgressCodeFailedMisconfigured, nil, ) } // obrimProgressValidate validates input parameters and configuration consistency. func obrimProgressValidate( progressType string, config map[string]any, ) bool { if config == nil { return false } stateValue, exists := config["state"] if !exists { return false } state, ok := stateValue.(string) if !ok { return false } switch state { case obrimProgressStateStarted, obrimProgressStateRunning, obrimProgressStateCompleted, obrimProgressStateCanceled: default: return false } switch progressType { case obrimProgressTypeCountable: currentValue, currentExists := config["current"] targetValue, targetExists := config["target"] if !currentExists || !targetExists { return false } current, currentOk := currentValue.(int) target, targetOk := targetValue.(int) if !currentOk || !targetOk { return false } if target <= 0 { return false } _ = current return true case obrimProgressTypeUncountable: placeholderValue, exists := config["placeholder"] if !exists { return false } placeholder, ok := placeholderValue.(string) if !ok { return false } return strings.TrimSpace(placeholder) != "" } return false } // obrimProgressHandleState processes lifecycle state transitions. func obrimProgressHandleState(state string) string { switch state { case obrimProgressStateStarted: return ObrimProgressCodeSuccessStarted case obrimProgressStateRunning: return ObrimProgressCodeSuccessRunning case obrimProgressStateCompleted: return ObrimProgressCodeSuccessCompleted case obrimProgressStateCanceled: return ObrimProgressCodeSuccessCanceled } return ObrimProgressCodeFailedMisconfigured } // obrimProgressGenerateMessage generates human-readable progress messages. func obrimProgressGenerateMessage( progressType string, state string, payload map[string]any, ) string { switch progressType { case obrimProgressTypeCountable: percentage := payload["percentage"].(int) switch state { case obrimProgressStateStarted: return fmt.Sprintf( "Progress started (%d%% complete).", percentage, ) case obrimProgressStateRunning: return fmt.Sprintf( "Progress running (%d%% complete).", percentage, ) case obrimProgressStateCompleted: return fmt.Sprintf( "Progress completed (%d%% complete).", percentage, ) case obrimProgressStateCanceled: return fmt.Sprintf( "Progress canceled (%d%% complete).", percentage, ) } case obrimProgressTypeUncountable: placeholder := payload["placeholder"].(string) switch state { case obrimProgressStateStarted: return fmt.Sprintf( "Activity started: %s", placeholder, ) case obrimProgressStateRunning: return fmt.Sprintf( "Activity running: %s", placeholder, ) case obrimProgressStateCompleted: return fmt.Sprintf( "Activity completed: %s", placeholder, ) case obrimProgressStateCanceled: return fmt.Sprintf( "Activity canceled: %s", placeholder, ) } } return "" } // obrimProgressGenerateVisual generates CLI-friendly visual progress representations. func obrimProgressGenerateVisual( progressType string, payload map[string]any, ) string { switch progressType { case obrimProgressTypeCountable: percentage := payload["percentage"].(int) filled := int(math.Round( (float64(percentage) / 100.0) * float64(obrimProgressVisualLength), )) if filled > obrimProgressVisualLength { filled = obrimProgressVisualLength } if filled < 0 { filled = 0 } return fmt.Sprintf( "[%s%s] %d%%", strings.Repeat("=", filled), strings.Repeat(" ", obrimProgressVisualLength-filled), percentage, ) case obrimProgressTypeUncountable: return "[....................]" } return "" } // obrimProgressBuildResponse constructs standardized utility response payloads. func obrimProgressBuildResponse( status bool, code string, payload any, ) map[string]any { return map[string]any{ "status": status, "code": code, "payload": payload, } } // obrimProgressCountable processes countable progress tracking workflows. func obrimProgressCountable( config map[string]any, code string, ) map[string]any { current := config["current"].(int) target := config["target"].(int) state := config["state"].(string) percentage := obrimProgressCalculatePercentage( current, target, ) payloadData := map[string]any{ "percentage": percentage, } payload := ObrimProgressCountablePayload{ State: state, Current: current, Target: target, Percentage: percentage, Message: obrimProgressGenerateMessage( obrimProgressTypeCountable, state, payloadData, ), Visual: obrimProgressGenerateVisual( obrimProgressTypeCountable, payloadData, ), } return obrimProgressBuildResponse( true, code, payload, ) } // obrimProgressCalculatePercentage calculates and normalizes completion percentages. func obrimProgressCalculatePercentage( current int, target int, ) int { if current < 0 { return 0 } percentage := int(math.Round( (float64(current) / float64(target)) * 100, )) if percentage > 100 { return 100 } if percentage < 0 { return 0 } return percentage } // obrimProgressUncountable processes uncountable progress tracking workflows. func obrimProgressUncountable( config map[string]any, code string, ) map[string]any { state := config["state"].(string) placeholder := obrimProgressResolvePlaceholder( config["placeholder"].(string), ) payloadData := map[string]any{ "placeholder": placeholder, } payload := ObrimProgressUncountablePayload{ State: state, Placeholder: placeholder, Message: obrimProgressGenerateMessage( obrimProgressTypeUncountable, state, payloadData, ), Visual: obrimProgressGenerateVisual( obrimProgressTypeUncountable, payloadData, ), } return obrimProgressBuildResponse( true, code, payload, ) } // obrimProgressResolvePlaceholder validates and prepares placeholder activity messages. func obrimProgressResolvePlaceholder( placeholder string, ) string { return strings.TrimSpace(placeholder) }