102 lines
2.6 KiB
Go
102 lines
2.6 KiB
Go
package domain
|
|
|
|
import "strings"
|
|
|
|
// GamePluginIdentityKey collapses generated manifest IDs for the same first-party
|
|
// plugin so platform storage keeps one current registry record per plugin.
|
|
func GamePluginIdentityKey(plugin GamePlugin) string {
|
|
baseID := CanonicalGamePluginID(plugin.ID)
|
|
return "id:" + baseID
|
|
}
|
|
|
|
func CanonicalGamePluginID(id string) string {
|
|
id = strings.ToLower(strings.TrimSpace(id))
|
|
if marker := strings.Index(id, ".codex."); marker > 0 {
|
|
return id[:marker]
|
|
}
|
|
return id
|
|
}
|
|
|
|
func GamePluginIsNewer(candidate GamePlugin, current GamePlugin) bool {
|
|
if comparison := CompareGamePluginVersions(candidate.Version, current.Version); comparison != 0 {
|
|
return comparison > 0
|
|
}
|
|
if score := gamePluginPreferenceScore(candidate) - gamePluginPreferenceScore(current); score != 0 {
|
|
return score > 0
|
|
}
|
|
return strings.Compare(strings.ToLower(strings.TrimSpace(candidate.ID)), strings.ToLower(strings.TrimSpace(current.ID))) < 0
|
|
}
|
|
|
|
func CompareGamePluginVersions(left string, right string) int {
|
|
leftParts := gamePluginVersionParts(left)
|
|
rightParts := gamePluginVersionParts(right)
|
|
limit := len(leftParts)
|
|
if len(rightParts) > limit {
|
|
limit = len(rightParts)
|
|
}
|
|
for index := 0; index < limit; index++ {
|
|
var leftValue, rightValue int
|
|
if index < len(leftParts) {
|
|
leftValue = leftParts[index]
|
|
}
|
|
if index < len(rightParts) {
|
|
rightValue = rightParts[index]
|
|
}
|
|
if leftValue != rightValue {
|
|
if leftValue > rightValue {
|
|
return 1
|
|
}
|
|
return -1
|
|
}
|
|
}
|
|
leftText := strings.ToLower(strings.TrimSpace(left))
|
|
rightText := strings.ToLower(strings.TrimSpace(right))
|
|
if leftText == rightText {
|
|
return 0
|
|
}
|
|
if leftText == "" {
|
|
return -1
|
|
}
|
|
if rightText == "" {
|
|
return 1
|
|
}
|
|
if strings.Contains(leftText, "-") != strings.Contains(rightText, "-") {
|
|
if strings.Contains(leftText, "-") {
|
|
return -1
|
|
}
|
|
return 1
|
|
}
|
|
if leftText > rightText {
|
|
return 1
|
|
}
|
|
return -1
|
|
}
|
|
|
|
func gamePluginVersionParts(version string) []int {
|
|
fields := strings.FieldsFunc(version, func(r rune) bool { return r < '0' || r > '9' })
|
|
parts := make([]int, 0, len(fields))
|
|
for _, field := range fields {
|
|
value := 0
|
|
for _, r := range field {
|
|
value = value*10 + int(r-'0')
|
|
}
|
|
parts = append(parts, value)
|
|
}
|
|
return parts
|
|
}
|
|
|
|
func gamePluginPreferenceScore(plugin GamePlugin) int {
|
|
score := 0
|
|
id := strings.ToLower(strings.TrimSpace(plugin.ID))
|
|
if id == CanonicalGamePluginID(id) {
|
|
score += 4
|
|
}
|
|
if strings.HasPrefix(strings.ToLower(strings.TrimSpace(plugin.ManifestRef)), "artifact://") {
|
|
score += 2
|
|
}
|
|
if plugin.Status == GamePluginStatusInstalled {
|
|
score++
|
|
}
|
|
return score
|
|
}
|