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
|
package core
type LegMetrics struct {
Weight float64
Time float64
Risk float64
}
// BuildTradeLegMetrics computes travel metrics for all legs needed by trades
func BuildTradeLegMetrics(graph *Graph, shipLocation int, trades []Trade) map[[2]int]*LegMetrics {
sourceTargets := make(map[int]map[int]bool)
sourceTargets[shipLocation] = make(map[int]bool)
for _, t := range trades {
if _, ok := sourceTargets[shipLocation]; !ok {
sourceTargets[shipLocation] = make(map[int]bool)
}
sourceTargets[shipLocation][t.FromStation] = true
if _, ok := sourceTargets[t.FromStation]; !ok {
sourceTargets[t.FromStation] = make(map[int]bool)
}
sourceTargets[t.FromStation][t.ToStation] = true
}
metrics := make(map[[2]int]*LegMetrics)
for source, targets := range sourceTargets {
dijkstraRes := graph.SingleSourceDijkstra(source)
for target := range targets {
if source == target {
metrics[[2]int{source, target}] = &LegMetrics{Weight: 0, Time: 0, Risk: 0}
continue
}
if res, ok := dijkstraRes[target]; ok {
metrics[[2]int{source, target}] = &LegMetrics{
Weight: res.TotalWeight,
Time: res.TotalTime,
Risk: res.TotalRisk,
}
} else {
metrics[[2]int{source, target}] = nil
}
}
}
return metrics
}
// Pathfinder filters trades that lack paths and calculates NetProfit
func Pathfinder(trades []Trade, graph *Graph, shipLocation int) []Trade {
var validTrades []Trade
for _, t := range trades {
_, hasFrom := graph.Adj[t.FromStation]
_, hasTo := graph.Adj[t.ToStation]
if hasFrom && hasTo {
validTrades = append(validTrades, t)
}
}
if len(validTrades) == 0 {
return validTrades
}
metrics := BuildTradeLegMetrics(graph, shipLocation, validTrades)
var profitable []Trade
for i := range validTrades {
sourceToFrom, ok1 := metrics[[2]int{shipLocation, validTrades[i].FromStation}]
fromToTo, ok2 := metrics[[2]int{validTrades[i].FromStation, validTrades[i].ToStation}]
if ok1 && ok2 && sourceToFrom != nil && fromToTo != nil {
totalCost := sourceToFrom.Weight + fromToTo.Weight
netProfit := validTrades[i].GrossProfit - totalCost
if netProfit > 0 {
validTrades[i].NetProfit = &netProfit
profitable = append(profitable, validTrades[i])
}
}
}
return profitable
}
|