package storage import ( "encoding/json" "fmt" "os" "path/filepath" "sync" "llm_processor/models" ) var ( criteriaPath = "criteria.txt" criteriaMux sync.RWMutex ) // SetCriteriaPath sets the path for the criteria file func SetCriteriaPath(path string) { criteriaMux.Lock() defer criteriaMux.Unlock() criteriaPath = path } // LoadPapers loads papers from a JSON file func LoadPapers(filePath string) ([]models.Paper, error) { absPath, err := filepath.Abs(filePath) if err != nil { return nil, fmt.Errorf("failed to resolve absolute path: %w", err) } file, err := os.ReadFile(absPath) if err != nil { return nil, fmt.Errorf("failed to read papers file: %w", err) } var papers []models.Paper if err := json.Unmarshal(file, &papers); err != nil { return nil, fmt.Errorf("failed to parse papers JSON: %w", err) } return papers, nil } // LoadCriteria loads evaluation criteria from a text file func LoadCriteria() (string, error) { criteriaMux.RLock() filePath := criteriaPath criteriaMux.RUnlock() content, err := os.ReadFile(filePath) if err != nil { return "", fmt.Errorf("failed to read criteria file: %w", err) } return string(content), nil } // InitializeResultsFile creates a new results file with empty categories func InitializeResultsFile(filePath string) error { results := models.OrganizedResults{ Accepted: []models.Result{}, Rejected: []models.Result{}, Errors: []models.Result{}, } return saveToFile(filePath, results) } // SaveResult appends a result to the appropriate category in the results file func SaveResult(result models.Result, filePath string) error { // Read existing results results, err := loadResults(filePath) if err != nil { return fmt.Errorf("failed to load results: %w", err) } // Append to appropriate category switch result.Decision { case "ACCEPT": results.Accepted = append(results.Accepted, result) case "REJECT": results.Rejected = append(results.Rejected, result) default: results.Errors = append(results.Errors, result) } // Save updated results if err := saveToFile(filePath, results); err != nil { // Try fallback save if fallbackErr := saveFallback(result, filePath); fallbackErr != nil { return fmt.Errorf("failed to save results: %w (fallback also failed: %v)", err, fallbackErr) } return nil } return nil } func loadResults(filePath string) (*models.OrganizedResults, error) { file, err := os.ReadFile(filePath) if err != nil { return nil, fmt.Errorf("failed to read results file: %w", err) } var results models.OrganizedResults if err := json.Unmarshal(file, &results); err != nil { return nil, fmt.Errorf("failed to parse results JSON: %w", err) } return &results, nil } func saveToFile(filePath string, data interface{}) error { file, err := os.Create(filePath) if err != nil { return fmt.Errorf("failed to create file: %w", err) } defer file.Close() encoder := json.NewEncoder(file) encoder.SetIndent("", " ") if err := encoder.Encode(data); err != nil { return fmt.Errorf("failed to encode JSON: %w", err) } return nil } func saveFallback(result models.Result, originalPath string) error { fallbackPath := originalPath + ".fallback" file, err := os.OpenFile(fallbackPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) if err != nil { return fmt.Errorf("failed to open fallback file: %w", err) } defer file.Close() encoder := json.NewEncoder(file) if err := encoder.Encode(result); err != nil { return fmt.Errorf("failed to encode result to fallback file: %w", err) } return nil }