music: implement genre linking

This commit is contained in:
Alexander Capehart 2024-11-25 16:34:02 -07:00
parent d633a6b9f1
commit db391da4b8
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
3 changed files with 66 additions and 4 deletions

View file

@ -0,0 +1,18 @@
package org.oxycblt.auxio.music.stack.interpret.linker
class Contribution<T> {
private val map = mutableMapOf<T, Int>()
val candidates: Collection<T> get() = map.keys
fun contribute(key: T) {
map[key] = map.getOrDefault(key, 0) + 1
}
fun contribute(keys: Collection<T>) {
keys.forEach { contribute(it) }
}
fun resolve() = map.maxByOrNull { it.value }?.key ?: error("Nothing was contributed")
}

View file

@ -2,16 +2,60 @@ package org.oxycblt.auxio.music.stack.interpret.linker
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.transform
import org.oxycblt.auxio.music.stack.interpret.model.GenreImpl import org.oxycblt.auxio.music.stack.interpret.model.GenreImpl
import org.oxycblt.auxio.music.stack.interpret.model.SongImpl import org.oxycblt.auxio.music.stack.interpret.model.SongImpl
import org.oxycblt.auxio.music.stack.interpret.prepare.PreGenre
import org.oxycblt.auxio.music.stack.interpret.prepare.PreSong import org.oxycblt.auxio.music.stack.interpret.prepare.PreSong
class GenreLinker { class GenreTree {
fun register(preSong: Flow<PreSong>): Flow<LinkedSong> = emptyFlow() private val tree = mutableMapOf<String?, GenreLink>()
fun resolve(): Collection<GenreImpl> = setOf()
fun register(preSong: Flow<PreSong>): Flow<LinkedSong> = preSong.map {
val genreLinks = it.preGenres.map { genre ->
val nameKey = genre.rawName?.lowercase()
val link = tree.getOrPut(nameKey) { GenreLink(GenreNode(Contribution())) }
link.node.contributors.contribute(genre)
link
}
LinkedSong(it, MultiGenreLink(genreLinks))
}
fun resolve() =
tree.values.map { it.node.resolve() }
data class LinkedSong( data class LinkedSong(
val preSong: PreSong, val preSong: PreSong,
val genres: Linked<List<GenreImpl>, SongImpl> val genres: Linked<List<GenreImpl>, SongImpl>
) )
private class MultiGenreLink(
val links: List<Linked<GenreImpl, SongImpl>>
) : Linked<List<GenreImpl>, SongImpl> {
override fun resolve(child: SongImpl): List<GenreImpl> {
return links.map { it.resolve(child) }.distinct()
}
}
private data class GenreLink(
var node: GenreNode
) : Linked<GenreImpl, SongImpl> {
override fun resolve(child: SongImpl): GenreImpl {
return requireNotNull(node.genreImpl) { "Link" }
}
}
private class GenreNode(
val contributors: Contribution<PreGenre>
) {
var genreImpl: GenreImpl? = null
private set
fun resolve(): GenreImpl {
val impl = GenreImpl(contributors.resolve())
genreImpl = impl
return impl
}
}
} }

View file

@ -16,7 +16,7 @@ import java.util.UUID
data class PreSong( data class PreSong(
val musicBrainzId: UUID?, val musicBrainzId: UUID?,
val name: Name, val name: Name,
val rawName: String?, val rawName: String,
val track: Int?, val track: Int?,
val disc: Disc?, val disc: Disc?,
val date: Date?, val date: Date?,