-
Notifications
You must be signed in to change notification settings - Fork 37
/
EVEMarketer.vb
278 lines (236 loc) · 11.3 KB
/
EVEMarketer.vb
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
Imports Newtonsoft.Json
' Class for querying data from EVE Markterer prices
Public Class EVEMarketer
Implements ICloneable
Private ErrorData As MyError
Private Structure PriceQuery
Dim ItemList As String
Dim Items As List(Of Long)
Dim PriceLocation As String
Dim PriceLocationHeader As String
End Structure
Private RegionOrSystemToFind As String
' Predicate for searching a list of pricequery
Private Function FindPriceQuery(ByVal ItemPrice As PriceQuery) As Boolean
If ItemPrice.PriceLocation = RegionOrSystemToFind Then
Return True
Else
Return False
End If
End Function
' Function takes an array of strings for Regions and a TypeID list, returns an array of EVE Marketeer prices
Public Function GetPrices(ByVal TypeIDList As List(Of PriceItem)) As List(Of EVEMarketerPrice)
Dim PriceRecords As New List(Of EVEMarketerPrice)
Dim TempRecord As EVEMarketerPrice
Dim PriceOutput As New List(Of EMType)
Dim EVEMarketerMainQuery As String = "https://api.evemarketer.com/ec/marketstat/json?"
Dim ProcessQueryList As New List(Of PriceQuery)
Dim FinalQueryList As New List(Of PriceQuery)
Dim FindPQ As New PriceQuery
Dim InsertPQ As New PriceQuery
Dim ItemListHeader As String = "typeid="
Dim RegionHeader As String = "®ionlimit="
Dim SystemHeader As String = "&usesystem="
Dim RegionSystemUsed As String = ""
Dim PriceLocationHeaderUsed As String = ""
' Set up for each region/system and item combos to be queried
For Each Item In TypeIDList
' Search the main query list for the region, if there add typeid to the list, else add new list
If Item.SystemID = "" Then
RegionSystemUsed = CStr(Item.RegionID)
PriceLocationHeaderUsed = RegionHeader
Else
RegionSystemUsed = CStr(Item.SystemID)
PriceLocationHeaderUsed = SystemHeader
End If
RegionOrSystemToFind = RegionSystemUsed
FindPQ = ProcessQueryList.Find(AddressOf FindPriceQuery)
If FindPQ.PriceLocation = "" Then
' Add it
InsertPQ.PriceLocation = RegionSystemUsed
InsertPQ.PriceLocationHeader = PriceLocationHeaderUsed
InsertPQ.ItemList = ItemListHeader & CStr(Item.TypeID) & ","
InsertPQ.Items = New List(Of Long)
InsertPQ.Items.Add(Item.TypeID) ' for counting
FindPQ = InsertPQ ' set them to the same now
ProcessQueryList.Add(InsertPQ)
Else
' Found, so update
Call ProcessQueryList.Remove(FindPQ)
FindPQ.ItemList &= CStr(Item.TypeID) & ","
FindPQ.Items.Add(Item.TypeID)
Call ProcessQueryList.Add(FindPQ)
End If
' if Len(EVEMarketerMainQuery & ItemList & RegionOrSystem) > 1900 (will get a too long error at 2000) or over 100 items at a time
If Len(EVEMarketerMainQuery & FindPQ.ItemList & FindPQ.PriceLocationHeader & FindPQ.PriceLocation) > 1900 Or FindPQ.Items.Count >= 100 Then
Call ProcessQueryList.Remove(FindPQ) ' remove from process list
' Insert the item to the final list
Call FinalQueryList.Add(FindPQ)
End If
Next
' Add whatever is left in the process lists
Call FinalQueryList.AddRange(ProcessQueryList)
PriceUpdateDown = False
For Each Record In FinalQueryList
Try
' Example get
'https://api.evemarketer.com/ec/marketstat/json?typeid=34,35&usesystem=30002659
Dim Output As String = GetJSONFile(EVEMarketerMainQuery & Record.ItemList.Substring(0, Len(Record.ItemList) - 1) & Record.PriceLocationHeader & Record.PriceLocation, "EVE Marketer Prices")
' Parse the out put into the object and process
PriceOutput = JsonConvert.DeserializeObject(Of List(Of EMType))(Output)
If PriceUpdateDown Then
Return PriceRecords
End If
If Not IsNothing(PriceOutput) Then
For Each Price In PriceOutput
With Price
TempRecord = New EVEMarketerPrice
TempRecord.TypeID = .buy.forQuery.types(0)
TempRecord.PriceLocation = CLng(Record.PriceLocation)
TempRecord.BuyAvgPrice = .buy.avg
TempRecord.BuyMaxPrice = .buy.max
TempRecord.BuyMedian = .buy.median
TempRecord.BuyMinPrice = .buy.min
TempRecord.BuyPercentile = .buy.fivePercent
TempRecord.BuyStdDev = .buy.stdDev
TempRecord.BuyVolume = .buy.volume
TempRecord.BuyWeightedAveragePrice = .buy.wavg
TempRecord.BuyVariance = .buy.variance
TempRecord.SellAvgPrice = .sell.avg
TempRecord.SellMaxPrice = .sell.max
TempRecord.SellMedian = .sell.median
TempRecord.SellMinPrice = .sell.min
TempRecord.SellPercentile = .sell.fivePercent
TempRecord.SellStdDev = .sell.stdDev
TempRecord.SellVolume = .sell.volume
TempRecord.SellWeightedAveragePrice = .sell.wavg
TempRecord.SellVariance = .sell.variance
End With
' Add the record
PriceRecords.Add(TempRecord)
Application.DoEvents()
Next
End If
Catch ex As Exception
' Determine if it's a 4xx error (my error) or 5xx (server error)
Dim ErrMsg As String = ex.Message
' Get the first digit
Dim ErrorCode As Integer
If InStr(ErrMsg, "(") <> 0 Then
' It has an error code
If IsNumeric(ErrMsg.Substring(InStr(ErrMsg, "("), 1)) Then
ErrorCode = CInt(ErrMsg.Substring(InStr(ErrMsg, "("), 1))
Else
' No clue what it is
' Message box and then exit
ErrorData.Description = ErrMsg & vbCrLf & " In: " & ex.Source & vbCrLf & " With: " & ex.Data.ToString & vbCrLf
ErrorData.Number = ErrorCode
Return Nothing
End If
Else
' No clue what it is
' Message box and then exit
ErrorData.Description = ErrMsg & vbCrLf & " In: " & ex.Source & vbCrLf & " With: " & ex.Data.ToString & vbCrLf
ErrorData.Number = ErrorCode
Return Nothing
End If
' If we error, that means one of the item list has errored. Probably a bad request for an item
' that isn't in the EVE Marketer DB. If bad request (4xx error) then try and run it with 1 per batch and weed out the errors
' If the TypeIDBatchCount isn't 1, then re-run
If ErrorCode = 4 Then
' Message box and then exit
ErrorData.Description = ex.Message
ErrorData.Number = ErrorCode
Return Nothing
ElseIf ErrorCode = 5 Then ' The server is down or something
' Message box and then exit
ErrorData.Description = ex.Message
ErrorData.Number = ErrorCode
Return Nothing
End If
End Try
Next
Return PriceRecords
End Function
' Allow the users to access the error data returned if an error occurs for processing outside class
Public Function GetErrorData() As MyError
Return ErrorData
End Function
Public Function Clone() As Object Implements ICloneable.Clone
Throw New NotImplementedException()
End Function
End Class
Public Structure EVEMarketerPrice
Dim TypeID As Long
Dim BuyVolume As Double
Dim BuyWeightedAveragePrice As Double
Dim BuyAvgPrice As Double
Dim BuyMaxPrice As Double
Dim BuyMinPrice As Double
Dim BuyStdDev As Double
Dim BuyMedian As Double
Dim BuyPercentile As Double
Dim BuyVariance As Double
Dim SellVolume As Double
Dim SellWeightedAveragePrice As Double
Dim SellAvgPrice As Double
Dim SellMaxPrice As Double
Dim SellMinPrice As Double
Dim SellStdDev As Double
Dim SellMedian As Double
Dim SellPercentile As Double
Dim SellVariance As Double
Dim PriceLocation As Long
Dim Errored As Boolean
End Structure
Public Class PriceItem
Implements ICloneable
Public TypeID As Long
Public Manufacture As Boolean
Public RegionID As String
Public SystemID As String
Public StructureID As String
Public GroupName As String
Public PriceModifier As Double
Public PriceType As String
Public JitaPerimeterPrice As Boolean
Public Function Clone() As Object Implements ICloneable.Clone
Dim CopyOfMe = New PriceItem
CopyOfMe.TypeID = TypeID
CopyOfMe.Manufacture = Manufacture
CopyOfMe.RegionID = RegionID
CopyOfMe.SystemID = SystemID
CopyOfMe.StructureID = StructureID
CopyOfMe.GroupName = GroupName
CopyOfMe.PriceModifier = PriceModifier
CopyOfMe.PriceType = PriceType
CopyOfMe.JitaPerimeterPrice = JitaPerimeterPrice
Return CopyOfMe
End Function
End Class
Public Class EMforQuery
<JsonProperty("bid")> Public bid As String
<JsonProperty("types")> Public types As List(Of Integer)
<JsonProperty("regions")> Public regions As List(Of Integer)
<JsonProperty("systems")> Public systems As List(Of Integer)
<JsonProperty("hours")> Public hours As Integer
<JsonProperty("minq")> Public minq As Integer
End Class
Public Class EMTypeStat
<JsonProperty("forQuery")> Public forQuery As EMforQuery
<JsonProperty("volume")> Public volume As Long
<JsonProperty("wavg")> Public wavg As Double
<JsonProperty("avg")> Public avg As Double
<JsonProperty("min")> Public min As Double
<JsonProperty("max")> Public max As Double
<JsonProperty("variance")> Public variance As Double
<JsonProperty("stdDev")> Public stdDev As Double
<JsonProperty("median")> Public median As Double
<JsonProperty("fivePercent")> Public fivePercent As Double
<JsonProperty("highToLow")> Public highToLow As Boolean
<JsonProperty("generated")> Public generated As Long
End Class
Public Class EMType
<JsonProperty("buy")> Public buy As EMTypeStat
<JsonProperty("sell")> Public sell As EMTypeStat
End Class