Skip to content

Commit

Permalink
fix: improve object simulator. (#799)
Browse files Browse the repository at this point in the history
Issues fixed:

- The simulator doesn't show masses (total and per-item)
- The "add item" button is missing when the product items list is empty.
- When selecting an existing example or bookmark, we'd like to fill its
name in the new bookmark text input.
- We'd also like a more meaningful query string representation than what
we currently have.
- We want to render the steps impact distribution chart in the sidebar.
  • Loading branch information
n1k0 authored Oct 14, 2024
1 parent abd9690 commit 1630a27
Show file tree
Hide file tree
Showing 10 changed files with 320 additions and 167 deletions.
8 changes: 8 additions & 0 deletions public/data/object/examples.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
[
{
"id": "0d08a9ff-5683-4d3d-a7b8-dce74f37cd3b",
"name": "Produit vide",
"category": "",
"query": {
"processes": []
}
},
{
"id": "7d78d30e-7c35-451f-b8ab-e590f39ed0e8",
"name": "Chaise",
Expand Down
1 change: 0 additions & 1 deletion public/data/object/processes.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
"id": "3295b2a5-328a-4c00-b046-e2ddeb0da823",
"name": "Plastic frame (PP)",
"display_name": "Composant en plastique (PP)",
"density": 900,
"unit": "kg",
"impacts": {
"acd": 0,
Expand Down
3 changes: 2 additions & 1 deletion src/Data/Bookmark.elm
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,8 @@ toQueryDescription db bookmark =

Object objectQuery ->
objectQuery
|> ObjectQuery.toString
|> ObjectQuery.toString db.object.processes
|> Result.withDefault "N/A"

Textile textileQuery ->
textileQuery
Expand Down
3 changes: 1 addition & 2 deletions src/Data/Object/Process.elm
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ module Data.Object.Process exposing
, encode
, encodeId
, findById
, idToString
)

import Data.Impact as Impact exposing (Impacts)
Expand Down Expand Up @@ -36,7 +35,7 @@ decodeProcess : Decoder Impact.Impacts -> Decoder Process
decodeProcess impactsDecoder =
Decode.succeed Process
|> Pipe.required "comment" Decode.string
|> Pipe.required "density" Decode.float
|> Pipe.optional "density" Decode.float 1
|> Pipe.required "display_name" Decode.string
|> Pipe.required "id" decodeId
|> Pipe.required "impacts" impactsDecoder
Expand Down
31 changes: 17 additions & 14 deletions src/Data/Object/Query.elm
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import Base64
import Data.Object.Process as Process exposing (Process)
import Json.Decode as Decode exposing (Decoder)
import Json.Encode as Encode
import Result.Extra as RE
import Url.Parser as Parser exposing (Parser)


Expand Down Expand Up @@ -120,21 +121,23 @@ updateItem newItem query =
}


toString : Query -> String
toString query =
query.items
|> List.map
(\i ->
(i.amount
|> amountToFloat
|> String.fromFloat
)
++ " "
++ (i.processId
|> Process.idToString
)
toString : List Process -> Query -> Result String String
toString processes =
.items
>> List.map
(\item ->
item.processId
|> Process.findById processes
|> Result.map
(\process ->
String.fromFloat (amountToFloat item.amount)
++ process.unit
++ " "
++ process.displayName
)
)
|> String.join " - "
>> RE.combine
>> Result.map (String.join ", ")



Expand Down
103 changes: 93 additions & 10 deletions src/Data/Object/Simulator.elm
Original file line number Diff line number Diff line change
@@ -1,17 +1,33 @@
module Data.Object.Simulator exposing
( availableProcesses
( Results(..)
, availableProcesses
, compute
, computeItemImpacts
, emptyResults
, expandItems
, extractImpacts
, extractItems
, extractMass
, toStepsImpacts
)

import Data.Impact as Impact exposing (Impacts)
import Data.Impact as Impact exposing (Impacts, noStepsImpacts)
import Data.Impact.Definition as Definition
import Data.Object.Process as Process exposing (Process)
import Data.Object.Query as Query exposing (Item, Query)
import Mass exposing (Mass)
import Quantity
import Result.Extra as RE
import Static.Db exposing (Db)


type Results
= Results
{ impacts : Impacts
, items : List Results
, mass : Mass
}


availableProcesses : Db -> Query -> List Process
availableProcesses { object } query =
let
Expand All @@ -22,19 +38,86 @@ availableProcesses { object } query =
|> List.filter (\{ id } -> not (List.member id usedIds))


compute : Db -> Query -> Result String Impacts
compute : Db -> Query -> Result String Results
compute db query =
query.items
|> List.map (computeItemImpacts db)
|> List.map (computeItemResults db)
|> RE.combine
|> Result.map Impact.sumImpacts
|> Result.map
(List.foldr
(\(Results { impacts, mass }) (Results acc) ->
Results
{ acc
| impacts = Impact.sumImpacts [ impacts, acc.impacts ]
, items = Results { impacts = impacts, items = [], mass = mass } :: acc.items
, mass = Quantity.sum [ mass, acc.mass ]
}
)
emptyResults
)


computeItemImpacts : Db -> Item -> Result String Impacts
computeItemImpacts { object } { amount, processId } =
computeItemResults : Db -> Item -> Result String Results
computeItemResults { object } { amount, processId } =
processId
|> Process.findById object.processes
|> Result.map
(.impacts
>> Impact.mapImpacts (\_ -> Quantity.multiplyBy (Query.amountToFloat amount))
(\process ->
Results
{ impacts =
process.impacts
|> Impact.mapImpacts (\_ -> Quantity.multiplyBy (Query.amountToFloat amount))
, items = []
, mass =
Mass.kilograms <|
if process.unit == "kg" then
Query.amountToFloat amount

else
-- apply density
Query.amountToFloat amount * process.density
}
)


emptyResults : Results
emptyResults =
Results
{ impacts = Impact.empty
, items = []
, mass = Quantity.zero
}


expandItems : Db -> Query -> Result String (List ( Query.Amount, Process ))
expandItems db =
.items
>> List.map (\{ amount, processId } -> ( amount, processId ))
>> List.map (RE.combineMapSecond (Process.findById db.object.processes))
>> RE.combine


extractImpacts : Results -> Impacts
extractImpacts (Results { impacts }) =
impacts


extractItems : Results -> List Results
extractItems (Results { items }) =
items


extractMass : Results -> Mass
extractMass (Results { mass }) =
mass


toStepsImpacts : Definition.Trigram -> Results -> Impact.StepsImpacts
toStepsImpacts trigram results =
{ noStepsImpacts
-- FIXME: for now, as we only have materials, assign everything to the material step
| materials =
extractImpacts results
|> Impact.getImpact trigram
|> Just
}
Loading

0 comments on commit 1630a27

Please sign in to comment.