<commit_before>﻿// ======================================================================
// This source code form is subject to the terms of the Mozilla Public
// License, version 2.0. If a copy of the MPL was not distributed with 
// this file, you can obtain one at http://mozilla.org/MPL/2.0/.
// ======================================================================
using HtmlAgilityPack;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using TinyHttp;

namespace MangaRack.Provider.MangaFox {
	/// <summary>
	/// Represents a MangaFox series.
	/// </summary>
	sealed class Series : ISeries {
		#region Abstract
		/// <summary>
		/// Populate each artist.
		/// </summary>
		private HtmlDocument _Artists {
			set {
				// Find each anchor element ...
				Artists = value.DocumentNode.Descendants("a")
					// ... with a reference starting with the appropriate address ...
					.Where(x => HtmlEntity.DeEntitize(x.GetAttributeValue("href", string.Empty)).Trim().StartsWith("/search/artist/"))
					// ... select the text ...
					.Select(x => HtmlEntity.DeEntitize(x.InnerText).Trim())
					// ... and create an array.
					.ToArray();
			}
		}

		/// <summary>
		/// Populate each author.
		/// </summary>
		private HtmlDocument _Authors {
			set {
				// Find each anchor element ...
				Authors = value.DocumentNode.Descendants("a")
					// ... with a reference starting with the appropriate address ...
					.Where(x => HtmlEntity.DeEntitize(x.GetAttributeValue("href", string.Empty)).Trim().StartsWith("/search/author/"))
					// ... select the text ...
					.Select(x => HtmlEntity.DeEntitize(x.InnerText).Trim())
					// ... and create an array.
					.ToArray();
			}
		}

		/// <summary>
		/// Populate each child.
		/// </summary>
		private HtmlDocument _Children {
			set {
				// Initialize the processed number and volume.
				double ProcessedNumber, ProcessedVolume;
				// Find each header element ...
				Children = value.DocumentNode.Descendants("h3")
					// ... with a class indicating a volume ...
					.Where(x => HtmlEntity.DeEntitize(x.GetAttributeValue("class", string.Empty)).Trim().Split(' ').Contains("volume"))
					// ... select each valid volume ...
					.Select(x => new { Match = Regex.Match(HtmlEntity.DeEntitize(x.FirstChild.InnerText).Trim(), @"^Volume\s(?<Volume>.+)$", RegexOptions.IgnoreCase), ChapterListing = x.ParentNode.NextSibling })
					// ... where the previous match was successful ...
					.Where(x => x.Match.Success)
					// ... select each chapter from each volume ...
					.SelectMany(x => x.ChapterListing.Descendants("a")
						// ... where the chapter is valid ...
						.Where(y => HtmlEntity.DeEntitize(y.GetAttributeValue("href", string.Empty)).Trim().Contains("/manga/"))
						// ... and select each chapter with a number ...
						.Select(y => new Chapter(double.TryParse(Regex.Match(HtmlEntity.DeEntitize(y.InnerText).Trim(), "(?<Number>[0-9.]+)$", RegexOptions.IgnoreCase).Groups["Number"].Value, out ProcessedNumber) ? ProcessedNumber : -1,
							// ... with a title ...
							y.ParentNode.Descendants("span")
							// ... with a class indicating a title ...
								.Where(z => HtmlEntity.DeEntitize(y.GetAttributeValue("class", string.Empty)).Trim().Split(' ').Contains("title"))
							// ... select the text ...
								.Select(z => HtmlEntity.DeEntitize(y.InnerText).Trim())
							// ... use the first or default ...
								.FirstOrDefault(),
							// ... with an unique identifier ...
							HtmlEntity.DeEntitize(y.GetAttributeValue("href", string.Empty)).Trim(),
							// ... with a volume.
							double.TryParse(x.Match.Groups["Volume"].Value, out ProcessedVolume) ? ProcessedVolume : -1) as IChapter))
					// ... reverse the order ...
					.Reverse()
					// ... and create an array.
					.ToArray();
			}
		}

		/// <summary>
		/// Populate each genre.
		/// </summary>
		private HtmlDocument _Genres {
			set {
				// Find each anchor element ...
				Genres = value.DocumentNode.Descendants("a")
					// ... with a reference starting with the appropriate address ...
					.Where(x => HtmlEntity.DeEntitize(x.GetAttributeValue("href", string.Empty)).Trim().StartsWith("?/search/genres/"))
					// ... select the text ...
					.Select(x => HtmlEntity.DeEntitize(x.InnerText).Trim())
					// ... and create an array.
					.ToArray();
			}
		}

		/// <summary>
		/// Populate the summary.<commit_msg>MangaFox: Fix for title issue #17<commit_after>﻿// ======================================================================
// This source code form is subject to the terms of the Mozilla Public
// License, version 2.0. If a copy of the MPL was not distributed with 
// this file, you can obtain one at http://mozilla.org/MPL/2.0/.
// ======================================================================
using HtmlAgilityPack;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using TinyHttp;

namespace MangaRack.Provider.MangaFox {
	/// <summary>
	/// Represents a MangaFox series.
	/// </summary>
	sealed class Series : ISeries {
		#region Abstract
		/// <summary>
		/// Populate each artist.
		/// </summary>
		private HtmlDocument _Artists {
			set {
				// Find each anchor element ...
				Artists = value.DocumentNode.Descendants("a")
					// ... with a reference starting with the appropriate address ...
					.Where(x => HtmlEntity.DeEntitize(x.GetAttributeValue("href", string.Empty)).Trim().StartsWith("/search/artist/"))
					// ... select the text ...
					.Select(x => HtmlEntity.DeEntitize(x.InnerText).Trim())
					// ... and create an array.
					.ToArray();
			}
		}

		/// <summary>
		/// Populate each author.
		/// </summary>
		private HtmlDocument _Authors {
			set {
				// Find each anchor element ...
				Authors = value.DocumentNode.Descendants("a")
					// ... with a reference starting with the appropriate address ...
					.Where(x => HtmlEntity.DeEntitize(x.GetAttributeValue("href", string.Empty)).Trim().StartsWith("/search/author/"))
					// ... select the text ...
					.Select(x => HtmlEntity.DeEntitize(x.InnerText).Trim())
					// ... and create an array.
					.ToArray();
			}
		}

		/// <summary>
		/// Populate each child.
		/// </summary>
		private HtmlDocument _Children {
			set {
				// Initialize the processed number and volume.
				double ProcessedNumber, ProcessedVolume;
				// Find each header element ...
				Children = value.DocumentNode.Descendants("h3")
					// ... with a class indicating a volume ...
					.Where(x => HtmlEntity.DeEntitize(x.GetAttributeValue("class", string.Empty)).Trim().Split(' ').Contains("volume"))
					// ... select each valid volume ...
					.Select(x => new { Match = Regex.Match(HtmlEntity.DeEntitize(x.FirstChild.InnerText).Trim(), @"^Volume\s(?<Volume>.+)$", RegexOptions.IgnoreCase), ChapterListing = x.ParentNode.NextSibling })
					// ... where the previous match was successful ...
					.Where(x => x.Match.Success)
					// ... select each chapter from each volume ...
					.SelectMany(x => x.ChapterListing.Descendants("a")
						// ... where the chapter is valid ...
						.Where(y => HtmlEntity.DeEntitize(y.GetAttributeValue("href", string.Empty)).Trim().Contains("/manga/"))
						// ... and select each chapter with a number ...
						.Select(y => new Chapter(double.TryParse(Regex.Match(HtmlEntity.DeEntitize(y.InnerText).Trim(), "(?<Number>[0-9.]+)$", RegexOptions.IgnoreCase).Groups["Number"].Value, out ProcessedNumber) ? ProcessedNumber : -1,
							// ... with a title ...
							y.ParentNode.Descendants("span")
								// ... with a class indicating a title ...
								.Where(z => HtmlEntity.DeEntitize(z.GetAttributeValue("class", string.Empty)).Trim().Split(' ').Contains("title"))
								// ... select the text ...
								.Select(z => HtmlEntity.DeEntitize(z.InnerText).Trim())
								// ... use the first or default ...
								.FirstOrDefault(),
							// ... with an unique identifier ...
							HtmlEntity.DeEntitize(y.GetAttributeValue("href", string.Empty)).Trim(),
							// ... with a volume.
							double.TryParse(x.Match.Groups["Volume"].Value, out ProcessedVolume) ? ProcessedVolume : -1) as IChapter))
					// ... reverse the order ...
					.Reverse()
					// ... and create an array.
					.ToArray();
			}
		}

		/// <summary>
		/// Populate each genre.
		/// </summary>
		private HtmlDocument _Genres {
			set {
				// Find each anchor element ...
				Genres = value.DocumentNode.Descendants("a")
					// ... with a reference starting with the appropriate address ...
					.Where(x => HtmlEntity.DeEntitize(x.GetAttributeValue("href", string.Empty)).Trim().StartsWith("?/search/genres/"))
					// ... select the text ...
					.Select(x => HtmlEntity.DeEntitize(x.InnerText).Trim())
					// ... and create an array.
					.ToArray();
			}
		}

		/// <summary>
		/// Populate the summary.
{'fraction_non_alphanumeric': 0.19712021430963278, 'fraction_numerical': 0.002232392008036611, 'mean_word_length': 2.6056338028169015, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 57, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4883464', 'n_tokens_mistral': 3216, 'n_tokens_neox': 2580, 'n_words': 626}