64 lines
1.7 KiB
Go
64 lines
1.7 KiB
Go
package domain
|
||
|
||
import "strings"
|
||
|
||
const (
|
||
SuggestUsageInclude = "include"
|
||
SuggestUsageExclude = "exclude"
|
||
|
||
// 建議數量上限:清單要能一眼看完並逐條決定,不是丟一大串讓人放棄。
|
||
MaxSuggestions = 20
|
||
DefaultSuggestions = 8
|
||
)
|
||
|
||
/*
|
||
WatchTermSuggestion 是一則關鍵字建議。
|
||
|
||
Reason 是必填的:使用者要逐條決定採不採用,看不到「為什麼建議這個詞」就只能全採或全不採,
|
||
那這個功能就退化成一個猜測產生器。
|
||
*/
|
||
type WatchTermSuggestion struct {
|
||
Term string `json:"term"`
|
||
Reason string `json:"reason"`
|
||
Usage string `json:"usage"`
|
||
}
|
||
|
||
func NormalizeSuggestUsage(s string) string {
|
||
if strings.EqualFold(strings.TrimSpace(s), SuggestUsageExclude) {
|
||
return SuggestUsageExclude
|
||
}
|
||
return SuggestUsageInclude
|
||
}
|
||
|
||
/*
|
||
CleanSuggestions 收掉空白與重複,丟掉沒有理由的項目,並套用數量上限。
|
||
|
||
沒有理由的項目直接丟:補一句「AI 建議」等於假裝有理由,比少一則更糟。
|
||
*/
|
||
func CleanSuggestions(in []WatchTermSuggestion, limit int) []WatchTermSuggestion {
|
||
if limit <= 0 || limit > MaxSuggestions {
|
||
limit = MaxSuggestions
|
||
}
|
||
out := make([]WatchTermSuggestion, 0, len(in))
|
||
seen := map[string]bool{}
|
||
for _, s := range in {
|
||
term := strings.ToLower(strings.Join(strings.Fields(strings.ReplaceAll(s.Term, "\u3000", " ")), " "))
|
||
reason := strings.TrimSpace(s.Reason)
|
||
if term == "" || reason == "" {
|
||
continue
|
||
}
|
||
if len([]rune(term)) < MinTermLen || len([]rune(term)) > MaxTermLen {
|
||
continue
|
||
}
|
||
if seen[term] {
|
||
continue
|
||
}
|
||
seen[term] = true
|
||
out = append(out, WatchTermSuggestion{Term: term, Reason: reason, Usage: NormalizeSuggestUsage(s.Usage)})
|
||
if len(out) >= limit {
|
||
break
|
||
}
|
||
}
|
||
return out
|
||
}
|