package main import ( "fmt" "sort" "strings" "verstak/internal/core/activity" ) // GetSuggestions analyzes today's activity and returns worklog suggestions. func (a *App) GetSuggestions() ([]activity.Suggestion, error) { events, err := a.activity.ListTodayEvents() if err != nil { return nil, err } if len(events) == 0 { return nil, nil } type acc struct { title string kind string events []activity.Event } grouped := make(map[string]*acc) for _, e := range events { grp, ok := grouped[e.NodeID] if !ok { n, err := a.nodes.GetActive(e.NodeID) title := "" kind := "" if err == nil && n != nil { title = n.Title kind = n.Type } grp = &acc{title: title, kind: kind} grouped[e.NodeID] = grp } grp.events = append(grp.events, e) } var suggestions []activity.Suggestion for nodeID, grp := range grouped { if grp.title == "" { continue } hasEntries, err := a.worklog.HasTodayEntries(nodeID) if err != nil || hasEntries { continue } noteCount := 0 fileCount := 0 actionCount := 0 otherCount := 0 for _, e := range grp.events { switch e.EventType { case activity.TypeNoteCreated, activity.TypeNoteUpdated, activity.TypeNoteDeleted: noteCount++ case activity.TypeFileAdded, activity.TypeFileDeleted, activity.TypeFileRenamed, activity.TypeFileCopied, activity.TypeFileMoved, activity.TypeFolderAdded, activity.TypeFolderDeleted, activity.TypeFolderRenamed: fileCount++ case activity.TypeActionCreated, activity.TypeActionDone: actionCount++ default: otherCount++ } } summary := buildSuggestionSummary(noteCount, fileCount, actionCount, otherCount) if summary == "" { continue } suggestions = append(suggestions, activity.Suggestion{ NodeID: nodeID, NodeTitle: grp.title, Summary: summary, SuggestedMin: suggestMinutes(noteCount + fileCount + actionCount + otherCount), EventCount: len(grp.events), NodeKind: grp.kind, }) } sort.Slice(suggestions, func(i, j int) bool { return suggestions[i].EventCount > suggestions[j].EventCount }) return suggestions, nil } // AcceptSuggestion creates a worklog entry from a suggestion. func (a *App) AcceptSuggestion(s activity.Suggestion) (*WorklogDTO, error) { return a.CreateWorklog(s.NodeID, s.Summary, s.SuggestedMin) } func buildSuggestionSummary(noteCount, fileCount, actionCount, otherCount int) string { var parts []string if noteCount > 0 { parts = append(parts, fmt.Sprintf("заметки (%d)", noteCount)) } if fileCount > 0 { parts = append(parts, fmt.Sprintf("файлы (%d)", fileCount)) } if actionCount > 0 { parts = append(parts, fmt.Sprintf("действия (%d)", actionCount)) } if otherCount > 0 { parts = append(parts, fmt.Sprintf("события (%d)", otherCount)) } return strings.Join(parts, ", ") } func suggestMinutes(totalEvents int) int { switch { case totalEvents >= 15: return 120 case totalEvents >= 10: return 90 case totalEvents >= 6: return 60 case totalEvents >= 3: return 30 default: return 15 } }