public void SetLastUpdateTime(CharOrCorp corc, APIDataType type, DateTime time) { switch (corc) { case CharOrCorp.Char: switch (type) { case APIDataType.Transactions: _lastCharTransUpdate = time; break; case APIDataType.Journal: _lastCharJournalUpdate = time; break; case APIDataType.Assets: _lastCharAssetsUpdate = time; break; case APIDataType.Orders: _lastCharOrdersUpdate = time; break; case APIDataType.IndustryJobs: _settings.LastCharIndustryJobsUpdate = time; break; default: break; } break; case CharOrCorp.Corp: switch (type) { case APIDataType.Transactions: _lastCorpTransUpdate = time; break; case APIDataType.Journal: _lastCorpJournalUpdate = time; break; case APIDataType.Assets: _lastCorpAssetsUpdate = time; break; case APIDataType.Orders: _lastCorpOrdersUpdate = time; break; case APIDataType.IndustryJobs: _settings.LastCorpIndustryJobsUpdate = time; break; default: break; } break; default: break; } }
public void SetHighestID(CharOrCorp corc, APIDataType type, long id) { _apiSettings.SetHighestID(corc, type, id); }
public void SetLastAPIUpdateTime(CharOrCorp corc, APIDataType type, DateTime time) { _apiSettings.SetLastUpdateTime(corc, type, time); }
public DateTime GetLastAPIUpdateTime(CharOrCorp corc, APIDataType type) { return _apiSettings.GetLastUpdateTime(corc, type); }
public void ProcessTransactionsXML(XmlDocument fileXml, CharOrCorp corc, short walletID) { DataImportParams parameters = new DataImportParams(); parameters.xmlData = fileXml; parameters.corc = corc; parameters.walletID = walletID; ThreadPool.QueueUserWorkItem(UpdateTransactionsFromXML, parameters); }
public void DownloadXMLFromAPI(CharOrCorp corc, APIDataType type) { switch (type) { case APIDataType.Transactions: SetLastAPIUpdateError(corc, type, "QUEUED"); ThreadPool.QueueUserWorkItem(RetrieveAPIXML, new APIUpdateInfo(corc, type)); break; case APIDataType.Journal: SetLastAPIUpdateError(corc, type, "QUEUED"); ThreadPool.QueueUserWorkItem(RetrieveAPIXML, new APIUpdateInfo(corc, type)); break; case APIDataType.Assets: SetLastAPIUpdateError(corc, type, "QUEUED"); ThreadPool.QueueUserWorkItem(RetrieveAPIXML, new APIUpdateInfo(corc, type)); break; case APIDataType.Orders: SetLastAPIUpdateError(corc, type, "QUEUED"); ThreadPool.QueueUserWorkItem(RetrieveAPIXML, new APIUpdateInfo(corc, type)); break; case APIDataType.IndustryJobs: SetLastAPIUpdateError(corc, type, "QUEUED"); ThreadPool.QueueUserWorkItem(RetrieveAPIXML, new APIUpdateInfo(corc, type)); break; case APIDataType.Unknown: break; case APIDataType.Full: SetLastAPIUpdateError(corc, APIDataType.Transactions, "QUEUED"); SetLastAPIUpdateError(corc, APIDataType.Orders, "QUEUED"); SetLastAPIUpdateError(corc, APIDataType.IndustryJobs, "QUEUED"); SetLastAPIUpdateError(corc, APIDataType.Journal, "QUEUED"); SetLastAPIUpdateError(corc, APIDataType.Assets, "QUEUED"); ThreadPool.QueueUserWorkItem(RetrieveAPIXML, new APIUpdateInfo(corc, APIDataType.Transactions)); ThreadPool.QueueUserWorkItem(RetrieveAPIXML, new APIUpdateInfo(corc, APIDataType.Orders)); ThreadPool.QueueUserWorkItem(RetrieveAPIXML, new APIUpdateInfo(corc, APIDataType.IndustryJobs)); ThreadPool.QueueUserWorkItem(RetrieveAPIXML, new APIUpdateInfo(corc, APIDataType.Journal)); ThreadPool.QueueUserWorkItem(RetrieveAPIXML, new APIUpdateInfo(corc, APIDataType.Assets)); break; default: break; } }
public long GetHighestID(CharOrCorp corc, APIDataType type) { return _apiSettings.GetHighestID(corc, type); }
private EMMADataSet.OrdersRow BuildOrdersRow(EMMADataSet.OrdersDataTable orderData, XmlNode orderEntry, CharOrCorp corc) { EMMADataSet.OrdersRow newRow = orderData.NewOrdersRow(); newRow.EveOrderID = long.Parse(orderEntry.SelectSingleNode("@orderID").Value, System.Globalization.CultureInfo.InvariantCulture.NumberFormat); //newRow.OwnerID = long.Parse(orderEntry.SelectSingleNode("@charID").Value, // System.Globalization.CultureInfo.InvariantCulture.NumberFormat); newRow.OwnerID = corc == CharOrCorp.Corp ? _corpID : _charID; newRow.ForCorp = corc == CharOrCorp.Corp; newRow.StationID = long.Parse(orderEntry.SelectSingleNode("@stationID").Value, System.Globalization.CultureInfo.InvariantCulture.NumberFormat); newRow.TotalVol = int.Parse(orderEntry.SelectSingleNode("@volEntered").Value, System.Globalization.CultureInfo.InvariantCulture.NumberFormat); newRow.RemainingVol = int.Parse(orderEntry.SelectSingleNode("@volRemaining").Value, System.Globalization.CultureInfo.InvariantCulture.NumberFormat); newRow.MinVolume = int.Parse(orderEntry.SelectSingleNode("@minVolume").Value, System.Globalization.CultureInfo.InvariantCulture.NumberFormat); newRow.OrderState = short.Parse(orderEntry.SelectSingleNode("@orderState").Value, System.Globalization.CultureInfo.InvariantCulture.NumberFormat); // We want to store 'Active' state code as 999, not 0. if (newRow.OrderState == 0) { newRow.OrderState = (short)OrderState.Active; } newRow.ItemID = int.Parse(orderEntry.SelectSingleNode("@typeID").Value, System.Globalization.CultureInfo.InvariantCulture.NumberFormat); newRow.Range = short.Parse(orderEntry.SelectSingleNode("@range").Value, System.Globalization.CultureInfo.InvariantCulture.NumberFormat); newRow.WalletID = short.Parse(orderEntry.SelectSingleNode("@accountKey").Value, System.Globalization.CultureInfo.InvariantCulture.NumberFormat); newRow.Duration = short.Parse(orderEntry.SelectSingleNode("@duration").Value, System.Globalization.CultureInfo.InvariantCulture.NumberFormat); newRow.Escrow = decimal.Parse(orderEntry.SelectSingleNode("@escrow").Value, System.Globalization.CultureInfo.InvariantCulture.NumberFormat); newRow.Price = decimal.Parse(orderEntry.SelectSingleNode("@price").Value, System.Globalization.CultureInfo.InvariantCulture.NumberFormat); int buyOrder = int.Parse(orderEntry.SelectSingleNode("@bid").Value); newRow.BuyOrder = buyOrder == 1; newRow.Issued = DateTime.Parse(orderEntry.SelectSingleNode("@issued").Value, System.Globalization.CultureInfo.InvariantCulture.DateTimeFormat); newRow.Processed = true; return newRow; }
/// <summary> /// Download XML from the Eve API /// </summary> /// <param name="corc"></param> /// <param name="type"></param> private void RetrieveAPIXML(CharOrCorp corc, APIDataType type) { TimeSpan timeBetweenUpdates = UserAccount.Settings.GetAPIUpdatePeriod(type); DateTime earliestUpdate = GetLastAPIUpdateTime(corc, type).Add(timeBetweenUpdates); DateTime dataDate = DateTime.MinValue; short walletID = corc == CharOrCorp.Corp ? (short)1000 : (short)0; decimal beforeID = 0; bool finishedDownloading = false; bool walletExhausted = false; bool noData = true; bool abort = false; string xmlFile = ""; int rowCount = 200; XmlDocument xml = null; long currentMaxID = 0; if (type == APIDataType.Transactions) { currentMaxID = _apiSettings.GetHighestID(corc, APIDataType.Transactions); } if (type == APIDataType.Journal) { currentMaxID = _apiSettings.GetHighestID(corc, APIDataType.Journal); } try { // Make sure we don't download if we've already done so recently. if (earliestUpdate.CompareTo(DateTime.UtcNow) > 0) { throw new EMMAEveAPIException(ExceptionSeverity.Warning, 1000, "Cannot get " + type.ToString() + " data so soon after the last update. Wait until at least " + earliestUpdate.ToLongTimeString() + " before updating."); } while (!finishedDownloading) { try { // Set parameters that will be passed to the API #region Set parameters StringBuilder parameters = new StringBuilder(); parameters.Append("keyID="); parameters.Append(_userID); parameters.Append("&vCode="); parameters.Append(_apiKey); parameters.Append("&characterID="); parameters.Append(_charID); if (type == APIDataType.Journal || type == APIDataType.Transactions) { parameters.Append("&rowCount="); parameters.Append(rowCount); if (walletID != 0) { parameters.Append("&accountKey="); parameters.Append(walletID); } if (beforeID != 0) { parameters.Append("&fromID="); parameters.Append(beforeID); } } if (type == APIDataType.Assets || type == APIDataType.Orders) { parameters.Append("&version=2"); } #endregion xml = EveAPI.GetXml(EveAPI.URL_EveApiHTTPS + EveAPI.GetURL(corc, type), parameters.ToString(), ref xmlFile); XmlNodeList tmp = EveAPI.GetResults(xml); if (xmlFile.Length > 0) { lock (_unprocessedXMLFiles) { _unprocessedXMLFiles.Enqueue(xmlFile); } noData = false; } if (type == APIDataType.Journal || type == APIDataType.Transactions) { if (tmp.Count < rowCount) { walletExhausted = true; } } // Set the last update time based upon the 'cached until' // time rather than the actual time the update occured // Note we could modify the API update period timer instead but // that would cause other issues. It's better for the user if // we just do things this way. if (type == APIDataType.Transactions) { // Transactions XML often gives a cache expiry date time that is too soon. // If we try and update again when it says then it will fail so just wait // for the usual 1 hour. (Or whatever the user has it set to) SetLastAPIUpdateTime(corc, type, DateTime.UtcNow); } else { DateTime nextAllowed = EveAPI.GetCachedUntilTime(xml); SetLastAPIUpdateTime(corc, type, nextAllowed.Subtract( UserAccount.Settings.GetAPIUpdatePeriod(type))); } // If we've been successfull in getting data and this is a corporate data request // then make sure we've got access set to true; if (corc == CharOrCorp.Corp) { Settings.SetCorpAPIAccess(type, true); } } catch (EMMAEveAPIException emmaApiEx) { #region API Error Handling if (emmaApiEx.EveCode == 100) { // Error code 100 indicates that a 'beforeRefID' has been passed in when the // api was not expecting it. If we know for sure that we've already called // the api once then have to abandon the data we have got so far. // (No idea why the API does this, it just happens from time to time) if (!noData) { walletExhausted = true; //SetLastAPIUpdateError(corc, type, "Eve API Error 100"); } else { throw emmaApiEx; } } else if (emmaApiEx.EveCode == 101 || emmaApiEx.EveCode == 102 || emmaApiEx.EveCode == 103 || emmaApiEx.EveCode == 116 || emmaApiEx.EveCode == 117) { // Data already retrieved string err = emmaApiEx.EveDescription; // If there is a cachedUntil tag, dont try and get data again until // after it has expired. DateTime nextAllowed = EveAPI.GetCachedUntilTime(xml); SetLastAPIUpdateTime(corc, type, nextAllowed.Subtract( UserAccount.Settings.GetAPIUpdatePeriod(type))); if (noData) { SetLastAPIUpdateError(corc, type, "The Eve API reports that this data has already been retrieved, no update has occured."); } walletExhausted = true; } else if (emmaApiEx.EveCode == 200) { // Security level not high enough SetLastAPIUpdateError(corc, type, "You must enter your FULL api key to retrieve financial and asset data.\r\n" + "Use the 'manage group' button to correct this."); abort = true; } else if (emmaApiEx.EveCode == 206 || emmaApiEx.EveCode == 208 || emmaApiEx.EveCode == 209 || emmaApiEx.EveCode == 213) { // Character does not have required corporate role. Settings.SetCorpAPIAccess(type, false); SetAPIAutoUpdate(corc, type, false); SetLastAPIUpdateError(corc, type, emmaApiEx.Message); abort = true; } else { throw emmaApiEx; } #endregion } /// By default, we're now done.. finishedDownloading = true; // However, for some update types, we'll want to go round a few more times #region Determine if we should access API again with different variables if (!abort) { if (type == APIDataType.Journal || type == APIDataType.Transactions) { //XmlNode lastRowNode = xml.SelectSingleNode(@"/eveapi/result/rowset/row[last()]"); XmlNodeList results = xml.SelectNodes(@"/eveapi/result/rowset/row"); long minID = long.MaxValue; if (results != null) { foreach (XmlNode node in results) { string idAttribName = ""; if (type == APIDataType.Journal) { idAttribName = "@refID"; } if (type == APIDataType.Transactions) { idAttribName = "@transactionID"; } long val = long.Parse(node.SelectSingleNode(idAttribName).Value); if (val < minID) { minID = val; } } } if (minID != long.MaxValue && minID > currentMaxID) { beforeID = minID; } else { walletExhausted = true; } if (!walletExhausted) { finishedDownloading = false; } if (walletExhausted && corc == CharOrCorp.Corp && walletID < 1006) { walletID++; beforeID = 0; finishedDownloading = false; } } } #endregion } } catch (Exception ex) { EMMAException emmaEx = ex as EMMAException; if (emmaEx == null) { // If we've caught a standard exception rather than an EMMA one then log it be creating a // new exception. // Note that we don't need to actually throw it.. emmaEx = new EMMAException(ExceptionSeverity.Error, "Error when downloading " + type.ToString() + " from Eve API", ex); } SetLastAPIUpdateError(corc, type, ex.Message); noData = true; } // If we have not retrieved any data at all then mark the update as completed. if (noData) { if (UpdateEvent != null) { UpdateEvent(this, new APIUpdateEventArgs(type, corc == CharOrCorp.Char ? _charID : _corpID, APIUpdateEventType.UpdateCompleted)); } } }
public static string GetURL(CharOrCorp corc, APIDataType type) { string retVal = ""; switch (type) { case APIDataType.Transactions: retVal = corc == CharOrCorp.Char ? URL_TransApi : URL_TransCorpApi; break; case APIDataType.Journal: retVal = corc == CharOrCorp.Char ? URL_JournApi : URL_JournCorpApi; break; case APIDataType.Assets: retVal = corc == CharOrCorp.Char ? URL_AssetApi : URL_AssetCorpApi; break; case APIDataType.Orders: retVal = corc == CharOrCorp.Char ? URL_CharOrdersApi : URL_CorpOrdersApi; break; case APIDataType.IndustryJobs: retVal = corc == CharOrCorp.Char ? URL_IndustryApi : URL_IndustryCorpApi; break; case APIDataType.Unknown: break; case APIDataType.Full: break; default: break; } return retVal; }
public APICharacter(long userID, string apiKey, CharOrCorp accessType, EMMADataSet.APICharactersRow data) { _userID = userID; _apiKey = apiKey; _charID = data.ID; _apiSettings = new APISettingsAndStatus(_charID); if (data.CharSheet.Length > 0) { _charSheetXMLCache.LoadXml(data.CharSheet); _charSheetXMLLastUpdate = data.LastCharSheetUpdate; GetDataFromCharXML(); } if (data.CorpSheet.Length > 0) { _corpSheetXMLCache.LoadXml(data.CorpSheet); _corpSheetXMLLastUpdate = data.LastCorpSheetUpdate; GetDataFromCorpXML(); } _corpFinanceAccess = data.CorpFinanceAccess; if (accessType == CharOrCorp.Char) { try { RefreshCharXMLFromAPI(); } catch { } } else { try { RefreshCorpXMLFromAPI(); } catch { } } SetLastAPIUpdateTime(CharOrCorp.Char, APIDataType.Assets, data.LastCharAssetsUpdate); SetLastAPIUpdateTime(CharOrCorp.Char, APIDataType.Journal, data.LastCharJournalUpdate); SetLastAPIUpdateTime(CharOrCorp.Char, APIDataType.Orders, data.LastCharOrdersUpdate); SetLastAPIUpdateTime(CharOrCorp.Char, APIDataType.Transactions, data.LastCharTransUpdate); SetLastAPIUpdateTime(CharOrCorp.Corp, APIDataType.Assets, data.LastCorpAssetsUpdate); SetLastAPIUpdateTime(CharOrCorp.Corp, APIDataType.Journal, data.LastCorpJournalUpdate); SetLastAPIUpdateTime(CharOrCorp.Corp, APIDataType.Orders, data.LastCorpOrdersUpdate); SetLastAPIUpdateTime(CharOrCorp.Corp, APIDataType.Transactions, data.LastCorpTransUpdate); // Note - don't need to set industry job update dates as they are stored in the settings xml // instead of directly on the character record. SetHighestID(CharOrCorp.Char, APIDataType.Transactions, data.HighestCharTransID); SetHighestID(CharOrCorp.Corp, APIDataType.Transactions, data.HighestCorpTransID); SetHighestID(CharOrCorp.Char, APIDataType.Journal, data.HighestCharJournalID); SetHighestID(CharOrCorp.Corp, APIDataType.Journal, data.HighestCorpJournalID); if (!Settings.UpdatedOwnerIDToCorpID) { UpdateOwnerIDToCorpID(); } }
private void UpdateLabel(Label label, Label otherLabel, CharOrCorp corc, APIDataType dataType, TimeSpan minTimeBetweenUpdates) { DateTime lastDataUpdate = _character.GetLastAPIUpdateTime(corc, dataType); TimeSpan time = DateTime.UtcNow.Subtract(lastDataUpdate); string errorText = _character.GetLastAPIUpdateError(corc, dataType); bool doUpdate = false; bool checkForAccess = false; // No need for this. // The 'update completed' event is fired by the APICharacter object and handled by the // UpdateStatus window anyway. //if (label.Text.ToUpper().Equals("UPDATING") && !errorText.ToUpper().Equals("UPDATING") // && !errorText.ToUpper().Equals("BLOCKED") && !errorText.ToUpper().Equals("AWAITING ACKNOWLEDGEMENT")) //{ // // If the label currently says 'updating' but the error text no longer says 'updating' (or blocked) // // then fire the update completed event. // if (UpdateEvent != null) // { // UpdateEvent(this, new APIUpdateEventArgs(dataType, corc == // CharOrCorp.Char ? _character.CharID : _character.CorpID, // APIUpdateEventType.UpdateCompleted)); // } //} if (errorText.Equals("") || (_type == CharOrCorp.Corp && ( errorText.ToUpper().Contains("CHARACTER MUST BE A") || errorText.ToUpper().Contains("CHARACTER MUST HAVE")))) { if (_type == CharOrCorp.Corp && !_character.CharHasCorporateAccess(dataType)) { label.Text = "No Access"; label.BackColor = _errorColour; otherLabel.BackColor = _errorColour; if (chkUpdate.Checked) { checkForAccess = true; } //switch (dataType) //{ // case APIDataType.Transactions: // if (chkAutoTrans.Checked) { checkForAccess = true; chkAutoTrans.Checked = false; } // break; // case APIDataType.Journal: // if (chkAutoJournal.Checked) { checkForAccess = true; chkAutoJournal.Checked = false; } // break; // case APIDataType.Assets: // if (chkAutoAssets.Checked) { checkForAccess = true; chkAutoAssets.Checked = false; } // break; // case APIDataType.Orders: // if (chkAutoOrders.Checked) { checkForAccess = true; chkAutoOrders.Checked = false; } // break; // default: // break; //} } else if (minTimeBetweenUpdates.CompareTo(time) > 0) { time = minTimeBetweenUpdates.Subtract(time); // Waiting for next update window label.Text = time.Hours.ToString().PadLeft(2, '0') + ":" + time.Minutes.ToString().PadLeft(2, '0') + ":" + time.Seconds.ToString().PadLeft(2, '0'); label.BackColor = _upToDateColour; otherLabel.BackColor = _upToDateColour; } else { // Update overdue label.Text = "Overdue"; label.BackColor = _overdueUpdateColour; otherLabel.BackColor = _overdueUpdateColour; doUpdate = true; } } else if (errorText.ToUpper().Equals("UPDATING")) { if (label.Text.Equals(BLOCKEDTEXT)) { // If the update was previously blocked then need to let the rest of EMMA // know that the update is now restarted. if (UpdateEvent != null) { UpdateEvent(this, new APIUpdateEventArgs(dataType, corc == CharOrCorp.Char ? _character.CharID : _character.CorpID, APIUpdateEventType.UpdateStarted)); } } // The update is in progress. label.Text = "Updating"; label.BackColor = _updatingColour; otherLabel.BackColor = _updatingColour; } else if (errorText.ToUpper().Equals("DOWNLOADING")) { // The update is in progress. label.Text = "Downloading"; label.BackColor = _updatingColour; otherLabel.BackColor = _updatingColour; } else if (errorText.ToUpper().Equals("QUEUED")) { // The thread performing the update has been started but is currently waiting // for some other update to complete before it can proceed. // No transaction, orders or assets update can be running at the same time for a particular // character or corp. // No journal update can be running at the same time for ANY character or corp. label.Text = "Queued"; label.BackColor = _updatingColour; otherLabel.BackColor = _updatingColour; } else if (errorText.ToUpper().Equals("BLOCKED")) { // An assets update has been blocked because the most recent transaction and orders // updates are not within the timeframe specified. // Ask the user if they want to reconfigure this to always allow asset updates. if (!label.Text.Equals(BLOCKEDTEXT)) { label.Text = BLOCKEDTEXT; label.BackColor = _updatingColour; otherLabel.BackColor = _updatingColour; // Make sure we let the rest of EMMA know that the update has stopped. // Otherwise, the user will be unable to use reports, exit, etc while // waiting for it to unblock. if (UpdateEvent != null) { UpdateEvent(this, new APIUpdateEventArgs(dataType, corc == CharOrCorp.Char ? _character.CharID : _character.CorpID, APIUpdateEventType.UpdateCompleted)); } DialogResult result = MessageBox.Show("An assets update for " + (corc == CharOrCorp.Char ? _character.CharName : _character.CorpName) + " has been blocked because transaction " + " & orders updates have not occured within the last " + UserAccount.Settings.AssetsUpdateMaxMinutes + " minutes.\r\n" + "The assets update is only allowed to run when the number of minutes since transactions & " + "orders updates is less than a configured number. This setting can be changed in " + "Settings -> API Update Settings.\r\n" + "Do you wish to set this to zero now? (i.e. always allow assets updates regardless of " + "the last time a transaction/orders update occured)", "Question", MessageBoxButtons.YesNo, MessageBoxIcon.Question); if (result == DialogResult.Yes) { UserAccount.Settings.AssetsUpdateMaxMinutes = 0; } } } else if (errorText.ToUpper().Equals("AWAITING ACKNOWLEDGEMENT")) { if (!label.Text.Equals(WAITINGTEXT)) { label.Text = WAITINGTEXT; label.BackColor = _updatingColour; otherLabel.BackColor = _updatingColour; } } else { // The last update caused an error of some sort. if (minTimeBetweenUpdates.CompareTo(time) > 0) { time = minTimeBetweenUpdates.Subtract(time); // Waiting for next update window label.Text = "Error " + time.Hours.ToString().PadLeft(2, '0') + ":" + time.Minutes.ToString().PadLeft(2, '0') + ":" + time.Seconds.ToString().PadLeft(2, '0'); label.BackColor = _errorColour; LabelMetaData metaData = (LabelMetaData)otherLabel.Tag; metaData.TimerType = APIUpdateTimerType.Normal; otherLabel.BackColor = _errorColour; } else { LabelMetaData metaData = (LabelMetaData)otherLabel.Tag; if (metaData.TimerType == APIUpdateTimerType.Normal) { // Update overdue label.Text = "Overdue"; label.BackColor = _overdueUpdateColour; otherLabel.BackColor = _overdueUpdateColour; doUpdate = true; } else { // If we didn't even get as far as setting the update time when // requesting data from the API last time then just use a one hour // timer to make sure we don't request updates every few seconds // after an error occurs. metaData.TimerType = APIUpdateTimerType.Error; DateTime lastAttempt = _lastUpdateAttempt[dataType]; TimeSpan timeSinceLastAttempt = DateTime.UtcNow.Subtract(lastAttempt); if (timeSinceLastAttempt.TotalMinutes > 60) { // Update overdue label.Text = "Overdue"; label.BackColor = _overdueUpdateColour; otherLabel.BackColor = _overdueUpdateColour; doUpdate = true; } else { // Error on the last update time = new TimeSpan(0, 61, 0); time = time.Subtract(timeSinceLastAttempt); label.Text = "Error " + time.Hours.ToString().PadLeft(2, '0') + ":" + time.Minutes.ToString().PadLeft(2, '0') + ":" + time.Seconds.ToString().PadLeft(2, '0'); ; label.BackColor = _errorColour; otherLabel.BackColor = _errorColour; } } } } if (checkForAccess || (doUpdate && _character.GetAPIAutoUpdate(corc, dataType))) { // If we're updating assets and order or transaction updates are pending then do those first. if (dataType == APIDataType.Assets && ((_character.GetAPIAutoUpdate(corc, APIDataType.Orders) && (lblOrdersStatus.Text.Equals("Overdue") || lblOrdersStatus.Text.Equals("Queued"))) || (_character.GetAPIAutoUpdate(corc, APIDataType.Transactions) && (lblTransStatus.Text.Equals("Overdue") || lblTransStatus.Text.Equals("Queued"))))) { } else { // If we're auto updating then kick it off. LabelMetaData metaData = (LabelMetaData)otherLabel.Tag; metaData.TimerType = APIUpdateTimerType.Normal; if (UpdateEvent != null) { UpdateEvent(this, new APIUpdateEventArgs(dataType, corc == CharOrCorp.Char ? _character.CharID : _character.CorpID, APIUpdateEventType.UpdateStarted)); } if (_lastUpdateAttempt.ContainsKey(dataType)) { _lastUpdateAttempt.Remove(dataType); } _lastUpdateAttempt.Add(dataType, DateTime.UtcNow); _character.DownloadXMLFromAPI(corc, dataType); //if (corc == CharOrCorp.Corp && dataType == APIDataType.Orders) //{ // // If we're dealing with corporate orders then we need to grab corporate orders for // // all characters in this report group that are part of the corp. // // This is because orders will only be returned that were actually created by // // the character we are retrieving data for. // foreach (EVEAccount account in UserAccount.CurrentGroup.Accounts) // { // foreach (APICharacter character in account.Chars) // { // if (character.CorpID == _character.CorpID && character.CharID != _character.CharID) // { // if (character.CharHasCorporateAccess(APIDataType.Orders)) // { // character.UpdateDataFromAPI(corc, dataType); // } // } // } // } //} } } // Make sure the state of the auto update checkboxes reflects the true values. // This only needs to be done for corps because the only way the auto-update // setting can change without user intervention is if a char does not have corp // data access. if (corc == CharOrCorp.Corp) { switch (dataType) { case APIDataType.Transactions: chkAutoTrans.Checked = _character.GetAPIAutoUpdate(corc, dataType); break; case APIDataType.Journal: chkAutoJournal.Checked = _character.GetAPIAutoUpdate(corc, dataType); break; case APIDataType.Assets: chkAutoAssets.Checked = _character.GetAPIAutoUpdate(corc, dataType); break; case APIDataType.Orders: chkAutoOrders.Checked = _character.GetAPIAutoUpdate(corc, dataType); break; case APIDataType.IndustryJobs: chkAutoIndustryJobs.Checked = _character.GetAPIAutoUpdate(corc, dataType); break; default: break; } SetOverallUpdateState(); } }
public UpdatePanel(CharOrCorp type, APICharacter character) { InitializeComponent(); _type = type; _character = character; lblName.Text = "Update " + (type == CharOrCorp.Char ? _character.CharName : _character.CorpName) + " from API"; lblJournal.BackColor = _upToDateColour; lblJournalStatus.BackColor = _upToDateColour; lblTransactions.BackColor = _upToDateColour; lblTransStatus.BackColor = _upToDateColour; lblOrders.BackColor = _upToDateColour; lblOrdersStatus.BackColor = _upToDateColour; lblAssets.BackColor = _upToDateColour; lblAssetsStatus.BackColor = _upToDateColour; lblIndustryJobs.BackColor = _upToDateColour; lblIndustryJobsStatus.BackColor = _upToDateColour; _showingTT.Add(APIDataType.Assets, false); _showingTT.Add(APIDataType.Journal, false); _showingTT.Add(APIDataType.Orders, false); _showingTT.Add(APIDataType.Transactions, false); _showingTT.Add(APIDataType.IndustryJobs, false); _lastUpdateAttempt.Add(APIDataType.Assets, DateTime.MinValue); _lastUpdateAttempt.Add(APIDataType.Journal, DateTime.MinValue); _lastUpdateAttempt.Add(APIDataType.Orders, DateTime.MinValue); _lastUpdateAttempt.Add(APIDataType.Transactions, DateTime.MinValue); _lastUpdateAttempt.Add(APIDataType.IndustryJobs, DateTime.MinValue); _individualUpdate = UserAccount.Settings.APIIndividualUpdate; RefreshCheckboxDisplay(); if (type == CharOrCorp.Char) { picPortrait.Image = Portaits.GetPortrait(character.CharID); lblCorpTag.Visible = false; } else { picPortrait.Image = null; picPortrait.BorderStyle = BorderStyle.FixedSingle; lblCorpTag.Visible = true; lblCorpTag.Text = "[" + character.CorpTag + "]"; // Get any other characters in the group with the same corp. List<APICharacter> otherCorpChars = new List<APICharacter>(); foreach (EVEAccount account in UserAccount.CurrentGroup.Accounts) { foreach (APICharacter tmpchar in account.Chars) { if (tmpchar.CharID != _character.CharID && tmpchar.CorpID == _character.CorpID) { otherCorpChars.Add(tmpchar); } } } otherCorpChars.Add(_character); _character.OtherCorpChars = otherCorpChars; } _toggleAll = !chkAutoTrans.Checked && !chkAutoOrders.Checked && !chkAutoJournal.Checked && !chkAutoAssets.Checked; chkUpdate.Enabled = !Globals.EveAPIDown; chkAutoAssets.Enabled = !Globals.EveAPIDown; chkAutoJournal.Enabled = !Globals.EveAPIDown; chkAutoOrders.Enabled = !Globals.EveAPIDown; chkAutoTrans.Enabled = !Globals.EveAPIDown; chkAutoAssets.Tag = APIDataType.Assets; chkAutoIndustryJobs.Tag = APIDataType.IndustryJobs; chkAutoJournal.Tag = APIDataType.Journal; chkAutoOrders.Tag = APIDataType.Orders; chkAutoTrans.Tag = APIDataType.Transactions; chkAutoAssets.CheckedChanged += new EventHandler(chk_CheckedChanged); chkAutoJournal.CheckedChanged += new EventHandler(chk_CheckedChanged); chkAutoOrders.CheckedChanged += new EventHandler(chk_CheckedChanged); chkAutoTrans.CheckedChanged += new EventHandler(chk_CheckedChanged); chkAutoIndustryJobs.CheckedChanged += new EventHandler(chk_CheckedChanged); lblAssets.Tag = new LabelMetaData(APIDataType.Assets); lblAssetsStatus.Tag = new LabelMetaData(APIDataType.Assets); lblJournal.Tag = new LabelMetaData(APIDataType.Journal); lblJournalStatus.Tag = new LabelMetaData(APIDataType.Journal); lblOrders.Tag = new LabelMetaData(APIDataType.Orders); lblOrdersStatus.Tag = new LabelMetaData(APIDataType.Orders); lblTransactions.Tag = new LabelMetaData(APIDataType.Transactions); lblTransStatus.Tag =new LabelMetaData( APIDataType.Transactions); lblIndustryJobs.Tag = new LabelMetaData(APIDataType.IndustryJobs); lblIndustryJobsStatus.Tag = new LabelMetaData(APIDataType.IndustryJobs); lblAssets.MouseHover += new EventHandler(Label_MouseHover); lblAssetsStatus.MouseHover += new EventHandler(Label_MouseHover); lblJournal.MouseHover += new EventHandler(Label_MouseHover); lblJournalStatus.MouseHover += new EventHandler(Label_MouseHover); lblOrders.MouseHover += new EventHandler(Label_MouseHover); lblOrdersStatus.MouseHover += new EventHandler(Label_MouseHover); lblTransactions.MouseHover += new EventHandler(Label_MouseHover); lblTransStatus.MouseHover += new EventHandler(Label_MouseHover); lblIndustryJobs.MouseHover += new EventHandler(Label_MouseHover); lblIndustryJobsStatus.MouseHover += new EventHandler(Label_MouseHover); lblAssets.MouseLeave += new EventHandler(Label_MouseLeave); lblAssetsStatus.MouseLeave += new EventHandler(Label_MouseLeave); lblJournal.MouseLeave += new EventHandler(Label_MouseLeave); lblJournalStatus.MouseLeave += new EventHandler(Label_MouseLeave); lblOrders.MouseLeave += new EventHandler(Label_MouseLeave); lblOrdersStatus.MouseLeave += new EventHandler(Label_MouseLeave); lblTransactions.MouseLeave += new EventHandler(Label_MouseLeave); lblTransStatus.MouseLeave += new EventHandler(Label_MouseLeave); lblIndustryJobs.MouseLeave += new EventHandler(Label_MouseLeave); lblIndustryJobsStatus.MouseLeave += new EventHandler(Label_MouseLeave); // Removed this because it causes the update to run before the creating // proceedure has had a chance to attach it's event listeners.. //UpdateData(); }
public bool GetAutoUpdateFlag(CharOrCorp corc, APIDataType type) { bool retVal = false; switch (corc) { case CharOrCorp.Char: switch (type) { case APIDataType.Transactions: retVal = _autoUpdateCharTrans; break; case APIDataType.Journal: retVal = _autoUpdateCharJournal; break; case APIDataType.Assets: retVal = _autoUpdateCharAssets; break; case APIDataType.Orders: retVal = _autoUpdateCharOrders; break; case APIDataType.IndustryJobs: retVal = _autoUpdateCharIndustryJobs; break; default: break; } break; case CharOrCorp.Corp: switch (type) { case APIDataType.Transactions: retVal = _autoUpdateCorpTrans; break; case APIDataType.Journal: retVal = _autoUpdateCorpJournal; break; case APIDataType.Assets: retVal = _autoUpdateCorpAssets; break; case APIDataType.Orders: retVal = _autoUpdateCorpOrders; break; case APIDataType.IndustryJobs: retVal = _autoUpdateCorpIndustryJobs; break; default: break; } break; default: break; } return retVal; }
public APIUpdateInfo(CharOrCorp corc, APIDataType type) { Corc = corc; Type = type; }
public APICharacter(long userID, string apiKey, CharOrCorp accessType, long charID) { _userID = userID; _apiKey = apiKey; _charID = charID; _accessType = accessType; _apiSettings = new APISettingsAndStatus(_charID); if (accessType == CharOrCorp.Char) { try { RefreshCharXMLFromAPI(); } catch { } } else { try { RefreshCorpXMLFromAPI(); } catch { } } if (!Settings.UpdatedOwnerIDToCorpID) { UpdateOwnerIDToCorpID(); } }
public EMMADataSet.JournalRow BuildJournalEntry(EMMADataSet.JournalDataTable journalData, XmlNode journEntry, long IDOffset, short walletID, CharOrCorp corc) { EMMADataSet.JournalRow retVal = null; XmlNode entryIDNode = journEntry.SelectSingleNode("@refID"); long entryID = long.Parse(entryIDNode.Value, System.Globalization.CultureInfo.InvariantCulture.NumberFormat); // Actually create the line and add it to the data table retVal = journalData.NewJournalRow(); retVal.ID = entryID + IDOffset; retVal.Date = DateTime.Parse(journEntry.SelectSingleNode("@date").Value); retVal.TypeID = short.Parse(journEntry.SelectSingleNode("@refTypeID").Value, System.Globalization.CultureInfo.InvariantCulture.NumberFormat); retVal.SenderID = long.Parse(journEntry.SelectSingleNode("@ownerID1").Value, System.Globalization.CultureInfo.InvariantCulture.NumberFormat); retVal.RecieverID = long.Parse(journEntry.SelectSingleNode("@ownerID2").Value, System.Globalization.CultureInfo.InvariantCulture.NumberFormat); decimal amount = decimal.Parse(journEntry.SelectSingleNode("@amount").Value, System.Globalization.CultureInfo.InvariantCulture.NumberFormat); retVal.Amount = Math.Abs(amount); // Entries of type 42 (market escrow) do not have a reciever ID whene retrieved from the API. // ID 1000132 is the secure commerce commission. // If the sender is the secure commerce commission then the receiver must be the current // char/corp and vice versa. if (retVal.TypeID == 42 && retVal.RecieverID == 0) { if (retVal.SenderID == 1000132) { retVal.RecieverID = corc == CharOrCorp.Char ? _charID : _corpID; } else { retVal.RecieverID = 1000132; } } if (corc == CharOrCorp.Corp) { // This is a special case. // When bounty prizes are received by the player, corp tax is applied. // This corp tax does not appear as a seperate journal entry for the // character. It is specified by the taxReceiverID and taxAmount fields // on the bounty prize entry itself in the XML. // On the corp side, there is a specifc entry for the tax but it has // the same journalentryID and ownerID2 as the character entry. // This means that EMMA does not differentiate between them and the // corp tax part is lost. // In order to resolve this we simply set receiver ID to be the corp // instead of character and the sender to be the character instead // of concord. if (int.Parse(journEntry.SelectSingleNode("@refTypeID").Value) == 85) { retVal.SenderID = retVal.RecieverID; retVal.RecieverID = _corpID; } } if (amount < 0) { retVal.SBalance = decimal.Parse(journEntry.SelectSingleNode("@balance").Value, System.Globalization.CultureInfo.InvariantCulture.NumberFormat); retVal.SWalletID = walletID == 0 ? (short)1000 : walletID; retVal.SArgName = journEntry.SelectSingleNode("@argName1").Value; retVal.SArgID = long.Parse(journEntry.SelectSingleNode("@argID1").Value, System.Globalization.CultureInfo.InvariantCulture.NumberFormat); retVal.SCorpID = corc == CharOrCorp.Corp ? _corpID : 0; retVal.RBalance = 0; retVal.RWalletID = 0; retVal.RArgName = ""; retVal.RArgID = 0; retVal.RCorpID = 0; } else { retVal.RBalance = decimal.Parse(journEntry.SelectSingleNode("@balance").Value, System.Globalization.CultureInfo.InvariantCulture.NumberFormat); retVal.RWalletID = walletID == 0 ? (short)1000 : walletID; retVal.RArgName = journEntry.SelectSingleNode("@argName1").Value; retVal.RArgID = long.Parse(journEntry.SelectSingleNode("@argID1").Value, System.Globalization.CultureInfo.InvariantCulture.NumberFormat); retVal.RCorpID = corc == CharOrCorp.Corp ? _corpID : 0; retVal.SBalance = 0; retVal.SWalletID = 0; retVal.SArgName = ""; retVal.SArgID = 0; retVal.SCorpID = 0; } // Reason text can be longer than 50 chars so truncate it if needed... string reason = journEntry.SelectSingleNode("@reason").Value; retVal.Reason = (reason.Length > 50 ? reason.Remove(50) : reason); return retVal; }
/// <summary> /// Recursive method to update the supplied assets data table based upon the supplied xml node list. /// </summary> /// <param name="assetData"></param> /// <param name="assetList"></param> /// <param name="locationID"></param> /// <param name="corc"></param> /// <param name="containerID"></param> /// <param name="expectedChanges"></param> private void UpdateAssets(EMMADataSet.AssetsDataTable assetData, XmlNodeList assetList, long locationID, CharOrCorp corc, long containerID, AssetList changes) { int counter = 0; if (containerID == 0) { UpdateStatus(counter, assetList.Count, "Getting asset data from file", "", false); } else { UpdateStatus(-1, -1, "Getting asset data from file", "", false, counter, assetList.Count, "Container progress"); } foreach (XmlNode asset in assetList) { int itemID; long assetID = 0, eveInstanceID, quantity; bool isContainer = false, needNewRow = false; XmlNode locationNode = asset.SelectSingleNode("@locationID"); if (locationNode != null) { locationID = long.Parse(locationNode.Value); // Translate location ID from a corporate office to a station ID if required. if (locationID >= 66000000 && locationID < 67000000) { // NPC station. locationID -= 6000001; } if (locationID >= 67000000 && locationID < 68000000) { // Conquerable station. locationID -= 6000000; } } itemID = int.Parse(asset.SelectSingleNode("@typeID").Value, System.Globalization.CultureInfo.InvariantCulture.NumberFormat); eveInstanceID = long.Parse(asset.SelectSingleNode("@itemID").Value, System.Globalization.CultureInfo.InvariantCulture.NumberFormat); quantity = long.Parse(asset.SelectSingleNode("@quantity").Value, System.Globalization.CultureInfo.InvariantCulture.NumberFormat); if (asset.LastChild != null && asset.LastChild.Name.Equals("rowset")) { isContainer = true; } EMMADataSet.AssetsRow assetRow; needNewRow = true; // Note that if a match is not found for the specific eve instance ID we pass in then // EMMA will automatically search for an asset matching all the other parameters. if (Assets.AssetExists(assetData, corc == CharOrCorp.Corp ? _corpID : _charID, locationID, itemID, (int)AssetStatus.States.Normal, containerID != 0, containerID, isContainer, false, !isContainer, false, true, eveInstanceID, ref assetID)) { needNewRow = false; } else if(!isContainer) { // We havn't actually updated the database with anything yet so we may already have a // matching item stack in memory but not in the database. Check for that here. DataRow[] data = assetData.Select("ItemID = " + itemID + " AND OwnerID = " + _charID + " AND CorpAsset = " + (corc == CharOrCorp.Corp ? 1 : 0) + " AND LocationID = " + locationID + " AND Status = " + (int)AssetStatus.States.Normal + " AND ContainerID = " + containerID + " AND EveItemID = " + eveInstanceID); if (data != null && data.Length > 0) { needNewRow = false; assetID = ((EMMADataSet.AssetsRow)data[0]).ID; } } Asset change = null; if (!needNewRow) { assetRow = assetData.FindByID(assetID); if (assetRow.Processed) { // Row is already in the database but has been processed so just add the current // quantity to the row. // (i.e. there are multiple stacks of the same item in the same location in-game // EMMA merges these since we don't care how things are stacked and it makes // things a little easier.) assetRow.Quantity = assetRow.Quantity + quantity; // We're stacking multiple eve item instances so just set the eve item ID to zero. assetRow.EveItemID = 0; // Store the changes that are being made to the quantity of // items here. // This means that once the update processing is complete, we // can try and work out where these items came from. #region Remember changes to item quantities changes.ItemFilter = "ID = " + assetRow.ID; if (changes.FiltredItems.Count > 0) { change = (Asset)changes.FiltredItems[0]; change.Quantity += quantity; change.EveItemInstanceID = 0; if (change.Quantity == 0) { changes.ItemFilter = ""; changes.Remove(change); } } else { change = new Asset(assetRow); change.Quantity = quantity; change.Processed = false; changes.Add(change); } #endregion } else { if (assetRow.Quantity == quantity) { // The row already exists in the database and quantity is the same so // set the processed flag on the database directly and remove the row // from the dataset without setting it to be deleted when the database // is updated. // Note the processed flag MUST be set on the database for later routines // to work correctly. (e.g. Assets.ProcessSellOrders) if (assetRow.EveItemID != 0) { Assets.SetProcessedFlag(assetID, true); assetData.RemoveAssetsRow(assetRow); } else { // If Eve instance ID is not yet set then set it. Assets.SetProcessedFlag(assetID, true); assetRow.Processed = true; assetRow.EveItemID = eveInstanceID; } } else if (assetRow.Quantity != quantity) { // The row already exists in the database, has not yet been processed // and the quantity does not match what we've got from the XML. // Store the changes that are being made to the quantity of // items here. // This means that once the update processing is complete, we // can try and work out where these items came from. #region Remember changes to item quantities change = new Asset(assetRow); change.Quantity = quantity - assetRow.Quantity; change.EveItemInstanceID = eveInstanceID; change.Processed = false; changes.Add(change); #endregion // All we need to do is update the quantity and set the processed flag. assetRow.Quantity = quantity; assetRow.Processed = true; assetRow.EveItemID = eveInstanceID; // Also set the processed flag on the database directly. This will // stop us from picking up this row later on (e.g. Assets.ProcessSellOrders) Assets.SetProcessedFlag(assetID, true); } } } else { // The row does not currently exist in the database so we need to create it. assetRow = assetData.NewAssetsRow(); //assetRow.OwnerID = _charID; assetRow.OwnerID = corc == CharOrCorp.Corp ? _corpID : _charID; assetRow.CorpAsset = corc == CharOrCorp.Corp; assetRow.ItemID = itemID; assetRow.EveItemID = eveInstanceID; assetRow.LocationID = locationID; assetRow.Status = 1; assetRow.Processed = true; assetRow.AutoConExclude = false; assetRow.ReprocExclude = false; assetRow.Cost = 0; assetRow.CostCalc = false; assetRow.BoughtViaContract = false; long systemID = 0, regionID = 0; if (locationID >= 30000000 && locationID < 40000000) { systemID = locationID; EveDataSet.mapSolarSystemsRow system = SolarSystems.GetSystem(locationID); if (system != null) { regionID = system.regionID; } else { new EMMAEveAPIException(ExceptionSeverity.Warning, "Asset row added with unknown " + "solar system ID (" + locationID + ")"); } } else { EveDataSet.staStationsRow station = null; try { station = Stations.GetStation(locationID); } catch (EMMADataMissingException) { } if (station != null) { systemID = station.solarSystemID; regionID = station.regionID; } else { new EMMAEveAPIException(ExceptionSeverity.Warning, "Asset row added with unknown " + "station ID (" + locationID + ")"); } } assetRow.SystemID = systemID; assetRow.RegionID = regionID; assetRow.Quantity = quantity; assetRow.ContainerID = containerID; assetRow.IsContainer = isContainer; if (isContainer) { // If this asset is a container and has child assets then we must add it to the // database now and get the correct ID number. // (Because IDs are assigned by the database itself) assetID = Assets.AddRowToDatabase(assetRow); } else { // Otherwise, we can just add it to the data table to be stored later along with // everything else. assetData.AddAssetsRow(assetRow); } // Store the changes that are being made to the quantity of // items here. // This means that once the update processing is complete, we // can try and work out where these items came from. #region Remember changes to item quantities change = new Asset(assetRow); if (isContainer) { change.ID = assetID; } change.Quantity = quantity; change.Processed = false; changes.Add(change); #endregion } if (isContainer) { XmlNodeList contained = asset.SelectNodes("rowset/row"); UpdateAssets(assetData, contained, locationID, corc, assetID, changes); } counter++; if (containerID == 0) { UpdateStatus(counter, assetList.Count, "Getting asset data from file", "", false); } else { UpdateStatus(-1, -1, "Getting asset data from file", "", false, counter, assetList.Count, "Container progress"); } } }
public bool GetAPIAutoUpdate(CharOrCorp corc, APIDataType type) { GetGroupLevelCharSettings(); return _apiSettings.GetAutoUpdateFlag(corc, type); }
private void UpdateAssetsFromXML(CharOrCorp corc, XmlDocument xml) { DateTime earliestUpdate = GetLastAPIUpdateTime(corc, APIDataType.Assets).AddHours(23); EMMADataSet.AssetsDataTable assetData = new EMMADataSet.AssetsDataTable(); DateTime dataDate = DateTime.MinValue; try { XmlNodeList assetList = null; UpdateStatus(0, 1, "Getting asset data from file", "", false); dataDate = EveAPI.GetDataTime(xml); DateTime assetsEffectiveDate = corc == CharOrCorp.Char ? Settings.CharAssetsEffectiveDate : Settings.CorpAssetsEffectiveDate; if (dataDate.CompareTo(assetsEffectiveDate) < 0) { UpdateStatus(1, 1, "Error", "This data in this file is from " + dataDate.ToString() + ". EMMA has already imported asset data dated " + assetsEffectiveDate + " therefore the" + " database will not be updated.", true); assetList = null; } else { assetList = EveAPI.GetResults(xml); UpdateStatus(1, 1, "", assetList.Count + " asset data lines found.", false); } if (assetList != null) { // Set the 'processed' flag to false for all of this char/corp's assets. Assets.SetProcessedFlag(corc == CharOrCorp.Corp ? _corpID : _charID, (int)AssetStatus.States.Normal, false); Assets.SetProcessedFlag(corc == CharOrCorp.Corp ? _corpID : _charID, (int)AssetStatus.States.ForSaleViaMarket, false); Assets.SetProcessedFlag(corc == CharOrCorp.Corp ? _corpID : _charID, (int)AssetStatus.States.ForSaleViaContract, false); Assets.SetProcessedFlag(corc == CharOrCorp.Corp ? _corpID : _charID, (int)AssetStatus.States.InTransit, false); AssetList changes = new AssetList(); // Create an in-memory datatable with all of the changes required to the assets // database in order to reflect the data in the xml file. UpdateAssets(assetData, assetList, 0, corc, 0, changes); // Use the currently active sell order to account for assets that appear to be // missing. UpdateStatus(0, 0, "Processing active sell orders", "", false); Assets.ProcessSellOrders(assetData, changes, corc == CharOrCorp.Corp ? _corpID : _charID); UpdateStatus(0, 0, "", "Complete", false); // Use transactions that occured after the effective date of the asset data file // to ensure that the asset list is as up-to-date as possible. UpdateStatus(0, 0, "Updating assets from transactions that occur after " + "the asset file's effective date", "", false); long maxID = Assets.UpdateFromTransactions(assetData, changes, _charID, _corpID, corc == CharOrCorp.Corp, dataDate); if (corc == CharOrCorp.Char) { Settings.CharAssetsTransUpdateID = maxID; } else { Settings.CorpAssetsTransUpdateID = maxID; } UpdateStatus(0, 0, "", "Complete", false); AssetList gained = new AssetList(); AssetList lost = new AssetList(); if ((corc == CharOrCorp.Char && Settings.FirstUpdateDoneAssetsChar) || (corc == CharOrCorp.Corp && Settings.FirstUpdateDoneAssetsCorp)) { UpdateStatus(0, 0, "Analysing changes to assets", "", false); Assets.AnalyseChanges(assetData, corc == CharOrCorp.Corp ? _corpID : _charID, changes, out gained, out lost); UpdateStatus(0, 0, "", "Complete", false); } // If this is the first assets update then we want to try and assign sensible cost // values to assets that we have not yet got a value for. if ((corc == CharOrCorp.Char && !Settings.FirstUpdateDoneAssetsChar) || (corc == CharOrCorp.Corp && !Settings.FirstUpdateDoneAssetsCorp)) { Assets.AssignApproxCosts(assetData, corc == CharOrCorp.Corp ? _corpID : _charID); } if (corc == CharOrCorp.Char) { _unacknowledgedGains = gained; _unacknowledgedLosses = lost; } else { _corpUnacknowledgedGains = gained; _corpUnacknowledgedLosses = lost; } UpdateStatus(0, 0, "Updating assets database", "", false); Assets.UpdateDatabase(assetData); UpdateStatus(0, 0, "", "Complete", false); // Set all 'for sale via contract' and 'in transit' assets in the database to processed. // These types of assets would not be expected to show up in either the XML from the // API or the list of current market orders. // Any assets of these types that have been moved to a different state (e.g. in transit // items that have arrived or contracts that have expired) will have been updated already // in this method or ProcessSellOrders. // Therefore, the ones that are left are still in the same situation as before. // i.e. either 'for sale via contract' or 'in transit'. // We set them to processed to prevent them from being removed along with other // unprocessed assets. Assets.SetProcessedFlag(corc == CharOrCorp.Corp ? _corpID : _charID, (int)AssetStatus.States.ForSaleViaContract, true); Assets.SetProcessedFlag(corc == CharOrCorp.Corp ? _corpID : _charID, (int)AssetStatus.States.InTransit, true); // Clear any remaining assets that have not been processed. Assets.ClearUnProcessed(corc == CharOrCorp.Corp ? _corpID : _charID, false); Assets.SetProcessedFlag(corc == CharOrCorp.Corp ? _corpID : _charID, 0, false); UpdateStatus(0, 0, assetData.Count + " asset database entries modified.", "", false); // Update the assets effective date setting. // Also set the 'FirstUpdateDone' flag if (corc == CharOrCorp.Char) { Settings.CharAssetsEffectiveDate = dataDate; Settings.FirstUpdateDoneAssetsChar = true; } else { Settings.CorpAssetsEffectiveDate = dataDate; if (!Settings.FirstUpdateDoneAssetsCorp) { Settings.FirstUpdateDoneAssetsCorp = true; foreach (EVEAccount account in UserAccount.CurrentGroup.Accounts) { foreach (APICharacter character in account.Chars) { if (character.CharID != _charID && character.CorpID == _corpID) { Settings.FirstUpdateDoneAssetsCorp = true; } } } } } UpdateStatus(1, 1, "", "Complete", true); } } catch (Exception ex) { EMMAException emmaEx = ex as EMMAException; if (emmaEx == null) { // If we've caught a standard exception rather than an EMMA one then log it be creating a // new exception. // Note that we don't need to actually throw it.. emmaEx = new EMMAException(ExceptionSeverity.Error, "Error when processing assets data", ex); } UpdateStatus(-1, -1, "Error", ex.Message, true); SetLastAPIUpdateError(corc, APIDataType.Assets, ex.Message); } if (UpdateEvent != null) { if (_unacknowledgedLosses == null) { _unacknowledgedLosses = new AssetList(); } if (_unacknowledgedGains == null) { _unacknowledgedGains = new AssetList(); } if (_corpUnacknowledgedLosses == null) { _corpUnacknowledgedLosses = new AssetList(); } if (_corpUnacknowledgedGains == null) { _corpUnacknowledgedGains = new AssetList(); } if ((corc == CharOrCorp.Char && _unacknowledgedLosses.Count + _unacknowledgedGains.Count == 0) || (corc == CharOrCorp.Corp && _corpUnacknowledgedGains.Count + _corpUnacknowledgedLosses.Count == 0)) { UpdateEvent(this, new APIUpdateEventArgs(APIDataType.Assets, corc == CharOrCorp.Char ? _charID : _corpID, APIUpdateEventType.UpdateCompleted)); } else { SetLastAPIUpdateError(corc, APIDataType.Assets, "AWAITING ACKNOWLEDGEMENT"); UpdateEvent(this, new APIUpdateEventArgs(APIDataType.Assets, corc == CharOrCorp.Char ? _charID : _corpID, APIUpdateEventType.AssetsAwaitingAcknowledgement)); } } }
public string GetLastAPIUpdateError(CharOrCorp corc, APIDataType type) { return _apiSettings.GetLastUpdateError(corc, type); }
private void UpdateIndustryJobsFromXML(CharOrCorp corc, XmlDocument fileXML) { EMMADataSet.IndustryJobsDataTable jobsData = new EMMADataSet.IndustryJobsDataTable(); try { XmlNodeList jobEntries = null; UpdateStatus(0, 1, "Getting industry jobs from file", "", false); jobEntries = EveAPI.GetResults(fileXML); UpdateStatus(1, 1, "", jobEntries.Count + " industry jobs found in file.", false); if (jobEntries != null && jobEntries.Count > 0) { UpdateStatus(0, jobEntries.Count, "Processing jobs", "", false); foreach (XmlNode jobEntry in jobEntries) { EMMADataSet.IndustryJobsRow jobRow = BuildIndustryJobRow(jobsData, jobEntry); if (IndustryJobs.GetJob(jobsData, jobRow.ID)) { // The job already exists in the database. Update if needed. EMMADataSet.IndustryJobsRow oldJobRow = jobsData.FindByID(jobRow.ID); if (oldJobRow.Completed != jobRow.Completed || oldJobRow.CompletedStatus != jobRow.CompletedStatus || oldJobRow.CompletedSuccessfully != jobRow.CompletedSuccessfully || oldJobRow.EndProductionTime.CompareTo(jobRow.EndProductionTime) != 0 || oldJobRow.PauseProductionTime.CompareTo(jobRow.PauseProductionTime) != 0) { oldJobRow.Completed = jobRow.Completed; oldJobRow.CompletedStatus = jobRow.CompletedStatus; oldJobRow.CompletedSuccessfully = jobRow.CompletedSuccessfully; oldJobRow.EndProductionTime = jobRow.EndProductionTime; oldJobRow.PauseProductionTime = jobRow.PauseProductionTime; } else { // No changes } } else { // This is a new job. Add it to the database. jobsData.AddIndustryJobsRow(jobRow); } } } if (jobsData != null && jobsData.Count > 0) { IndustryJobs.Store(jobsData); } } catch (Exception ex) { EMMAException emmaEx = ex as EMMAException; if (emmaEx == null) { // If we've caught a standard exception rather than an EMMA one then log it by creating a // new exception. // Note that we don't need to actually throw it.. emmaEx = new EMMAException(ExceptionSeverity.Error, "Error when adding industry jobs", ex); } SetLastAPIUpdateError(corc, APIDataType.IndustryJobs, ex.Message); UpdateStatus(-1, 0, "Error", ex.Message, true); } if (UpdateEvent != null) { UpdateEvent(this, new APIUpdateEventArgs(APIDataType.IndustryJobs, corc == CharOrCorp.Char ? _charID : _corpID, APIUpdateEventType.UpdateCompleted)); } }
public void ProcessOrdersXML(XmlDocument fileXml, CharOrCorp corc) { DataImportParams parameters = new DataImportParams(); parameters.xmlData = fileXml; parameters.corc = corc; parameters.walletID = 0; ThreadPool.QueueUserWorkItem(UpdateOrdersFromXML, parameters); }
/// <summary> /// Add journal entries from the supplied XML to the database. /// </summary> /// <param name="corc"></param> /// <param name="fileXML"></param> /// <returns>The number of rows added to the journal table.</returns> private int UpdateJournalFromXML(CharOrCorp corc, XmlDocument fileXML, short walletID) { int retVal = 0; int updatedEntries = 0; EMMADataSet.JournalDataTable journalData = new EMMADataSet.JournalDataTable(); long highestIDSoFar = _apiSettings.GetHighestID(corc, APIDataType.Journal); long oldHighestID = _apiSettings.GetHighestID(corc, APIDataType.Journal); DateTime dataDate = DateTime.UtcNow; try { XmlNodeList journEntries = null; XmlDocument xml = new XmlDocument(); UpdateStatus(0, 1, "Getting journal entries from file", "", false); journEntries = EveAPI.GetResults(fileXML); dataDate = EveAPI.GetDataTime(fileXML); UpdateStatus(1, 1, "", journEntries.Count + " entries found in file.", false); if (journEntries != null && journEntries.Count > 0) { // Offset will always be the same since CCP switched over to 64 bit IDs // (At least until we break the 64bit limit... As of mid 2010, we're using // around 2 billion IDs a year so breaking the 64 bit limit will take around // 9 billion years... Don't think it will be a problem :)) long offset = 2591720933; int batchPrg = 0; UpdateStatus(0, journEntries.Count, "Processing entries", "", false); // Loop through the results returned from this call to the API and add the line // to the data table. foreach (XmlNode journEntry in journEntries) { bool tryUpdate = false; long id = long.Parse(journEntry.SelectSingleNode("@refID").Value) + offset; long recieverID = 0; if (corc == CharOrCorp.Corp) { // This is a special case. // When bounty prizes are received by the player, corp tax is applied. // This corp tax does not appear as a seperate journal entry for the // character. It is specified by the taxReceiverID and taxAmount fields // on the bounty prize entry itself in the XML. // On the corp side, there is a specifc entry for the tax but it has // the same journalentryID and ownerID2 as the character entry. // This means that EMMA does not differentiate between them and the // corp tax part is lost. // In order to resolve this we simply set receiver ID to be the corp // instead of character in these cases. // Note that 'BuildJournalEntry' has similar processing. if (int.Parse(journEntry.SelectSingleNode("@refTypeID").Value) == 85) { recieverID = _corpID; } } if (recieverID == 0) { recieverID = long.Parse(journEntry.SelectSingleNode("@ownerID2").Value); } //if (id - offset > oldHighestID) //{ if (id - offset > highestIDSoFar) { highestIDSoFar = id - offset; } if (Journal.EntryExists(journalData, id, recieverID)) { tryUpdate = true; } else { EMMADataSet.JournalRow tmpRow = journalData.FindByIDRecieverID(id, recieverID); if (tmpRow == null) { EMMADataSet.JournalRow newRow = BuildJournalEntry(journalData, journEntry, offset, walletID, corc); journalData.AddJournalRow(newRow); retVal++; // This section searches the character and journal ref type tables // for the values used in this new journal entry. // If they are not present in the tables then they are added. #region Check other tables and add values if needed. SortedList<long, string> entityIDs = new SortedList<long, string>(); entityIDs.Add(newRow.SenderID, journEntry.SelectSingleNode("@ownerName1").Value); if (!entityIDs.ContainsKey(newRow.RecieverID)) { entityIDs.Add(newRow.RecieverID, journEntry.SelectSingleNode("@ownerName2").Value); } foreach (KeyValuePair<long, string> checkName in entityIDs) { Names.AddName(checkName.Key, checkName.Value); } #endregion } else { tryUpdate = true; } } if (tryUpdate) { EMMADataSet.JournalRow newRow = BuildJournalEntry(journalData, journEntry, offset, walletID, corc); EMMADataSet.JournalRow oldRow = journalData.FindByIDRecieverID(newRow.ID, newRow.RecieverID); bool updated = false; if (oldRow != null) { if ((newRow.RBalance > 0 && oldRow.RBalance == 0) || (newRow.RCorpID != 0 && oldRow.RCorpID == 0)) { oldRow.RBalance = newRow.RBalance; oldRow.RCorpID = newRow.RCorpID; oldRow.RArgID = newRow.RArgID; oldRow.RArgName = newRow.RArgName; oldRow.RWalletID = newRow.RWalletID; updated = true; } if ((newRow.SBalance > 0 && oldRow.SBalance == 0) || (newRow.SCorpID != 0 && oldRow.SCorpID == 0)) { oldRow.SBalance = newRow.SBalance; oldRow.SCorpID = newRow.SCorpID; oldRow.SArgID = newRow.SArgID; oldRow.SArgName = newRow.SArgName; oldRow.SWalletID = newRow.SWalletID; updated = true; } } if (updated) { updatedEntries++; } } //} batchPrg++; UpdateStatus(batchPrg, journEntries.Count, "", "", false); } SetHighestID(corc, APIDataType.Journal, highestIDSoFar); } UpdateStatus(0, 0, retVal + " journal entries added to database.", "", false); UpdateStatus(0, 0, updatedEntries + " existing journal entries updated.", "", true); if (journalData.Count > 0) { Journal.Store(journalData); } } catch (Exception ex) { EMMAException emmaEx = ex as EMMAException; if (emmaEx == null) { // If we've caught a standard exception rather than an EMMA one then log // it by creating a new exception. // Note that we don't need to actually throw it.. emmaEx = new EMMAException(ExceptionSeverity.Error, "Error when adding journal data", ex); } SetLastAPIUpdateError(corc, APIDataType.Journal, ex.Message); UpdateStatus(-1, 0, "Error", ex.Message, true); } if (UpdateEvent != null) { UpdateEvent(this, new APIUpdateEventArgs(APIDataType.Journal, corc == CharOrCorp.Char ? _charID : _corpID, APIUpdateEventType.UpdateCompleted)); } return retVal; }
public void SetAPIAutoUpdate(CharOrCorp corc, APIDataType type, bool auto) { _apiSettings.SetAutoUpdateFlag(corc, type, auto); StoreGroupLevelSettings(corc == CharOrCorp.Char ? SettingsStoreType.Char : SettingsStoreType.Corp); }
private void UpdateOrdersFromXML(CharOrCorp corc, XmlDocument fileXML) { EMMADataSet.OrdersDataTable orderData = new EMMADataSet.OrdersDataTable(); int added = 0; int updated = 0; try { Orders.SetProcessed(corc == CharOrCorp.Corp ? _corpID : _charID, false); XmlNodeList orderEntries = null; XmlDocument xml = new XmlDocument(); UpdateStatus(0, 1, "Getting orders from file", "", false); orderEntries = EveAPI.GetResults(fileXML); UpdateStatus(1, 1, "", orderEntries.Count + " orders found in file.", false); if (orderEntries != null && orderEntries.Count > 0) { UpdateStatus(0, orderEntries.Count, "Processing orders", "", false); foreach (XmlNode orderEntry in orderEntries) { EMMADataSet.OrdersRow orderRow = BuildOrdersRow(orderData, orderEntry, corc); int id = 0; if (!Orders.Exists(orderData, orderRow, ref id, _corpID, _charID)) { // Order does not exist in the database so add it. orderData.AddOrdersRow(orderRow); if (orderRow.OrderState == (short)OrderState.ExpiredOrFilled) { bool notify = false; notify = UserAccount.CurrentGroup.Settings.OrdersNotifyEnabled && ((UserAccount.CurrentGroup.Settings.OrdersNotifyBuy && orderRow.BuyOrder) || (UserAccount.CurrentGroup.Settings.OrdersNotifySell && !orderRow.BuyOrder)); if (notify) { orderRow.OrderState = (short)OrderState.ExpiredOrFilledAndUnacknowledged; } else { orderRow.OrderState = (short)OrderState.ExpiredOrFilledAndAcknowledged; } } added++; } else { EMMADataSet.OrdersRow oldRow = orderData.FindByID(id); if (oldRow.TotalVol == orderRow.TotalVol && oldRow.RemainingVol == orderRow.RemainingVol && oldRow.MinVolume == orderRow.MinVolume && oldRow.Range == orderRow.Range && oldRow.Duration == orderRow.Duration && oldRow.Escrow == orderRow.Escrow && oldRow.Price == orderRow.Price && oldRow.OrderState == orderRow.OrderState && oldRow.EveOrderID == orderRow.EveOrderID) { // If the order from the XML exactly matches what we have in the database // then just set the processed flag and remove it from the orderData table // without setting it to be removed from the database. //Orders.SetProcessedByID(oldRow.ID, true); orderData.RemoveOrdersRow(oldRow); } else { // Set the row to processed right now. oldRow.Processed = true; // Accept the changes to the row (will only be the processed flag at // this point) and set the processed flag on the database. // This will prevent the row from being double matched with another // order later. // The 'accept changes' will prevent the concurency error that we // would get if we only updated the processed flag on the database // side. oldRow.AcceptChanges(); //Orders.SetProcessedByID(oldRow.ID, true); // If the order was active and is now completed/expired then flag it for // the unacknowledged orders viewer to display. bool notify = false; notify = UserAccount.CurrentGroup.Settings.OrdersNotifyEnabled && ((UserAccount.CurrentGroup.Settings.OrdersNotifyBuy && orderRow.BuyOrder) || (UserAccount.CurrentGroup.Settings.OrdersNotifySell && !orderRow.BuyOrder)); if (/*orderRow.RemainingVol == 0 &&*/ orderRow.OrderState == (short)OrderState.ExpiredOrFilled && (oldRow.OrderState == (short)OrderState.Active || oldRow.OrderState == (short)OrderState.ExpiredOrFilled)) { if (notify) { oldRow.OrderState = (short)OrderState.ExpiredOrFilledAndUnacknowledged; // No longer needed as the unacknowledged orders form is displayed/refreshed // as needed when refreshing the main form after an update is complete. //if (UpdateEvent != null) //{ // UpdateEvent(this, new APIUpdateEventArgs(APIDataType.Orders, // corc == CharOrCorp.Corp ? _corpID : _charID, // APIUpdateEventType.OrderHasExpiredOrCompleted)); //} } else { oldRow.OrderState = (short)OrderState.ExpiredOrFilledAndAcknowledged; } } else if (orderRow.OrderState != (short)OrderState.ExpiredOrFilled) { oldRow.OrderState = orderRow.OrderState; } if (oldRow.TotalVol != orderRow.TotalVol || oldRow.RemainingVol != orderRow.RemainingVol || oldRow.MinVolume != orderRow.MinVolume || oldRow.Range != orderRow.Range || oldRow.Duration != orderRow.Duration || oldRow.Escrow != orderRow.Escrow || oldRow.Price != orderRow.Price || oldRow.EveOrderID != orderRow.EveOrderID) { oldRow.TotalVol = orderRow.TotalVol; oldRow.RemainingVol = orderRow.RemainingVol; oldRow.MinVolume = orderRow.MinVolume; oldRow.Range = orderRow.Range; oldRow.Duration = orderRow.Duration; oldRow.Escrow = orderRow.Escrow; oldRow.Price = orderRow.Price; oldRow.EveOrderID = orderRow.EveOrderID; // Note, only other fields are 'buyOrder' and 'issued'. Neither of which we want to change. updated++; } } } UpdateStatus(added + updated, orderEntries.Count, "", "", false); } } UpdateStatus(0, 0, added + " orders added to database.", "", false); UpdateStatus(0, 0, updated + " orders updated.", "", true); if (orderData.Count > 0) { Orders.Store(orderData); } Orders.FinishUnProcessed(corc == CharOrCorp.Corp ? _corpID : _charID); } catch (Exception ex) { EMMAException emmaEx = ex as EMMAException; if (emmaEx == null) { // If we've caught a standard exception rather than an EMMA one then log it by creating a // new exception. // Note that we don't need to actually throw it.. emmaEx = new EMMAException(ExceptionSeverity.Error, "Error when adding market orders", ex); } SetLastAPIUpdateError(corc, APIDataType.Orders, ex.Message); UpdateStatus(-1, 0, "Error", ex.Message, true); } if (UpdateEvent != null) { UpdateEvent(this, new APIUpdateEventArgs(APIDataType.Orders, corc == CharOrCorp.Char ? _charID : _corpID, APIUpdateEventType.UpdateCompleted)); } }
public void SetLastAPIUpdateError(CharOrCorp corc, APIDataType type, string error) { _apiSettings.SetLastUpdateError(corc, type, error); }
/// <summary> /// Update the database transactions table from the specified XML. /// </summary> /// <param name="corc"></param> /// <param name="fileXML"></param> /// <returns></returns> private int UpdateTransactionsFromXML(CharOrCorp corc, XmlDocument fileXML, short walletID) { int retVal = 0; EMMADataSet.TransactionsDataTable transData = new EMMADataSet.TransactionsDataTable(); long highestIDSoFar = _apiSettings.GetHighestID(corc, APIDataType.Transactions); long highestID = 0; DateTime ticker = DateTime.UtcNow.AddSeconds(-10); try { int updated = 0; XmlNodeList transEntries = null; XmlDocument xml = new XmlDocument(); UpdateStatus(0, 1, "Getting transactions from file", "", false); transEntries = EveAPI.GetResults(fileXML); UpdateStatus(1, 1, "", transEntries.Count + " entries found in file.", false); if (transEntries != null && transEntries.Count > 0) { int batchPrg = 0; UpdateStatus(0, transEntries.Count, "Processing transactions", "", false); XmlNode entryIDNode = transEntries[0].SelectSingleNode("@transactionID"); //long fileMaxID = long.Parse(entryIDNode.Value, // System.Globalization.CultureInfo.InvariantCulture.NumberFormat); // Loop through the results returned from this call to the API and add the line to // the data table if the transactionID is not already in the database. foreach (XmlNode transEntry in transEntries) { XmlNode transIDNode = transEntry.SelectSingleNode("@transactionID"); long transID = long.Parse(transIDNode.Value, System.Globalization.CultureInfo.InvariantCulture.NumberFormat); if (transID > highestID) { highestID = transID; } //if (transID > highestIDSoFar) //{ if (!Transactions.TransactionExists(transData, transID) && transData.FindByID(transID) == null) { // Actually create the line and add it to the data table SortedList<long, string> nameIDs = new SortedList<long, string>(); EMMADataSet.TransactionsRow newRow = BuildTransRow(transID, transData, transEntry, walletID, nameIDs, false); transData.AddTransactionsRow(newRow); retVal++; // This section searches the character, item and station ref type tables // for the values used in this new transaction entry. // If they are not present in the table then they are added. #region Check other tables and add values if needed. foreach (KeyValuePair<long, string> checkName in nameIDs) { Names.AddName(checkName.Key, checkName.Value); } Items.AddItem(newRow.ItemID, transEntry.SelectSingleNode("@typeName").Value); #endregion } else { SortedList<long, string> nameIDs = new SortedList<long, string>(); // We've got a transaction that already exists in the database, // update the row with additional data if available. EMMADataSet.TransactionsRow newRow = BuildTransRow(transID, transData, transEntry, walletID, nameIDs, true); EMMADataSet.TransactionsRow oldRow = transData.FindByID(transID); bool updateDone = false; if (newRow.BuyerWalletID != oldRow.BuyerWalletID && newRow.BuyerWalletID != 0) { oldRow.BuyerWalletID = newRow.BuyerWalletID; updateDone = true; } if (newRow.SellerWalletID != oldRow.SellerWalletID && newRow.SellerWalletID != 0) { oldRow.SellerWalletID = newRow.SellerWalletID; updateDone = true; } // If a corp sells somthing to another corp (or itself) then we will get into // the position of having the other party set as a character when in fact // it is that character's corp. // We check for this here and correct it if required. if (oldRow.BuyerID == _charID && newRow.BuyerID == _corpID) { oldRow.BuyerID = newRow.BuyerID; oldRow.BuyerCharacterID = newRow.BuyerCharacterID; oldRow.BuyerWalletID = newRow.BuyerWalletID; oldRow.BuyerForCorp = newRow.BuyerForCorp; updateDone = true; } if (oldRow.SellerID == _charID && newRow.SellerID == _corpID) { oldRow.SellerID = newRow.SellerID; oldRow.SellerCharacterID = newRow.SellerCharacterID; oldRow.SellerWalletID = newRow.SellerWalletID; oldRow.SellerForCorp = newRow.SellerForCorp; updateDone = true; } if (updateDone) { updated++; } } //} batchPrg++; UpdateStatus(batchPrg, transEntries.Count, "", "", false); } } if (highestID > highestIDSoFar) { SetHighestID(corc, APIDataType.Transactions, highestID); } UpdateStatus(0, 0, retVal + " transactions added to database.", "", false); UpdateStatus(0, 0, updated + " transactions updated.", "", false); if (transData.Count > 0) { Transactions.Store(transData); UpdateStatus(1, 1, "", "Complete", true); } } catch (Exception ex) { EMMAException emmaEx = ex as EMMAException; if (emmaEx == null) { // If we've caught a standard exception rather than an EMMA one then log it be creating a // new exception. // Note that we don't need to actually throw it.. emmaEx = new EMMAException(ExceptionSeverity.Error, "Error when adding transactions", ex); } SetLastAPIUpdateError(corc, APIDataType.Transactions, ex.Message); UpdateStatus(-1, 0, "Error", ex.Message, true); } if (UpdateEvent != null) { UpdateEvent(this, new APIUpdateEventArgs(APIDataType.Transactions, corc == CharOrCorp.Char ? _charID : _corpID, APIUpdateEventType.UpdateCompleted)); } return retVal; }
/// <summary> /// Update standings for this character or corporation with the latest from the Eve API /// </summary> /// <param name="corc"></param> public void UpdateStandings(CharOrCorp corc) { long id = (corc == CharOrCorp.Char ? _charID : _corpID); XmlDocument xml = EveAPI.GetXml(EveAPI.URL_EveApiHTTPS + (corc == CharOrCorp.Corp ? EveAPI.URL_CorpStandingsApi : EveAPI.URL_CharStandingsApi), "keyID=" + _userID + "&vCode=" + _apiKey + "&characterID=" + _charID); // Standings xml does not have the normal format so can't use EveAPI.GetResults... if (xml != null) { // First check if we've been returned an error. XmlNode errorNode = xml.SelectSingleNode("/eveapi/error"); if (errorNode != null) { string file = string.Format("{0}Logging{1}APIError.xml", Globals.AppDataDir, Path.DirectorySeparatorChar); lock (Globals.APIErrorFileLock) { xml.Save(file); } XmlNode errCodeNode = errorNode.SelectSingleNode("@code"); XmlNode errTextNode = errorNode.FirstChild; throw new EMMAEveAPIException(ExceptionSeverity.Error, int.Parse(errCodeNode.Value), errTextNode.Value); } // If there is no error then clear current standings, get the data we need // and update with the new standings as we go along. Standings.ClearStandings(id, 0); Standings.ClearStandings(0, id); XmlNodeList xmlNodes = null; // First we do standings set by this char/corp towards others... xmlNodes = xml.SelectNodes("/eveapi/result/standingsTo/rowset/row"); foreach (XmlNode node in xmlNodes) { long toID = long.Parse(node.Attributes.GetNamedItem("toID").Value); string toName = node.Attributes.GetNamedItem("toName").Value; decimal standing = decimal.Parse(node.Attributes.GetNamedItem("standing").Value, System.Globalization.CultureInfo.InvariantCulture.NumberFormat) * 10; if (standing > 10) { standing = 10; } if (standing < -10) { standing = -10; } Names.AddName(toID, toName); Standings.SetStanding(toID, id, standing); } // ...then standings set by others towrds this char/corp xmlNodes = xml.SelectNodes("/eveapi/result/standingsFrom/rowset/row"); foreach (XmlNode node in xmlNodes) { long fromID = long.Parse(node.Attributes.GetNamedItem("fromID").Value); string fromName = node.Attributes.GetNamedItem("fromName").Value; decimal standing = decimal.Parse(node.Attributes.GetNamedItem("standing").Value, System.Globalization.CultureInfo.InvariantCulture.NumberFormat); //* 10; if (standing > 10) { standing = 10; } if (standing < -10) { standing = -10; } Names.AddName(fromID, fromName); Standings.SetStanding(id, fromID, standing); } } else { throw new EMMAEveAPIException(ExceptionSeverity.Critical, "No XML document to process"); } }
public void SetLastUpdateError(CharOrCorp corc, APIDataType type, string error) { switch (corc) { case CharOrCorp.Char: switch (type) { case APIDataType.Transactions: _lastCharTransUpdateError = error; break; case APIDataType.Journal: _lastCharJournalUpdateError = error; break; case APIDataType.Assets: _lastCharAssetsUpdateError = error; break; case APIDataType.Orders: _lastCharOrdersUpdateError = error; break; case APIDataType.IndustryJobs: _lastCharIndustryJobsUpdateError = error; break; default: break; } break; case CharOrCorp.Corp: switch (type) { case APIDataType.Transactions: _lastCorpTransUpdateError = error; break; case APIDataType.Journal: _lastCorpJournalUpdateError = error; break; case APIDataType.Assets: _lastCorpAssetsUpdateError = error; break; case APIDataType.Orders: _lastCorpOrdersUpdateError = error; break; case APIDataType.IndustryJobs: _lastCorpIndustryJobsUpdateError = error; break; default: break; } break; default: break; } }