Skip to content

Commit

Permalink
Merge pull request #24 from kleis-technology/feature/lc_step
Browse files Browse the repository at this point in the history
feature/lc step
  • Loading branch information
pevab authored Nov 26, 2024
2 parents efd09b2 + 774a3df commit 63278a4
Show file tree
Hide file tree
Showing 23 changed files with 535 additions and 80 deletions.
31 changes: 31 additions & 0 deletions .github/workflows/publish.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Publish

on:
push:
tags: [ "v*.*.*" ]
workflow_dispatch:

jobs:
publish:
runs-on: ubuntu-latest
steps:
# Checkout the repository
- name: Checkout code
uses: actions/checkout@v3

# Log in to GitHub Container Registry
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

# Build and push the Docker image
- name: Build and push Docker image
uses: docker/build-push-action@v6
with:
push: true
tags: |
ghcr.io/${{ github.repository_owner }}/${{ github.repository }}:${{ github.ref_name }}
ghcr.io/${{ github.repository_owner }}/${{ github.repository }}:latest
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ plugins {
}

group = "org.cloud_assess"
version = "1.7.4"
version = "1.8.0"

java {
sourceCompatibility = JavaVersion.VERSION_17
Expand Down
31 changes: 29 additions & 2 deletions openapi/api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -184,10 +184,12 @@ components:
type: object
required:
- total
- per_lc_step
properties:
total:
$ref: '#/components/schemas/QuantityDto'
# TODO: per lc step
per_lc_step:
$ref: '#/components/schemas/ImpactPerLcStepDto'
PoolDto:
type: object
required:
Expand Down Expand Up @@ -437,7 +439,9 @@ components:
supply:
$ref: '#/components/schemas/QuantityDto'
impacts:
$ref: '#/components/schemas/ImpactsDto'
type: array
items:
$ref: '#/components/schemas/RawImpactDto'
ParameterDto:
type: object
required:
Expand Down Expand Up @@ -512,4 +516,27 @@ components:
default: [ ]
items:
$ref: '#/components/schemas/ProcessLabelDto'
ImpactPerLcStepDto:
type: object
required:
- manufacturing
- transport
- use
- end_of_life
properties:
manufacturing:
$ref: '#/components/schemas/QuantityDto'
transport:
$ref: '#/components/schemas/QuantityDto'
use:
$ref: '#/components/schemas/QuantityDto'
end_of_life:
$ref: '#/components/schemas/QuantityDto'
RawImpactDto:
type: object
properties:
indicator:
type: string
value:
$ref: '#/components/schemas/QuantityDto'

2 changes: 1 addition & 1 deletion samples/trace_server.http
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Content-Type: application/json
},
"demand": {
"productName": "server",
"processName": "server",
"processName": "server_fn",
"quantity": {
"amount": 10.0,
"unit": "hour"
Expand Down
2 changes: 1 addition & 1 deletion samples/trace_vm.http
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Content-Type: application/json
"requestId": "r01",
"demand": {
"productName": "vm",
"processName": "vm",
"processName": "vm_fn",
"quantity": {
"amount": 1.0,
"unit": "hour"
Expand Down
42 changes: 42 additions & 0 deletions src/main/kotlin/org/cloud_assess/model/ProductMatcher.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package org.cloud_assess.model

import ch.kleis.lcaac.core.lang.value.ProductValue
import ch.kleis.lcaac.core.lang.value.StringValue
import ch.kleis.lcaac.core.math.basic.BasicNumber

data class ProductMatcher(
private val name: String,
private val process: String,
private val labels: Map<String, String> = emptyMap(),
private val arguments: Map<String, String> = emptyMap(),
) {
override fun toString(): String {
return "$name from $process$arguments$labels"
}

fun addLabel(name: String, value: String): ProductMatcher = this.copy(
labels = this.labels.plus(name to value)
)

fun addArgument(name: String, value: String): ProductMatcher = this.copy(
arguments = this.arguments.plus(name to value)
)

fun matches(product: ProductValue<BasicNumber>): Boolean {
val matchName = name == product.name
val matchProcessName = process == product.fromProcessRef?.name
val actualLabels = product.fromProcessRef
?.matchLabels
?.mapValues { it.value.s }
?.entries ?: emptySet()
val sameLabels = actualLabels.containsAll(labels.entries)
&& labels.entries.containsAll(actualLabels)
val actualArguments = product.fromProcessRef
?.arguments
?.filterValues { it is StringValue<BasicNumber> }
?.mapValues { (it.value as StringValue).s }
?.entries ?: emptySet()
val containsArguments = actualArguments.containsAll(arguments.entries)
return matchName && matchProcessName && sameLabels && containsArguments
}
}
56 changes: 49 additions & 7 deletions src/main/kotlin/org/cloud_assess/model/ResourceAnalysis.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,60 @@ import ch.kleis.lcaac.core.math.basic.BasicNumber
import org.cloud_assess.dto.QuantityTimeDto

class ResourceAnalysis(
id: String,
private val target: ProductMatcher,
val period: QuantityTimeDto,
private val rawAnalysis: ContributionAnalysis<BasicNumber, BasicMatrix>,
private val entryPointRef: String = "__main__",
private val targetManufacturing: ProductMatcher = target
.addLabel("phase", "embodied")
.addArgument("lc_step", "manufacturing"),
private val targetTransport: ProductMatcher = target
.addLabel("phase", "embodied")
.addArgument("lc_step", "transport"),
private val targetUse: ProductMatcher = target
.addLabel("phase", "use"),
private val targetEndOfLife: ProductMatcher = target
.addLabel("phase", "embodied")
.addArgument("lc_step", "end-of-life"),
) {
private val main = rawAnalysis.getObservablePorts().getElements()
private val mainPort = rawAnalysis.getObservablePorts().getElements()
.filterIsInstance<ProductValue<BasicNumber>>()
.firstOrNull { it.name == entryPointRef }
?: throw IllegalStateException("no impacts found for id=$id")
.firstOrNull { target.matches(it) }
?: throw IllegalStateException("no impacts found for '$target'")
private val manufacturingPort = rawAnalysis.getObservablePorts().getElements()
.filterIsInstance<ProductValue<BasicNumber>>()
.firstOrNull { targetManufacturing.matches(it) }
?: throw IllegalStateException("no impacts found for '$targetManufacturing'")
private val transportPort = rawAnalysis.getObservablePorts().getElements()
.filterIsInstance<ProductValue<BasicNumber>>()
.firstOrNull { targetTransport.matches(it) }
?: throw IllegalStateException("no impacts found for '$targetTransport'")
private val usePort = rawAnalysis.getObservablePorts().getElements()
.filterIsInstance<ProductValue<BasicNumber>>()
.firstOrNull { targetUse.matches(it) }
?: throw IllegalStateException("no impacts found for '$targetUse'")
private val endOfLifePort = rawAnalysis.getObservablePorts().getElements()
.filterIsInstance<ProductValue<BasicNumber>>()
.firstOrNull { targetEndOfLife.matches(it) }
?: throw IllegalStateException("no impacts found for '$targetEndOfLife'")

fun total(target: Indicator): QuantityValue<BasicNumber> {
return rawAnalysis.getPortContribution(mainPort, indicator(target))
}

fun manufacturing(target: Indicator): QuantityValue<BasicNumber> {
return rawAnalysis.getPortContribution(manufacturingPort, indicator(target))
}

fun transport(target: Indicator): QuantityValue<BasicNumber> {
return rawAnalysis.getPortContribution(transportPort, indicator(target))
}

fun use(target: Indicator): QuantityValue<BasicNumber> {
return rawAnalysis.getPortContribution(usePort, indicator(target))
}

fun contribution(target: Indicator): QuantityValue<BasicNumber> {
return rawAnalysis.getPortContribution(main, indicator(target))
fun endOfLife(target: Indicator): QuantityValue<BasicNumber> {
return rawAnalysis.getPortContribution(endOfLifePort, indicator(target))
}

private fun indicator(indicator: Indicator): IndicatorValue<BasicNumber> {
Expand Down
5 changes: 5 additions & 0 deletions src/main/kotlin/org/cloud_assess/model/ResourceTrace.kt
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ class ResourceTrace(
?: 1.0) * (demandedProduct.allocation?.unit?.scale ?: 1.0)
observablePorts.map { row ->
val supply = contributionAnalysis.supplyOf(row)
val rawImpacts = controllablePorts.associateWith { col ->
contributionAnalysis.getPortContribution(row, col)
}
val impacts = Indicator.entries.associateWith { indicator ->
controllablePorts.firstOrNull { it.getShortName() == indicator.name }
?.let { col ->
Expand All @@ -61,6 +64,7 @@ class ResourceTrace(
target = row,
supply = supply,
impacts = impacts,
rawImpacts = rawImpacts,
)
}
}
Expand All @@ -74,4 +78,5 @@ class ResourceTraceElement(
val target: MatrixColumnIndex<BasicNumber>,
val supply: QuantityValue<BasicNumber>,
val impacts: Map<Indicator, QuantityValue<BasicNumber>?>,
val rawImpacts: Map<MatrixColumnIndex<BasicNumber>, QuantityValue<BasicNumber>?>,
)
56 changes: 25 additions & 31 deletions src/main/kotlin/org/cloud_assess/service/MapperService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class MapperService {
depth = element.depth,
name = target.name,
supply = element.supply.toQuantityDto(),
impacts = impactsDto(element.impacts)
impacts = rawImpactsDto(element.rawImpacts)
)

is ProductValue -> TraceResponseRowDto(
Expand All @@ -50,7 +50,7 @@ class MapperService {
processLabelDto(it)
},
supply = element.supply.toQuantityDto(),
impacts = impactsDto(element.impacts)
impacts = rawImpactsDto(element.rawImpacts)
)

is FullyQualifiedSubstanceValue -> TraceResponseRowDto(
Expand All @@ -59,14 +59,14 @@ class MapperService {
compartment = target.compartment,
subCompartment = target.subcompartment,
supply = element.supply.toQuantityDto(),
impacts = impactsDto(element.impacts)
impacts = rawImpactsDto(element.rawImpacts)
)

is PartiallyQualifiedSubstanceValue -> TraceResponseRowDto(
depth = element.depth,
name = target.name,
supply = element.supply.toQuantityDto(),
impacts = impactsDto(element.impacts)
impacts = rawImpactsDto(element.rawImpacts)
)
}
}
Expand Down Expand Up @@ -94,31 +94,15 @@ class MapperService {
is RecordValue -> null
}

@Suppress("DuplicatedCode")
private fun impactsDto(impacts: Map<Indicator, QuantityValue<BasicNumber>?>): ImpactsDto {
return ImpactsDto(
adPe = impactDto(impacts, Indicator.ADPe),
adPf = impactDto(impacts, Indicator.ADPf),
AP = impactDto(impacts, Indicator.AP),
GWP = impactDto(impacts, Indicator.GWP),
LU = impactDto(impacts, Indicator.LU),
ODP = impactDto(impacts, Indicator.ODP),
PM = impactDto(impacts, Indicator.PM),
POCP = impactDto(impacts, Indicator.POCP),
WU = impactDto(impacts, Indicator.WU),
ctUe = impactDto(impacts, Indicator.CTUe),
ctUhC = impactDto(impacts, Indicator.CTUh_c),
ctUhNc = impactDto(impacts, Indicator.CTUh_nc),
epf = impactDto(impacts, Indicator.Epf),
epm = impactDto(impacts, Indicator.Epm),
ept = impactDto(impacts, Indicator.Ept),
IR = impactDto(impacts, Indicator.IR),
)
}

private fun impactDto(impacts: Map<Indicator, QuantityValue<BasicNumber>?>, indicator: Indicator): ImpactDto {
return impacts[indicator]?.let { ImpactDto(total = it.toQuantityDto()) }
?: ImpactDto(total = QuantityDto(amount = 0.0, unit = ""))
private fun rawImpactsDto(impacts: Map<MatrixColumnIndex<BasicNumber>, QuantityValue<BasicNumber>?>): List<RawImpactDto> {
return impacts.entries.map { entry ->
RawImpactDto(
indicator = entry.key.getShortName(),
value = entry.value?.let {
it.toQuantityDto()
} ?: QuantityDto( amount = 0.0, unit = "")
)
}.toList()
}

fun map(
Expand Down Expand Up @@ -154,9 +138,19 @@ class MapperService {
}

private fun impactDto(analysis: ResourceAnalysis, target: Indicator): ImpactDto {
val quantity = analysis.contribution(target)
val total = analysis.total(target)
val manufacturing = analysis.manufacturing(target)
val transport = analysis.transport(target)
val use = analysis.use(target)
val endOfLife = analysis.endOfLife(target)
return ImpactDto(
total = quantity.toQuantityDto()
total = total.toQuantityDto(),
perLcStep = ImpactPerLcStepDto(
manufacturing = manufacturing.toQuantityDto(),
transport = transport.toQuantityDto(),
use = use.toQuantityDto(),
endOfLife = endOfLife.toQuantityDto(),
)
)
}

Expand Down
15 changes: 11 additions & 4 deletions src/main/kotlin/org/cloud_assess/service/PoolService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ import ch.kleis.lcaac.core.lang.evaluator.Evaluator
import ch.kleis.lcaac.core.lang.expression.EProcessTemplateApplication
import ch.kleis.lcaac.core.math.basic.BasicNumber
import ch.kleis.lcaac.core.math.basic.BasicOperations
import org.cloud_assess.dto.DimensionlessUnitsDto
import org.cloud_assess.dto.PoolListDto
import org.cloud_assess.dto.TimeUnitsDto
import org.cloud_assess.model.ProductMatcher
import org.cloud_assess.model.ResourceAnalysis
import org.springframework.stereotype.Service

Expand All @@ -33,7 +33,15 @@ class PoolService(
val entryPoint = trace.getEntryPoint()
val program = ContributionAnalysisProgram(systemValue, entryPoint)
val rawAnalysis = program.run()
mapOf(it.key to ResourceAnalysis(it.key, period, rawAnalysis))
mapOf(
it.key to ResourceAnalysis(
ProductMatcher(
name = "service",
process = "service_fn",
arguments = mapOf("id" to it.key)
), period, rawAnalysis
)
)
}.reduce { acc, element -> acc.plus(element) }
.orElse(emptyMap())
return analysis
Expand All @@ -46,14 +54,13 @@ class PoolService(
TimeUnitsDto.hour -> "${pools.period.amount} hour"
}
val cases = pools.pools.associate {
// TODO: swagger: remove service level
val content = """
process __main__ {
products {
1 u __main__
}
inputs {
$period service from service(id = "${it.id}")
$period service from service_fn(id = "${it.id}")
}
}
""".trimIndent()
Expand Down
Loading

0 comments on commit 63278a4

Please sign in to comment.