From 26d038cee6eb999d407abd08c92962a49cde742e Mon Sep 17 00:00:00 2001 From: TakenPt Date: Sun, 28 Apr 2024 17:26:42 +0900 Subject: [PATCH 1/8] =?UTF-8?q?#36=20ExceptionType=E3=82=92=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- KoeBook.Core/EbookException.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/KoeBook.Core/EbookException.cs b/KoeBook.Core/EbookException.cs index a0e7647..704714b 100644 --- a/KoeBook.Core/EbookException.cs +++ b/KoeBook.Core/EbookException.cs @@ -62,4 +62,7 @@ public enum ExceptionType /// [EnumMember(Value = "無効なURLです")] InvalidUrl, + + [EnumMember(Value = "xmlがスキーマを満たしていません")] + XmlSchemaUnfulfilled } From 0a3968170763edb65591e926486e26b7974e1ca9 Mon Sep 17 00:00:00 2001 From: TakenPt Date: Sun, 28 Apr 2024 17:28:47 +0900 Subject: [PATCH 2/8] =?UTF-8?q?#36=20=E8=AA=AD=E3=81=BF=E8=BE=BC=E3=81=BF?= =?UTF-8?q?=E7=94=A8=E3=81=AE=E3=82=AF=E3=83=A9=E3=82=B9=E3=82=92=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Epub/KoeBook.Epub/Models/ClaudeStory.cs | 54 +++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 Epub/KoeBook.Epub/Models/ClaudeStory.cs diff --git a/Epub/KoeBook.Epub/Models/ClaudeStory.cs b/Epub/KoeBook.Epub/Models/ClaudeStory.cs new file mode 100644 index 0000000..a256133 --- /dev/null +++ b/Epub/KoeBook.Epub/Models/ClaudeStory.cs @@ -0,0 +1,54 @@ +using System.Collections.Generic; +using System.Xml.Serialization; + +namespace KoeBook.Epub.Models; + +[XmlRoot("Book")] +public record Book +{ + [XmlElement("Title", typeof(string))] + public string Title; + + [XmlElement("Content")] + public Content Content; +} + +public record Content +{ + [XmlElement("Section")] + public List Sections; +} + +public record XmlSection +{ + [XmlElement("Title")] + public string? Title; + + [XmlElement("Paragraph")] + public List Paragraphs; +} + +public record ParagraphPart { } + +public record XmlParagraph +{ + [XmlElement("Text", typeof(Text))] + [XmlElement("Ruby", typeof(Ruby))] + public List Texts; +} + +public record Text : ParagraphPart +{ + [XmlElement("Text")] + public string InnerText; +} + + +public record Ruby : ParagraphPart +{ + [XmlElement("Rb")] + public string Rb; + + [XmlElement("Rt")] + public string Rt; +} From 7c74a35d801928b011f29bcf658a486d0d8a4043 Mon Sep 17 00:00:00 2001 From: TakenPt Date: Sun, 28 Apr 2024 17:29:35 +0900 Subject: [PATCH 3/8] =?UTF-8?q?#36=20=E8=AA=AD=E3=81=BF=E8=BE=BC=E3=81=BF?= =?UTF-8?q?=E3=82=B5=E3=83=BC=E3=83=93=E3=82=B9=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Services/ScrapingClaudeStroyService.cs | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 Epub/KoeBook.Epub/Services/ScrapingClaudeStroyService.cs diff --git a/Epub/KoeBook.Epub/Services/ScrapingClaudeStroyService.cs b/Epub/KoeBook.Epub/Services/ScrapingClaudeStroyService.cs new file mode 100644 index 0000000..715d7d7 --- /dev/null +++ b/Epub/KoeBook.Epub/Services/ScrapingClaudeStroyService.cs @@ -0,0 +1,88 @@ +using System.Xml; +using System.Xml.Linq; +using System.Xml.Schema; +using KoeBook.Epub.Models; +using KoeBook.Core; +using System.Xml.Serialization; +using KoeBook.Core.Utilities; +using KoeBook.Epub.Contracts.Services; +using KoeBook.Core.Models; + +namespace KoeBook.Epub.Services +{ + public partial class ScrapingClaudeStroyService(ISplitBraceService splitBraceService) + { + + private readonly ISplitBraceService _splitBraceService = splitBraceService; + public async ValueTask ScrapingAsync(string xmlText, string coverFillePath, string imgDirectory, Guid id, CancellationToken ct) + { + if (!FitXmlSchema(xmlText)) + throw new EbookException(ExceptionType.XmlSchemaUnfulfilled); + + var book = LoadBook(xmlText); + + var paragraphbuilder = new SplittedLineBuilder(); + var scriptLineBuilder = new SplittedLineBuilder(); + + var document = new EpubDocument(book.Title, "", coverFillePath, id); + document.Chapters.Add(new Chapter()); + foreach (var section in book.Content.Sections) + { + var docSection = new Section(section.Title ?? ""); + foreach (var paragraph in section.Paragraphs) + { + foreach (var item in paragraph.Texts) + { + switch (item) + { + case Text text: + paragraphbuilder.Append(text.InnerText); + scriptLineBuilder.Append(text.InnerText); + break; + case Ruby ruby: + paragraphbuilder.Append($"{ruby.Rb}({ruby.Rt})"); + scriptLineBuilder.Append($"{ruby.Rt}"); + break; + default: + throw new EbookException(ExceptionType.XmlSchemaUnfulfilled); + } + } + + foreach ((var textSplit, var scriptSplit) in + _splitBraceService.SplitBrace(paragraphbuilder.ToLinesAndClear()).Zip( + _splitBraceService.SplitBrace(scriptLineBuilder.ToLinesAndClear()) + ) + ) + { + docSection.Elements.Add(new Paragraph() { Text = textSplit, ScriptLine = new ScriptLine(scriptSplit, "", "") }); + } + } + document.Chapters.Single().Sections.Add(docSection); + } + return document; + } + + internal bool FitXmlSchema(string xmlText) + { + // スキーマファイルのパスを入れる。 + using var xsdFs = new FileStream(@"", FileMode.Open); + XmlSchemaSet schema = new XmlSchemaSet(); + schema.Add("", XmlReader.Create(xsdFs)); + + XDocument xml = XDocument.Parse(xmlText); + + bool errorExist = false; + xml.Validate(schema, (o, e) => errorExist = true); + + return !errorExist; + } + + internal Book LoadBook(string xmlText) + { + using var xmlStringReader = new StringReader(xmlText); + var serializer = new XmlSerializer(typeof(Book)); + return (Book)serializer.Deserialize(xmlStringReader) + ?? throw new EbookException(ExceptionType.XmlSchemaUnfulfilled); + } + } +} From 9ba22813f5bee05e7bb92aa28c541f982819b2e8 Mon Sep 17 00:00:00 2001 From: miyaji255 <84168445+miyaji255@users.noreply.github.com> Date: Sun, 28 Apr 2024 22:50:35 +0900 Subject: [PATCH 4/8] =?UTF-8?q?#36=20AiStory=E3=82=AF=E3=83=A9=E3=82=B9?= =?UTF-8?q?=E3=81=AE=E5=87=A6=E7=90=86=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Epub/KoeBook.Epub/Models/ClaudeStory.cs | 54 ------------ .../Services/AiStoryAnalyzerService.cs | 31 +++++++ Epub/KoeBook.Epub/Services/AnalyzerService.cs | 39 +++++--- .../Services/ScrapingClaudeStroyService.cs | 88 ------------------- KoeBook.Core/Models/AiStory.cs | 44 ++++++++++ KoeBook.Core/Models/BookProperties.cs | 30 +++++-- KoeBook.Core/Models/SourceType.cs | 3 + KoeBook/Models/GenerationTask.cs | 42 +++++++-- .../Services/GenerationTaskRunnerService.cs | 2 +- KoeBook/Startup.cs | 3 +- 10 files changed, 170 insertions(+), 166 deletions(-) delete mode 100644 Epub/KoeBook.Epub/Models/ClaudeStory.cs create mode 100644 Epub/KoeBook.Epub/Services/AiStoryAnalyzerService.cs delete mode 100644 Epub/KoeBook.Epub/Services/ScrapingClaudeStroyService.cs create mode 100644 KoeBook.Core/Models/AiStory.cs diff --git a/Epub/KoeBook.Epub/Models/ClaudeStory.cs b/Epub/KoeBook.Epub/Models/ClaudeStory.cs deleted file mode 100644 index a256133..0000000 --- a/Epub/KoeBook.Epub/Models/ClaudeStory.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System.Collections.Generic; -using System.Xml.Serialization; - -namespace KoeBook.Epub.Models; - -[XmlRoot("Book")] -public record Book -{ - [XmlElement("Title", typeof(string))] - public string Title; - - [XmlElement("Content")] - public Content Content; -} - -public record Content -{ - [XmlElement("Section")] - public List Sections; -} - -public record XmlSection -{ - [XmlElement("Title")] - public string? Title; - - [XmlElement("Paragraph")] - public List Paragraphs; -} - -public record ParagraphPart { } - -public record XmlParagraph -{ - [XmlElement("Text", typeof(Text))] - [XmlElement("Ruby", typeof(Ruby))] - public List Texts; -} - -public record Text : ParagraphPart -{ - [XmlElement("Text")] - public string InnerText; -} - - -public record Ruby : ParagraphPart -{ - [XmlElement("Rb")] - public string Rb; - - [XmlElement("Rt")] - public string Rt; -} diff --git a/Epub/KoeBook.Epub/Services/AiStoryAnalyzerService.cs b/Epub/KoeBook.Epub/Services/AiStoryAnalyzerService.cs new file mode 100644 index 0000000..d65ffea --- /dev/null +++ b/Epub/KoeBook.Epub/Services/AiStoryAnalyzerService.cs @@ -0,0 +1,31 @@ +using KoeBook.Core.Utilities; +using KoeBook.Epub.Contracts.Services; +using KoeBook.Epub.Models; +using KoeBook.Models; + +namespace KoeBook.Epub.Services; + +public partial class AiStoryAnalyzerService(ISplitBraceService splitBraceService) +{ + private readonly ISplitBraceService _splitBraceService = splitBraceService; + + + public EpubDocument CreateEpubDocument(AiStory aiStory, Guid id) + { + return new EpubDocument(aiStory.Title, "", "", id) + { + Chapters = [new Chapter() { + Sections = aiStory.Sections.Select(s => new Section("") { + Elements = s.Paragraphs.SelectMany(p => + _splitBraceService.SplitBrace(p.GetText()) + .Zip(_splitBraceService.SplitBrace(p.GetScript())) + .Select(Element (p) => new Paragraph { + Text = p.First, + ScriptLine = new(p.Second, "","") + }) + ).ToList(), + }).ToList(), + }] + }; + } +} diff --git a/Epub/KoeBook.Epub/Services/AnalyzerService.cs b/Epub/KoeBook.Epub/Services/AnalyzerService.cs index b65da6a..85ef87e 100644 --- a/Epub/KoeBook.Epub/Services/AnalyzerService.cs +++ b/Epub/KoeBook.Epub/Services/AnalyzerService.cs @@ -1,18 +1,25 @@ -using System.Text; +using System.Diagnostics; +using System.Text; using System.Text.RegularExpressions; using KoeBook.Core; using KoeBook.Core.Contracts.Services; using KoeBook.Core.Models; using KoeBook.Epub.Contracts.Services; using KoeBook.Epub.Models; +using KoeBook.Models; namespace KoeBook.Epub.Services; -public partial class AnalyzerService(IScraperSelectorService scrapingService, IEpubDocumentStoreService epubDocumentStoreService, ILlmAnalyzerService llmAnalyzerService) : IAnalyzerService +public partial class AnalyzerService( + IScraperSelectorService scrapingService, + IEpubDocumentStoreService epubDocumentStoreService, + ILlmAnalyzerService llmAnalyzerService, + AiStoryAnalyzerService aiStoryAnalyzerService) : IAnalyzerService { private readonly IScraperSelectorService _scrapingService = scrapingService; private readonly IEpubDocumentStoreService _epubDocumentStoreService = epubDocumentStoreService; private readonly ILlmAnalyzerService _llmAnalyzerService = llmAnalyzerService; + private readonly AiStoryAnalyzerService _aiStoryAnalyzerService = aiStoryAnalyzerService; public async ValueTask AnalyzeAsync(BookProperties bookProperties, string tempDirectory, CancellationToken cancellationToken) { @@ -22,26 +29,36 @@ public async ValueTask AnalyzeAsync(BookProperties bookProperties, await fs.WriteAsync(CoverFile.ToArray(), cancellationToken); await fs.FlushAsync(cancellationToken); - EpubDocument? document; + var rubyReplaced = false; + EpubDocument document; try { - document = await _scrapingService.ScrapingAsync(bookProperties.Source, coverFilePath, tempDirectory, bookProperties.Id, cancellationToken); - } - catch (EbookException) - { - throw; + switch (bookProperties) + { + case { SourceType: SourceType.Url or SourceType.FilePath, Source: string uri }: + document = await _scrapingService.ScrapingAsync(uri, coverFilePath, tempDirectory, bookProperties.Id, cancellationToken); + break; + case { SourceType: SourceType.AiStory, Source: AiStory aiStory }: + document = _aiStoryAnalyzerService.CreateEpubDocument(aiStory, bookProperties.Id); + rubyReplaced = true; + break; + default: + throw new UnreachableException($"SourceType: {bookProperties.SourceType}, Source: {bookProperties.Source}"); + } } + catch (EbookException) { throw; } catch (Exception ex) { - EbookException.Throw(ExceptionType.WebScrapingFailed, innerException: ex); - return default; + throw new EbookException(ExceptionType.WebScrapingFailed, innerException: ex); } _epubDocumentStoreService.Register(document, cancellationToken); var scriptLines = document.Chapters.SelectMany(c => c.Sections) .SelectMany(s => s.Elements) .OfType() - .Select(p => + .Select(rubyReplaced + ? p => p.ScriptLine! + : p => { // ルビを置換 var line = ReplaceBaseTextWithRuby(p.Text); diff --git a/Epub/KoeBook.Epub/Services/ScrapingClaudeStroyService.cs b/Epub/KoeBook.Epub/Services/ScrapingClaudeStroyService.cs deleted file mode 100644 index 715d7d7..0000000 --- a/Epub/KoeBook.Epub/Services/ScrapingClaudeStroyService.cs +++ /dev/null @@ -1,88 +0,0 @@ -using System.Xml; -using System.Xml.Linq; -using System.Xml.Schema; -using KoeBook.Epub.Models; -using KoeBook.Core; -using System.Xml.Serialization; -using KoeBook.Core.Utilities; -using KoeBook.Epub.Contracts.Services; -using KoeBook.Core.Models; - -namespace KoeBook.Epub.Services -{ - public partial class ScrapingClaudeStroyService(ISplitBraceService splitBraceService) - { - - private readonly ISplitBraceService _splitBraceService = splitBraceService; - public async ValueTask ScrapingAsync(string xmlText, string coverFillePath, string imgDirectory, Guid id, CancellationToken ct) - { - if (!FitXmlSchema(xmlText)) - throw new EbookException(ExceptionType.XmlSchemaUnfulfilled); - - var book = LoadBook(xmlText); - - var paragraphbuilder = new SplittedLineBuilder(); - var scriptLineBuilder = new SplittedLineBuilder(); - - var document = new EpubDocument(book.Title, "", coverFillePath, id); - document.Chapters.Add(new Chapter()); - foreach (var section in book.Content.Sections) - { - var docSection = new Section(section.Title ?? ""); - foreach (var paragraph in section.Paragraphs) - { - foreach (var item in paragraph.Texts) - { - switch (item) - { - case Text text: - paragraphbuilder.Append(text.InnerText); - scriptLineBuilder.Append(text.InnerText); - break; - case Ruby ruby: - paragraphbuilder.Append($"{ruby.Rb}({ruby.Rt})"); - scriptLineBuilder.Append($"{ruby.Rt}"); - break; - default: - throw new EbookException(ExceptionType.XmlSchemaUnfulfilled); - } - } - - foreach ((var textSplit, var scriptSplit) in - _splitBraceService.SplitBrace(paragraphbuilder.ToLinesAndClear()).Zip( - _splitBraceService.SplitBrace(scriptLineBuilder.ToLinesAndClear()) - ) - ) - { - docSection.Elements.Add(new Paragraph() { Text = textSplit, ScriptLine = new ScriptLine(scriptSplit, "", "") }); - } - } - document.Chapters.Single().Sections.Add(docSection); - } - return document; - } - - internal bool FitXmlSchema(string xmlText) - { - // スキーマファイルのパスを入れる。 - using var xsdFs = new FileStream(@"", FileMode.Open); - XmlSchemaSet schema = new XmlSchemaSet(); - schema.Add("", XmlReader.Create(xsdFs)); - - XDocument xml = XDocument.Parse(xmlText); - - bool errorExist = false; - xml.Validate(schema, (o, e) => errorExist = true); - - return !errorExist; - } - - internal Book LoadBook(string xmlText) - { - using var xmlStringReader = new StringReader(xmlText); - var serializer = new XmlSerializer(typeof(Book)); - return (Book)serializer.Deserialize(xmlStringReader) - ?? throw new EbookException(ExceptionType.XmlSchemaUnfulfilled); - } - } -} diff --git a/KoeBook.Core/Models/AiStory.cs b/KoeBook.Core/Models/AiStory.cs new file mode 100644 index 0000000..3ba8466 --- /dev/null +++ b/KoeBook.Core/Models/AiStory.cs @@ -0,0 +1,44 @@ +using System.Xml.Serialization; +using KoeBook.Core.Utilities; + +namespace KoeBook.Models; + +[XmlRoot("Book", IsNullable = false)] +public record AiStory( + [XmlElement("Title", typeof(string), IsNullable = false)] string Title, + [XmlArray("Content", IsNullable = false), XmlArrayItem("Section", IsNullable = false)] AiStory.Section[] Sections) +{ + public record Section( + [XmlElement("Paragraph", IsNullable = false)] Paragraph[] Paragraphs); + + + public record Paragraph( + [XmlElement("Text", typeof(TextElement), IsNullable = false), XmlElement("Ruby", typeof(Ruby), IsNullable = false)] InlineElement[] Inlines) + { + public string GetText() => string.Concat(Inlines.Select(e => e.Text)); + + public string GetScript() => string.Concat(Inlines.Select(e => e.Script)); + } + + public abstract record class InlineElement + { + public abstract string Text { get; } + public abstract string Script { get; } + } + + public record TextElement([XmlText] string InnerText) : InlineElement + { + public override string Text => InnerText; + public override string Script => InnerText; + } + + + public record Ruby( + [XmlElement("Rb", IsNullable = false)] string Rb, + [XmlElement("Rt", IsNullable = false)] string Rt) : InlineElement + { + public override string Text => Rb; + public override string Script => Rt; + } + +} diff --git a/KoeBook.Core/Models/BookProperties.cs b/KoeBook.Core/Models/BookProperties.cs index ebe3618..b60cab5 100644 --- a/KoeBook.Core/Models/BookProperties.cs +++ b/KoeBook.Core/Models/BookProperties.cs @@ -1,13 +1,33 @@ -namespace KoeBook.Core.Models; +using System.Diagnostics; +using KoeBook.Models; + +namespace KoeBook.Core.Models; /// /// 読み上げる本の情報 /// -public class BookProperties(Guid id, string source, SourceType sourceType) +public class BookProperties { - public Guid Id { get; } = id; + public BookProperties(Guid id, string source, SourceType sourceType) + { + if (sourceType != SourceType.FilePath && sourceType != SourceType.Url) + throw new ArgumentException($"{nameof(sourceType)}は{nameof(SourceType.FilePath)}か{nameof(SourceType.Url)}である必要があります。"); + Id = id; + Source = source; + SourceType = sourceType; + } + + public BookProperties(Guid id, AiStory aiStory) { + Id = id; + Source = aiStory; + } + + public Guid Id { get; } - public string Source { get; } = source; + /// + /// UriまたはAiStory + /// + public object Source { get; } - public SourceType SourceType { get; } = sourceType; + public SourceType SourceType { get; } } diff --git a/KoeBook.Core/Models/SourceType.cs b/KoeBook.Core/Models/SourceType.cs index bc59068..5af40a0 100644 --- a/KoeBook.Core/Models/SourceType.cs +++ b/KoeBook.Core/Models/SourceType.cs @@ -9,4 +9,7 @@ public enum SourceType [EnumMember(Value = "ローカルファイル")] FilePath, + + [EnumMember(Value = "AI生成")] + AiStory, } diff --git a/KoeBook/Models/GenerationTask.cs b/KoeBook/Models/GenerationTask.cs index 24dd4f7..8ea7008 100644 --- a/KoeBook/Models/GenerationTask.cs +++ b/KoeBook/Models/GenerationTask.cs @@ -4,27 +4,57 @@ namespace KoeBook.Models; -public partial class GenerationTask(Guid id, string source, SourceType sourceType, bool skipEdit) : ObservableObject +public partial class GenerationTask : ObservableObject { - public Guid Id { get; } = id; + public GenerationTask(Guid id, string source, SourceType sourceType, bool skipEdit) + { + if (sourceType != SourceType.FilePath && sourceType != SourceType.Url) + throw new ArgumentException($"{nameof(sourceType)}は{nameof(SourceType.FilePath)}か{nameof(SourceType.Url)}である必要があります。"); + Id = id; + _rawSource = source; + SourceType = sourceType; + _skipEdit = skipEdit; + _title = sourceType == SourceType.FilePath ? Path.GetFileName(source) : source; + } + + public GenerationTask(Guid id, AiStory aiStory, bool skipEdit) + { + Id = id; + _rawSource = aiStory; + SourceType = SourceType.AiStory; + _skipEdit= skipEdit; + _title = aiStory.Title; + } + + public BookProperties ToBookProperties() + { + return SourceType == SourceType.AiStory + ? new BookProperties(Id, (AiStory)_rawSource) + : new BookProperties(Id, Source, SourceType); + } + + public Guid Id { get; } public CancellationTokenSource CancellationTokenSource { get; } = new(); public CancellationToken CancellationToken => CancellationTokenSource.Token; - public string Source { get; } = source; + public string Source => _rawSource is string uri ? uri : "AI生成"; + + private readonly object _rawSource; - public SourceType SourceType { get; } = sourceType; + public SourceType SourceType { get; } public string SourceDescription => SourceType switch { SourceType.Url => "URL", SourceType.FilePath => "ファイルパス", + SourceType.AiStory => "AI生成", _ => string.Empty, }; [ObservableProperty] - private string _title = sourceType == SourceType.FilePath ? Path.GetFileName(source) : source; + private string _title; [ObservableProperty] [NotifyPropertyChangedFor(nameof(ProgressText))] @@ -57,7 +87,7 @@ public bool SkipEdit } } } - private bool _skipEdit = skipEdit; + private bool _skipEdit; public bool SkipEditChangable => State < GenerationState.Editting; diff --git a/KoeBook/Services/GenerationTaskRunnerService.cs b/KoeBook/Services/GenerationTaskRunnerService.cs index 68fddbe..d728437 100644 --- a/KoeBook/Services/GenerationTaskRunnerService.cs +++ b/KoeBook/Services/GenerationTaskRunnerService.cs @@ -71,7 +71,7 @@ private async ValueTask RunAsyncCore(GenerationTask task, bool firstStep) { if (firstStep) { - var scripts = await _analyzerService.AnalyzeAsync(new(task.Id, task.Source, task.SourceType), tempDirectory, task.CancellationToken); + var scripts = await _analyzerService.AnalyzeAsync(task.ToBookProperties(), tempDirectory, task.CancellationToken); task.BookScripts = scripts; task.State = GenerationState.Editting; task.Progress = 0; diff --git a/KoeBook/Startup.cs b/KoeBook/Startup.cs index 1a546b5..d19c6a9 100644 --- a/KoeBook/Startup.cs +++ b/KoeBook/Startup.cs @@ -42,7 +42,8 @@ public static IHostBuilder UseCoreStartup(this IHostBuilder builder) .AddKeyedSingleton(nameof(ScrapingNaroService)) .AddSingleton() .AddSingleton() - .AddSingleton(); + .AddSingleton() + .AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); From 4973b04be50dbe5d42b48fccb77c0b736b27312d Mon Sep 17 00:00:00 2001 From: miyaji255 <84168445+miyaji255@users.noreply.github.com> Date: Sun, 28 Apr 2024 22:54:03 +0900 Subject: [PATCH 5/8] =?UTF-8?q?#36=20=E4=BE=8B=E5=A4=96=E3=82=BF=E3=82=A4?= =?UTF-8?q?=E3=83=97=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Services/AiStoryAnalyzerService.cs | 27 ++++++++++--------- KoeBook.Core/EbookException.cs | 4 +-- KoeBook.Core/Models/BookProperties.cs | 9 ++++--- KoeBook/Models/GenerationTask.cs | 4 +-- 4 files changed, 24 insertions(+), 20 deletions(-) diff --git a/Epub/KoeBook.Epub/Services/AiStoryAnalyzerService.cs b/Epub/KoeBook.Epub/Services/AiStoryAnalyzerService.cs index d65ffea..f328f37 100644 --- a/Epub/KoeBook.Epub/Services/AiStoryAnalyzerService.cs +++ b/Epub/KoeBook.Epub/Services/AiStoryAnalyzerService.cs @@ -14,18 +14,21 @@ public EpubDocument CreateEpubDocument(AiStory aiStory, Guid id) { return new EpubDocument(aiStory.Title, "", "", id) { - Chapters = [new Chapter() { - Sections = aiStory.Sections.Select(s => new Section("") { - Elements = s.Paragraphs.SelectMany(p => - _splitBraceService.SplitBrace(p.GetText()) - .Zip(_splitBraceService.SplitBrace(p.GetScript())) - .Select(Element (p) => new Paragraph { - Text = p.First, - ScriptLine = new(p.Second, "","") - }) - ).ToList(), - }).ToList(), - }] + Chapters = [new Chapter() + { + Sections = aiStory.Sections.Select(s => new Section("") + { + Elements = s.Paragraphs.SelectMany(p => + _splitBraceService.SplitBrace(p.GetText()) + .Zip(_splitBraceService.SplitBrace(p.GetScript())) + .Select(Element (p) => new Paragraph + { + Text = p.First, + ScriptLine = new(p.Second, "", "") + }) + ).ToList(), + }).ToList(), + }] }; } } diff --git a/KoeBook.Core/EbookException.cs b/KoeBook.Core/EbookException.cs index 704714b..bd88010 100644 --- a/KoeBook.Core/EbookException.cs +++ b/KoeBook.Core/EbookException.cs @@ -63,6 +63,6 @@ public enum ExceptionType [EnumMember(Value = "無効なURLです")] InvalidUrl, - [EnumMember(Value = "xmlがスキーマを満たしていません")] - XmlSchemaUnfulfilled + [EnumMember(Value = "不正なXMLです")] + InvalidXml, } diff --git a/KoeBook.Core/Models/BookProperties.cs b/KoeBook.Core/Models/BookProperties.cs index b60cab5..74a277d 100644 --- a/KoeBook.Core/Models/BookProperties.cs +++ b/KoeBook.Core/Models/BookProperties.cs @@ -17,17 +17,18 @@ public BookProperties(Guid id, string source, SourceType sourceType) SourceType = sourceType; } - public BookProperties(Guid id, AiStory aiStory) { + public BookProperties(Guid id, AiStory aiStory) + { Id = id; Source = aiStory; } - public Guid Id { get; } + public Guid Id { get; } /// /// UriまたはAiStory /// - public object Source { get; } + public object Source { get; } - public SourceType SourceType { get; } + public SourceType SourceType { get; } } diff --git a/KoeBook/Models/GenerationTask.cs b/KoeBook/Models/GenerationTask.cs index 8ea7008..26a7448 100644 --- a/KoeBook/Models/GenerationTask.cs +++ b/KoeBook/Models/GenerationTask.cs @@ -14,7 +14,7 @@ public GenerationTask(Guid id, string source, SourceType sourceType, bool skipEd _rawSource = source; SourceType = sourceType; _skipEdit = skipEdit; - _title = sourceType == SourceType.FilePath ? Path.GetFileName(source) : source; + _title = sourceType == SourceType.FilePath ? Path.GetFileName(source) : source; } public GenerationTask(Guid id, AiStory aiStory, bool skipEdit) @@ -22,7 +22,7 @@ public GenerationTask(Guid id, AiStory aiStory, bool skipEdit) Id = id; _rawSource = aiStory; SourceType = SourceType.AiStory; - _skipEdit= skipEdit; + _skipEdit = skipEdit; _title = aiStory.Title; } From ee1ebad237e5f26e4fb4fd1d7917fbd7f43f8fd1 Mon Sep 17 00:00:00 2001 From: miyaji255 <84168445+miyaji255@users.noreply.github.com> Date: Sun, 28 Apr 2024 22:57:42 +0900 Subject: [PATCH 6/8] =?UTF-8?q?#36=20AiStory=E3=81=AE=E3=81=A8=E3=81=8D?= =?UTF-8?q?=E3=81=AF=E8=91=97=E8=80=85=E3=82=92AI=E3=81=A8=E3=81=99?= =?UTF-8?q?=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Epub/KoeBook.Epub/Services/AiStoryAnalyzerService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Epub/KoeBook.Epub/Services/AiStoryAnalyzerService.cs b/Epub/KoeBook.Epub/Services/AiStoryAnalyzerService.cs index f328f37..2a465e9 100644 --- a/Epub/KoeBook.Epub/Services/AiStoryAnalyzerService.cs +++ b/Epub/KoeBook.Epub/Services/AiStoryAnalyzerService.cs @@ -12,7 +12,7 @@ public partial class AiStoryAnalyzerService(ISplitBraceService splitBraceService public EpubDocument CreateEpubDocument(AiStory aiStory, Guid id) { - return new EpubDocument(aiStory.Title, "", "", id) + return new EpubDocument(aiStory.Title, "AI", "", id) { Chapters = [new Chapter() { From 935632cda345ef08070b33a556427b9c110f9843 Mon Sep 17 00:00:00 2001 From: TakenPt Date: Mon, 29 Apr 2024 01:40:28 +0900 Subject: [PATCH 7/8] =?UTF-8?q?#36=20Sectio=E3=81=8C=E9=80=A3=E7=95=AA?= =?UTF-8?q?=E3=81=AETitle=E3=82=92=E6=8C=81=E3=81=A4=E3=82=88=E3=81=86?= =?UTF-8?q?=E3=81=AB=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Epub/KoeBook.Epub/Services/AiStoryAnalyzerService.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Epub/KoeBook.Epub/Services/AiStoryAnalyzerService.cs b/Epub/KoeBook.Epub/Services/AiStoryAnalyzerService.cs index 2a465e9..eede256 100644 --- a/Epub/KoeBook.Epub/Services/AiStoryAnalyzerService.cs +++ b/Epub/KoeBook.Epub/Services/AiStoryAnalyzerService.cs @@ -12,11 +12,12 @@ public partial class AiStoryAnalyzerService(ISplitBraceService splitBraceService public EpubDocument CreateEpubDocument(AiStory aiStory, Guid id) { + int sectionNumber = 1; return new EpubDocument(aiStory.Title, "AI", "", id) { Chapters = [new Chapter() { - Sections = aiStory.Sections.Select(s => new Section("") + Sections = aiStory.Sections.Select(s => new Section($"第{sectionNumber++}章") { Elements = s.Paragraphs.SelectMany(p => _splitBraceService.SplitBrace(p.GetText()) From e31a665b388b5e732c059421edff1e9296587c40 Mon Sep 17 00:00:00 2001 From: miyaji255 <84168445+miyaji255@users.noreply.github.com> Date: Mon, 29 Apr 2024 10:50:33 +0900 Subject: [PATCH 8/8] =?UTF-8?q?#36=20AiStory=E3=81=AE=E5=B1=9E=E6=80=A7?= =?UTF-8?q?=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Services/AiStoryAnalyzerService.cs | 3 +- KoeBook.Core/Models/AiStory.cs | 30 ++++++++++++------- KoeBook.Core/Models/BookProperties.cs | 4 +-- KoeBook/Models/GenerationTask.cs | 6 ++-- KoeBook/Views/EditDetailsTab.xaml | 2 +- 5 files changed, 26 insertions(+), 19 deletions(-) diff --git a/Epub/KoeBook.Epub/Services/AiStoryAnalyzerService.cs b/Epub/KoeBook.Epub/Services/AiStoryAnalyzerService.cs index eede256..262a26d 100644 --- a/Epub/KoeBook.Epub/Services/AiStoryAnalyzerService.cs +++ b/Epub/KoeBook.Epub/Services/AiStoryAnalyzerService.cs @@ -1,5 +1,4 @@ -using KoeBook.Core.Utilities; -using KoeBook.Epub.Contracts.Services; +using KoeBook.Epub.Contracts.Services; using KoeBook.Epub.Models; using KoeBook.Models; diff --git a/KoeBook.Core/Models/AiStory.cs b/KoeBook.Core/Models/AiStory.cs index 3ba8466..f48324d 100644 --- a/KoeBook.Core/Models/AiStory.cs +++ b/KoeBook.Core/Models/AiStory.cs @@ -1,20 +1,26 @@ using System.Xml.Serialization; -using KoeBook.Core.Utilities; namespace KoeBook.Models; -[XmlRoot("Book", IsNullable = false)] +[XmlRoot("Book")] public record AiStory( - [XmlElement("Title", typeof(string), IsNullable = false)] string Title, - [XmlArray("Content", IsNullable = false), XmlArrayItem("Section", IsNullable = false)] AiStory.Section[] Sections) + [property: XmlElement("Title", typeof(string), IsNullable = false)] string Title, + [property: XmlArray("Content", IsNullable = false), XmlArrayItem("Section", IsNullable = false)] AiStory.Section[] Sections) { + private AiStory() : this("", []) { } + public record Section( - [XmlElement("Paragraph", IsNullable = false)] Paragraph[] Paragraphs); + [property: XmlArrayItem("Paragraph", IsNullable = false)] Paragraph[] Paragraphs) + { + private Section() : this([]) { } + } public record Paragraph( - [XmlElement("Text", typeof(TextElement), IsNullable = false), XmlElement("Ruby", typeof(Ruby), IsNullable = false)] InlineElement[] Inlines) + [property: XmlElement("Text", typeof(TextElement), IsNullable = false), XmlElement("Ruby", typeof(Ruby), IsNullable = false)] InlineElement[] Inlines) { + private Paragraph() : this([]) { } + public string GetText() => string.Concat(Inlines.Select(e => e.Text)); public string GetScript() => string.Concat(Inlines.Select(e => e.Script)); @@ -26,19 +32,21 @@ public abstract record class InlineElement public abstract string Script { get; } } - public record TextElement([XmlText] string InnerText) : InlineElement + public record TextElement([property: XmlText] string InnerText) : InlineElement { + private TextElement() : this("") { } + public override string Text => InnerText; public override string Script => InnerText; } - public record Ruby( - [XmlElement("Rb", IsNullable = false)] string Rb, - [XmlElement("Rt", IsNullable = false)] string Rt) : InlineElement + [property: XmlElement("Rb", IsNullable = false)] string Rb, + [property: XmlElement("Rt", IsNullable = false)] string Rt) : InlineElement { + private Ruby() : this("", "") { } + public override string Text => Rb; public override string Script => Rt; } - } diff --git a/KoeBook.Core/Models/BookProperties.cs b/KoeBook.Core/Models/BookProperties.cs index 74a277d..f2ac50e 100644 --- a/KoeBook.Core/Models/BookProperties.cs +++ b/KoeBook.Core/Models/BookProperties.cs @@ -1,5 +1,4 @@ -using System.Diagnostics; -using KoeBook.Models; +using KoeBook.Models; namespace KoeBook.Core.Models; @@ -21,6 +20,7 @@ public BookProperties(Guid id, AiStory aiStory) { Id = id; Source = aiStory; + SourceType = SourceType.AiStory; } public Guid Id { get; } diff --git a/KoeBook/Models/GenerationTask.cs b/KoeBook/Models/GenerationTask.cs index 26a7448..33e044d 100644 --- a/KoeBook/Models/GenerationTask.cs +++ b/KoeBook/Models/GenerationTask.cs @@ -66,7 +66,7 @@ public BookProperties ToBookProperties() [ObservableProperty] [NotifyPropertyChangedFor(nameof(StateText))] - [NotifyPropertyChangedFor(nameof(SkipEditChangable))] + [NotifyPropertyChangedFor(nameof(SkipEditChangeable))] [NotifyPropertyChangedFor(nameof(Editable))] private GenerationState _state; @@ -79,7 +79,7 @@ public bool SkipEdit get => _skipEdit; set { - if (_skipEdit != value && SkipEditChangable) + if (_skipEdit != value && SkipEditChangeable) { OnPropertyChanging(nameof(SkipEdit)); _skipEdit = value; @@ -89,7 +89,7 @@ public bool SkipEdit } private bool _skipEdit; - public bool SkipEditChangable => State < GenerationState.Editting; + public bool SkipEditChangeable => State < GenerationState.Editting; public bool Editable => State == GenerationState.Editting; diff --git a/KoeBook/Views/EditDetailsTab.xaml b/KoeBook/Views/EditDetailsTab.xaml index 970837a..5c7ee2b 100644 --- a/KoeBook/Views/EditDetailsTab.xaml +++ b/KoeBook/Views/EditDetailsTab.xaml @@ -61,7 +61,7 @@ Margin="{StaticResource XXSmallLeftTopRightBottomMargin}" OffContent="編集する" OnContent="編集しない" - IsEnabled="{x:Bind ViewModel.Task.SkipEditChangable, Mode=OneWay}" + IsEnabled="{x:Bind ViewModel.Task.SkipEditChangeable, Mode=OneWay}" IsOn="{x:Bind ViewModel.Task.SkipEdit, Mode=TwoWay}"/>