if else conditions not checking properly in c#? - c#

I am coming to a problem where I am checking if some of the elements key values are valid in order to proceed with the QR code scanning. For example: If my Active attribute is true, and completed is false and the schedule time is current time +- 30 minutes of start window then proceed with the scanning. If not, let me show them an error. I tried implementing the checking part with a simple if - but only checking the active, and completed key values. Can anyone check and help me solve this issue. thanks for the help.
here is my code:
public void ScanQrCode()
{
BarcodeScanner.Scan(async (barCodeType, barCodeValue) =>
{
BarcodeScanner.Stop();
var results = JsonConvert.DeserializeObject<dynamic>(barCodeValue);
var gettingTheName = (string) results.Evaluation.Value;
TextHeader.text = gettingTheName;
var qrCodeString = $"***************.firebaseio.com/Evaluations/.json?orderBy=\"$key\"&startAt=\"{gettingTheName}\"&limitToFirst=1";
Debug.Log(barCodeValue);
var qrCodeObj = JsonConvert.DeserializeObject<dynamic>(qrCodeString);
try
{
bool parseSuccessful = DateTime.TryParse("ScheduleStartTime", out var scheduledStartTime);
if (results.Contains("Active").Equals(true) &&
results.Contains("Completed").Equals(false) &&
DateTime.Now < scheduledStartTime.AddMinutes(30) &&
DateTime.Now > scheduledStartTime.AddMinutes(-30)) {
var matchingLink = new WebClient().DownloadString(qrCodeString);
var obj = Newtonsoft.Json.JsonConvert.DeserializeObject<JObject>(matchingLink);
var candidateId = obj.First.First["CandiateID"].ToString();
string page = $"https://***********.firebaseio.com/Candidates/.json?orderBy=\"$key\"&startAt=\"{candidateId}\"&limitToFirst=1";
using (HttpClient client = new HttpClient())
using (HttpResponseMessage response = await client.GetAsync(page))
using (HttpContent content = response.Content)
{
// Reading the string.
Dictionary<string, Candidates> evaluationDictionary = new Dictionary<string, Candidates>();
string result = await content.ReadAsStringAsync();
evaluationDictionary = JsonConvert.DeserializeObject<Dictionary<string, Candidates>>(result);
Debug.Log(evaluationDictionary);
foreach (Candidates candidates in evaluationDictionary.Values)
{
string evaluationMessage = candidates.FirstName + " " + candidates.LastName;
candidateMessage = GetComponent<Text>();
candidateMessage.text = evaluationMessage;
}
// Getting a reference to the text component.
candidateMessage = GetComponent<Text>();
candidateMessage.text = matchingLink.ToString();
candidateMessage.text = matchingLink.Trim(new char[] {'"'});
}
}
else
{
EditorUtility.DisplayDialog("Incorrect credentials", "Please scan a valid QR code", "OK");
}
}
catch (Exception e)
{
Console.WriteLine(e);
SceneManager.LoadScene("Verify");
throw;
}
});
}
}
JSON:
{
"Active": true,
"Completed": false,
"ScheduleStartTime": "2019-12-16T20:10:57.649418-08:00"
}

Yeah. I was kind of stuck on that part too. I tried doing it by adding
&& qrCodeString.Contains("ScheduleStartTime").Equals(I GOT STUCK IN
HERE)
I'd accomplish this portion by parsing the date string to a DateTime object, then comparing the current time with your new DateTime shifted in both directions.
I might do something like this:
try {
bool parseSuccessful = DateTime.TryParse( ScheduledStartTimeFromJSON, out var scheduledStartTime );
if ( qrCodeString.Contains( "Active" ).Equals( true ) &&
qrCodeString.Contains( "CompletedMessage" ).Equals( false ) &&
DateTime.Now < scheduledStartTime.AddMinutes(30) &&
DateTime.Now > scheduledStartTime.AddMinutes( -30 ) ) {
var matchingLink = new WebClient().DownloadString( qrCodeString );
...
}
}
You should also check to make sure the date was parsed successfully before comparing it to anything.

According to your JSON example:
First i think you should check for Completed value insted of CompletedMessage.
Secound with this code qrCodeString.Contains("Active").Equals(true) you are just checking if Active is contained in the string. I think you should be looking for the value of it.
In my vision the right way to do the check you need is to first deserialize the JSON like this
var qrCodeObj = JsonConvert.DeserializeObject<dynamic>(qrCodeString);
And then check for the respectives values
if (qrCodeObj["Active"] == true && qrCodeObj["Completed"] == false)
{
var matchingLink = new WebClient().DownloadString(qrCodeString);
var obj = Newtonsoft.Json.JsonConvert.DeserializeObject<JObject (matchingLink);
var candidateId = obj.First.First["CandiateID"].ToString();
string page = $"https://*********.firebaseio.com/Candidates/.json?orderBy=\"$key\"&startAt=\"{candidateId}\"&limitToFirst=1";
using (HttpClient client = new HttpClient())
using (HttpResponseMessage response = await client.GetAsync(page))
using (HttpContent content = response.Content)
{
// Reading the string.
Dictionary<string, Candidates> evaluationDictionary = new Dictionary<string, Candidates>();
string result = await content.ReadAsStringAsync();
evaluationDictionary = JsonConvert.DeserializeObject<Dictionary<string, Candidates>>(result);
Debug.Log(evaluationDictionary);
foreach (Candidates candidates in evaluationDictionary.Values)
{
string evaluationMessage = candidates.FirstName + " " + candidates.LastName;
candidateMessage = GetComponent<Text>();
candidateMessage.text = evaluationMessage;
}
// Getting a reference to the text component.
candidateMessage = GetComponent<Text>();
candidateMessage.text = matchingLink.ToString();
candidateMessage.text = matchingLink.Trim(new char[] {'"'});
}
}
else
{
EditorUtility.DisplayDialog("Incorrect Credentials ",
"Please scan a valid QR code. " , "OK");
}

Related

How to have an AWS Lambda/Rekognition Function return an array of object keys

This feels like a simple question and I feel like I am overthinking it. I am doing an AWS project that will compare face(s) on an image to a database (s3bucket) of other faces. So far, I have a lambda function for the comparefacerequest, a class library which invokes the function, and an UWP that inputs the image file and outputs a result. It has worked so far being based on boolean (true or false) functions, but now I want it to instead return what face(s) are recognized via an array. I struggling at implementing this.
Below is my lambda function. I have adjusted the task to be an Array instead of a bool and changed the return to be an array. At the bottom, I have created a global variable class with a testing array so I could attempt to reference the array elsewhere.
public class Function
{
//Function
public async Task<Array> FunctionHandler(string input, ILambdaContext context)
{
//number of matched faces
int matched = 0;
//Client setup
var rekognitionclient = new AmazonRekognitionClient();
var s3client = new AmazonS3Client();
//Create list of target images
ListObjectsRequest list = new ListObjectsRequest
{
BucketName = "bucket2"
};
ListObjectsResponse listre = await s3client.ListObjectsAsync(list);
//loop of list
foreach (Amazon.S3.Model.S3Object obj in listre.S3Objects)
{
//face request with input and obj.key images
var comparefacesrequest = new CompareFacesRequest
{
SourceImage = new Image
{
S3Object = new S3Objects
{
Bucket = "bucket1",
Name = input
}
},
TargetImage = new Image
{
S3Object = new S3Objects
{
Bucket = "bucket2",
Name = obj.Key
}
},
};
//compare with confidence of 95 (subject to change) to current target image
var detectresponse = await rekognitionclient.CompareFacesAsync(comparefacesrequest);
detectresponse.FaceMatches.ForEach(match =>
{
ComparedFace face = match.Face;
if (match.Similarity > 95)
{
//if face detected, raise matched
matched++;
for(int i = 0; i < Globaltest.testingarray.Length; i++)
{
if (Globaltest.testingarray[i] == "test")
{
Globaltest.testingarray[i] = obj.Key;
}
}
}
});
}
//Return true or false depending on if it is matched
if (matched > 0)
{
return Globaltest.testingarray;
}
return Globaltest.testingarray;
}
}
public static class Globaltest
{
public static string[] testingarray = { "test", "test", "test" };
}
Next, is my invoke request in my class library. It has so far been based on the lambda outputting a boolean result, but I thought, "hey, it is parsing the result, it should be fine, right"? I do convert the result to a string, as there is no GetArray, from what I know.
public async Task<bool> IsFace(string filePath, string fileName)
{
await UploadS3(filePath, fileName);
AmazonLambdaClient client = new AmazonLambdaClient(accessKey, secretKey, Amazon.RegionEndpoint.USWest2);
InvokeRequest ir = new InvokeRequest();
ir.InvocationType = InvocationType.RequestResponse;
ir.FunctionName = "ImageTesting";
ir.Payload = "\"" + fileName + "\"";
var result = await client.InvokeAsync(ir);
var strResponse = Encoding.ASCII.GetString(result.Payload.ToArray());
if (bool.TryParse(strResponse, out bool result2))
{
return result2;
}
return false;
}
Finally, here is the section of my UWP where I perform the function. I am referencing the lambda client via "using Lambdaclienttest" (name of lamda project, and this is its only instance I use the reference though). When I run my project, I do still get a face detected when it should, but the Globaltest.testingarray[0] is still equal to "test".
var Facedetector = new FaceDetector(Credentials.accesskey, Credentials.secretkey);
try
{
var result = await Facedetector.IsFace(filepath, filename);
if (result)
{
textBox1.Text = "There is a face detected";
textBox2.Text = Globaltest.testingarray[0];
}
else
{
textBox1.Text = "Try Again";
}
}
catch
{
textBox1.Text = "Please use a photo";
}
Does anyone have any suggestions?

C# Multiple Web Data/Stream Reader

I'm trying to learn programming by myself the best I can but, seems like my code isn't as productive as it can be. I'm trying to learn by doing things that I would use on a normal occasion and I can't figure out how to properly manage it, so any information would be greatly appreciated.
I'm working on a discord bot for personal use at the moment, it works fine, the loadout time is just terrible when it comes to this part of the command. Maybe cause I'm trying to have it open, read, and close multiple databases? Or is there another explanation or method to doing this that can make it load within a faster time?
string NormalExp = "0";
string IronExp = "0";
string HCExp = "0";
string UIMExp = "0";
//Normal Account
try
{
WebRequest NormalScore = WebRequest.Create("https://secure.runescape.com/m=hiscore_oldschool/index_lite.ws?player=" + player);
WebResponse NormalResponse = NormalScore.GetResponse();
using (Stream NormalDStream = NormalResponse.GetResponseStream())
{
StreamReader NormalReader = new StreamReader(NormalDStream);
string NormalResponseFromServer = NormalReader.ReadToEnd();
var _Score = NormalResponseFromServer.Split('\n');
var _Total = _Score[0];
var _TotalGet = _Total.Split(',');
var _TotalRank = _TotalGet[0];
var _TotalLevel = _TotalGet[1];
var _TotalExp = _TotalGet[2];
NormalExp = _TotalExp;
}
NormalResponse.Close();
}
catch (Exception)
{
}
//Normal Ironman
try
{
WebRequest IronScore = WebRequest.Create("https://secure.runescape.com/m=hiscore_oldschool_ironman/index_lite.ws?player=" + player);
WebResponse IronResponse = IronScore.GetResponse();
using (Stream IronDStream = IronResponse.GetResponseStream())
{
StreamReader IronReader = new StreamReader(IronDStream);
string IronResponseFromServer = IronReader.ReadToEnd();
var _Score = IronResponseFromServer.Split('\n');
var _Total = _Score[0];
var _TotalGet = _Total.Split(',');
var _TotalRank = _TotalGet[0];
var _TotalLevel = _TotalGet[1];
var _TotalExp = _TotalGet[2];
IronExp = _TotalExp;
}
IronResponse.Close();
}
catch (Exception)
{
}
//Hardcore Ironman
try
{
WebRequest HCScore = WebRequest.Create("https://secure.runescape.com/m=hiscore_oldschool_hardcore_ironman/index_lite.ws?player=" + player);
WebResponse HCResponse = HCScore.GetResponse();
using (Stream HCDStream = HCResponse.GetResponseStream())
{
StreamReader HCReader = new StreamReader(HCDStream);
string HCResponseFromServer = HCReader.ReadToEnd();
var _Score = HCResponseFromServer.Split('\n');
var _Total = _Score[0];
var _TotalGet = _Total.Split(',');
var _TotalRank = _TotalGet[0];
var _TotalLevel = _TotalGet[1];
var _TotalExp = _TotalGet[2];
HCExp = _TotalExp;
}
HCResponse.Close();
}
catch (Exception)
{
}
//Ultimate Ironman
try
{
WebRequest UIMScore = WebRequest.Create("https://secure.runescape.com/m=hiscore_oldschool_ultimate/index_lite.ws?player=" + player);
WebResponse UIMResponse = UIMScore.GetResponse();
using (Stream UIMDStream = UIMResponse.GetResponseStream())
{
StreamReader UIMReader = new StreamReader(UIMDStream);
string UIMResponseFromServer = UIMReader.ReadToEnd();
var _Score = UIMResponseFromServer.Split('\n');
var _Total = _Score[0];
var _TotalGet = _Total.Split(',');
var _TotalRank = _TotalGet[0];
var _TotalLevel = _TotalGet[1];
var _TotalExp = _TotalGet[2];
UIMExp = _TotalExp;
}
UIMResponse.Close();
}
catch (Exception)
{
}
await ReplyAsync(
$"**Normal: ** {NormalExp}\n" +
$"**Ironman: ** {IronExp}\n" +
$"**Hardcore: ** {HCExp}\n" +
$"**UIM: ** {UIMExp}");
if (Convert.ToInt64(UIMExp) == Convert.ToInt64(NormalExp))
{
await ReplyAsync("Account is a UIM");
}
else if (Convert.ToInt64(HCExp) == Convert.ToInt64(NormalExp))
{
await ReplyAsync("Account is a HC");
}
else if (Convert.ToInt64(IronExp) == Convert.ToInt64(NormalExp) && Convert.ToInt64(IronExp) > Convert.ToInt64(UIMExp + HCExp))
{
if (Convert.ToInt32(UIMExp) > 1)
{
await ReplyAsync("Account is a ~~UIM~~ Normal Ironman");
}
else if (Convert.ToInt64(HCExp) > 1)
{
await ReplyAsync("Account is a ~~HC~~ Normal Ironman");
}
else
{
await ReplyAsync("Account is a Normal Ironman");
}
}
else
{
if (Convert.ToInt64(UIMExp) > 1 && Convert.ToInt64(IronExp) > 1)
{
await ReplyAsync("Account is a ~~UIM~~, ~~Ironman~~, normal player.");
}
else if (Convert.ToInt64(HCExp) > 1 && Convert.ToInt64(IronExp) > 1)
{
await ReplyAsync("Account is a ~~HC~~, ~~Ironman~~, normal player.");
}
else if (Convert.ToInt64(IronExp) > 1 && Convert.ToInt64(HCExp) == 0 && Convert.ToInt64(UIMExp) == 0)
{
await ReplyAsync("Account is a ~~Ironman~~ normal player.");
}
else
{
await ReplyAsync("Account is a Normal Player");
}
}
In general, sending requests is an expensive operation but you can improve it by changing your method.
Try to use HttpClient instead of WebRequest
and I suggest reading about Async/Sync operations

call back query data from inline keyboard

I'm trying to get the data from an inline keyboard, I've searched a lot but unfortunately didn't get my answer and non of codes worked for me. Here's my code please help me
static void Main(string[] args){
InlineKeyboardButton[][] buttons =
new InlineKeyboardButton[][]{
new InlineKeyboardButton[]{newInlineKeyboardButton() { Text = "show Channel", CallbackData = "Data1" }},
new InlineKeyboardButton[]{new InlineKeyboardButton() { Text = "show Website", CallbackData = "Data2" }}};
inlineKeyboardMarkup = new InlineKeyboardMarkup() { InlineKeyboard = buttons };
Task.Run(() => RunBot());
Console.ReadLine();
} // End of main method
public static async Task RunBot(){
while (true){
var u = await bot.MakeRequestAsync(new GetUpdates() { Offset
= offset });
foreach (var update in u)
{
offset = update.UpdateId + 1;
var text = update.Message.Text;
// here I want to get the data like this, but it doesn't work
if (update.ChosenInlineResult != null){
Console.WriteLine("Chosen Inline Result: " +
update.ChosenInlineResult.ToString());
}
switch(text){
case "Something":{
var req = new SendMessage(update.Message.Chat.Id, "راهنما") { ReplyMarkup = inlineKeyboardMarkup };
await bot.MakeRequestAsync(req);
break;
}
}
}
}
}
you must replace this
if (update.ChosenInlineResult != null){
Console.WriteLine("Chosen Inline Result: " +
update.ChosenInlineResult.ToString());
}
with something like This :
if (update.CallbackQuery != null)
{
Console.WriteLine(val.CallbackQuery.Message+"-"+val.CallbackQuery.Data);
}

Check if AWS Lambda function completed the job

I am currently sending a file to be transcoded to my AWS lambda function. After I send the file, I send a notification to the SQS for some external aplication to start downloading the transcoded files.
The problem is, sometimes, the download of the files happen before the Lambda function completed.
How can I only send the notification to SQS after the Lambda completed.
I tried getting the Job.Status as follow, but not sure how to query it again if Status is not Complete.
Here is my code:
using (var eClient = new AmazonElasticTranscoderClient())
{
var response = await this.S3Client.GetObjectMetadataAsync(s3Event.Bucket.Name, s3Event.Object.Key);
var videoPresets = new List<Preset>();
var presetRequest = new ListPresetsRequest();
ListPresetsResponse presetResponse;
do
{
presetResponse = await eClient.ListPresetsAsync(presetRequest);
videoPresets.AddRange(presetResponse.Presets);
presetRequest.PageToken = presetResponse.NextPageToken;
} while (presetResponse.NextPageToken != null);
var pipelines = new List<Pipeline>();
var pipelineRequest = new ListPipelinesRequest();
ListPipelinesResponse pipelineResponse;
do
{
pipelineResponse = await eClient.ListPipelinesAsync(pipelineRequest);
pipelines.AddRange(pipelineResponse.Pipelines);
pipelineRequest.PageToken = pipelineResponse.NextPageToken;
} while (pipelineResponse.NextPageToken != null);
var pipeLine = s3Event.Bucket.Name.ToLower().Contains("test") ? pipelines.First(p => p.Name.ToLower().Contains("test")) : pipelines.First(p => !p.Name.ToLower().Contains("test"));
//HLS Stuff for Apple
var usablePreset = videoPresets.Where(p => p.Name.Contains("HLS") && !p.Name.Contains("HLS Video")).ToList();
var hlsPresets = new List<Preset>();
foreach (var preset in usablePreset)
{
var resolution = preset.Name.Replace("System preset: HLS ", "");
switch (resolution)
{
case "2M":
case "1M":
case "400k":
hlsPresets.Add(preset);
break;
}
}
var jobReq = new CreateJobRequest
{
PipelineId = pipeLine.Id,
Input = new JobInput() { Key = fileName, },
OutputKeyPrefix = outPutPrefix
//OutputKeyPrefix = "LambdaTest/" + playlistName + "/"
};
var outputs = new List<CreateJobOutput>();
var playlistHLS = new CreateJobPlaylist() { Name = "HLS_" + playlistName, Format = "HLSv3" };
foreach (var preset in hlsPresets)
{
var resolution = preset.Name.Replace("System preset: HLS ", "").Replace(".", "");
var newName = resolution + "_" + playlistName;
var output = new CreateJobOutput() { Key = newName, PresetId = preset.Id, SegmentDuration = "10" };
outputs.Add(output);
playlistHLS.OutputKeys.Add(newName);
}
jobReq.Playlists.Add(playlistHLS);
jobReq.Outputs = outputs;
//var temp = JsonConvert.SerializeObject(jobReq);
var reply = eClient.CreateJobAsync(jobReq);
var transcodingCompleted = reply.Result.Job.Status == "Complete" ? true : false;
do {
//somehow need to query status again
} while (!transcodingCompleted);
if (transcodingCompleted)
await SendAsync(jobReq.OutputKeyPrefix, pipeLine.OutputBucket);
}
The part I am interested in:
var reply = eClient.CreateJobAsync(jobReq);
var transcodingCompleted = reply.Result.Job.Status == "Complete" ? true : false;
do {
//somehow need to query status again
} while (!transcodingCompleted);
if (transcodingCompleted)
await SendAsync(jobReq.OutputKeyPrefix, pipeLine.OutputBucket);

How to get Bitcoin value for corresponding USD value in ASP.NET C#?

I want to get Bitcoin value for corresponding USD value and store it in table or variable. I got this URL from which I can get a Bitcoin value for USK amount. I searched on blockchain and I found this URL.
For example:
500usd = 0.76105818 btc
I tried:
https://blockchain.info/tobtc?currency=USD&value=500
at the end, its USD value which we want to convert in Bitcoin.
I want to get the result in the variable in C# (backend).
How can I accomplish this?
You need to just make call to server and parse the response.
var uri = String.Format("https://blockchain.info/tobtc?currency=USD&value={0}", 500);
WebClient client = new WebClient();
client.UseDefaultCredentials = true;
var data = client.DownloadString(uri);
var result = Convert.ToDouble(data);
Install-Package CoinMarketCapClient
using CoinMarketCap;
public static async Task<double> GetBitcoinInUsd(double usd){
//https://api.coinmarketcap.com/v1/ticker/bitcoin/
CoinMarketCapClient client = CoinMarketCapClient.GetInstance();
var entity = await client.GetTickerAsync("bitcoin");
return entity.PriceUsd * usd;
}
var uri = String.Format(#"https://blockchain.info/tobtc?currency=USD&value={0}",1);
WebClient client = new WebClient();
client.UseDefaultCredentials = true;
var data = client.DownloadString(uri);
var result = 1/Convert.ToDouble(data.Replace('.',',')); //you will receive 1 btc = result;
There are several APIs out there that will allow you to request the prices for a list of crypto currencies, and/or fiat currencies. The problem is that all the APIs do it in a disparate way. The follow on from that is that any one could be down at any given time, so you need to have some failure tolerance built in. I.e. the code should attempt to use one API, and if that fails, move to the next. Of course, this is further complicated by the fact that price is subjective and localised to a given country, exchange and so on. So, getting an accurate value is very difficult.
Here is example Crypto Compare client from CryptoCurrency.Net (https://github.com/MelbourneDeveloper/CryptoCurrency.Net/blob/master/src/CryptoCurrency.Net/APIClients/PriceEstimationClients/CryptoCompareClient.cs):
public class CryptoCompareClient : PriceEstimationClientBase, IPriceEstimationClient
{
public CryptoCompareClient(IRestClientFactory restClientFactory) : base(restClientFactory)
{
RESTClient = restClientFactory.CreateRESTClient(new Uri("https://min-api.cryptocompare.com"));
}
protected override Func<GetPricesArgs, Task<EstimatedPricesModel>> GetPricesFunc { get; } = async a =>
{
var retVal = new EstimatedPricesModel();
if (a.Currencies.ToList().Count == 0)
{
return retVal;
}
retVal.LastUpdate = DateTime.Now;
var symbolsPart = string.Join(",", a.Currencies.Select(c => c.Name));
var priceJson = await a.RESTClient.GetAsync<string>($"data/pricemultifull?fsyms={symbolsPart}&tsyms={a.FiatCurrency}");
var jObject = (JObject)JsonConvert.DeserializeObject(priceJson);
var rawNode = (JObject)jObject.First.First;
foreach (JProperty coinNode in rawNode.Children())
{
var fiatNode = (JProperty)coinNode.First().First;
var allProperties = fiatNode.First.Children().Cast<JProperty>().ToList();
var change24HourProperty = allProperties.FirstOrDefault(p => string.Compare(p.Name, "CHANGEPCT24HOUR", true) == 0);
var priceProperty = allProperties.FirstOrDefault(p => string.Compare(p.Name, "PRICE", true) == 0);
var price = (decimal)priceProperty.Value;
var change24Hour = (decimal)change24HourProperty.Value;
retVal.Result.Add(new CoinEstimate { CurrencySymbol = new CurrencySymbol(coinNode.Name), ChangePercentage24Hour = change24Hour, FiatEstimate = price, LastUpdate = DateTime.Now });
}
//Extreme hack. It's better to show zero than nothing at all and get the coins stuck
foreach (var currency in a.Currencies)
{
if (retVal.Result.FirstOrDefault(ce => ce.CurrencySymbol.Equals(currency)) == null)
{
retVal.Result.Add(new CoinEstimate { ChangePercentage24Hour = 0, CurrencySymbol = currency, FiatEstimate = 0, LastUpdate = DateTime.Now });
}
}
return retVal;
};
}
The PriceEstimationManager will flick through APIs until it finds one that works (https://github.com/MelbourneDeveloper/CryptoCurrency.Net/blob/master/src/CryptoCurrency.Net/APIClients/PriceEstimationClients/PriceEstimationManager.cs):
public class PriceEstimationManager
{
#region Fields
private readonly Collection<IPriceEstimationClient> _Clients = new Collection<IPriceEstimationClient>();
#endregion
#region Constructor
public PriceEstimationManager(IRestClientFactory restClientFactory)
{
foreach (var typeInfo in typeof(PriceEstimationManager).GetTypeInfo().Assembly.DefinedTypes)
{
var type = typeInfo.AsType();
if (typeInfo.ImplementedInterfaces.Contains(typeof(IPriceEstimationClient)))
{
_Clients.Add((IPriceEstimationClient)Activator.CreateInstance(type, restClientFactory));
}
}
}
#endregion
#region Public Methods
/// <summary>
/// TODO: This needs to be averaged. The two current clients give wildly different values. Need to include some Australian exchanges etc.
/// </summary>
public async Task<EstimatedPricesModel> GetPrices(IEnumerable<CurrencySymbol> currencySymbols, string fiatCurrency)
{
//Lets try a client that hasn't been used before if there is one
var client = _Clients.FirstOrDefault(c => c.AverageCallTimespan.TotalMilliseconds == 0);
var currencies = currencySymbols.ToList();
if (client != null)
{
try
{
return await client.GetPrices(currencies, fiatCurrency);
}
catch
{
//Do nothing
}
}
foreach (var client2 in _Clients.OrderBy(c => c.SuccessRate).ThenBy(c => c.AverageCallTimespan).ToList())
{
try
{
return await client2.GetPrices(currencies, fiatCurrency);
}
catch (Exception ex)
{
Logger.Log("Error Getting Prices", ex, nameof(PriceEstimationManager));
}
}
throw new Exception("Can't get prices");
}
#endregion
}
At a higher level, you can use the code like this (https://github.com/MelbourneDeveloper/CryptoCurrency.Net/blob/master/src/CryptoCurrency.Net.UnitTests/PricingTests.cs):
public async Task GetUSDBitcoinPrice()
{
var priceEstimationManager = new PriceEstimationManager(new RESTClientFactory());
var estimatedPrice = await priceEstimationManager.GetPrices(new List<CurrencySymbol> { CurrencySymbol.Bitcoin }, "USD");
Console.WriteLine($"Estimate: {estimatedPrice.Result.First().FiatEstimate}");
}
As more pricing clients are added, it will get more and more reliable.

Categories