private static void ExecuteDelete(ProgramParameters parameters, CloudTable cardsTable, CloudTable indexTable) { TableUtils <MonsterCardEntity> cardUtils = new TableUtils <MonsterCardEntity>(cardsTable); TableUtils <IndexByMonsterEntity> indexUtils = new TableUtils <IndexByMonsterEntity>(indexTable); Console.Write("Retrieving entities to be deleted..."); var cards = cardsTable.ExecuteQuery <MonsterCardEntity>(new TableQuery <MonsterCardEntity>()).Where(e => { return(e.RowKey.StartsWith(parameters.CardName)); }).ToList(); Console.WriteLine($"done\n{cards.Count} entries found."); foreach (MonsterCardEntity card in cards) { string option; Console.WriteLine($"**************\n{card}\n**************\nIf you confirm deletion, this card and all its index entries will be deleted."); option = ReadOption("Are you sure (y/n)? ", "Y", "y", "yes", "Yes", "N", "n", "No", "no"); switch (option) { case "y": case "Y": case "yes": case "Yes": { Console.Write("Searching related index entries..."); var indexEntries = indexTable.ExecuteQuery(new TableQuery <IndexByMonsterEntity>()).Where((e) => { return(e.RowKey.Equals(card.RowKey)); }).ToList(); Console.WriteLine($"done\n{indexEntries.Count} entr{(indexEntries.Count == 1 ? "y" : "ies")} found."); Console.Write("Deleting card entry..."); cardUtils.DeleteEntityAsync(card).GetAwaiter().GetResult(); Console.WriteLine("done"); Console.Write("Deleting index entries..."); foreach (IndexByMonsterEntity indexEntry in indexEntries) { indexUtils.DeleteEntityAsync(indexEntry).GetAwaiter().GetResult(); } Console.WriteLine("done"); } break; default: { Console.Write("Skipping this entry. "); } break; } AddContinuation(); } }
private static void ExecuteFind(ProgramParameters parameters, CloudTable cardsTable) { Console.Write("Querying cards table..."); var entities = cardsTable.ExecuteQuery(new TableQuery <MonsterCardEntity>()).Where((item) => { return (item.PartitionKey.Contains(parameters.CardName, StringComparison.InvariantCultureIgnoreCase) || item.RowKey.Contains(parameters.CardName, StringComparison.InvariantCultureIgnoreCase)); }).ToList(); Console.WriteLine($"done\n{entities.Count} entr{(entities.Count != 1 ? "ies" : "y")} found.\n\n*******************"); foreach (MonsterCardEntity entity in entities) { Console.WriteLine($"{entity}\n*******************"); AddContinuation(); } }
static ProgramParameters ParseParameters(string[] args, out bool verbose) { ProgramParameters result = new ProgramParameters(); bool expectType = false, expectName = false, expectFile = false; verbose = false; foreach (string arg in args) { Trace.TraceInformation($"Parsing argument {arg}, operation: {result}"); if (result.Operation == OperationRequested.Invalid) { break; } switch (arg) { case "-v": case "/v": case "--verbose": { verbose = true; } break; case "-add": { if (result.Operation != OperationRequested.Unknown) { result.Operation = OperationRequested.Invalid; } else { result.Operation = OperationRequested.Add; expectType = true; } } break; case "-l": { if (result.Operation != OperationRequested.Unknown) { result.Operation = OperationRequested.Invalid; } else { result.Operation = OperationRequested.List; } } break; case "-del": { if (result.Operation != OperationRequested.Unknown) { result.Operation = OperationRequested.Invalid; } else { result.Operation = OperationRequested.Delete; expectName = true; } } break; case "-find": { if (result.Operation != OperationRequested.Unknown) { result.Operation = OperationRequested.Invalid; } else { result.Operation = OperationRequested.Find; expectName = true; } } break; case "--rebuild-indexes": { if (result.Operation != OperationRequested.Unknown) { result.Operation = OperationRequested.Invalid; } else { result.Operation = OperationRequested.RebuildIndexes; } } break; case "--dump": { if (result.Operation != OperationRequested.Unknown) { result.Operation = OperationRequested.Invalid; } else { result.Operation = OperationRequested.DumpTables; expectFile = true; } } break; case "--upload": { if (result.Operation != OperationRequested.Unknown) { result.Operation = OperationRequested.Invalid; } else { result.Operation = OperationRequested.RebuildTables; expectFile = true; } } break; default: if (expectType) { if (Enum.TryParse(arg, out CardType type)) { result.CardType = type; expectType = false; } else { result.Operation = OperationRequested.Invalid; expectType = false; } } else if (expectName) { result.CardName = arg; expectName = false; } else if (expectFile) { result.DataFile = arg; expectFile = false; } else { result.Operation = OperationRequested.Invalid; } break; } } if (result.Operation == OperationRequested.Unknown || expectType || expectName || expectFile) { result.Operation = OperationRequested.Invalid; } return(result); }
private static void ExecuteAdd(ProgramParameters parameters, CloudTable cardsTable, CloudTable indexTable) { MonsterCardEntity monsterCard = new MonsterCardEntity(); IndexByMonsterEntity indexCard = new IndexByMonsterEntity(); TableUtils <MonsterCardEntity> cardUtils = new TableUtils <MonsterCardEntity>(cardsTable); TableUtils <IndexByMonsterEntity> indexUtils = new TableUtils <IndexByMonsterEntity>(indexTable); monsterCard.PartitionKey = parameters.CardType.ToString(); indexCard.CardType = parameters.CardType.ToString(); monsterCard.RowKey = ReadNotEmptyLine("Card name: "); MonsterCardEntity existingCard = cardUtils.RetrieveEntityUsingPointQueryAsync(monsterCard.PartitionKey, monsterCard.RowKey).GetAwaiter().GetResult(); if (existingCard != null) { Console.WriteLine($"Entry '{monsterCard.PartitionKey} {monsterCard.RowKey}' already exists in database. If you continue, existing entry will be REPLACED."); string option = ReadOption("Continue (yes/no)? ", "Y", "y", "yes", "Yes", "N", "n", "No", "no"); switch (option) { case "N": case "n": case "no": case "No": { Console.WriteLine("Aborted by user."); return; } } } indexCard.RowKey = monsterCard.RowKey; monsterCard.Expansion = ReadNotEmptyLine("Expansion: "); monsterCard.Versions = ReadNotEmptyLine("Versions: "); if (parameters.CardType != CardType.StrangeResource && parameters.CardType != CardType.BasicResource && parameters.CardType != CardType.Universal && parameters.CardType != CardType.BasicHuntEvent && parameters.CardType != CardType.SpecialHuntEvent) { indexCard.PartitionKey = ReadNotEmptyLine("Monster: "); } switch (parameters.CardType) { case CardType.AI: case CardType.Universal: { monsterCard.AILevel = ReadNotEmptyLine("AI Level: "); Console.Write("AI card types (if any): "); monsterCard.AITypes = Console.ReadLine(); monsterCard.CardText = ReadNotEmptyLine("Card Text: "); } break; case CardType.MonsterResource: case CardType.BasicResource: case CardType.StrangeResource: { monsterCard.ResourceKeywords = ReadNotEmptyLine("Keywords: "); monsterCard.CardText = ReadNotEmptyLine("Card Text: "); } break; case CardType.HitLocation: { Console.Write("HL types (if any): "); monsterCard.HLTypes = Console.ReadLine(); Console.Write("Card text (if any): "); monsterCard.CardText = Console.ReadLine(); Console.Write("Reaction - Failure (if any): "); monsterCard.HLReactionFailure = Console.ReadLine(); Console.Write("Reaction - Wound (if any): "); monsterCard.HLReactionWound = Console.ReadLine(); Console.Write("Reaction - Reflex (if any): "); monsterCard.HLReactionReflex = Console.ReadLine(); Console.Write("Critical Wound text (if any): "); monsterCard.HLCriticalText = Console.ReadLine(); } break; case CardType.HuntEvent: case CardType.SpecialHuntEvent: case CardType.BasicHuntEvent: { monsterCard.EventSubtitle = ReadNotEmptyLine("Event subtitle: "); monsterCard.CardText = ReadNotEmptyLine("Card text: "); Console.Write("Event bottom text (if any): "); monsterCard.EventBottomText = Console.ReadLine(); } break; default: { Trace.TraceError($"Unable to parse CardType '{parameters.CardType}'"); return; } } monsterCard.Multiplicity = ReadInt("# of cards (default 1): ", 1); Trace.TraceInformation($"Adding to database: [{monsterCard}]"); Console.WriteLine($"*************\n{monsterCard}\n*************"); cardUtils.InsertOrMergeEntityAsync(monsterCard, true).GetAwaiter().GetResult(); if (parameters.CardType != CardType.BasicResource && parameters.CardType != CardType.StrangeResource && parameters.CardType != CardType.Universal && parameters.CardType != CardType.BasicHuntEvent && parameters.CardType != CardType.SpecialHuntEvent) { indexUtils.InsertOrMergeEntityAsync(indexCard, true).GetAwaiter().GetResult(); } Console.WriteLine("Data added."); }
static void Main(string[] args) { AppSettings settings = null; CloudStorageAccount account = null; CloudTable cardsTable = null, indexTable = null, monsterTable = null; ProgramParameters parameters = ParseParameters(args, out bool verbose); if (parameters.Operation == OperationRequested.Invalid) { Console.WriteLine("Usage:\n\tkdacli (-add {type} | -del \"card name\" | -l | -find {\"card name\"|cardType} | --rebuild-indexes | --dump {file}| --upload {file})[-v | --verbose]"); Environment.Exit(-1); } try { Out("Loading application settings...", verbose); settings = AppSettings.LoadAppSettings(); OutL($"done\nSAS Token in use: {settings.SASToken}\nStorage account: {settings.StorageAccountName}", verbose); } catch (Exception ex) { Trace.TraceError($"Error loading application settings:\n{ex}"); OutL($"error\nFailed to load application settings ({ex.Message})", verbose); Environment.Exit(-1); } try { Out("Logging in to storage account...", verbose); account = Common.CreateStorageAccountFromSASToken(settings.SASToken, settings.StorageAccountName); OutL("done\n", verbose); } catch (Exception ex) { Trace.TraceError($"Error logging in to storage account:\n{ex}"); OutL($"error\nLogin failed ({ex.Message})", verbose); Environment.Exit(-1); } cardsTable = Task.Run(async() => await Common.CreateTableAsync(account, cardsTableName)).GetAwaiter().GetResult(); indexTable = Task.Run(async() => await Common.CreateTableAsync(account, indexTableName)).GetAwaiter().GetResult(); monsterTable = Task.Run(async() => await Common.CreateTableAsync(account, monsterTableName)).GetAwaiter().GetResult(); switch (parameters.Operation) { case OperationRequested.Add: { ExecuteAdd(parameters, cardsTable, indexTable); } break; case OperationRequested.List: { ExecuteList(cardsTable, indexTable); } break; case OperationRequested.Find: { ExecuteFind(parameters, cardsTable); } break; case OperationRequested.Delete: { ExecuteDelete(parameters, cardsTable, indexTable); } break; case OperationRequested.RebuildIndexes: { ExecuteRebuildIndexes(cardsTable, indexTable); } break; case OperationRequested.DumpTables: { List <CloudTable> tables = new List <CloudTable>(); List <string> names = new List <string>(); ExecuteDump(cardsTable, indexTable, monsterTable, parameters.DataFile); } break; case OperationRequested.RebuildTables: { ExecuteUpload(account, parameters.DataFile); } break; } }