/
step.go
115 lines (100 loc) · 3.44 KB
/
step.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package greet
import (
"fmt"
"github.com/ctessum/unit"
)
// Step is a holder for a step in a transportation process.
type Step struct {
DestRef LocationID `xml:"dest_ref,attr"`
OriginRef LocationID `xml:"origin_ref,attr"`
Ref ModeID `xml:"ref,attr"`
Distance Param `xml:"distance"`
Share Param `xml:"share"`
FuelShareRef FuelShareID `xml:"fuel_share_ref,attr"`
BackHaul bool `xml:"back_haul,attr"` // Is an empty backhaul required?
ID string `xml:"id,attr"`
NLoss *NLoss `xml:"nloss"`
}
// Locations is a holder for transportation source and
// destination locations.
type Locations struct {
LocationGroups []LocationGroup `xml:"groups>group"`
Locations []*Location `xml:"location"`
}
// Location holds information about a transportation
// source or destination location.
type Location struct {
Name string `xml:"name,attr"`
Picture string `xml:"picture,attr"`
ID LocationID `xml:"id,attr"`
Notes string `xml:"notes,attr"`
Membership []*LocationMembership `xml:"membership"`
}
// LocationGroup holds information about how different locations
// can be combined into groups.
type LocationGroup struct {
Name string `xml:"name,attr"`
ID LocationGroupID `xml:"id,attr"`
Notes string `xml:"notes,attr"`
}
// LocationMembership gives information about which group a
// location belongs to.
type LocationMembership struct {
GroupID LocationGroupID `xml:"group_id,attr"`
}
// GetDistance returns the distance traveled by this step.
func (s *Step) GetDistance(db *DB) *unit.Unit {
return db.InterpolateValue(s.Distance.ValueYears)
}
// GetShare gets the share of the product that is transported by this step.
func (s *Step) GetShare(db *DB) *unit.Unit {
return db.InterpolateValue(s.Share.ValueYears)
}
// GetNLoss returns the fraction of product that is lost during this step.
func (s *Step) GetNLoss(db *DB) *unit.Unit {
if s.NLoss == nil {
return unit.New(0, unit.Dimless)
}
return db.evalExpr(s.NLoss.Rate)
}
// GetLossAmount calculates the loss of the transported resource during this
// step.
func (s *Step) GetLossAmount(res *Resource, amountTransported *unit.Unit,
db *DB) *unit.Unit {
loss := s.GetNLoss(db)
amtTrans := res.ConvertToMass(amountTransported, db)
return unit.Mul(loss, amtTrans)
}
// GetLossEmissions calculates emissions through evaporation of a product (or other losses).
func (s *Step) GetLossEmissions(res *Resource, amountTransported *unit.Unit, db *DB) (
[]*Gas, []*unit.Unit) {
loss := s.GetNLoss(db)
if loss.Value() == 0. {
return nil, nil
}
amtTrans := res.ConvertToMass(amountTransported, db)
gases, shares := res.GetEvaporationShares(db)
amounts := make([]*unit.Unit, len(shares))
for i, sh := range shares {
amounts[i] = unit.Mul(loss, amtTrans, sh)
}
return gases, amounts
}
// GetModeAndFuelShare gets the mode and fuel share associated with this step
func (s *Step) GetModeAndFuelShare(db *DB) (*Mode, *FuelShare) {
for _, m := range db.Data.Modes {
if m.ID == s.Ref {
for _, fs := range m.FuelShares {
if fs.ID == s.FuelShareRef {
return m, fs
}
}
}
}
panic(fmt.Sprintf("Couldn't find mode and/or fuel share for %#v.", s))
}
// NLoss is a holder for product loss fraction during a transportation step.
type NLoss struct {
Rate Expression `xml:"rate,attr"`
Dependency string `xml:"dependency,attr"`
}