Hazel Noack f1b075f47b draft
2025-10-07 13:28:45 +02:00

213 lines
4.1 KiB
Go

package data
import (
"strconv"
"gitea.elara.ws/Hazel/music-kraken/internal/common"
)
type MusicObject interface {
Compile() MusicObject
GetIndices() []string
Merge(other MusicObject) MusicObject
}
func dedupeMusicObjects[T MusicObject](inputMusicObjects []T) []T {
indexMapping := map[string]int{}
deduped := []T{}
for _, musicObject := range inputMusicObjects {
musicObject = musicObject.Compile().(T)
indices := musicObject.GetIndices()
// Check if we've seen any of these indices before
found := false
var existingIndex int
for _, index := range indices {
if idx, exists := indexMapping[index]; exists {
found = true
existingIndex = idx
break
}
}
if found {
// Merge with existing object
existing := deduped[existingIndex]
merged := existing.Merge(musicObject).(T)
deduped[existingIndex] = merged
// Update indices for the merged object
newIndices := merged.GetIndices()
for _, index := range newIndices {
indexMapping[index] = existingIndex
}
} else {
// Add new object
deduped = append(deduped, musicObject)
newIndex := len(deduped) - 1
// Register all indices for this object
for _, index := range indices {
indexMapping[index] = newIndex
}
}
}
return deduped
}
type Song struct {
Id int
Name string
UnifiedName string
Album Album
Artists []Artist
Sources []Source
}
func (m Song) GetIndices() []string {
res := sourceIndices(m.Sources)
if m.UnifiedName != "" {
res = append(res, "name"+m.UnifiedName)
}
if m.Id != 0 {
res = append(res, "id"+strconv.Itoa(m.Id))
}
return res
}
func (m Song) Merge(other MusicObject) MusicObject {
otherSong, ok := other.(Song)
if !ok {
return m
}
if m.Id == 0 && otherSong.Id != 0 {
m.Id = otherSong.Id
}
if m.Name == "" && otherSong.Name != "" {
m.Name = otherSong.Name
m.UnifiedName = otherSong.UnifiedName
}
m.Album = m.Album.Merge(otherSong.Album).(Album)
m.Sources = dedupeSources(append(m.Sources, otherSong.Sources...))
return m
}
func (m Song) Compile() MusicObject {
m.Sources = dedupeSources(m.Sources)
m.UnifiedName = common.Unify(m.Name)
m.Artists = dedupeMusicObjects(m.Artists)
return m
}
type Album struct {
Id int
Name string
UnifiedName string
Songs []Song
Artists []Artist
Sources []Source
}
func (m Album) GetIndices() []string {
res := sourceIndices(m.Sources)
if m.UnifiedName != "" {
res = append(res, "name"+m.UnifiedName)
}
if m.Id != 0 {
res = append(res, "id"+strconv.Itoa(m.Id))
}
return res
}
func (m Album) Merge(other MusicObject) MusicObject {
otherAlbum, ok := other.(Album)
if !ok {
return m
}
if m.Id == 0 && otherAlbum.Id != 0 {
m.Id = otherAlbum.Id
}
if m.Name == "" && otherAlbum.Name != "" {
m.Name = otherAlbum.Name
m.UnifiedName = otherAlbum.UnifiedName
}
m.Songs = dedupeMusicObjects(append(m.Songs, otherAlbum.Songs...))
m.Artists = dedupeMusicObjects(append(m.Artists, otherAlbum.Artists...))
m.Sources = dedupeSources(append(m.Sources, otherAlbum.Sources...))
return m
}
func (m Album) Compile() MusicObject {
m.Sources = dedupeSources(m.Sources)
m.UnifiedName = common.Unify(m.Name)
m.Songs = dedupeMusicObjects(m.Songs)
m.Artists = dedupeMusicObjects(m.Artists)
return m
}
type Artist struct {
Id int
Name string
UnifiedName string
Albums []Album
Sources []Source
}
func (m Artist) Merge(other MusicObject) MusicObject {
otherArtist, ok := other.(Artist)
if !ok {
return m
}
if m.Id == 0 && otherArtist.Id != 0 {
m.Id = otherArtist.Id
}
if m.Name == "" && otherArtist.Name != "" {
m.Name = otherArtist.Name
m.UnifiedName = otherArtist.UnifiedName
}
m.Albums = dedupeMusicObjects(append(m.Albums, otherArtist.Albums...))
m.Sources = dedupeSources(append(m.Sources, otherArtist.Sources...))
return m
}
func (m Artist) GetIndices() []string {
res := sourceIndices(m.Sources)
if m.UnifiedName != "" {
res = append(res, "name"+m.UnifiedName)
}
if m.Id != 0 {
res = append(res, "id"+strconv.Itoa(m.Id))
}
return res
}
func (m Artist) Compile() MusicObject {
m.Sources = dedupeSources(m.Sources)
m.UnifiedName = common.Unify(m.Name)
m.Albums = dedupeMusicObjects(m.Albums)
return m
}