temp: broken push to laptop
This commit is contained in:
1 parent
0a0ea86d25
commit
3a819ce180
32 files changed
+503
-573
No files matched your search
+128
-130
@@ -1,22 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Data.SQLite;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using PcgsInvUi.Models;
|
||||
|
||||
namespace PcgsInvUi.Services;
|
||||
|
||||
public class CoinDatabase {
|
||||
public SQLiteConnection Connection { get; set; }
|
||||
private Boolean IsConnected { get; set; }
|
||||
public ObservableCollection<Coin> Collection { get; set; }
|
||||
public Boolean IsClientConnected { get; set; }
|
||||
|
||||
private PcgsClient? _pcgsClient;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Creates and initilizes a new instance of the CoinDatabase.
|
||||
/// Must call TryInitApiClient() after creating a new instance.
|
||||
/// Creates and initilizes a new instance of the CoinDatabase.
|
||||
/// Must call TryInitApiClient() after creating a new instance.
|
||||
/// </summary>
|
||||
public CoinDatabase() {
|
||||
// Create a connection to SQLite
|
||||
@@ -25,13 +20,18 @@ public class CoinDatabase {
|
||||
CreateCollection("CollectionTable");
|
||||
CreateApiTable();
|
||||
Console.WriteLine("Connected to database.");
|
||||
Collection = new ObservableCollection<Coin>();
|
||||
Collection = new ObservableCollection<PcgsCoin>();
|
||||
GetCollection("CollectionTable");
|
||||
Console.WriteLine("Got collection.");
|
||||
}
|
||||
|
||||
public SQLiteConnection Connection { get; set; }
|
||||
private bool IsConnected { get; set; }
|
||||
public ObservableCollection<PcgsCoin> Collection { get; set; }
|
||||
public bool IsClientConnected { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Destructor. Currently not used, due to the strange nature of desktop applications.
|
||||
/// Destructor. Currently not used, due to the strange nature of desktop applications.
|
||||
/// </summary>
|
||||
~CoinDatabase() {
|
||||
Console.WriteLine("Destructor called, saving collection.");
|
||||
@@ -40,14 +40,14 @@ public class CoinDatabase {
|
||||
// Close the connection.
|
||||
Connection.Close();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to intitialize the API client by selecting the API key from the database.
|
||||
/// Attempts to intitialize the API client by selecting the API key from the database.
|
||||
/// </summary>
|
||||
/// <returns>True if the API key was found, false otherwise.</returns>
|
||||
public async Task<bool> TryInitApiClient() {
|
||||
Console.Write("Attempting to initialize API client... ");
|
||||
SQLiteCommand cmd = Connection.CreateCommand();
|
||||
var cmd = Connection.CreateCommand();
|
||||
cmd.CommandText = "SELECT API_KEY FROM ApiTable";
|
||||
|
||||
using (var reader = cmd.ExecuteReader()) {
|
||||
@@ -70,13 +70,14 @@ public class CoinDatabase {
|
||||
Console.WriteLine("Failed. API key not found.");
|
||||
}
|
||||
}
|
||||
|
||||
return IsClientConnected;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Atttempts to initialize the PCGS API client.
|
||||
/// Atttempts to initialize the PCGS API client.
|
||||
/// </summary>
|
||||
/// <param name=apiKey>The API key to verify.</param>
|
||||
/// <param name= apiKey>The API key to verify.</param>
|
||||
/// <returns>A Task with a return value that returns true if the client intializes properly.</returns>
|
||||
public async Task<bool> TryInitApiClient(string apiKey) {
|
||||
Console.Write("Attempting to initialize API client with key param... ");
|
||||
@@ -98,23 +99,23 @@ public class CoinDatabase {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the collection from the database and stores it in the Collection property.
|
||||
/// Creates the collection table if it does not exist already.
|
||||
/// Gets the collection from the database and stores it in the Collection property.
|
||||
/// Creates the collection table if it does not exist already.
|
||||
/// </summary>
|
||||
/// <returns>The SQLiteConnection that corresponds to the connected database.</returns>
|
||||
private SQLiteConnection CreateConnection() {
|
||||
// Check if database exists.
|
||||
if (!System.IO.File.Exists("coin_collection")) {
|
||||
if (!File.Exists("coin_collection")) {
|
||||
// If not, create the database.
|
||||
Console.Write("Creating database... ");
|
||||
SQLiteConnection.CreateFile("coin_collection.sqlite");
|
||||
Console.WriteLine("Done.");
|
||||
}
|
||||
|
||||
|
||||
// Create a connection to the database.
|
||||
SQLiteConnection connection =
|
||||
var connection =
|
||||
new SQLiteConnection("DataSource=coin_collection");
|
||||
|
||||
|
||||
// Open the connection.
|
||||
try {
|
||||
connection.Open();
|
||||
@@ -128,7 +129,7 @@ public class CoinDatabase {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the table that stores the API key and the number of requests remaining.
|
||||
/// Creates the table that stores the API key and the number of requests remaining.
|
||||
/// </summary>
|
||||
public void CreateApiTable() {
|
||||
// Create a table to store the API key and the number of requests remaining.
|
||||
@@ -139,12 +140,12 @@ public class CoinDatabase {
|
||||
}
|
||||
|
||||
// Create a SQL command.
|
||||
SQLiteCommand cmd = Connection.CreateCommand();
|
||||
var cmd = Connection.CreateCommand();
|
||||
cmd.CommandText =
|
||||
"CREATE TABLE IF NOT EXISTS ApiTable (" +
|
||||
"API_KEY TEXT, " +
|
||||
"REQUESTS_REMAINING INTEGER, " +
|
||||
"PRIMARY KEY(API_KEY))";
|
||||
"CREATE TABLE IF NOT EXISTS ApiTable (" +
|
||||
"API_KEY TEXT, " +
|
||||
"REQUESTS_REMAINING INTEGER, " +
|
||||
"PRIMARY KEY(API_KEY))";
|
||||
|
||||
// Execute the command
|
||||
cmd.ExecuteNonQuery();
|
||||
@@ -152,7 +153,7 @@ public class CoinDatabase {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a table to store the collection.
|
||||
/// Creates a table to store the collection.
|
||||
/// </summary>
|
||||
public void CreateCollection(string collectionName) {
|
||||
// Create a table to store the collection.
|
||||
@@ -161,9 +162,9 @@ public class CoinDatabase {
|
||||
Console.WriteLine("Not connected to database.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Create a SQL command.
|
||||
SQLiteCommand cmd = Connection.CreateCommand();
|
||||
var cmd = Connection.CreateCommand();
|
||||
cmd.CommandText =
|
||||
$"CREATE TABLE IF NOT EXISTS {collectionName} (" +
|
||||
"PCGS_NUMBER TEXT," +
|
||||
@@ -184,16 +185,16 @@ public class CoinDatabase {
|
||||
"QUANTITY INTEGER," +
|
||||
"NOTES TEXT," +
|
||||
"PRIMARY KEY(PCGS_NUMBER, GRADE))";
|
||||
|
||||
|
||||
// Execute the command.
|
||||
cmd.ExecuteNonQuery();
|
||||
Console.WriteLine("Collection table initialized.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inserts a Coin object into the database.
|
||||
/// Inserts a Coin object into the database.
|
||||
/// </summary>
|
||||
public void InsertCoin(Coin coin) {
|
||||
public void InsertCoin(PcgsCoin pcgsCoin) {
|
||||
Console.WriteLine("Inserting coin...");
|
||||
// Use our existing connection to insert a coin to the database.
|
||||
if (!IsConnected) {
|
||||
@@ -201,26 +202,26 @@ public class CoinDatabase {
|
||||
Console.WriteLine("Not connected to database.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Create a SQL command.
|
||||
SQLiteCommand cmd = Connection.CreateCommand();
|
||||
var cmd = Connection.CreateCommand();
|
||||
cmd.CommandText =
|
||||
"INSERT INTO CollectionTable (PCGS_NUMBER, GRADE, YEAR," +
|
||||
"DENOMINATION, MINT_MARK, PRICE_GUIDE_VALUE, COIN_FACTS_LINK," +
|
||||
"MAJOR_VARIETY, MINOR_VARIETY, DIE_VARIETY, SERIES_NAME, CATEGORY, DESIGNATION," +
|
||||
"CERT_NUM, QUANTITY, NOTES) " +
|
||||
$"VALUES ('{coin.PCGSNo}', '{coin.Grade}', {coin.Year}, '{coin.Denomination}', '{coin.MintMark}', {coin.PriceGuideValue}," +
|
||||
$"'{coin.CoinFactsLink}', '{coin.MajorVariety}', '{coin.MinorVariety}', '{coin.DieVariety}', '{coin.SeriesName}', " +
|
||||
$"'{coin.Category}', '{coin.Designation}', {coin.CertificateNumber}, {coin.Quantity}, @Notes)";
|
||||
cmd.Parameters.AddWithValue("@Notes", coin.Notes);
|
||||
|
||||
$"VALUES ('{pcgsCoin.PcgsNumber}', '{pcgsCoin.Grade}', {pcgsCoin.Year}, '{pcgsCoin.Denomination}', '{pcgsCoin.MintMark}', {pcgsCoin.PriceGuideValue}," +
|
||||
$"'{pcgsCoin.CoinFactsLink}', '{pcgsCoin.MajorVariety}', '{pcgsCoin.MinorVariety}', '{pcgsCoin.DieVariety}', '{pcgsCoin.SeriesName}', " +
|
||||
$"'{pcgsCoin.Category}', '{pcgsCoin.Designation}', {pcgsCoin.CertificateNumber}, {pcgsCoin.Quantity}, @Notes)";
|
||||
cmd.Parameters.AddWithValue("@Notes", pcgsCoin.Notes);
|
||||
|
||||
// Execute the command.
|
||||
cmd.ExecuteNonQuery();
|
||||
Console.WriteLine("Coin inserted.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a Coin object and saves it to the database.
|
||||
/// Creates a Coin object and saves it to the database.
|
||||
/// </summary>
|
||||
/// <param name="pcgsNumber">The PCGS number of the coin.</param>
|
||||
/// <param name="grade">The grade of the coin.</param>
|
||||
@@ -236,7 +237,7 @@ public class CoinDatabase {
|
||||
SaveCoin("CollectionTable", coin);
|
||||
return PcgsClient.ErrorType.None;
|
||||
}
|
||||
|
||||
|
||||
// Otherwise, build a new coin with the API and insert it.
|
||||
var apiResult = await _pcgsClient.GetCoinFactsByGrade(pcgsNumber, grade);
|
||||
if (apiResult.Item1 == PcgsClient.ErrorType.None) {
|
||||
@@ -246,68 +247,68 @@ public class CoinDatabase {
|
||||
Collection.Add(newCoin);
|
||||
return PcgsClient.ErrorType.None;
|
||||
}
|
||||
|
||||
|
||||
Console.WriteLine("Error getting coin from API - {0}", apiResult.Item1);
|
||||
return apiResult.Item1;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets a coin from the database.
|
||||
/// Gets a coin from the database.
|
||||
/// </summary>
|
||||
/// <param name="pcgsNumber">The PCGS number of the coin.</param>
|
||||
/// <param name="grade">The grade of the coin.</param>
|
||||
/// <returns>The coin if it exists, null otherwise.</returns>
|
||||
public Coin? GetCoin(int pcgsNumber, string grade) {
|
||||
public PcgsCoin? GetCoin(int pcgsNumber, string grade) {
|
||||
Console.WriteLine($"Getting coin {pcgsNumber}, {grade}...");
|
||||
int gradeInt = GetGradeFromString(grade);
|
||||
|
||||
var gradeInt = GetGradeFromString(grade);
|
||||
|
||||
// Check the collection to see if the coin exists.
|
||||
// We can't make a more efficient algorithm since there's not really an ordering to the collection.
|
||||
foreach (var coin in Collection) {
|
||||
if (coin.PCGSNo == pcgsNumber.ToString() && coin.Grade.Contains(gradeInt.ToString())) { // This has the possibility of a false positive for single digit grades.
|
||||
foreach (var coin in Collection)
|
||||
if (coin.PcgsNumber == pcgsNumber.ToString() && coin.Grade.Contains(gradeInt.ToString())) {
|
||||
// This has the possibility of a false positive for single digit grades.
|
||||
if (gradeInt < 10)
|
||||
if (char.IsDigit(coin.Grade[3])) continue; // TODO For right now, we're going to assume that the first 2 characters are ciruclation strings, and the next 2 are grade numbers.
|
||||
if (char.IsDigit(coin.Grade[3]))
|
||||
continue; // TODO For right now, we're going to assume that the first 2 characters are ciruclation strings, and the next 2 are grade numbers.
|
||||
Console.WriteLine("Found coin.");
|
||||
return coin;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Console.WriteLine("Couldn't find coin.");
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to get all Coin objects within the database.
|
||||
/// Used to get all Coin objects within the database.
|
||||
/// </summary>
|
||||
/// <param name="collectionName">The name of the collection table.</param>
|
||||
public void GetCollection(string collectionName) {
|
||||
Console.WriteLine("Getting collection...");
|
||||
SQLiteCommand cmd = Connection.CreateCommand();
|
||||
var cmd = Connection.CreateCommand();
|
||||
cmd.CommandText = $"SELECT * FROM {collectionName}";
|
||||
|
||||
|
||||
using (var reader = cmd.ExecuteReader()) {
|
||||
while (reader.Read()) {
|
||||
while (reader.Read())
|
||||
// Create coin from reader then add to list.
|
||||
Collection.Add(CoinFromReader(reader));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a CSV formatted string from a collection.
|
||||
/// Creates a CSV formatted string from a collection.
|
||||
/// </summary>
|
||||
/// <param name="collectionName">The name of the collection table.</param>
|
||||
/// <returns>A CSV formatted string.</returns>
|
||||
public String CollectionToCSV(string collectionName) {
|
||||
public string CollectionToCSV(string collectionName) {
|
||||
var cmd = Connection.CreateCommand();
|
||||
cmd.CommandText = $"SELECT * FROM {collectionName}";
|
||||
|
||||
var headersCommand = Connection.CreateCommand();
|
||||
headersCommand.CommandText = $"PRAGMA table_info({collectionName})";
|
||||
|
||||
|
||||
var resultString = "";
|
||||
var numHeaders = 0;
|
||||
|
||||
|
||||
// Get the headers.
|
||||
using (var reader = headersCommand.ExecuteReader()) {
|
||||
while (reader.Read()) {
|
||||
@@ -322,23 +323,20 @@ public class CoinDatabase {
|
||||
using (var reader = cmd.ExecuteReader()) {
|
||||
while (reader.Read()) {
|
||||
// Read information from the reader, then add to CSV string.
|
||||
for (int i = 0; i < numHeaders; i++) {
|
||||
for (var i = 0; i < numHeaders; i++) {
|
||||
// Get the type of each column.
|
||||
var type = reader.GetFieldType(i);
|
||||
Console.WriteLine("Type: " + type);
|
||||
if (type == typeof(Int64)) {
|
||||
if (type == typeof(long))
|
||||
resultString += reader.GetInt32(i) + ",";
|
||||
}
|
||||
else if (type == typeof(Double)) {
|
||||
else if (type == typeof(double))
|
||||
resultString += reader.GetDouble(i) + ",";
|
||||
}
|
||||
else if (type == typeof(String)) {
|
||||
else if (type == typeof(string))
|
||||
resultString += reader.GetString(i) + ",";
|
||||
}
|
||||
else {
|
||||
else
|
||||
resultString += "NULL" + ",";
|
||||
}
|
||||
}
|
||||
|
||||
resultString += "\n";
|
||||
}
|
||||
}
|
||||
@@ -347,91 +345,91 @@ public class CoinDatabase {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves a Coin object to the database.
|
||||
/// Saves a Coin object to the database.
|
||||
/// </summary>
|
||||
/// <param name="collectionName">The name of the collection table.</param>
|
||||
/// <param name="coin">The coin to save.</param>
|
||||
public void SaveCoin(string collectionName, Coin coin) {
|
||||
/// <param name="pcgsCoin">The coin to save.</param>
|
||||
public void SaveCoin(string collectionName, PcgsCoin pcgsCoin) {
|
||||
// Get and replace the coin from the database.
|
||||
Console.WriteLine("Saving coin...");
|
||||
SQLiteCommand cmd = Connection.CreateCommand();
|
||||
var cmd = Connection.CreateCommand();
|
||||
cmd.CommandText = $"UPDATE {collectionName} " +
|
||||
$"SET YEAR = {coin.Year}, " +
|
||||
$"DENOMINATION = \'{coin.Denomination}\', " +
|
||||
$"MINT_MARK = \'{coin.MintMark}\', " +
|
||||
$"PRICE_GUIDE_VALUE = \'{coin.PriceGuideValue}\', " +
|
||||
$"COIN_FACTS_LINK = \'{coin.CoinFactsLink}\', " +
|
||||
$"MAJOR_VARIETY = \'{coin.MajorVariety}\', " +
|
||||
$"MINOR_VARIETY = \'{coin.MinorVariety}\', " +
|
||||
$"DIE_VARIETY = \'{coin.DieVariety}\', " +
|
||||
$"SERIES_NAME = \'{coin.SeriesName}\', " +
|
||||
$"CATEGORY = \'{coin.Category}\', " +
|
||||
$"DESIGNATION = \'{coin.Designation}\', " +
|
||||
$"CERT_NUM = \'{coin.CertificateNumber}\', " +
|
||||
$"QUANTITY = {coin.Quantity}, " +
|
||||
$"NOTES = @Notes " +
|
||||
$"WHERE PCGS_NUMBER = {coin.PCGSNo} AND GRADE = \'{coin.Grade}\'";
|
||||
cmd.Parameters.AddWithValue("@Notes", coin.Notes);
|
||||
$"SET YEAR = {pcgsCoin.Year}, " +
|
||||
$"DENOMINATION = \'{pcgsCoin.Denomination}\', " +
|
||||
$"MINT_MARK = \'{pcgsCoin.MintMark}\', " +
|
||||
$"PRICE_GUIDE_VALUE = \'{pcgsCoin.PriceGuideValue}\', " +
|
||||
$"COIN_FACTS_LINK = \'{pcgsCoin.CoinFactsLink}\', " +
|
||||
$"MAJOR_VARIETY = \'{pcgsCoin.MajorVariety}\', " +
|
||||
$"MINOR_VARIETY = \'{pcgsCoin.MinorVariety}\', " +
|
||||
$"DIE_VARIETY = \'{pcgsCoin.DieVariety}\', " +
|
||||
$"SERIES_NAME = \'{pcgsCoin.SeriesName}\', " +
|
||||
$"CATEGORY = \'{pcgsCoin.Category}\', " +
|
||||
$"DESIGNATION = \'{pcgsCoin.Designation}\', " +
|
||||
$"CERT_NUM = \'{pcgsCoin.CertificateNumber}\', " +
|
||||
$"QUANTITY = {pcgsCoin.Quantity}, " +
|
||||
$"NOTES = @Notes " +
|
||||
$"WHERE PCGS_NUMBER = {pcgsCoin.PcgsNumber} AND GRADE = \'{pcgsCoin.Grade}\'";
|
||||
cmd.Parameters.AddWithValue("@Notes", pcgsCoin.Notes);
|
||||
Console.WriteLine(cmd.CommandText);
|
||||
// Execute the command.
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Synchronizes the database with the current contents of the specified collection.
|
||||
/// Synchronizes the database with the current contents of the specified collection.
|
||||
/// </summary>
|
||||
/// <param name="collectionName">The name of the collection table.</param>
|
||||
public void UpdateCollection(string collectionName) {
|
||||
// Update the database with the contents of the collection.
|
||||
// TODO This is a very inefficient way of doing this. I should be able to do this in one command.
|
||||
foreach (var coin in Collection) {
|
||||
SaveCoin(collectionName, coin); // CAREFUL! This will not create a coin if it doesn't currently exist.
|
||||
}
|
||||
foreach (var coin in
|
||||
Collection)
|
||||
SaveCoin(collectionName, coin); // CAREFUL! This will not create a coin if it doesn't currently exist.
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Creates a Coin from the information in a reader specifically from this database.
|
||||
/// Creates a Coin from the information in a reader specifically from this database.
|
||||
/// </summary>
|
||||
/// <param name="reader">The reader to get the information from.</param>
|
||||
private Coin CoinFromReader(SQLiteDataReader reader) {
|
||||
private PcgsCoin CoinFromReader(SQLiteDataReader reader) {
|
||||
// Create a coin while filtering out any possible null values - they throw exceptions.
|
||||
Coin coin = new Coin();
|
||||
if (!reader.IsDBNull(0)) coin.PCGSNo = reader.GetString(0);
|
||||
if (!reader.IsDBNull(1)) coin.Grade = reader.GetString(1);
|
||||
if (!reader.IsDBNull(2)) coin.Year = reader.GetInt32(2);
|
||||
if (!reader.IsDBNull(3)) coin.Denomination = reader.GetString(3);
|
||||
if (!reader.IsDBNull(4)) coin.MintMark = reader.GetString(4);
|
||||
if (!reader.IsDBNull(5)) coin.PriceGuideValue = reader.GetDouble(5);
|
||||
if (!reader.IsDBNull(6)) coin.CoinFactsLink = reader.GetString(6);
|
||||
if (!reader.IsDBNull(7)) coin.MajorVariety = reader.GetString(7);
|
||||
if (!reader.IsDBNull(8)) coin.MinorVariety = reader.GetString(8);
|
||||
if (!reader.IsDBNull(9)) coin.DieVariety = reader.GetString(9);
|
||||
if (!reader.IsDBNull(10)) coin.SeriesName = reader.GetString(10);
|
||||
if (!reader.IsDBNull(11)) coin.Category = reader.GetString(11);
|
||||
if (!reader.IsDBNull(12)) coin.Designation = reader.GetString(12);
|
||||
if (!reader.IsDBNull(13)) coin.CertificateNumber = reader.GetInt32(13);
|
||||
if (!reader.IsDBNull(14)) coin.Quantity = reader.GetInt32(14);
|
||||
if (!reader.IsDBNull(15)) coin.Notes = reader.GetString(15);
|
||||
coin.TotalPrice = coin.Quantity * coin.PriceGuideValue;
|
||||
return coin;
|
||||
PcgsCoin pcgsCoin = new PcgsCoin();
|
||||
if (!reader.IsDBNull(0)) pcgsCoin.PcgsNumber = reader.GetString(0);
|
||||
if (!reader.IsDBNull(1)) pcgsCoin.Grade = reader.GetString(1);
|
||||
if (!reader.IsDBNull(2)) pcgsCoin.Year = reader.GetInt32(2);
|
||||
if (!reader.IsDBNull(3)) pcgsCoin.Denomination = reader.GetString(3);
|
||||
if (!reader.IsDBNull(4)) pcgsCoin.MintMark = reader.GetString(4);
|
||||
if (!reader.IsDBNull(5)) pcgsCoin.PriceGuideValue = reader.GetDouble(5);
|
||||
if (!reader.IsDBNull(6)) pcgsCoin.CoinFactsLink = reader.GetString(6);
|
||||
if (!reader.IsDBNull(7)) pcgsCoin.MajorVariety = reader.GetString(7);
|
||||
if (!reader.IsDBNull(8)) pcgsCoin.MinorVariety = reader.GetString(8);
|
||||
if (!reader.IsDBNull(9)) pcgsCoin.DieVariety = reader.GetString(9);
|
||||
if (!reader.IsDBNull(10)) pcgsCoin.SeriesName = reader.GetString(10);
|
||||
if (!reader.IsDBNull(11)) pcgsCoin.Category = reader.GetString(11);
|
||||
if (!reader.IsDBNull(12)) pcgsCoin.Designation = reader.GetString(12);
|
||||
if (!reader.IsDBNull(13)) pcgsCoin.CertificateNumber = reader.GetInt32(13);
|
||||
if (!reader.IsDBNull(14)) pcgsCoin.Quantity = reader.GetInt32(14);
|
||||
if (!reader.IsDBNull(15)) pcgsCoin.Notes = reader.GetString(15);
|
||||
// pcgsCoin.TotalPrice = pcgsCoin.Quantity * pcgsCoin.PriceGuideValue;
|
||||
return pcgsCoin;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Deletes a Coin object from the database.
|
||||
/// Deletes a Coin object from the database.
|
||||
/// </summary>
|
||||
/// <param name="delCoin">The coin to delete.</param>
|
||||
public void DeleteCoin(Coin delCoin) {
|
||||
SQLiteCommand cmd = Connection.CreateCommand();
|
||||
/// <param name="delPcgsCoin">The coin to delete.</param>
|
||||
public void DeleteCoin(PcgsCoin delPcgsCoin) {
|
||||
var cmd = Connection.CreateCommand();
|
||||
cmd.CommandText = "DELETE FROM CollectionTable WHERE PCGS_NUMBER = @PcgsNumber AND GRADE = @Grade";
|
||||
cmd.Parameters.AddWithValue("@PcgsNumber", delCoin.PCGSNo);
|
||||
cmd.Parameters.AddWithValue("@Grade", delCoin.Grade);
|
||||
|
||||
cmd.Parameters.AddWithValue("@PcgsNumber", delPcgsCoin.PcgsNumber);
|
||||
cmd.Parameters.AddWithValue("@Grade", delPcgsCoin.Grade);
|
||||
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets the grade from a string returned from the main window.
|
||||
/// These are always in a format similar to "MS-65", so we can just get the last two characters.
|
||||
/// Gets the grade from a string returned from the main window.
|
||||
/// These are always in a format similar to "MS-65", so we can just get the last two characters.
|
||||
/// </summary>
|
||||
/// <param name="grade">The grade string.</param>
|
||||
private int GetGradeFromString(string grade) {
|
||||
@@ -443,4 +441,4 @@ public class CoinDatabase {
|
||||
|
||||
public class NotConnectedToDatabaseException : Exception {
|
||||
public NotConnectedToDatabaseException() : base("Not connected to database.") { }
|
||||
}
|
||||
}
|
||||
@@ -1,129 +0,0 @@
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Threading.Tasks;
|
||||
using PcgsInvUi.Models;
|
||||
using System.Text.Json;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace PcgsInvUi.Services;
|
||||
|
||||
public class PcgsClient : ReactiveObject {
|
||||
public enum ErrorType {
|
||||
None,
|
||||
NoCoinFound,
|
||||
InvalidRequestFormat,
|
||||
ApiKeyInvalid
|
||||
}
|
||||
|
||||
public int NumApiRequests {
|
||||
get => _numApiRequests;
|
||||
set => this.RaiseAndSetIfChanged(ref _numApiRequests, value);
|
||||
}
|
||||
|
||||
private string _apiUri = "https://api.pcgs.com/publicapi";
|
||||
private readonly string _apiKey;
|
||||
private int _numApiRequests;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the PcgsClient class.
|
||||
/// Although this is a constructor, it's meant to be called only from the CreateClient method.
|
||||
/// </summary>
|
||||
private PcgsClient(string apiKey) {
|
||||
_apiKey = apiKey;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the PcgsClient class.
|
||||
/// </summary>
|
||||
/// <param name="apiKey">The api key to use for requests.</param>
|
||||
/// <returns>A new instance of the PcgsClient class, or null if the key is invalid.</returns>
|
||||
public static async Task<PcgsClient?> CreateClient(string apiKey) {
|
||||
// Check if the api key is valid.
|
||||
var testClient = new PcgsClient(apiKey);
|
||||
var validCreds = await testClient.VerifyCredentials();
|
||||
if (!validCreds) return null;
|
||||
return testClient;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a request to the API to verify the credentials.
|
||||
/// </summary>
|
||||
/// <returns>A boolean indicating whether or not the credentials are valid.</returns>
|
||||
public async Task<bool> VerifyCredentials() {
|
||||
// Create a way to check if the api key given is valid
|
||||
// I think the best way to do this is to make a request to the api and see if it returns the expected response.
|
||||
var result = await this.GetCoinFactsByGrade(1, "AG-03"); // This is a known invalid coin id - this is because the api is very fast with invalid requests.
|
||||
if (result.Item1 == ErrorType.ApiKeyInvalid) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the coin information for a given PCGS number and grade.
|
||||
/// </summary>
|
||||
/// <param name="pcgsNumber">The PCGS number of the coin.</param>
|
||||
/// <param name="grade">The grade of the coin.</param>
|
||||
/// <param name="plusGrade">Whether or not the coin is a plus grade.</param>
|
||||
/// <returns>A tuple containing the error type and the coin information.</returns>
|
||||
public async Task<(ErrorType, Coin?)> GetCoinFactsByGrade(int pcgsNumber, string grade, bool plusGrade = false) {
|
||||
using (HttpClient client = new HttpClient()) {
|
||||
var gradeParam = GetGradeFromString(grade);
|
||||
|
||||
string requestUri =
|
||||
$"{_apiUri}/coindetail/GetCoinFactsByGrade/?PCGSNo={pcgsNumber}&GradeNo={gradeParam}&PlusGrade={plusGrade}";
|
||||
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", _apiKey);
|
||||
Console.WriteLine($"Sending request to {requestUri}");
|
||||
HttpResponseMessage response = await client.GetAsync(requestUri);
|
||||
Console.WriteLine("Got response.");
|
||||
|
||||
if (response.IsSuccessStatusCode) {
|
||||
// Check response for errors.
|
||||
string jsonResponse = await response.Content.ReadAsStringAsync();
|
||||
var parsedResponse = ParseJsonResponse(jsonResponse);
|
||||
return parsedResponse;
|
||||
}
|
||||
}
|
||||
|
||||
return (ErrorType.ApiKeyInvalid, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Utility function to parse the grade number from the grade string passed from the front end.
|
||||
/// </summary>
|
||||
/// <param name="grade">The grade string.</param>
|
||||
/// <returns>The grade number.</returns>
|
||||
private int GetGradeFromString(string grade) {
|
||||
var actualGrade = int.Parse(grade.Substring(grade.Length - 2)); // Throws an exception if the grade doesn't exist.
|
||||
Console.WriteLine($"Grade is {actualGrade}");
|
||||
return actualGrade;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses the json response from the api.
|
||||
/// </summary>
|
||||
/// <param name="json">The json response.</param>
|
||||
/// <returns>A tuple containing an error type and the coin information.</returns>
|
||||
private (ErrorType, Coin?) ParseJsonResponse(string json) {
|
||||
Console.WriteLine(json);
|
||||
// Check for errors in the response
|
||||
if (json.Contains("\"ServerMessage\":\"No data found\"")) return (ErrorType.NoCoinFound, null);
|
||||
if (json.Contains("\"IsValidRequest\":false")) return (ErrorType.InvalidRequestFormat, null);
|
||||
|
||||
var newCoin = JsonSerializer.Deserialize<Coin>(json);
|
||||
return (ErrorType.None, newCoin);
|
||||
}
|
||||
}
|
||||
|
||||
// Exception for invalid request format
|
||||
class InvalidRequestFormatException : Exception {
|
||||
public InvalidRequestFormatException() { }
|
||||
public InvalidRequestFormatException(string message) : base(message) { }
|
||||
public InvalidRequestFormatException(string message, Exception inner) : base(message, inner) { }
|
||||
}
|
||||
|
||||
// Exception for no coin found
|
||||
class CoinNotFoundException : Exception {
|
||||
public CoinNotFoundException() { }
|
||||
public CoinNotFoundException(string message) : base(message) { }
|
||||
public CoinNotFoundException(string message, Exception inner) : base(message, inner) { }
|
||||
}
|
||||
Reference in new issue
Block a user