Make ChapterRecognition return the result (#7279)

This commit is contained in:
AntsyLich 2022-06-10 19:26:56 +06:00 committed by GitHub
parent cf48bbc176
commit 06fdfcdb23
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 106 additions and 135 deletions

View file

@ -193,7 +193,7 @@ class LocalSource(
}
date_upload = chapterFile.lastModified()
ChapterRecognition.parseChapterNumber(this, sManga)
chapter_number = ChapterRecognition.parseChapterNumber(sManga.title, this.name, this.chapter_number)
val format = getFormat(chapterFile)
if (format is Format.Epub) {

View file

@ -1,8 +1,5 @@
package eu.kanade.tachiyomi.util.chapter
import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga
/**
* -R> = regex conversion.
*/
@ -37,14 +34,14 @@ object ChapterRecognition {
*/
private val unwantedWhiteSpace = Regex("""(\s)(extra|special|omake)""")
fun parseChapterNumber(chapter: SChapter, manga: SManga) {
fun parseChapterNumber(mangaTitle: String, chapterName: String, chapterNumber: Float? = null): Float {
// If chapter number is known return.
if (chapter.chapter_number == -2f || chapter.chapter_number > -1f) {
return
if (chapterNumber != null && (chapterNumber == -2f || chapterNumber > -1f)) {
return chapterNumber
}
// Get chapter title with lower case
var name = chapter.name.lowercase()
var name = chapterName.lowercase()
// Remove comma's or hyphens.
name = name.replace(',', '.').replace('-', '.')
@ -60,9 +57,7 @@ object ChapterRecognition {
}
// Check base case ch.xx
if (updateChapter(basic.find(name), chapter)) {
return
}
getChapterNumberFromMatch(basic.find(name))?.let { return it }
// Check one number occurrence.
val occurrences: MutableList<MatchResult> = arrayListOf()
@ -71,41 +66,34 @@ object ChapterRecognition {
}
if (occurrences.size == 1) {
if (updateChapter(occurrences[0], chapter)) {
return
}
getChapterNumberFromMatch(occurrences[0])?.let { return it }
}
// Remove manga title from chapter title.
val nameWithoutManga = name.replace(manga.title.lowercase(), "").trim()
val nameWithoutManga = name.replace(mangaTitle.lowercase(), "").trim()
// Check if first value is number after title remove.
if (updateChapter(withoutManga.find(nameWithoutManga), chapter)) {
return
}
getChapterNumberFromMatch(withoutManga.find(nameWithoutManga))?.let { return it }
// Take the first number encountered.
if (updateChapter(occurrence.find(nameWithoutManga), chapter)) {
return
}
getChapterNumberFromMatch(occurrence.find(nameWithoutManga))?.let { return it }
return chapterNumber ?: -1f
}
/**
* Check if volume is found and update chapter
* Check if chapter number is found and return it
* @param match result of regex
* @param chapter chapter object
* @return true if volume is found
* @return chapter number if found else null
*/
private fun updateChapter(match: MatchResult?, chapter: SChapter): Boolean {
match?.let {
private fun getChapterNumberFromMatch(match: MatchResult?): Float? {
return match?.let {
val initial = it.groups[1]?.value?.toFloat()!!
val subChapterDecimal = it.groups[2]?.value
val subChapterAlpha = it.groups[3]?.value
val addition = checkForDecimal(subChapterDecimal, subChapterAlpha)
chapter.chapter_number = initial.plus(addition)
return true
initial.plus(addition)
}
return false
}
/**

View file

@ -70,7 +70,7 @@ fun syncChaptersWithSource(
source.prepareNewChapter(sourceChapter, manga)
}
// Recognize chapter number for the chapter.
ChapterRecognition.parseChapterNumber(sourceChapter, manga)
sourceChapter.chapter_number = ChapterRecognition.parseChapterNumber(manga.title, sourceChapter.name, sourceChapter.chapter_number)
val dbChapter = dbChapters.find { it.url == sourceChapter.url }

View file

@ -1,7 +1,5 @@
package eu.kanade.tachiyomi.data.database
import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.util.chapter.ChapterRecognition.parseChapterNumber
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test
@ -13,154 +11,154 @@ class ChapterRecognitionTest {
@Test
fun `Basic Ch prefix`() {
val manga = createManga("Mokushiroku Alice")
val mangaTitle = "Mokushiroku Alice"
assertChapter(manga, "Mokushiroku Alice Vol.1 Ch.4: Misrepresentation", 4f)
assertChapter(mangaTitle, "Mokushiroku Alice Vol.1 Ch.4: Misrepresentation", 4f)
}
@Test
fun `Basic Ch prefix with space after period`() {
val manga = createManga("Mokushiroku Alice")
val mangaTitle = "Mokushiroku Alice"
assertChapter(manga, "Mokushiroku Alice Vol. 1 Ch. 4: Misrepresentation", 4f)
assertChapter(mangaTitle, "Mokushiroku Alice Vol. 1 Ch. 4: Misrepresentation", 4f)
}
@Test
fun `Basic Ch prefix with decimal`() {
val manga = createManga("Mokushiroku Alice")
val mangaTitle = "Mokushiroku Alice"
assertChapter(manga, "Mokushiroku Alice Vol.1 Ch.4.1: Misrepresentation", 4.1f)
assertChapter(manga, "Mokushiroku Alice Vol.1 Ch.4.4: Misrepresentation", 4.4f)
assertChapter(mangaTitle, "Mokushiroku Alice Vol.1 Ch.4.1: Misrepresentation", 4.1f)
assertChapter(mangaTitle, "Mokushiroku Alice Vol.1 Ch.4.4: Misrepresentation", 4.4f)
}
@Test
fun `Basic Ch prefix with alpha postfix`() {
val manga = createManga("Mokushiroku Alice")
val mangaTitle = "Mokushiroku Alice"
assertChapter(manga, "Mokushiroku Alice Vol.1 Ch.4.a: Misrepresentation", 4.1f)
assertChapter(manga, "Mokushiroku Alice Vol.1 Ch.4.b: Misrepresentation", 4.2f)
assertChapter(manga, "Mokushiroku Alice Vol.1 Ch.4.extra: Misrepresentation", 4.99f)
assertChapter(mangaTitle, "Mokushiroku Alice Vol.1 Ch.4.a: Misrepresentation", 4.1f)
assertChapter(mangaTitle, "Mokushiroku Alice Vol.1 Ch.4.b: Misrepresentation", 4.2f)
assertChapter(mangaTitle, "Mokushiroku Alice Vol.1 Ch.4.extra: Misrepresentation", 4.99f)
}
@Test
fun `Name containing one number`() {
val manga = createManga("Bleach")
val mangaTitle = "Bleach"
assertChapter(manga, "Bleach 567 Down With Snowwhite", 567f)
assertChapter(mangaTitle, "Bleach 567 Down With Snowwhite", 567f)
}
@Test
fun `Name containing one number and decimal`() {
val manga = createManga("Bleach")
val mangaTitle = "Bleach"
assertChapter(manga, "Bleach 567.1 Down With Snowwhite", 567.1f)
assertChapter(manga, "Bleach 567.4 Down With Snowwhite", 567.4f)
assertChapter(mangaTitle, "Bleach 567.1 Down With Snowwhite", 567.1f)
assertChapter(mangaTitle, "Bleach 567.4 Down With Snowwhite", 567.4f)
}
@Test
fun `Name containing one number and alpha`() {
val manga = createManga("Bleach")
val mangaTitle = "Bleach"
assertChapter(manga, "Bleach 567.a Down With Snowwhite", 567.1f)
assertChapter(manga, "Bleach 567.b Down With Snowwhite", 567.2f)
assertChapter(manga, "Bleach 567.extra Down With Snowwhite", 567.99f)
assertChapter(mangaTitle, "Bleach 567.a Down With Snowwhite", 567.1f)
assertChapter(mangaTitle, "Bleach 567.b Down With Snowwhite", 567.2f)
assertChapter(mangaTitle, "Bleach 567.extra Down With Snowwhite", 567.99f)
}
@Test
fun `Chapter containing manga title and number`() {
val manga = createManga("Solanin")
val mangaTitle = "Solanin"
assertChapter(manga, "Solanin 028 Vol. 2", 28f)
assertChapter(mangaTitle, "Solanin 028 Vol. 2", 28f)
}
@Test
fun `Chapter containing manga title and number decimal`() {
val manga = createManga("Solanin")
val mangaTitle = "Solanin"
assertChapter(manga, "Solanin 028.1 Vol. 2", 28.1f)
assertChapter(manga, "Solanin 028.4 Vol. 2", 28.4f)
assertChapter(mangaTitle, "Solanin 028.1 Vol. 2", 28.1f)
assertChapter(mangaTitle, "Solanin 028.4 Vol. 2", 28.4f)
}
@Test
fun `Chapter containing manga title and number alpha`() {
val manga = createManga("Solanin")
val mangaTitle = "Solanin"
assertChapter(manga, "Solanin 028.a Vol. 2", 28.1f)
assertChapter(manga, "Solanin 028.b Vol. 2", 28.2f)
assertChapter(manga, "Solanin 028.extra Vol. 2", 28.99f)
assertChapter(mangaTitle, "Solanin 028.a Vol. 2", 28.1f)
assertChapter(mangaTitle, "Solanin 028.b Vol. 2", 28.2f)
assertChapter(mangaTitle, "Solanin 028.extra Vol. 2", 28.99f)
}
@Test
fun `Extreme case`() {
val manga = createManga("Onepunch-Man")
val mangaTitle = "Onepunch-Man"
assertChapter(manga, "Onepunch-Man Punch Ver002 028", 28f)
assertChapter(mangaTitle, "Onepunch-Man Punch Ver002 028", 28f)
}
@Test
fun `Extreme case with decimal`() {
val manga = createManga("Onepunch-Man")
val mangaTitle = "Onepunch-Man"
assertChapter(manga, "Onepunch-Man Punch Ver002 028.1", 28.1f)
assertChapter(manga, "Onepunch-Man Punch Ver002 028.4", 28.4f)
assertChapter(mangaTitle, "Onepunch-Man Punch Ver002 028.1", 28.1f)
assertChapter(mangaTitle, "Onepunch-Man Punch Ver002 028.4", 28.4f)
}
@Test
fun `Extreme case with alpha`() {
val manga = createManga("Onepunch-Man")
val mangaTitle = "Onepunch-Man"
assertChapter(manga, "Onepunch-Man Punch Ver002 028.a", 28.1f)
assertChapter(manga, "Onepunch-Man Punch Ver002 028.b", 28.2f)
assertChapter(manga, "Onepunch-Man Punch Ver002 028.extra", 28.99f)
assertChapter(mangaTitle, "Onepunch-Man Punch Ver002 028.a", 28.1f)
assertChapter(mangaTitle, "Onepunch-Man Punch Ver002 028.b", 28.2f)
assertChapter(mangaTitle, "Onepunch-Man Punch Ver002 028.extra", 28.99f)
}
@Test
fun `Chapter containing dot v2`() {
val manga = createManga("random")
val mangaTitle = "random"
assertChapter(manga, "Vol.1 Ch.5v.2: Alones", 5f)
assertChapter(mangaTitle, "Vol.1 Ch.5v.2: Alones", 5f)
}
@Test
fun `Number in manga title`() {
val manga = createManga("Ayame 14")
val mangaTitle = "Ayame 14"
assertChapter(manga, "Ayame 14 1 - The summer of 14", 1f)
assertChapter(mangaTitle, "Ayame 14 1 - The summer of 14", 1f)
}
@Test
fun `Space between ch x`() {
val manga = createManga("Mokushiroku Alice")
val mangaTitle = "Mokushiroku Alice"
assertChapter(manga, "Mokushiroku Alice Vol.1 Ch. 4: Misrepresentation", 4f)
assertChapter(mangaTitle, "Mokushiroku Alice Vol.1 Ch. 4: Misrepresentation", 4f)
}
@Test
fun `Chapter title with ch substring`() {
val manga = createManga("Ayame 14")
val mangaTitle = "Ayame 14"
assertChapter(manga, "Vol.1 Ch.1: March 25 (First Day Cohabiting)", 1f)
assertChapter(mangaTitle, "Vol.1 Ch.1: March 25 (First Day Cohabiting)", 1f)
}
@Test
fun `Chapter containing multiple zeros`() {
val manga = createManga("random")
val mangaTitle = "random"
assertChapter(manga, "Vol.001 Ch.003: Kaguya Doesn't Know Much", 3f)
assertChapter(mangaTitle, "Vol.001 Ch.003: Kaguya Doesn't Know Much", 3f)
}
@Test
fun `Chapter with version before number`() {
val manga = createManga("Onepunch-Man")
val mangaTitle = "Onepunch-Man"
assertChapter(manga, "Onepunch-Man Punch Ver002 086 : Creeping Darkness [3]", 86f)
assertChapter(mangaTitle, "Onepunch-Man Punch Ver002 086 : Creeping Darkness [3]", 86f)
}
@Test
fun `Version attached to chapter number`() {
val manga = createManga("Ansatsu Kyoushitsu")
val mangaTitle = "Ansatsu Kyoushitsu"
assertChapter(manga, "Ansatsu Kyoushitsu 011v002: Assembly Time", 11f)
assertChapter(mangaTitle, "Ansatsu Kyoushitsu 011v002: Assembly Time", 11f)
}
/**
@ -169,110 +167,95 @@ class ChapterRecognitionTest {
*/
@Test
fun `Number after manga title with chapter in chapter title case`() {
val manga = createManga("Tokyo ESP")
val mangaTitle = "Tokyo ESP"
assertChapter(manga, "Tokyo ESP 027: Part 002: Chapter 001", 027f)
assertChapter(mangaTitle, "Tokyo ESP 027: Part 002: Chapter 001", 027f)
}
@Test
fun `Unparseable chapter`() {
val manga = createManga("random")
val mangaTitle = "random"
assertChapter(manga, "Foo", -1f)
assertChapter(mangaTitle, "Foo", -1f)
}
@Test
fun `Chapter with time in title`() {
val manga = createManga("random")
val mangaTitle = "random"
assertChapter(manga, "Fairy Tail 404: 00:00", 404f)
assertChapter(mangaTitle, "Fairy Tail 404: 00:00", 404f)
}
@Test
fun `Chapter with alpha without dot`() {
val manga = createManga("random")
val mangaTitle = "random"
assertChapter(manga, "Asu No Yoichi 19a", 19.1f)
assertChapter(mangaTitle, "Asu No Yoichi 19a", 19.1f)
}
@Test
fun `Chapter title containing extra and vol`() {
val manga = createManga("Fairy Tail")
val mangaTitle = "Fairy Tail"
assertChapter(manga, "Fairy Tail 404.extravol002", 404.99f)
assertChapter(manga, "Fairy Tail 404 extravol002", 404.99f)
assertChapter(manga, "Fairy Tail 404.evol002", 404.5f)
assertChapter(mangaTitle, "Fairy Tail 404.extravol002", 404.99f)
assertChapter(mangaTitle, "Fairy Tail 404 extravol002", 404.99f)
assertChapter(mangaTitle, "Fairy Tail 404.evol002", 404.5f)
}
@Test
fun `Chapter title containing omake (japanese extra) and vol`() {
val manga = createManga("Fairy Tail")
val mangaTitle = "Fairy Tail"
assertChapter(manga, "Fairy Tail 404.omakevol002", 404.98f)
assertChapter(manga, "Fairy Tail 404 omakevol002", 404.98f)
assertChapter(manga, "Fairy Tail 404.ovol002", 404.15f)
assertChapter(mangaTitle, "Fairy Tail 404.omakevol002", 404.98f)
assertChapter(mangaTitle, "Fairy Tail 404 omakevol002", 404.98f)
assertChapter(mangaTitle, "Fairy Tail 404.ovol002", 404.15f)
}
@Test
fun `Chapter title containing special and vol`() {
val manga = createManga("Fairy Tail")
val mangaTitle = "Fairy Tail"
assertChapter(manga, "Fairy Tail 404.specialvol002", 404.97f)
assertChapter(manga, "Fairy Tail 404 specialvol002", 404.97f)
assertChapter(manga, "Fairy Tail 404.svol002", 404.19f)
assertChapter(mangaTitle, "Fairy Tail 404.specialvol002", 404.97f)
assertChapter(mangaTitle, "Fairy Tail 404 specialvol002", 404.97f)
assertChapter(mangaTitle, "Fairy Tail 404.svol002", 404.19f)
}
@Test
fun `Chapter title containing commas`() {
val manga = createManga("One Piece")
val mangaTitle = "One Piece"
assertChapter(manga, "One Piece 300,a", 300.1f)
assertChapter(manga, "One Piece Ch,123,extra", 123.99f)
assertChapter(manga, "One Piece the sunny, goes swimming 024,005", 24.005f)
assertChapter(mangaTitle, "One Piece 300,a", 300.1f)
assertChapter(mangaTitle, "One Piece Ch,123,extra", 123.99f)
assertChapter(mangaTitle, "One Piece the sunny, goes swimming 024,005", 24.005f)
}
@Test
fun `Chapter title containing hyphens`() {
val manga = createManga("Solo Leveling")
val mangaTitle = "Solo Leveling"
assertChapter(manga, "ch 122-a", 122.1f)
assertChapter(manga, "Solo Leveling Ch.123-extra", 123.99f)
assertChapter(manga, "Solo Leveling, 024-005", 24.005f)
assertChapter(manga, "Ch.191-200 Read Online", 191.200f)
assertChapter(mangaTitle, "ch 122-a", 122.1f)
assertChapter(mangaTitle, "Solo Leveling Ch.123-extra", 123.99f)
assertChapter(mangaTitle, "Solo Leveling, 024-005", 24.005f)
assertChapter(mangaTitle, "Ch.191-200 Read Online", 191.200f)
}
@Test
fun `Chapters containing season`() {
val manga = createManga("D.I.C.E")
assertChapter(manga, "D.I.C.E[Season 001] Ep. 007", 7f)
assertChapter("D.I.C.E", "D.I.C.E[Season 001] Ep. 007", 7f)
}
@Test
fun `Chapters in format sx - chapter xx`() {
val manga = createManga("The Gamer")
assertChapter(manga, "S3 - Chapter 20", 20f)
assertChapter("The Gamer", "S3 - Chapter 20", 20f)
}
@Test
fun `Chapters ending with s`() {
val manga = createManga("One Outs")
assertChapter(manga, "One Outs 001", 1f)
assertChapter("One Outs", "One Outs 001", 1f)
}
private fun assertChapter(manga: Manga, name: String, expected: Float) {
val chapter = Chapter.create()
chapter.name = name
parseChapterNumber(chapter, manga)
assertEquals(expected, chapter.chapter_number)
private fun assertChapter(mangaTitle: String, name: String, expected: Float) {
val chapterNumber = parseChapterNumber(mangaTitle, name)
assertEquals(chapterNumber, expected)
}
private fun createManga(title: String): Manga {
val manga = Manga.create(0)
manga.title = title
return manga
}
}
}