Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/max min strategy #31

Merged
merged 13 commits into from
Oct 30, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,16 @@ import de.fraunhofer.iem.spha.model.kpi.hierarchy.KpiNode
internal fun getKpiCalculationStrategy(strategyId: KpiStrategyId): KpiCalculationStrategy {
return when (strategyId) {
KpiStrategyId.RAW_VALUE_STRATEGY -> RawValueKpiCalculationStrategy
KpiStrategyId.RATIO_STRATEGY -> RatioKPICalculationStrategy

KpiStrategyId.AGGREGATION_STRATEGY -> AggregationKPICalculationStrategy
KpiStrategyId.WEIGHTED_RATIO_STRATEGY -> WeightedRatioKPICalculationStrategy

KpiStrategyId.WEIGHTED_AVERAGE_STRATEGY -> WeightedAverageKPICalculationStrategy

KpiStrategyId.MAXIMUM_STRATEGY -> MaximumKPICalculationStrategy

KpiStrategyId.WEIGHTED_MAXIMUM_STRATEGY -> MaximumKPICalculationStrategy
KpiStrategyId.WEIGHTED_MAXIMUM_STRATEGY -> WeightedMaximumKPICalculationStrategy

KpiStrategyId.WEIGHTED_MINIMUM_STRATEGY -> WeightedMinimumKPICalculationStrategy
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ import io.github.oshai.kotlinlogging.KotlinLogging

private val logger = KotlinLogging.logger {}

internal object AggregationKPICalculationStrategy : BaseKpiCalculationStrategy() {
internal object WeightedAverageKPICalculationStrategy : BaseKpiCalculationStrategy() {

override val kpiStrategyId: KpiStrategyId
get() = KpiStrategyId.AGGREGATION_STRATEGY
get() = KpiStrategyId.WEIGHTED_AVERAGE_STRATEGY

/**
* This function calculates the aggregate sum of all given children. If a child is empty it is
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ internal object WeightedMaximumKPICalculationStrategy : BaseKpiCalculationStrate

override fun internalCalculateKpi(edges: Collection<KpiHierarchyEdge>): KpiCalculationResult {

val max = if (edges.isEmpty()) 0 else edges.maxOf { it.to.score * it.actualWeight }.toInt()
val max = edges.maxByOrNull { it.to.score * it.actualWeight }?.to?.score ?: 0

return KpiCalculationResult.Success(score = max)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright (c) 2024 Fraunhofer IEM. All rights reserved.
*
* Licensed under the MIT license. See LICENSE file in the project root for details.
*
* SPDX-License-Identifier: MIT
* License-Filename: LICENSE
*/

package de.fraunhofer.iem.spha.core.strategy

import de.fraunhofer.iem.spha.core.hierarchy.KpiHierarchyEdge
import de.fraunhofer.iem.spha.model.kpi.KpiStrategyId
import de.fraunhofer.iem.spha.model.kpi.hierarchy.KpiCalculationResult
import de.fraunhofer.iem.spha.model.kpi.hierarchy.KpiNode
import io.github.oshai.kotlinlogging.KotlinLogging

private val logger = KotlinLogging.logger {}

internal object WeightedMinimumKPICalculationStrategy : BaseKpiCalculationStrategy() {

override val kpiStrategyId: KpiStrategyId
get() = KpiStrategyId.WEIGHTED_MINIMUM_STRATEGY

override fun internalCalculateKpi(edges: Collection<KpiHierarchyEdge>): KpiCalculationResult {

val min = edges.minByOrNull { it.to.score * it.actualWeight }?.to?.score ?: 0

return KpiCalculationResult.Success(score = min)
}

/** There is no validity requirement for this strategy. */
override fun internalIsValid(node: KpiNode, strict: Boolean): Boolean {

if (node.edges.size == 1) {
logger.warn {
"Maximum KPI calculation strategy for node $node is planned " +
"for a single child."
}
}

return true
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ import io.github.oshai.kotlinlogging.KotlinLogging

private val logger = KotlinLogging.logger {}

internal object RatioKPICalculationStrategy : BaseKpiCalculationStrategy() {
internal object WeightedRatioKPICalculationStrategy : BaseKpiCalculationStrategy() {

override val kpiStrategyId: KpiStrategyId
get() = KpiStrategyId.RATIO_STRATEGY
get() = KpiStrategyId.WEIGHTED_RATIO_STRATEGY

/** Returns smallerValue / biggerValue, regardless in which order the values are given. */
override fun internalCalculateKpi(edges: Collection<KpiHierarchyEdge>): KpiCalculationResult {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class KpiCalculatorTest {
val root =
KpiNode(
kpiId = KpiId.ROOT,
kpiStrategyId = KpiStrategyId.AGGREGATION_STRATEGY,
kpiStrategyId = KpiStrategyId.WEIGHTED_AVERAGE_STRATEGY,
edges =
listOf(
KpiEdge(
Expand Down Expand Up @@ -106,7 +106,7 @@ class KpiCalculatorTest {
val root =
KpiNode(
kpiId = KpiId.ROOT,
kpiStrategyId = KpiStrategyId.AGGREGATION_STRATEGY,
kpiStrategyId = KpiStrategyId.WEIGHTED_AVERAGE_STRATEGY,
edges =
listOf(
KpiEdge(
Expand Down Expand Up @@ -166,14 +166,14 @@ class KpiCalculatorTest {
val root =
KpiNode(
kpiId = KpiId.ROOT,
kpiStrategyId = KpiStrategyId.AGGREGATION_STRATEGY,
kpiStrategyId = KpiStrategyId.WEIGHTED_AVERAGE_STRATEGY,
edges =
listOf(
KpiEdge(
target =
KpiNode(
kpiId = KpiId.SIGNED_COMMITS_RATIO,
kpiStrategyId = KpiStrategyId.RATIO_STRATEGY,
kpiStrategyId = KpiStrategyId.WEIGHTED_RATIO_STRATEGY,
edges =
listOf(
KpiEdge(
Expand Down Expand Up @@ -247,7 +247,7 @@ class KpiCalculatorTest {
val root =
KpiNode(
kpiId = KpiId.ROOT,
kpiStrategyId = KpiStrategyId.AGGREGATION_STRATEGY,
kpiStrategyId = KpiStrategyId.WEIGHTED_AVERAGE_STRATEGY,
edges =
listOf(
KpiEdge(
Expand Down Expand Up @@ -284,7 +284,7 @@ class KpiCalculatorTest {
val root =
KpiNode(
kpiId = KpiId.ROOT,
kpiStrategyId = KpiStrategyId.AGGREGATION_STRATEGY,
kpiStrategyId = KpiStrategyId.WEIGHTED_AVERAGE_STRATEGY,
edges =
listOf(
KpiEdge(
Expand Down Expand Up @@ -338,7 +338,7 @@ class KpiCalculatorTest {
val root =
KpiNode(
kpiId = KpiId.ROOT,
kpiStrategyId = KpiStrategyId.AGGREGATION_STRATEGY,
kpiStrategyId = KpiStrategyId.WEIGHTED_AVERAGE_STRATEGY,
edges =
listOf(
KpiEdge(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class HierarchyValidatorTest {
rootNode =
KpiNode(
kpiId = KpiId.ROOT,
kpiStrategyId = KpiStrategyId.AGGREGATION_STRATEGY,
kpiStrategyId = KpiStrategyId.WEIGHTED_AVERAGE_STRATEGY,
edges = emptyList(),
)
)
Expand All @@ -43,7 +43,7 @@ class HierarchyValidatorTest {
rootNode =
KpiNode(
kpiId = KpiId.ROOT,
kpiStrategyId = KpiStrategyId.AGGREGATION_STRATEGY,
kpiStrategyId = KpiStrategyId.WEIGHTED_AVERAGE_STRATEGY,
edges =
listOf(
KpiEdge(
Expand Down Expand Up @@ -72,7 +72,7 @@ class HierarchyValidatorTest {
rootNode =
KpiNode(
kpiId = KpiId.ROOT,
kpiStrategyId = KpiStrategyId.AGGREGATION_STRATEGY,
kpiStrategyId = KpiStrategyId.WEIGHTED_AVERAGE_STRATEGY,
edges =
listOf(
KpiEdge(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ internal fun getNodeWithErrorResult(plannedWeight: Double): KpiHierarchyNode {
val node =
KpiNode(
kpiId = KpiId.NUMBER_OF_COMMITS,
kpiStrategyId = KpiStrategyId.RATIO_STRATEGY,
kpiStrategyId = KpiStrategyId.WEIGHTED_RATIO_STRATEGY,
edges =
listOf(
KpiEdge(
Expand All @@ -51,7 +51,7 @@ internal fun getNodeIncompleteResult(plannedWeight: Double): KpiHierarchyNode {
val node =
KpiNode(
kpiId = KpiId.SECRETS,
kpiStrategyId = KpiStrategyId.AGGREGATION_STRATEGY,
kpiStrategyId = KpiStrategyId.WEIGHTED_AVERAGE_STRATEGY,
edges =
listOf(
KpiEdge(
Expand Down Expand Up @@ -103,7 +103,7 @@ class AbstractKpiCalculationTest {
val nodeCorrectChildren =
KpiNode(
kpiId = KpiId.ROOT,
kpiStrategyId = KpiStrategyId.RATIO_STRATEGY,
kpiStrategyId = KpiStrategyId.WEIGHTED_RATIO_STRATEGY,
edges =
listOf(
KpiEdge(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ class AggregationKpiCalculationStrategyTest {
fun calculateEmpty() {

val calcRelaxed =
AggregationKPICalculationStrategy.calculateKpi(
WeightedAverageKPICalculationStrategy.calculateKpi(
hierarchyEdges = listOf(),
strict = false,
)
val calcStrict =
AggregationKPICalculationStrategy.calculateKpi(hierarchyEdges = listOf(), strict = true)
WeightedAverageKPICalculationStrategy.calculateKpi(hierarchyEdges = listOf(), strict = true)

assertEquals(true, calcRelaxed is KpiCalculationResult.Empty)
assertEquals(true, calcStrict is KpiCalculationResult.Empty)
Expand Down Expand Up @@ -72,9 +72,9 @@ class AggregationKpiCalculationStrategyTest {
)

val calcRelaxed =
AggregationKPICalculationStrategy.calculateKpi(root.hierarchyEdges, strict = false)
WeightedAverageKPICalculationStrategy.calculateKpi(root.hierarchyEdges, strict = false)
val calcStrict =
AggregationKPICalculationStrategy.calculateKpi(root.hierarchyEdges, strict = true)
WeightedAverageKPICalculationStrategy.calculateKpi(root.hierarchyEdges, strict = true)

assert(calcRelaxed is KpiCalculationResult.Success)
assert(calcStrict is KpiCalculationResult.Success)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ class WeightedWeightedMaximumKPICalculationStrategyTest {

assert(calcRelaxed is KpiCalculationResult.Success)
assert(calcStrict is KpiCalculationResult.Success)
assertEquals(10, (calcStrict as KpiCalculationResult.Success).score)
assertEquals(10, (calcRelaxed as KpiCalculationResult.Success).score)
assertEquals(20, (calcStrict as KpiCalculationResult.Success).score)
assertEquals(20, (calcRelaxed as KpiCalculationResult.Success).score)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
* Copyright (c) 2024 Fraunhofer IEM. All rights reserved.
*
* Licensed under the MIT license. See LICENSE file in the project root for details.
*
* SPDX-License-Identifier: MIT
* License-Filename: LICENSE
*/

package de.fraunhofer.iem.spha.core.strategy

import de.fraunhofer.iem.spha.core.hierarchy.KpiHierarchyNode
import de.fraunhofer.iem.spha.model.kpi.KpiId
import de.fraunhofer.iem.spha.model.kpi.KpiStrategyId
import de.fraunhofer.iem.spha.model.kpi.RawValueKpi
import de.fraunhofer.iem.spha.model.kpi.hierarchy.KpiCalculationResult
import de.fraunhofer.iem.spha.model.kpi.hierarchy.KpiEdge
import de.fraunhofer.iem.spha.model.kpi.hierarchy.KpiNode
import kotlin.test.Test
import kotlin.test.assertEquals

class WeightedWeightedMinimumKPICalculationStrategyTest {

@Test
fun calculateEmpty() {

val calcRelaxed =
WeightedMinimumKPICalculationStrategy.calculateKpi(
hierarchyEdges = listOf(),
strict = false,
)
val calcStrict =
WeightedMinimumKPICalculationStrategy.calculateKpi(
hierarchyEdges = listOf(),
strict = true,
)

assertEquals(true, calcRelaxed is KpiCalculationResult.Empty)
assertEquals(true, calcStrict is KpiCalculationResult.Empty)
}

@Test
fun calculateCorrect() {
val root =
KpiHierarchyNode.from(
KpiNode(
kpiId = KpiId.ROOT,
kpiStrategyId = KpiStrategyId.MAXIMUM_STRATEGY,
edges =
listOf(
KpiEdge(
target =
KpiNode(
kpiId = KpiId.NUMBER_OF_SIGNED_COMMITS,
kpiStrategyId = KpiStrategyId.RAW_VALUE_STRATEGY,
edges = listOf(),
),
weight = 0.5,
),
KpiEdge(
target =
KpiNode(
kpiId = KpiId.NUMBER_OF_COMMITS,
kpiStrategyId = KpiStrategyId.RAW_VALUE_STRATEGY,
edges = listOf(),
),
weight = 0.5,
),
),
),
listOf(
RawValueKpi(kind = KpiId.NUMBER_OF_SIGNED_COMMITS, score = 15),
RawValueKpi(kind = KpiId.NUMBER_OF_COMMITS, score = 20),
),
)

val calcRelaxed =
WeightedMinimumKPICalculationStrategy.calculateKpi(root.hierarchyEdges, strict = false)
val calcStrict =
WeightedMinimumKPICalculationStrategy.calculateKpi(root.hierarchyEdges, strict = true)

assert(calcRelaxed is KpiCalculationResult.Success)
assert(calcStrict is KpiCalculationResult.Success)
assertEquals(15, (calcStrict as KpiCalculationResult.Success).score)
assertEquals(15, (calcRelaxed as KpiCalculationResult.Success).score)
}
}
Loading
Loading