Skip to content

Commit

Permalink
Merge pull request #36 from SettingDust/feature/loader-order
Browse files Browse the repository at this point in the history
feat: prefer the loader by order in lock file
  • Loading branch information
juraj-hrivnak authored Oct 8, 2024
2 parents e85dd7e + 1f5403a commit 435d51f
Show file tree
Hide file tree
Showing 4 changed files with 210 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ object CurseForge : Platform(

// -- FILES --

private const val LOADER_VERSION_TYPE_ID = 68441
internal const val LOADER_VERSION_TYPE_ID = 68441

private fun List<CfModModel.File>.filterFileModels(
mcVersions: List<String>, loaders: List<String>
Expand All @@ -124,10 +124,19 @@ object CurseForge : Platform(
.filter { it.gameVersionTypeId == LOADER_VERSION_TYPE_ID } // Filter to loader only
.takeIf { it.isNotEmpty() }
?.map { it.gameVersionName.lowercase() }?.any {
loaders.any { loader -> loader == it } || it in validLoaders // Check default valid loaders
it in loaders || it in validLoaders // Check default valid loaders
} ?: true // If no loaders found, accept model
}

internal fun List<CfModModel.File>.sortByLoaders(loaders: List<String>) = this.sortedWith { fileA, fileB ->
val aLoaders = fileA.sortableGameVersions.filter { it.gameVersionTypeId == LOADER_VERSION_TYPE_ID }
.map { it.gameVersionName.lowercase() }
val bLoaders = fileB.sortableGameVersions.filter { it.gameVersionTypeId == LOADER_VERSION_TYPE_ID }
.map { it.gameVersionName.lowercase() }
loaders.indexOfFirst { it in aLoaders }.let { if (it == -1) loaders.size else it }
.minus(loaders.indexOfFirst { it in bLoaders }.let { if (it == -1) loaders.size else it })
}

private fun CfModModel.File.toProjectFile(gameVersionTypeIds: List<Int>): ProjectFile
{
return ProjectFile(
Expand Down Expand Up @@ -192,6 +201,7 @@ object CurseForge : Platform(
this.requestProjectBody(requestUrl) ?: return mutableSetOf()
).data
.filterFileModels(mcVersions, loaders)
.sortByLoaders(loaders)
.map { it.toProjectFile(gameVersionTypeIds) }
.debugIfEmpty {
println("${this::class.simpleName}#requestProjectFiles: file is null")
Expand Down Expand Up @@ -223,6 +233,7 @@ object CurseForge : Platform(
).data
.filterFileModels(mcVersions, loaders)
.sortedByDescending { it.fileDate }
.sortByLoaders(loaders)
.map { it.toProjectFile(gameVersionTypeIds) }
.debugIfEmpty {
println("${this::class.simpleName}#requestMultipleProjectFiles: file is null")
Expand Down
12 changes: 10 additions & 2 deletions src/commonMain/kotlin/teksturepako/pakku/api/platforms/Modrinth.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import teksturepako.pakku.api.models.mr.GetVersionsFromHashesRequest
import teksturepako.pakku.api.models.mr.MrProjectModel
import teksturepako.pakku.api.models.mr.MrVersionModel
import teksturepako.pakku.api.projects.*
import teksturepako.pakku.debug
import teksturepako.pakku.debugIfEmpty
import kotlin.system.exitProcess
import kotlin.time.Duration.Companion.seconds
Expand Down Expand Up @@ -139,10 +140,15 @@ object Modrinth : Platform(
version.gameVersions.any { it in mcVersions } && version.loaders
.takeIf { it.isNotEmpty() }
?.map { it.lowercase() }?.any {
loaders.any { loader -> loader == it } || it in validLoaders // Check default valid loaders
it in loaders || it in validLoaders // Check default valid loaders
} ?: true // If no loaders found, accept model
}

internal fun List<MrVersionModel>.sortByLoaders(loaders: List<String>) = this.sortedWith { aVersion, bVersion ->
loaders.indexOfFirst { it in aVersion.loaders }.let { if (it == -1) loaders.size else it }
.minus(loaders.indexOfFirst { it in bVersion.loaders }.let { if (it == -1) loaders.size else it })
}

private fun MrVersionModel.toProjectFiles(): List<ProjectFile>
{
return this.files.sortedBy { it.primary }.map { versionFile ->
Expand Down Expand Up @@ -182,6 +188,7 @@ object Modrinth : Platform(
this.requestProjectBody("project/$projectId/version") ?: return mutableSetOf()
)
.filterFileModels(mcVersions, loaders)
.sortByLoaders(loaders)
.flatMap { version -> version.toProjectFiles() }
.debugIfEmpty {
println("${this::class.simpleName}#requestProjectFiles: file is null")
Expand Down Expand Up @@ -213,8 +220,9 @@ object Modrinth : Platform(
}
.awaitAll()
.flatten()
.sortedByDescending { it.datePublished }
.filterFileModels(mcVersions, loaders)
.sortedByDescending { it.datePublished }
.sortByLoaders(loaders)
.flatMap { version -> version.toProjectFiles() }
.toMutableSet()
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,129 @@
package teksturepako.pakku.api.platforms

import io.mockk.every
import io.mockk.mockk
import teksturepako.pakku.api.models.cf.CfModModel
import teksturepako.pakku.api.platforms.CurseForge.LOADER_VERSION_TYPE_ID
import teksturepako.pakku.api.platforms.CurseForge.sortByLoaders
import kotlin.test.Test
import kotlin.test.assertContentEquals
import kotlin.test.assertEquals

class CurseForgeTest
{
@Test
fun requestProject()
{
}

@Test
fun sortByLoaders_WithValidLoaders_ShouldSortCorrectly() {
val files = listOf(
mockk<CfModModel.File> {
every { sortableGameVersions } returns listOf(
mockk<CfModModel.File.SortableGameVersion> {
every { gameVersionTypeId } returns LOADER_VERSION_TYPE_ID
every { gameVersionName } returns "loaderB"
},
mockk<CfModModel.File.SortableGameVersion> {
every { gameVersionTypeId } returns LOADER_VERSION_TYPE_ID
every { gameVersionName } returns "loaderC"
}
)
},
mockk<CfModModel.File> {
every { sortableGameVersions } returns listOf(
mockk<CfModModel.File.SortableGameVersion> {
every { gameVersionTypeId } returns LOADER_VERSION_TYPE_ID
every { gameVersionName } returns "loaderA"
},
mockk<CfModModel.File.SortableGameVersion> {
every { gameVersionTypeId } returns LOADER_VERSION_TYPE_ID
every { gameVersionName } returns "loaderB"
}
)
},
mockk<CfModModel.File> {
every { sortableGameVersions } returns listOf(
mockk<CfModModel.File.SortableGameVersion> {
every { gameVersionTypeId } returns LOADER_VERSION_TYPE_ID
every { gameVersionName } returns "loaderB"
},
mockk<CfModModel.File.SortableGameVersion> {
every { gameVersionTypeId } returns LOADER_VERSION_TYPE_ID
every { gameVersionName } returns "loaderB"
}
)
},
mockk<CfModModel.File> {
every { sortableGameVersions } returns listOf(
mockk<CfModModel.File.SortableGameVersion> {
every { gameVersionTypeId } returns LOADER_VERSION_TYPE_ID
every { gameVersionName } returns "loaderA"
},
mockk<CfModModel.File.SortableGameVersion> {
every { gameVersionTypeId } returns LOADER_VERSION_TYPE_ID
every { gameVersionName } returns "loaderC"
}
)
}
)

val loaders = listOf("loadera", "loaderb", "loaderc")
val sortedFiles = files.toList().sortByLoaders(loaders)

assertContentEquals(listOf(files[1], files[3], files[0], files[2]), sortedFiles)
}

@Test
fun sortByLoaders_WithNoMatchingLoaders_ShouldNotChangeOrder() {
val files = listOf(
mockk<CfModModel.File> {
every { sortableGameVersions } returns listOf(
mockk<CfModModel.File.SortableGameVersion> {
every { gameVersionTypeId } returns LOADER_VERSION_TYPE_ID
every { gameVersionName } returns "loaderB"
}
)
},
mockk<CfModModel.File> {
every { sortableGameVersions } returns listOf(
mockk<CfModModel.File.SortableGameVersion> {
every { gameVersionTypeId } returns LOADER_VERSION_TYPE_ID
every { gameVersionName } returns "loaderA"
}
)
}
)

val loaders = listOf("loader1", "loader2")
val sortedFiles = files.toList().sortByLoaders(loaders)
assertContentEquals(files, sortedFiles)
}

@Test
fun sortByLoaders_WithSomeMatchingLoaders_ShouldSortCorrectly() {
val files = listOf(
mockk<CfModModel.File> {
every { sortableGameVersions } returns listOf(
mockk<CfModModel.File.SortableGameVersion> {
every { gameVersionTypeId } returns LOADER_VERSION_TYPE_ID
every { gameVersionName } returns "loaderA"
}
)
},
mockk<CfModModel.File> {
every { sortableGameVersions } returns listOf(
mockk<CfModModel.File.SortableGameVersion> {
every { gameVersionTypeId } returns LOADER_VERSION_TYPE_ID
every { gameVersionName } returns "loader1"
}
)
}
)

val loaders = listOf("loader1", "loader2")
val sortedFiles = files.toList().sortByLoaders(loaders)
assertEquals(files[0], sortedFiles[1])
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package teksturepako.pakku.api.platforms

import io.mockk.every
import io.mockk.mockk
import teksturepako.pakku.api.models.mr.MrVersionModel
import teksturepako.pakku.api.platforms.Modrinth.sortByLoaders
import kotlin.test.Test
import kotlin.test.assertContentEquals
import kotlin.test.assertEquals

class ModrinthTest
{
@Test
fun sortByLoaders_WithValidLoaders_ShouldSortCorrectly() {
val versions = listOf(
mockk<MrVersionModel> {
every { loaders } returns listOf("loaderb", "loaderc")
},
mockk<MrVersionModel> {
every { loaders } returns listOf("loadera", "loaderb")
},
mockk<MrVersionModel> {
every { loaders } returns listOf("loaderb", "loaderb")
},
mockk<MrVersionModel> {
every { loaders } returns listOf("loadera", "loaderc")
}
)

val loaders = listOf("loadera", "loaderb", "loaderc")
val sortedVersions = versions.toList().sortByLoaders(loaders)

assertContentEquals(listOf(versions[1], versions[3], versions[0], versions[2]), sortedVersions)
}

@Test
fun sortByLoaders_WithNoMatchingLoaders_ShouldNotChangeOrder() {
val versions = listOf(
mockk<MrVersionModel> {
every { loaders } returns listOf("loaderB")
},
mockk<MrVersionModel> {
every { loaders } returns listOf("loaderA")
}
)

val loaders = listOf("loader1", "loader2")
val sortedVersions = versions.toList().sortByLoaders(loaders)

assertContentEquals(versions, sortedVersions)
}

@Test
fun sortByLoaders_WithSomeMatchingLoaders_ShouldSortCorrectly() {
val versions = listOf(
mockk<MrVersionModel> {
every { loaders } returns listOf("loadera")
},
mockk<MrVersionModel> {
every { loaders } returns listOf("loader1")
}
)

val loaders = listOf("loader1", "loader2")
val sortedVersions = versions.toList().sortByLoaders(loaders)

assertEquals(versions[0], sortedVersions[1])
}
}

0 comments on commit 435d51f

Please sign in to comment.