Jobmaker-LdPost/shared/formats/formats.go
Ricardo Carneiro ea532659b0 feat: pipeline inicial ldpost-squad (6 agentes)
Pipeline completo de publicação no LinkedIn:
evaluator → redator → editor → art → director → publisher

- Seed com 37 posts em _sugestoes.md
- Sorteio de formato com N=3 bloqueados (format-history)
- Reciclagem mensal de posts com rotação de formato
- Revisão via Telegram com chat livre (Gemini 2.5 Flash)
- Publicação via LinkedIn API (OAuth2)
- Makefile com targets para Windows/Linux/ARM64

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 18:55:39 -03:00

89 lines
1.8 KiB
Go

package formats
import (
"fmt"
"math/rand"
"time"
)
// FormatPesos defines selection weights for each format.
var FormatPesos = map[string]int{
"como": 5,
"erro": 2,
"porque": 2,
"checklist": 1,
"comparacao": 1,
"bastidor": 1,
}
// SortearFormato picks a weighted random format, excluding bloqueados.
// Uses a fresh rand source seeded with time.Now().UnixNano() per call.
func SortearFormato(bloqueados []string) string {
r := rand.New(rand.NewSource(time.Now().UnixNano()))
blocked := make(map[string]bool, len(bloqueados))
for _, b := range bloqueados {
blocked[b] = true
}
type item struct {
formato string
peso int
}
var pool []item
total := 0
for formato, peso := range FormatPesos {
if !blocked[formato] {
pool = append(pool, item{formato, peso})
total += peso
}
}
// Fallback: unblock all when every format is blocked
if total == 0 {
for formato, peso := range FormatPesos {
pool = append(pool, item{formato, peso})
total += peso
}
}
pick := r.Intn(total)
acc := 0
for _, it := range pool {
acc += it.peso
if pick < acc {
return it.formato
}
}
return pool[0].formato
}
// ValidarFormato returns an error if f is not one of the 6 valid formats.
func ValidarFormato(f string) error {
if _, ok := FormatPesos[f]; ok {
return nil
}
return fmt.Errorf("formato %q inválido — válidos: como, erro, porque, checklist, comparacao, bastidor", f)
}
// FormatLabel returns the human-readable label for a format.
func FormatLabel(f string) string {
switch f {
case "como":
return "Como fazer"
case "erro":
return "Erro clássico"
case "porque":
return "Por que"
case "checklist":
return "Checklist"
case "comparacao":
return "Comparação"
case "bastidor":
return "Bastidor"
default:
return f
}
}