-
Notifications
You must be signed in to change notification settings - Fork 37
/
MarketPriceInterface.vb
430 lines (352 loc) · 16.9 KB
/
MarketPriceInterface.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
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
Imports System.Data.SQLite
Imports System.Threading
Public Class MarketPriceInterface
Private TypeIDToFind As Long ' For searching a price list
Private PriceHistoryUpdateCount As Integer ' For counting price history updates
Private PriceOrdersUpdateCount As Integer ' for counting price updates
Private RefProgressBar As ToolStripProgressBar
Private TrackingRecords As Boolean
Public Sub New(ByRef SentPG As ToolStripProgressBar)
RefProgressBar = SentPG
PriceHistoryUpdateCount = 0
TrackingRecords = False
End Sub
' For updating market prices and history
Public Structure ItemRegionPairs
Dim ItemID As Long
Dim RegionID As Long
End Structure
Public Enum MarketPriceCacheType
History = 0
Orders = 1
End Enum
' Updates all the price history from ESI
Public Function UpdateESIPriceHistory(SentTypeIDs As List(Of Long), UpdateRegionID As Long) As Boolean
Dim Pairs As New List(Of ItemRegionPairs)
Dim ReturnValue As Boolean = True
Dim Threads As New ThreadingArray
' If the last time we called for history update was one minute, then reset the last date called and calls per minute counter
If DateDiff(DateInterval.Second, LastMarketHistoryUpdate, Now) > 60 Then
MarketHistoryCallsPerMinute = 0
LastMarketHistoryUpdate = Now
End If
' Build the pairs
For i = 0 To SentTypeIDs.Count - 1
' Only add data we want to query
Dim TempPair As New ItemRegionPairs
TempPair.ItemID = SentTypeIDs(i)
TempPair.RegionID = UpdateRegionID
If UpdatableMarketData(TempPair, MarketPriceCacheType.History) Then
' Check if we reached the max per calls and then don't add anything else
If MarketHistoryCallsPerMinute < MaxMarketHIstoryCallsPerMinute Then
Pairs.Add(TempPair)
MarketHistoryCallsPerMinute += 1
Else
' Can't do more than max calls
Exit For
End If
End If
Next
Try
If Pairs.Count > 0 Then
Dim ESIData As New ESI
Dim NumberofThreads As Integer = 0
' How many records per thread do we need?
Dim Splits As Integer = CInt(Math.Ceiling(Pairs.Count / ESIData.GetMaximumConnections))
If Splits = 1 Then
' If the return is 1, then we have less than the max connections
' so just set up enough pairs for 1 run each
NumberofThreads = Pairs.Count
Else
NumberofThreads = ESIData.GetMaximumConnections
End If
' For processing
Dim ThreadPairs As New List(Of List(Of ItemRegionPairs))
Dim TempPairs As New List(Of ItemRegionPairs)
Dim PairMarker As Integer = 0
Dim j As Integer = 0
' Cut up the pairs into chunks of split count and put them into the threadpairs list for threading later
For i = 0 To NumberofThreads - 1
For j = PairMarker To Pairs.Count - 1
If j < Splits * (i + 1) Then
TempPairs.Add(Pairs(j))
Else
Exit For
End If
Next
ThreadPairs.Add(TempPairs)
TempPairs = New List(Of ItemRegionPairs)
PairMarker = j
If j = Pairs.Count Then
Exit For
End If
Next
' Start a transaction here to speed up processing in the updates
Call EVEDB.BeginSQLiteTransaction()
' Reset the value of the progress bar
If Not IsNothing(RefProgressBar) Then
RefProgressBar.Visible = True
RefProgressBar.Value = 0
PriceHistoryUpdateCount = 0
RefProgressBar.Maximum = Pairs.Count
End If
Application.DoEvents()
' Call this manually if it's just one item to update
If ThreadPairs.Count = 1 Then
Call UpdateMarketHistory(ThreadPairs(0))
Else
' Call each thread for the pairs
For i = 0 To ThreadPairs.Count - 1
Dim UPHThread As New Thread(AddressOf UpdateMarketHistory)
UPHThread.Start(ThreadPairs(i))
' Save the thread if we need to kill it
Threads.AddThread(UPHThread)
Next
' Now loop until all the threads are done
ReturnValue = WaitforUpdatetoComplete(Threads, CancelManufacturingTabCalc, PriceHistoryUpdateCount, Pairs.Count)
End If
' Make sure all threads are not running
Call Threads.StopAllThreads()
' Reset the error handler
ESIErrorHandler = New ESIErrorProcessor
' Finish updating the DB
Call EVEDB.CommitSQLiteTransaction()
If Not IsNothing(RefProgressBar) Then
RefProgressBar.Visible = False
End If
Application.DoEvents()
End If
Catch ex As Exception
Application.DoEvents()
End Try
Return ReturnValue
End Function
' For use with threading to speed up the ESI calls
Private Sub UpdateMarketHistory(ByVal PairsList As Object)
Dim PricesUpdated As Boolean
Dim TotalTimes As New List(Of Double)
Dim DownloadTime As New List(Of Double)
Dim ProcessingTime As New List(Of Double)
Dim ESIHistory As New ESI
Dim ESIData As New ESI
Dim Pairs As List(Of ItemRegionPairs) = CType(PairsList, List(Of ItemRegionPairs))
Try
For i = 0 To Pairs.Count - 1
' Update the prices then check limiting if needed - Note, the internets suggests opening new threads with new db connections but I can't do transactions in each thread, which slows it down and this seems to work fine.
PricesUpdated = ESIData.UpdateMarketHistory(EVEDB, Pairs(i).ItemID, Pairs(i).RegionID)
' Increment the count for reach record
PriceHistoryUpdateCount += 1
Next
Catch ex As Exception
Application.DoEvents()
End Try
End Sub
' Uses ESI to update market prices from CCP
Public Function UpdateESIMarketOrders(ByVal CacheItems As List(Of TypeIDRegion)) As Boolean
Dim ReturnValue As Boolean = True
Dim Pairs As New List(Of ItemRegionPairs)
Dim Threads As New ThreadingArray
Dim RegionIDList As New List(Of String)
CancelUpdatePrices = False
' Build the pairs
For i = 0 To CacheItems.Count - 1
Dim TempPair As New ItemRegionPairs
TempPair.ItemID = CLng(CacheItems(i).TypeIDs(0))
TempPair.RegionID = CLng(CacheItems(i).RegionString)
' Make sure they are ready to update by cache
If UpdatableMarketData(TempPair, MarketPriceCacheType.Orders) Then
' Save all the region IDs and check for one remaining at end for unknown stations
If Not RegionIDList.Contains(CStr(TempPair.RegionID)) Then
RegionIDList.Add(CStr(TempPair.RegionID))
End If
Pairs.Add(TempPair)
End If
Next
If Pairs.Count > 0 Then
Dim ESIData As New ESI
Dim NumberofThreads As Integer = 0
' How many records per thread do we need?
Dim Splits As Integer = CInt(Math.Ceiling(Pairs.Count / ESIData.GetMaximumConnections))
If Splits = 1 Then
' If the return is 1, then we have less than the max connections
' so just set up enough pairs for 1 run each
NumberofThreads = Pairs.Count
Else
NumberofThreads = ESIData.GetMaximumConnections
End If
' For processing
Dim ThreadPairs As New List(Of List(Of ItemRegionPairs))
Dim TempPairs As New List(Of ItemRegionPairs)
Dim PairMarker As Integer = 0
Dim j As Integer = 0
' Cut up the pairs into chunks of split count and put them into the threadpairs list for threading later
For i = 0 To NumberofThreads - 1
For j = PairMarker To Pairs.Count - 1
If j < Splits * (i + 1) Then
TempPairs.Add(Pairs(j))
Else
Exit For
End If
Next
ThreadPairs.Add(TempPairs)
TempPairs = New List(Of ItemRegionPairs)
PairMarker = j
If j = Pairs.Count Then
Exit For
End If
Next
' Start a transaction here to speed up processing in the updates
Call EVEDB.BeginSQLiteTransaction()
' Reset the value of the progress bar
If Not IsNothing(RefProgressBar) Then
RefProgressBar.Visible = True
RefProgressBar.Value = 0
PriceHistoryUpdateCount = 0
RefProgressBar.Maximum = Pairs.Count
End If
Application.DoEvents()
' Call this manually if it's just one item to update
If ThreadPairs.Count = 1 Then
Call UpdateMarketOrders(ThreadPairs(0))
Else
' Call each thread for the pairs
For i = 0 To ThreadPairs.Count - 1
Dim UPHThread As New Thread(AddressOf UpdateMarketOrders)
UPHThread.Start(ThreadPairs(i))
' Save the thread if we need to kill it
Threads.AddThread(UPHThread)
Next
' Now loop until all the threads are done
ReturnValue = WaitforUpdatetoComplete(Threads, CancelUpdatePrices, PriceOrdersUpdateCount, Pairs.Count)
End If
' Make sure all threads are not running
Call Threads.StopAllThreads()
' Reset the error handler
ESIErrorHandler = New ESIErrorProcessor
' Finally, update any location data on structures we imported without region or system ID
Dim UpdateIDs As New List(Of Long)
Dim rsUpdate As SQLiteDataReader
DBCommand = New SQLiteCommand("SELECT DISTINCT LOCATION_ID FROM MARKET_ORDERS WHERE REGION_ID = 0", EVEDB.DBREf)
rsUpdate = DBCommand.ExecuteReader
While rsUpdate.Read
UpdateIDs.Add(rsUpdate.GetInt64(0))
End While
rsUpdate.Close()
' Now with this list, run the structures update
Dim SP As New StructureProcessor
Dim TempRegionID As String = ""
Call SP.UpdateStructuresData(UpdateIDs, SelectedCharacter.CharacterTokenData, RefProgressBar)
For Each ID In UpdateIDs
DBCommand = New SQLiteCommand("SELECT REGION_ID, SOLAR_SYSTEM_ID FROM STATIONS WHERE STATION_ID =" & CStr(ID), EVEDB.DBREf)
rsUpdate = DBCommand.ExecuteReader
If rsUpdate.Read Then
TempRegionID = CStr(rsUpdate.GetInt64(0))
If TempRegionID = "0" And RegionIDList.Count = 1 Then
' They only wanted prices from one region and we have an unknown structure, so at least save the region ID we set the query up for
TempRegionID = RegionIDList(0)
End If
Call EVEDB.ExecuteNonQuerySQL(String.Format("UPDATE MARKET_ORDERS SET REGION_ID = {0}, SOLAR_SYSTEM_ID = {1} WHERE LOCATION_ID = {2}", TempRegionID, rsUpdate.GetInt64(1), ID))
End If
rsUpdate.Close()
Next
' Finish updating the DB
Call EVEDB.CommitSQLiteTransaction()
If Not IsNothing(RefProgressBar) Then
RefProgressBar.Visible = False
End If
Application.DoEvents()
End If
Return ReturnValue
End Function
Private Function WaitforUpdatetoComplete(ByRef ThreadsArray As ThreadingArray, ByRef CancelUpdate As Boolean, ByRef Counter As Integer, ByVal MaxValue As Integer) As Boolean
Dim StartTime As DateTime = NoDate
Dim Counting As Boolean = False
Dim StillWorking As Boolean = False
While Counter < MaxValue
' Now loop until all the threads are done
StillWorking = Not ThreadsArray.Complete
' Update the progress bar with data from each thread
Call IncrementToolStripProgressBar(Counter)
Application.DoEvents()
If Not StillWorking Then
Exit While
End If
' If we are at the last 20 records, start a timer for finishing in case it hangs
If MaxValue - Counter <= 20 And Not Counting Then
StartTime = Now
Counting = True
TrackingRecords = True
End If
' Check if we need to leave
If CancelUpdate Or (StartTime <> NoDate And DateDiff(DateInterval.Second, StartTime, Now) >= 30) Then
Call ThreadsArray.StopAllThreads()
' Reset the error handler
ESIErrorHandler = New ESIErrorProcessor
If CancelUpdate Then
Return True ' They wanted this so don't error
Else
Return False
End If
End If
End While
Return True
End Function
' Threading call to speed up the ESI calls for market orders
Private Sub UpdateMarketOrders(PairsList As Object)
Dim PricesUpdated As Boolean
Dim TotalTimes As New List(Of Double)
Dim DownloadTime As New List(Of Double)
Dim ProcessingTime As New List(Of Double)
Dim ESIData As New ESI
Dim Pairs As List(Of ItemRegionPairs) = CType(PairsList, List(Of ItemRegionPairs))
Try
For i = 0 To Pairs.Count - 1
' Update the prices then check limiting if needed
PricesUpdated = ESIData.UpdateMarketOrders(EVEDB, Pairs(i).ItemID, Pairs(i).RegionID, False, True)
' Now that we updated it, for each record, update the total record count for the progressbar on frmMain
PriceOrdersUpdateCount += 1
Next
Catch ex As Exception
Application.DoEvents()
End Try
End Sub
' Sees if the typid and region sent is ready to be updated by a cache date look up
Public Function UpdatableMarketData(ByVal Item As ItemRegionPairs, ByVal CacheType As MarketPriceCacheType) As Boolean
Dim SQL As String
Dim TableName As String
Dim rsCache As SQLiteDataReader
Dim Cachedate As Date
' First look up the cache date to see if it's time to run the update
If CacheType = MarketPriceCacheType.History Then
TableName = "MARKET_HISTORY_UPDATE_CACHE"
ElseIf CacheType = MarketPriceCacheType.Orders Then
TableName = "MARKET_ORDERS_UPDATE_CACHE"
Else
Return False
End If
SQL = "SELECT CACHE_DATE FROM " & TableName & " WHERE TYPE_ID = " & CStr(Item.ItemID) & " AND REGION_ID = " & CStr(Item.RegionID)
DBCommand = New SQLiteCommand(SQL, EVEDB.DBREf)
rsCache = DBCommand.ExecuteReader
Cachedate = ProcessCacheDate(rsCache)
rsCache.Close()
If Cachedate <= Date.UtcNow Then
Return True
Else
Return False
End If
End Function
' Updates the class referenced toolbar
Private Sub IncrementToolStripProgressBar(inValue As Integer)
If IsNothing(RefProgressBar) Then
Exit Sub
End If
' Updates the value in the progressbar for a smooth progress (slows procesing a little)
If inValue <= RefProgressBar.Maximum - 1 And inValue <> 0 Then
RefProgressBar.Value = inValue
RefProgressBar.Value = inValue - 1
RefProgressBar.Value = inValue
Else
RefProgressBar.Value = inValue
End If
End Sub
End Class