tweak(anitomy): update version v0.4.0
This commit is contained in:
parent
f222258080
commit
b7541fbb03
|
@ -4,23 +4,25 @@
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||||
<PackageId>AnitomySharp.NET6</PackageId>
|
<PackageId>AnitomySharp.NET6</PackageId>
|
||||||
<Authors>tabratton;senritsu</Authors>
|
<PackageVersion>0.4.0</PackageVersion>
|
||||||
|
<Version>0.4.0</Version>
|
||||||
|
<Authors>tabratton;senritsu;chu-shen</Authors>
|
||||||
<Description>AnitomySharp is a C# port of Anitomy by erengy, a library for parsing anime video filenames. All credit to erengy for the actual library and logic.
|
<Description>AnitomySharp is a C# port of Anitomy by erengy, a library for parsing anime video filenames. All credit to erengy for the actual library and logic.
|
||||||
|
This fork of AnitomySharp is inspired by tabratton and senritsu, which adds more custom rules.
|
||||||
</Description>
|
</Description>
|
||||||
<RepositoryUrl>https://github.com/chu-shen/AnitomySharp.git</RepositoryUrl>
|
<RepositoryUrl>https://github.com/chu-shen/AnitomySharp.git</RepositoryUrl>
|
||||||
<RepositoryType>git</RepositoryType>
|
<RepositoryType>git</RepositoryType>
|
||||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
<PackageTags>Anitomy Anime</PackageTags>
|
||||||
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
|
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
|
||||||
<AssemblyVersion>0.3.0</AssemblyVersion>
|
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||||
<FileVersion>0.3.0</FileVersion>
|
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||||
<Version>0.3.0</Version>
|
|
||||||
<GenerateDocumentationFile>false</GenerateDocumentationFile>
|
|
||||||
<DocumentationFile>AnitomySharp.xml</DocumentationFile>
|
<DocumentationFile>AnitomySharp.xml</DocumentationFile>
|
||||||
|
<GenerateDocumentationFile>false</GenerateDocumentationFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="..\LICENSE" Pack="true" Visible="false" PackagePath="" />
|
<None Include="..\LICENSE" Pack="true" Visible="false" PackagePath="" />
|
||||||
<PackageReference Include="Microsoft.DocAsCode.App" Version="2.60.0" />
|
<None Include="..\README.md" Pack="true" PackagePath=""/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -24,13 +24,13 @@ namespace AnitomySharp
|
||||||
public static class KeywordManager
|
public static class KeywordManager
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 包含所有关键词(大写)的内部关键词元素词典
|
/// 包含所有关键词的内部关键词元素词典,比较器忽略大小写
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static readonly Dictionary<string, Keyword> Keys = new Dictionary<string, Keyword>();
|
private static readonly Dictionary<string, Keyword> Keys = new Dictionary<string, Keyword>(StringComparer.OrdinalIgnoreCase);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 文件扩展名,无值
|
/// 文件扩展名,无值,比较器忽略大小写
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static readonly Dictionary<string, Keyword> Extensions = new Dictionary<string, Keyword>();
|
private static readonly Dictionary<string, Keyword> Extensions = new Dictionary<string, Keyword>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ~~一眼真~~
|
/// ~~一眼真~~
|
||||||
|
@ -64,18 +64,19 @@ namespace AnitomySharp
|
||||||
"GEKIJOUBAN", "MOVIE",
|
"GEKIJOUBAN", "MOVIE",
|
||||||
"OAD", "OAV", "ONA", "OVA",
|
"OAD", "OAV", "ONA", "OVA",
|
||||||
"TV",
|
"TV",
|
||||||
"番外編", "總集編","映像特典","特典","特典アニメ",
|
"番外編", "總集編","DRAMA",
|
||||||
|
"映像特典","特典","特典アニメ",
|
||||||
// 特典 Special 剩下的各种类型可以全部命名成 SP,对于较特殊意义的特典也可以自定义命名
|
// 特典 Special 剩下的各种类型可以全部命名成 SP,对于较特殊意义的特典也可以自定义命名
|
||||||
"SPECIAL", "SPECIALS", "SP",
|
"SPECIAL", "SPECIALS", "SP", "SPs",
|
||||||
// 真人特典 Interview/Talk/Stage... 目前我们对于节目、采访、舞台活动、制作等三次元画面的长视频,一概怼成 IV。
|
// 真人特典 Interview/Talk/Stage... 目前我们对于节目、采访、舞台活动、制作等三次元画面的长视频,一概怼成 IV。
|
||||||
"IV",
|
"IV",
|
||||||
// 音乐视频 Music Video
|
// 音乐视频 Music Video
|
||||||
"MV"});
|
"MV"});
|
||||||
|
|
||||||
// add "SP" to ElementAnimeType with optionsUnidentifiable
|
// add "SP" to ElementAnimeType with optionsUnidentifiable
|
||||||
// Add(Element.ElementCategory.ElementAnimeType,
|
// Add(Element.ElementCategory.ElementAnimeType,
|
||||||
// optionsUnidentifiableUnsearchable,
|
// optionsUnidentifiableUnsearchable,
|
||||||
// new List<string> {"SP"}); // e.g. "Yumeiro Patissiere SP Professional"
|
// new List<string> { "SP" }); // e.g. "Yumeiro Patissiere SP Professional", but it is widely used to represent special
|
||||||
|
|
||||||
Add(Element.ElementCategory.ElementAnimeType,
|
Add(Element.ElementCategory.ElementAnimeType,
|
||||||
optionsUnidentifiableInvalid,
|
optionsUnidentifiableInvalid,
|
||||||
|
@ -84,7 +85,7 @@ namespace AnitomySharp
|
||||||
// 无字 OP/ED Non-Credit Opening/Ending
|
// 无字 OP/ED Non-Credit Opening/Ending
|
||||||
"ED", "ENDING", "NCED", "NCOP", "OP", "OPENING",
|
"ED", "ENDING", "NCED", "NCOP", "OP", "OPENING",
|
||||||
// 预告 Preview 预告下一话内容 注意编号表示其预告的是第几话的内容而不是跟在哪一话后面
|
// 预告 Preview 预告下一话内容 注意编号表示其预告的是第几话的内容而不是跟在哪一话后面
|
||||||
"PREVIEW",
|
"PREVIEW", "YOKOKU",
|
||||||
// 菜单 Menu BD/DVD 播放选择菜单
|
// 菜单 Menu BD/DVD 播放选择菜单
|
||||||
"MENU",
|
"MENU",
|
||||||
// 广告 Commercial Message 电视放送广告,时长一般在 7s/15s/30s/45s/... 左右
|
// 广告 Commercial Message 电视放送广告,时长一般在 7s/15s/30s/45s/... 左右
|
||||||
|
@ -92,7 +93,7 @@ namespace AnitomySharp
|
||||||
// 语音信息
|
// 语音信息
|
||||||
"MESSAGE",
|
"MESSAGE",
|
||||||
// 宣传片/预告片 Promotion Video / Trailer 一般时长在 1~2min 命名参考原盘和 jsum
|
// 宣传片/预告片 Promotion Video / Trailer 一般时长在 1~2min 命名参考原盘和 jsum
|
||||||
"PV", "Teaser","TRAILER", "DRAMA",
|
"PV", "Teaser","TRAILER",
|
||||||
// 真人特典 Interview/Talk/Stage... 目前我们对于节目、采访、舞台活动、制作等三次元画面的长视频,一概怼成 IV。
|
// 真人特典 Interview/Talk/Stage... 目前我们对于节目、采访、舞台活动、制作等三次元画面的长视频,一概怼成 IV。
|
||||||
"INTERVIEW",
|
"INTERVIEW",
|
||||||
"EVENT", "TOKUTEN", "LOGO"});
|
"EVENT", "TOKUTEN", "LOGO"});
|
||||||
|
@ -150,7 +151,7 @@ namespace AnitomySharp
|
||||||
|
|
||||||
Add(Element.ElementCategory.ElementOther,
|
Add(Element.ElementCategory.ElementOther,
|
||||||
optionsDefault,
|
optionsDefault,
|
||||||
new List<string> { "REMASTER", "REMASTERED", "UNCUT", "TS", "VFR", "WIDESCREEN", "WS", "SPURSENGINE" });
|
new List<string> { "REMASTER", "REMASTERED", "UNCUT", "TS", "VFR", "WIDESCREEN", "WS", "SPURSENGINE","DISC" });
|
||||||
|
|
||||||
Add(Element.ElementCategory.ElementReleaseGroup,
|
Add(Element.ElementCategory.ElementReleaseGroup,
|
||||||
optionsDefault,
|
optionsDefault,
|
||||||
|
@ -281,6 +282,16 @@ namespace AnitomySharp
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 判断预处理元素列表中是否包含给定的字符串(<paramref name="keyword"/>)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="category">元素类别</param>
|
||||||
|
/// <param name="keyword">待判断的字符串</param>
|
||||||
|
/// <returns>`true`表示包含</returns>
|
||||||
|
public static bool ContainsInPeekEntries(Element.ElementCategory category, string keyword)
|
||||||
|
{
|
||||||
|
return PeekEntries.Any(entry => entry.Item1 == category && entry.Item2.Contains(keyword, StringComparer.OrdinalIgnoreCase));
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Finds a particular <c>keyword</c>. If found sets <c>category</c> and <c>options</c> to the found search result.
|
/// Finds a particular <c>keyword</c>. If found sets <c>category</c> and <c>options</c> to the found search result.
|
||||||
|
|
|
@ -179,6 +179,7 @@ namespace AnitomySharp
|
||||||
private void SearchForEpisodeNumber()
|
private void SearchForEpisodeNumber()
|
||||||
{
|
{
|
||||||
var tokens = new List<int>();
|
var tokens = new List<int>();
|
||||||
|
var allTokens = new List<int>();
|
||||||
for (var i = 0; i < Tokens.Count; i++)
|
for (var i = 0; i < Tokens.Count; i++)
|
||||||
{
|
{
|
||||||
var token = Tokens[i];
|
var token = Tokens[i];
|
||||||
|
@ -187,6 +188,7 @@ namespace AnitomySharp
|
||||||
ParserHelper.IndexOfFirstDigit(token.Content) != -1)
|
ParserHelper.IndexOfFirstDigit(token.Content) != -1)
|
||||||
{
|
{
|
||||||
tokens.Add(i);
|
tokens.Add(i);
|
||||||
|
allTokens.Add(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,6 +230,12 @@ namespace AnitomySharp
|
||||||
// "e.g. "[12]", "(2006)"
|
// "e.g. "[12]", "(2006)"
|
||||||
if (ParseNumber.SearchForIsolatedNumbers(tokens)) return;
|
if (ParseNumber.SearchForIsolatedNumbers(tokens)) return;
|
||||||
|
|
||||||
|
// e.g. "OVA 3", "OtherToken[Hint05]", "[Web Preview 06]": maybe incorrect, so put the last
|
||||||
|
if (ParseNumber.SearchForSymbolWithEpisode(allTokens)) return;
|
||||||
|
|
||||||
|
// e.g. [13(341)], [13 (341)]
|
||||||
|
if (ParseNumber.SearchForEquivalentNumbersWithBracket(allTokens)) return;
|
||||||
|
|
||||||
// Consider using the last number as a last resort
|
// Consider using the last number as a last resort
|
||||||
ParseNumber.SearchForLastNumber(tokens);
|
ParseNumber.SearchForLastNumber(tokens);
|
||||||
}
|
}
|
||||||
|
@ -235,7 +243,7 @@ namespace AnitomySharp
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Search for anime title
|
/// Search for anime title
|
||||||
///
|
///
|
||||||
/// 搜索动画名
|
/// 搜索动画名
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void SearchForAnimeTitle()
|
private void SearchForAnimeTitle()
|
||||||
{
|
{
|
||||||
|
@ -283,6 +291,13 @@ namespace AnitomySharp
|
||||||
{
|
{
|
||||||
tokenBegin = tokenBeginWithNoReleaseGroup;
|
tokenBegin = tokenBeginWithNoReleaseGroup;
|
||||||
}
|
}
|
||||||
|
// 去除纯数字标题
|
||||||
|
// skip token with only number
|
||||||
|
if (Regex.Match(Tokens[tokenBegin].Content, ParserNumber.RegexMatchOnlyStart + @"^[0-9]+$" + ParserNumber.RegexMatchOnlyEnd).Success)
|
||||||
|
{
|
||||||
|
tokenBegin = tokenBeginWithNoReleaseGroup;
|
||||||
|
}
|
||||||
|
|
||||||
skippedPreviousGroup = true;
|
skippedPreviousGroup = true;
|
||||||
} while (Token.InListRange(tokenBegin, Tokens));
|
} while (Token.InListRange(tokenBegin, Tokens));
|
||||||
}
|
}
|
||||||
|
@ -398,7 +413,7 @@ namespace AnitomySharp
|
||||||
{
|
{
|
||||||
var token = Tokens[i];
|
var token = Tokens[i];
|
||||||
/** 跳过括号标记类型的标记 */
|
/** 跳过括号标记类型的标记 */
|
||||||
if (token.Category == Token.TokenCategory.Bracket) continue;
|
if (token.Category != Token.TokenCategory.Unknown) continue;
|
||||||
var tokenContent = token.Content;
|
var tokenContent = token.Content;
|
||||||
|
|
||||||
// e.g. "2016-17"
|
// e.g. "2016-17"
|
||||||
|
@ -408,13 +423,21 @@ namespace AnitomySharp
|
||||||
{
|
{
|
||||||
tokenContent = tokenContent.Split(match.Groups[2].Value)[0];
|
tokenContent = tokenContent.Split(match.Groups[2].Value)[0];
|
||||||
}
|
}
|
||||||
// add newtype e.g. "2021 OVA"
|
|
||||||
if (token.Category != Token.TokenCategory.Unknown || !StringHelper.IsNumericString(tokenContent) ||
|
if (!StringHelper.IsNumericString(tokenContent))
|
||||||
!(ParseHelper.IsTokenContainAnimeType(i) ^ ParseHelper.IsTokenIsolated(i)))
|
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// e.g. "[2021 OVA]"
|
||||||
|
if(ParseHelper.IsNextTokenContainAnimeType(i)&&!ParseHelper.IsTokenIsolated(i)){}
|
||||||
|
|
||||||
|
// TODO may not be necessary
|
||||||
|
// if (!ParseHelper.IsTokenIsolated(i))
|
||||||
|
// {
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
|
||||||
var number = StringHelper.StringToInt(tokenContent);
|
var number = StringHelper.StringToInt(tokenContent);
|
||||||
|
|
||||||
// Anime year
|
// Anime year
|
||||||
|
@ -422,7 +445,7 @@ namespace AnitomySharp
|
||||||
{
|
{
|
||||||
if (Empty(Element.ElementCategory.ElementAnimeYear))
|
if (Empty(Element.ElementCategory.ElementAnimeYear))
|
||||||
{
|
{
|
||||||
Elements.Add(new Element(Element.ElementCategory.ElementAnimeYear, token.Content));
|
Elements.Add(new Element(Element.ElementCategory.ElementAnimeYear, tokenContent));
|
||||||
token.Category = Token.TokenCategory.Identifier;
|
token.Category = Token.TokenCategory.Identifier;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -235,7 +235,7 @@ namespace AnitomySharp
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns whether or not a token at the current <c>pos</c> is isolated(surrounded by braces).
|
/// Returns whether or not a token at the current <c>pos</c> is isolated(surrounded by braces).
|
||||||
///
|
///
|
||||||
/// 判断当前位置标记(token)是否孤立,即是否被括号包裹
|
/// 判断当前位置标记(token)是否孤立,是否被括号包裹
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="pos"></param>
|
/// <param name="pos"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
|
@ -246,6 +246,20 @@ namespace AnitomySharp
|
||||||
var nextToken = Token.FindNextToken(_parser.Tokens, pos, Token.TokenFlag.FlagNotDelimiter);
|
var nextToken = Token.FindNextToken(_parser.Tokens, pos, Token.TokenFlag.FlagNotDelimiter);
|
||||||
return IsTokenCategory(nextToken, Token.TokenCategory.Bracket);
|
return IsTokenCategory(nextToken, Token.TokenCategory.Bracket);
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Returns whether or not a token at the current <c>pos</c> is isolated(surrounded by braces, delimiter).
|
||||||
|
///
|
||||||
|
/// 判断当前位置标记(token)是否孤立,前面是否为分隔符,后面是否为括号包裹
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="pos"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public bool IsTokenIsolatedWithDelimiterAndBracket(int pos)
|
||||||
|
{
|
||||||
|
var prevToken = Token.FindPrevToken(_parser.Tokens, pos, Token.TokenFlag.FlagNone);
|
||||||
|
if (!IsTokenCategory(prevToken, Token.TokenCategory.Delimiter)) return false;
|
||||||
|
var nextToken = Token.FindNextToken(_parser.Tokens, pos, Token.TokenFlag.FlagNotDelimiter);
|
||||||
|
return IsTokenCategory(nextToken, Token.TokenCategory.Bracket);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns whether or not a token at the current <c>pos+1</c> is ElementAnimeType.
|
/// Returns whether or not a token at the current <c>pos+1</c> is ElementAnimeType.
|
||||||
|
@ -254,13 +268,37 @@ namespace AnitomySharp
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="pos"></param>
|
/// <param name="pos"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public bool IsTokenContainAnimeType(int pos)
|
public bool IsNextTokenContainAnimeType(int pos)
|
||||||
{
|
{
|
||||||
var prevToken = Token.FindPrevToken(_parser.Tokens, pos, Token.TokenFlag.FlagNotDelimiter);
|
var prevToken = Token.FindPrevToken(_parser.Tokens, pos, Token.TokenFlag.FlagNotDelimiter);
|
||||||
if (!IsTokenCategory(prevToken, Token.TokenCategory.Bracket)) return false;
|
if (!IsTokenCategory(prevToken, Token.TokenCategory.Bracket)) return false;
|
||||||
var nextToken = Token.FindNextToken(_parser.Tokens, pos, Token.TokenFlag.FlagNotDelimiter);
|
var nextToken = Token.FindNextToken(_parser.Tokens, pos, Token.TokenFlag.FlagNotDelimiter);
|
||||||
return KeywordManager.Contains(Element.ElementCategory.ElementAnimeType, _parser.Tokens[nextToken].Content);
|
return KeywordManager.Contains(Element.ElementCategory.ElementAnimeType, _parser.Tokens[nextToken].Content);
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 判断当前标记(token)的上一个标记的类型是否为ElementAnimeType。如果是,则返回`true`
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="pos"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public bool IsPrevTokenContainAnimeType(int pos)
|
||||||
|
{
|
||||||
|
var prevToken = Token.FindPrevToken(_parser.Tokens, pos, Token.TokenFlag.FlagNotDelimiter);
|
||||||
|
var nextToken = Token.FindNextToken(_parser.Tokens, pos, Token.TokenFlag.FlagNotDelimiter);
|
||||||
|
if (!IsTokenCategory(nextToken, Token.TokenCategory.Bracket)) return false;
|
||||||
|
return KeywordManager.Contains(Element.ElementCategory.ElementAnimeType, _parser.Tokens[prevToken].Content);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 判断当前标记(token)的上一个标记的类型是否为ElementAnimeType(在 PeekEntries 中)。如果是,则返回`true`
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="pos"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public bool IsPrevTokenContainAnimeTypeInPeekEntries(int pos)
|
||||||
|
{
|
||||||
|
var prevToken = Token.FindPrevToken(_parser.Tokens, pos, Token.TokenFlag.FlagNotDelimiter);
|
||||||
|
var nextToken = Token.FindNextToken(_parser.Tokens, pos, Token.TokenFlag.FlagNotDelimiter);
|
||||||
|
if (!IsTokenCategory(nextToken, Token.TokenCategory.Bracket)) return false;
|
||||||
|
return KeywordManager.ContainsInPeekEntries(Element.ElementCategory.ElementAnimeType, _parser.Tokens[prevToken].Content);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Finds and sets the anime season keyword.
|
/// Finds and sets the anime season keyword.
|
||||||
|
|
|
@ -412,7 +412,7 @@ namespace AnitomySharp
|
||||||
_parser.Tokens.Insert(foundIdx,
|
_parser.Tokens.Insert(foundIdx,
|
||||||
new Token(options.Identifiable ? Token.TokenCategory.Identifier : Token.TokenCategory.Unknown, token.Enclosed, prefix));
|
new Token(options.Identifiable ? Token.TokenCategory.Identifier : Token.TokenCategory.Unknown, token.Enclosed, prefix));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -698,6 +698,50 @@ namespace AnitomySharp
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 搜索同动画类型同时出现的集数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tokens"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public bool SearchForSymbolWithEpisode(List<int> tokens)
|
||||||
|
{
|
||||||
|
// Match from back to front
|
||||||
|
for (int i = tokens.Count - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
var it = tokens[i];
|
||||||
|
|
||||||
|
// e.g. OVA 3, [Web Preview 06]: Web Preview in PeekEntries
|
||||||
|
if ((_parser.ParseHelper.IsPrevTokenContainAnimeType(it) || _parser.ParseHelper.IsPrevTokenContainAnimeTypeInPeekEntries(it)) && !_parser.ParseHelper.IsTokenIsolated(it))
|
||||||
|
{
|
||||||
|
SetEpisodeNumber(_parser.Tokens[it].Content, _parser.Tokens[it], false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// e.g. OtherToken[Hint05]
|
||||||
|
// it>1: makesure this token is not first one
|
||||||
|
if (it > 1 && _parser.Tokens[it].Enclosed && _parser.ParseHelper.IsTokenIsolated(it))
|
||||||
|
{
|
||||||
|
var tokenContent = _parser.Tokens[it].Content;
|
||||||
|
var numberBegin = ParserHelper.IndexOfFirstDigit(tokenContent);
|
||||||
|
var prefix = StringHelper.SubstringWithCheck(tokenContent, 0, numberBegin);
|
||||||
|
var number = StringHelper.SubstringWithCheck(tokenContent, numberBegin, tokenContent.Length - numberBegin);
|
||||||
|
// token should be: alphaNumeric
|
||||||
|
if (prefix != "" && StringHelper.IsAlphaString(prefix) && StringHelper.IsNumericString(number))
|
||||||
|
{
|
||||||
|
SetEpisodeNumber(number, _parser.Tokens[it], true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// e.g. OtherToken[Disc 01]
|
||||||
|
if (it > 1 && _parser.Tokens[it].Enclosed && _parser.ParseHelper.IsTokenIsolatedWithDelimiterAndBracket(it) && StringHelper.IsNumericString(_parser.Tokens[it].Content))
|
||||||
|
{
|
||||||
|
SetEpisodeNumber(_parser.Tokens[it].Content, _parser.Tokens[it], true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Searches for equivalent number in a list of <c>tokens</c>. e.g. 08(114)
|
/// Searches for equivalent number in a list of <c>tokens</c>. e.g. 08(114)
|
||||||
///
|
///
|
||||||
|
@ -730,10 +774,7 @@ namespace AnitomySharp
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var list = new List<Token>
|
var list = new List<Token> { _parser.Tokens[it], _parser.Tokens[nextToken] };
|
||||||
{
|
|
||||||
_parser.Tokens[it], _parser.Tokens[nextToken]
|
|
||||||
};
|
|
||||||
|
|
||||||
list.Sort((o1, o2) => StringHelper.StringToInt(o1.Content) - StringHelper.StringToInt(o2.Content));
|
list.Sort((o1, o2) => StringHelper.StringToInt(o1.Content) - StringHelper.StringToInt(o2.Content));
|
||||||
SetEpisodeNumber(list[0].Content, list[0], false);
|
SetEpisodeNumber(list[0].Content, list[0], false);
|
||||||
|
@ -743,6 +784,50 @@ namespace AnitomySharp
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Searches for equivalent number in a list of <c>tokens</c>. e.g. 08(114)
|
||||||
|
///
|
||||||
|
/// 匹配自带等效集数的数字,常见于分割放送,匹配括号包裹的数字
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tokens">the list of tokens</param>
|
||||||
|
/// <returns>true if an equivalent number was found</returns>
|
||||||
|
public bool SearchForEquivalentNumbersWithBracket(List<int> tokens)
|
||||||
|
{
|
||||||
|
foreach (var it in tokens)
|
||||||
|
{
|
||||||
|
// Find the first enclosed, non-delimiter token
|
||||||
|
var nextToken = Token.FindNextToken(_parser.Tokens, it, Token.TokenFlag.FlagNotDelimiter);
|
||||||
|
if (!Token.InListRange(nextToken, _parser.Tokens) || !(_parser.Tokens[it].Content.Contains("(") || _parser.Tokens[nextToken].Content.Contains(")")))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// e.g. [13(341)]
|
||||||
|
if (it > 1 && _parser.Tokens[it].Enclosed && _parser.ParseHelper.IsTokenIsolated(it))
|
||||||
|
{
|
||||||
|
string[] episodes = _parser.Tokens[it].Content.Split(new string[] { "(", ")" }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
if (StringHelper.IsNumericString(episodes[0]) && StringHelper.IsNumericString(episodes[1]))
|
||||||
|
{
|
||||||
|
SetEpisodeNumber(episodes[0], _parser.Tokens[it], false);
|
||||||
|
SetAlternativeEpisodeNumber(episodes[1], _parser.Tokens[it]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// e.g. [13 (341)]
|
||||||
|
if (it > 1 && _parser.Tokens[nextToken].Enclosed && _parser.ParseHelper.IsTokenIsolatedWithDelimiterAndBracket(nextToken))
|
||||||
|
{
|
||||||
|
string episode = _parser.Tokens[nextToken].Content.Replace("(", "").Replace(")", "");
|
||||||
|
if (StringHelper.IsNumericString(_parser.Tokens[it].Content) && StringHelper.IsNumericString(episode))
|
||||||
|
{
|
||||||
|
SetEpisodeNumber(_parser.Tokens[it].Content, _parser.Tokens[it], true);
|
||||||
|
SetAlternativeEpisodeNumber(episode, _parser.Tokens[nextToken]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Searches for the last number token in a list of <c>tokens</c>
|
/// Searches for the last number token in a list of <c>tokens</c>
|
||||||
|
|
|
@ -120,6 +120,17 @@ namespace AnitomySharp
|
||||||
{
|
{
|
||||||
return str.All(char.IsDigit);
|
return str.All(char.IsDigit);
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Returns whether or not the <c>str</c> is a alpha string.
|
||||||
|
///
|
||||||
|
/// 判断字符串是否全字母
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="str"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool IsAlphaString(string str)
|
||||||
|
{
|
||||||
|
return str.All(char.IsLetter);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the int value of the <c>str</c>; 0 otherwise.
|
/// Returns the int value of the <c>str</c>; 0 otherwise.
|
||||||
|
|
Loading…
Reference in New Issue