213 lines
4.1 KiB
Go
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
|
|
}
|