74 lines
2.2 KiB
Go
74 lines
2.2 KiB
Go
package main
|
|
|
|
import "strings"
|
|
|
|
// CD-tier filtering for the suitbuilder. The allowed_crit_damage constraint
|
|
// restricts which crit-damage tiers are permitted on ARMOR pieces; jewelry and
|
|
// clothing are never affected. "Prefer the highest allowed tier" is NOT done
|
|
// here — it falls out of the existing scoring (CritDamage2 > CritDamage1) and
|
|
// the CD-descending armor sort once disallowed tiers are removed.
|
|
|
|
// critTier normalizes a raw crit_damage_rating into a tier in {0,1,2}. Rare
|
|
// high-crit gear (rating >= 2, including 3+) collapses to tier 2 so it counts
|
|
// as "CD2" rather than being silently excluded.
|
|
func critTier(rating int) int {
|
|
switch {
|
|
case rating <= 0:
|
|
return 0
|
|
case rating == 1:
|
|
return 1
|
|
default:
|
|
return 2
|
|
}
|
|
}
|
|
|
|
// isArmorSlot reports whether a slot name denotes an armor coverage slot,
|
|
// including comma-joined multi-coverage slots like "Chest, Abdomen".
|
|
func isArmorSlot(slot string) bool {
|
|
if armorSlotSet[slot] {
|
|
return true
|
|
}
|
|
if strings.Contains(slot, ", ") {
|
|
for _, p := range strings.Split(slot, ", ") {
|
|
if armorSlotSet[strings.TrimSpace(p)] {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// allowedCritSet normalizes the constraint's allowed crit-damage tiers into a
|
|
// set, or returns nil when the filter is INACTIVE: no values, or all three
|
|
// tiers {0,1,2} present (== default). A nil result means "no filter" and keeps
|
|
// the default search path byte-identical to the unfiltered solver.
|
|
func allowedCritSet(vals []int) map[int]bool {
|
|
if len(vals) == 0 {
|
|
return nil
|
|
}
|
|
set := map[int]bool{}
|
|
for _, v := range vals {
|
|
set[critTier(v)] = true
|
|
}
|
|
if set[0] && set[1] && set[2] {
|
|
return nil
|
|
}
|
|
return set
|
|
}
|
|
|
|
// filterArmorByCD drops armor items whose crit-damage tier is not in allowed.
|
|
// Non-armor items (jewelry, clothing, unknown) always pass through. When
|
|
// allowed is nil the input is returned unchanged.
|
|
func filterArmorByCD(items []*SuitItem, allowed map[int]bool) []*SuitItem {
|
|
if allowed == nil {
|
|
return items
|
|
}
|
|
out := make([]*SuitItem, 0, len(items))
|
|
for _, it := range items {
|
|
if isArmorSlot(it.Slot) && !allowed[critTier(it.Ratings["crit_damage_rating"])] {
|
|
continue
|
|
}
|
|
out = append(out, it)
|
|
}
|
|
return out
|
|
}
|