public async Task Export(WeissSchwarzDeck deck, IExportInfo info)
        {
            Log.Information("Serializing: {name}", deck.Name);

            using (var db = _database())
            {
                Log.Information("Replacing all foils with non-foils...");
                foreach (var card in deck.Ratios.Keys)
                {
                    if (card.IsFoil)
                    {
                        deck.ReplaceCard(card, await db.FindNonFoil(card));
                    }
                }
            }

            Log.Information("Creating deck.cod...");
            var cckDeck = new CockatriceDeck();

            cckDeck.DeckName      = deck.Name;
            cckDeck.Comments      = deck.Remarks;
            cckDeck.Ratios        = new CockatriceDeckRatio();
            cckDeck.Ratios.Ratios = deck.Ratios.Select(Translate).ToList();

            var resultDeck = Path.CreateDirectory(info.Destination).Combine($"{deck.Name?.AsFileNameFriendly() ?? "deck"}.cod");

            resultDeck.Open(s => _serializer.Serialize(s, cckDeck),
                            System.IO.FileMode.Create,
                            System.IO.FileAccess.Write,
                            System.IO.FileShare.ReadWrite
                            );
            Log.Information($"Saved: {resultDeck.FullPath}");
        }
Ejemplo n.º 2
0
        public async Task <WeissSchwarzDeck> Inspect(WeissSchwarzDeck deck, InspectionOptions options)
        {
            Log.Debug("Starting...");
            var keyCards      = deck.Ratios.Keys.Where(c => ((!c.Images?.Any()) ?? false) && String.IsNullOrWhiteSpace(c.CachedImagePath));
            var inspectedDeck = deck.Clone();

            foreach (var card in keyCards)
            {
                Log.Information("{serial} has no image URL nor a cached image. This deck cannot be exported without an image. Do you want to supply an image instead? [Y/N] (Default is N)", card.Serial);
                if (ConsoleUtils.Prompted(options.IsNonInteractive, false))
                {
                    if (inspectedDeck.ReplaceCard(card, await AddImageFromConsole(card, options)))
                    {
                        Log.Information("Checking for other missing images (if any)...");
                    }
                    else
                    {
                        return(WeissSchwarzDeck.Empty);
                    }
                }
                else
                {
                    Log.Information("Selected No; inspection failed.");
                    return(WeissSchwarzDeck.Empty);
                }
            }
            Log.Debug("Finished inspection.");
            return(inspectedDeck);
        }
        public async Task <WeissSchwarzDeck> Inspect(WeissSchwarzDeck deck, InspectionOptions options)
        {
            Log.Information("Starting...");
            var imageFolder = Path.Get(_imageCachePath);

            try
            {
                foreach (var card in deck.Ratios.Keys)
                {
                    try
                    {
                        var serialImage = imageFolder
                                          .Files($"{card.Serial.Replace('-', '_').AsFileNameFriendly()}.*", true)
                                          .WhereExtensionIs(".png", ".jpeg", ".jpg", "jfif")
                                          .First();
                        var relativeFileName = _imageCachePath + serialImage.FileName;
                        serialImage = await InspectImage(serialImage, relativeFileName);

                        if (serialImage != null)
                        {
                            Log.Information($"Using cached image: {serialImage}");
                            card.CachedImagePath = serialImage.FullPath;
                        }
                    } catch (InvalidOperationException)
                    {
                        // Do nothing.
                    }
                }
            } catch (System.IO.DirectoryNotFoundException)
            {
                // Do nothing.
            }
            return(deck);
        }
        public async Task <WeissSchwarzDeck> Inspect(WeissSchwarzDeck deck, InspectionOptions options)
        {
            var allEmptyTranslations = deck.Ratios.Keys.Where(card => String.IsNullOrWhiteSpace(card.Name.EN))
                                       .Select(card => card.ReleaseID)
                                       .Distinct();

            if (allEmptyTranslations.Any())
            {
                Log.Warning("The following sets (based on Release ID) do not have proper English translations: {allEmptyTranslations}", allEmptyTranslations.ToList());
                Log.Warning("This may result in a deck generator with only Japanese text.");
                Log.Warning("Do you wish to continue? [Y/N] (Default is N)");
                if (ConsoleUtils.Prompted(options.IsNonInteractive, options.NoWarning))
                {
                    return(deck);
                }
                else
                {
                    Log.Information("Operation cancelled.");
                    Log.Information("If you need to add card data from other sources, use this command: {command}", "wstools parse link_url");
                    Log.Information("For more information, please see: {url}", new Uri("https://github.com/ronelm2000/wsmtools"));
                    return(WeissSchwarzDeck.Empty);
                }
            }
            else
            {
                await Task.CompletedTask; //placebo way to stop warning about async/await
                return(deck);
            }
        }
Ejemplo n.º 5
0
        public async Task <WeissSchwarzDeck> Parse(string sourceUrlOrFile)
        {
            var        filePath = Path.Get(sourceUrlOrFile);
            SimpleDeck deckJSON = null;

            deckJSON = JsonSerializer.Deserialize <SimpleDeck>(filePath.ReadBytes());
            WeissSchwarzDeck deck = new WeissSchwarzDeck();

            deck.Name    = deckJSON.Name;
            deck.Remarks = deckJSON.Remarks;
            using (var db = _database())
            {
                await db.Database.MigrateAsync();

                foreach (var serial in deckJSON.Ratios.Keys)
                {
                    var card = await db.WeissSchwarzCards.FindAsync(serial);

                    if (card == null)
                    {
                        Log.Error("This card is missing in your local card db: {serial}", serial);
                        Log.Error("You must obtain information about this card first using the command {cmd}", "./wstools parse");
                        return(WeissSchwarzDeck.Empty);
                    }
                    else
                    {
                        deck.Ratios[card] = deckJSON.Ratios[serial];
                    }
                }
            }
            return(deck);
        }
Ejemplo n.º 6
0
    public WeissSchwarzDeck Clone()
    {
        var res = new WeissSchwarzDeck();

        res.Ratios  = this.Ratios.ToDictionary(kyd => kyd.Key, kyd => kyd.Value);
        res.Name    = this.Name;
        res.Remarks = this.Remarks;
        return(res);
    }
Ejemplo n.º 7
0
 internal void ReportParsedDeckData(WeissSchwarzDeck newDeck)
 {
     report = report with {
         Percentage = 10, ReportMessage = new MultiLanguageString {
             EN = $"Found Deck [{newDeck.Name}] [{newDeck.Remarks}]"
         }
     };
     progress.Report(report);
 }
Ejemplo n.º 8
0
        public async Task <WeissSchwarzDeck> Inspect(WeissSchwarzDeck deck, InspectionOptions options)
        {
            var allEmptyTranslations = deck.Ratios.Keys.Where(card => String.IsNullOrWhiteSpace(card.Name.EN))
                                       .Select(card => card.ReleaseID)
                                       .Distinct();
            var setsWithTranslations = deck.Ratios.Keys.Where(card => !String.IsNullOrWhiteSpace(card.Name.EN))
                                       .Select(card => card.ReleaseID)
                                       .Distinct()
                                       .ToList();
            var allNonTranslatedCards = deck.Ratios.Keys.Where(card => String.IsNullOrWhiteSpace(card.Name.EN))
                                        //.Select(card => card.Serial)
                                        .Distinct()
                                        .ToList();

            if (allEmptyTranslations.Any())
            {
                if (setsWithTranslations.Any(rid => allEmptyTranslations.Contains(rid)))
                {
                    Log.Warning("The following cards have missing translations: {allNonTranslatedCards}", allNonTranslatedCards.Select(card => card.Serial).ToList());
                    Log.Warning("These are very likely untranslated PRs, please go back and manually export PRs using any of the ff. where applicable and retry:\n" +
                                "\t./wstools export https://www.heartofthecards.com/translations/schwarz_promos.html\n" +
                                "\t./wstools export https://www.heartofthecards.com/translations/weiss_promos.html");
                    Log.Warning("Note that to avoid too much bandwidth, images are not exported this way. You will need to put an image manually on the Images sub-folder. The process to improve this process is still in progress.");
                    return(WeissSchwarzDeck.Empty);
                }
                else
                {
                    Log.Warning("The following sets (based on Release ID) do not have proper English translations: {allEmptyTranslations}", allEmptyTranslations.ToList());
                    Log.Warning("Cards with missing EN Translations: {allNonTranslatedCards}", allNonTranslatedCards.Select(card => card.Serial).ToList());
                    Log.Warning("This may result in a deck generator with only Japanese text.");
                    Log.Warning("Do you wish to continue? [Y/N] (Default is N)");
                    if (ConsoleUtils.Prompted(options.IsNonInteractive, options.NoWarning))
                    {
                        return(deck);
                    }
                    else
                    {
                        Log.Information("Operation cancelled.");
                        Log.Information("If you need to add card data from other sources, use this command: {command}", "wstools parse link_url");
                        Log.Information("For more information, please see: {url}", new Uri("https://github.com/ronelm2000/wsmtools"));
                        return(WeissSchwarzDeck.Empty);
                    }
                }
            }
            else
            {
                await Task.CompletedTask; //placebo way to stop warning about async/await
                return(deck);
            }
        }
Ejemplo n.º 9
0
        private async Task <WeissSchwarzDeck> Parse(Uri uri)
        {
            var encoreDecksDeckAPIURL = "https://www.encoredecks.com/api/deck";

            var localPath = uri.LocalPath;
            var deckID    = localPath.Substring(localPath.LastIndexOf('/') + 1);

            Log.Information("Deck ID: {deckID}", deckID);

            dynamic deckJSON = await GetDeckJSON(encoreDecksDeckAPIURL, deckID);

            WeissSchwarzDeck res = new WeissSchwarzDeck();

            res.Name = deckJSON.name;

            using (var db = _database())
            {
                await db.Database.MigrateAsync();

                foreach (dynamic card in deckJSON.cards)
                {
                    string           serial = WeissSchwarzCard.GetSerial(card.set.ToString(), card.side.ToString(), card.lang.ToString(), card.release.ToString(), card.sid.ToString());
                    WeissSchwarzCard wscard = await db.WeissSchwarzCards.FindAsync(serial);

                    if (wscard == null)
                    {
                        string setID = card.series;
                        await _parse($"https://www.encoredecks.com/api/series/{setID}/cards");

                        wscard = await db.WeissSchwarzCards.FindAsync(serial);
                    }

                    if (res.Ratios.TryGetValue(wscard, out int quantity))
                    {
                        res.Ratios[wscard]++;
                    }
                    else
                    {
                        res.Ratios[wscard] = 1;
                    }

                    //Log.Information("Parsed: {@wscard}", wscard);
                }
            }
            var simpleRatios = res.AsSimpleDictionary();

            Log.Information("Deck Parsed: {@simpleRatios}", simpleRatios);
            Log.Information("Cards in Deck: {@count}", simpleRatios.Values.Sum());
            return(res);
        }
Ejemplo n.º 10
0
        public async Task <WeissSchwarzDeck> Parse(string sourceUrlOrFile)
        {
            Log.Information("Parsing: {source}", sourceUrlOrFile);
            var file       = Fluent.IO.Path.Get(sourceUrlOrFile);
            var serializer = new XmlSerializer(typeof(CockatriceDeck));

            using (var stream = file.GetStream())
            {
                var cockatriceDeck = serializer.Deserialize(stream) as CockatriceDeck;
                var result         = new WeissSchwarzDeck();
                result.Name    = cockatriceDeck.DeckName;
                result.Remarks = cockatriceDeck.Comments;
                result.Ratios  = cockatriceDeck.Ratios.Ratios.Select(Translate).ToDictionary(p => p.card, p => p.amount);
                return(await Task.FromResult(result));
            }
        }
Ejemplo n.º 11
0
        public async Task <WeissSchwarzDeck> Inspect(WeissSchwarzDeck deck, InspectionOptions options)
        {
            var englishEditionCards = deck.Ratios.Keys.Where(card => card.EnglishSetType == EnglishSetType.EnglishEdition);

            if (HeededWarningOnEnglishEditionSets(englishEditionCards, options))
            {
                return(WeissSchwarzDeck.Empty);
            }

            var japaneseImportCards = deck.Ratios.Keys.Where(card => card.EnglishSetType == EnglishSetType.JapaneseImport);

            if (HeededWarningOnJapaneseImports(japaneseImportCards, options))
            {
                return(WeissSchwarzDeck.Empty);
            }

            return(await Task.FromResult(deck));
        }
Ejemplo n.º 12
0
        private async Task <WeissSchwarzDeck> ParseFromCSV(string sourceCSV)
        {
            WeissSchwarzDeck res = new WeissSchwarzDeck();

            using (var db = _database())
                foreach (var row in ParseCSV(sourceCSV, b => b.SetDelimiters(",")))
                {
                    if (row[0] == "Code")
                    {
                        continue;
                    }
                    var card = await db.WeissSchwarzCards.FindAsync(row[0]);

                    var quantity = row[1].AsParsed <int>(int.TryParse).GetValueOrDefault(0);
                    res.Ratios.Add(card, quantity);
                }

            res.Remarks = (res.Remarks ?? "") + $"\nParsed: {this.GetType().Name}";
            res.Remarks = res.Remarks.Trim();
            return(res);
        }
Ejemplo n.º 13
0
        public async Task Export(WeissSchwarzDeck deck, IExportInfo info)
        {
            Log.Information("Exporting as Deck JSON.");
            var jsonFilename   = Path.CreateDirectory(info.Destination).Combine($"deck_{deck.Name.AsFileNameFriendly()}.json");
            var simplifiedDeck = new
            {
                Name    = deck.Name,
                Remarks = deck.Remarks,
                Ratios  = deck.AsSimpleDictionary()
            };

            jsonFilename.Open(
                async s => await JsonSerializer.SerializeAsync(s, simplifiedDeck, options: _defaultOptions),
                System.IO.FileMode.Create,
                System.IO.FileAccess.Write,
                System.IO.FileShare.ReadWrite
                );
            Log.Information($"Done: {jsonFilename.FullPath}");

            if (!String.IsNullOrWhiteSpace(info.OutCommand))
            {
                await ExecuteCommandAsync(info.OutCommand, jsonFilename);
            }
        }
Ejemplo n.º 14
0
 public static DeckParserProgressReport ObtainedParseDeckData(this DeckParserProgressReport report, WeissSchwarzDeck deck)
 {
     return(report with
     {
         Percentage = 10,
         ReportMessage = new Card.API.Entities.Impls.MultiLanguageString {
             EN = $"Obtained data for [{deck.Name}]"
         }
     });
 }
Ejemplo n.º 15
0
 public static DeckParserProgressReport SuccessfullyParsedDeck(this DeckParserProgressReport report, WeissSchwarzDeck deck)
 {
     return(report with
     {
         Percentage = 100,
         ReportMessage = new Card.API.Entities.Impls.MultiLanguageString {
             EN = $"Successfully Parsed [{deck.Name}]"
         }
     });
 }
Ejemplo n.º 16
0
        public async Task <WeissSchwarzDeck> Parse(string sourceUrlOrFile)
        {
            var document = await sourceUrlOrFile.WithHTMLHeaders().GetHTMLAsync();

            //var deckView = document.QuerySelector(".deckview");
            //var cardControllers = deckView.QuerySelectorAll(".card-controller-inner");
            var deckID = urlMatcher.Match(sourceUrlOrFile).Groups[2];

            Log.Information("Parsing ID: {deckID}", deckID);
            var response = await $"{deckLogApiUrlPrefix}{deckID}" //
                           .WithReferrer(sourceUrlOrFile)         //
                           .PostJsonAsync(null);
            var json = JsonConvert.DeserializeObject <dynamic>(await response.Content.ReadAsStringAsync());
            //var json = JsonConverter.CreateDefault().Deserialize<dynamic>(new JsonReader(await response.Content.ReadAsStreamAsync()));
            var newDeck        = new WeissSchwarzDeck();
            var missingSerials = new List <string>();

            newDeck.Name    = json.title.ToString();
            newDeck.Remarks = json.memo.ToString();
            using (var db = _database())
            {
                List <dynamic> items = new List <dynamic>();
                items.AddRange(json.list);
                items.AddRange(json.sub_list);
                foreach (var cardJSON in items)
                {
                    string serial = cardJSON.card_number.ToString();
                    serial = serial.Replace('+', '+');
                    if (serial == null)
                    {
                        Log.Warning("serial is null for some reason!");
                    }
                    var card = await db.WeissSchwarzCards.FindAsync(serial);

                    int quantity = cardJSON.num;
                    if (card != null)
                    {
                        Log.Debug("Adding: {card} [{quantity}]", card?.Serial, quantity);
                        if (newDeck.Ratios.TryGetValue(card, out int oldVal))
                        {
                            newDeck.Ratios[card] = oldVal + quantity;
                        }
                        else
                        {
                            var url = awsWeissSchwarzSitePrefix + cardJSON.img;
                            Log.Debug("Adding URL into Images: {url}", url);
                            card.Images.Add(new Uri(url));
                            newDeck.Ratios.Add(card, quantity);
                        }
                    }
                    else
                    {
                        missingSerials.Add(serial);
                        //throw new DeckParsingException($"MISSING_SERIAL_{serial}");
                        Log.Warning("Serial has been effectively skipped because it's not found on the local db: [{serial}]", serial);
                    }
                }
            }
            if (missingSerials.Count > 0)
            {
                throw new DeckParsingException($"The following serials are missing from the DB:\n{missingSerials.ConcatAsString("\n")}");
            }
            else
            {
                Log.Debug($"Result Deck: {JsonConvert.SerializeObject(newDeck.AsSimpleDictionary())}");
                return(newDeck);
            }
        }
Ejemplo n.º 17
0
 internal void ReportSuccessfulParsedDeckData(WeissSchwarzDeck newDeck)
 {
     report = report.SuccessfullyParsedDeck(newDeck);
     progress.Report(report);
 }