Skip to content

Commit 7177308

Browse files
committed
feat: 入力セクションの内容をクリーンアップし、数式をTeX形式で表示する処理を追加
1 parent 2fee73e commit 7177308

File tree

1 file changed

+91
-12
lines changed

1 file changed

+91
-12
lines changed

lib/services/atcoder_service.dart

Lines changed: 91 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -163,15 +163,36 @@ class AtCoderService {
163163
break;
164164
}
165165

166+
// divやsectionでサンプル系の要素があればそこで終了
167+
if (currentElement.localName == 'div' || currentElement.localName == 'section') {
168+
// クラス名やidに「sample」や「example」が含まれていればセクション終了
169+
final className = currentElement.className.toLowerCase();
170+
final id = currentElement.id.toLowerCase();
171+
if (className.contains('sample') || className.contains('example') ||
172+
id.contains('sample') || id.contains('example')) {
173+
break;
174+
}
175+
}
176+
166177
// preタグの場合は特別処理(入力形式のフォーマットなど)
167178
if (currentElement.localName == 'pre') {
168179
// preタグの内容をログ出力する
169180
developer.log("preタグの内容: ${currentElement.text}");
170181

171-
// preタグの内容をそのまま追加
172-
contentBuffer.write('\n\n```\n');
173-
contentBuffer.write(currentElement.text.trim());
174-
contentBuffer.write('\n```\n\n');
182+
// 入力セクションの場合はTeX形式で表示、それ以外はコードブロック
183+
if (headingTexts.contains('入力') || headingTexts.contains('Input')) {
184+
// 入力形式の場合はTeX表示(コードブロック化しない)
185+
// preタグ内のテキストも数式として処理
186+
final processedText = _processTextWithMath(currentElement);
187+
contentBuffer.write('\n\n');
188+
contentBuffer.write(processedText);
189+
contentBuffer.write('\n\n');
190+
} else {
191+
// その他(出力形式など)の場合はコードブロック
192+
contentBuffer.write('\n\n```\n');
193+
contentBuffer.write(currentElement.text.trim());
194+
contentBuffer.write('\n```\n\n');
195+
}
175196
} else {
176197
// テキストノードの内容を追加し、数式を自動検出
177198
final text = _processTextWithMath(currentElement);
@@ -184,9 +205,14 @@ class AtCoderService {
184205

185206
// 特定のセクションの追加処理(入力形式の場合)
186207
String content = contentBuffer.toString().trim();
208+
209+
// 入力セクションの場合の追加処理とクリーンアップ
187210
if (headingTexts.contains('入力') || headingTexts.contains('Input')) {
211+
// 不要な数値のみの行や入力例データを除去
212+
content = _cleanInputSectionContent(content);
213+
188214
// 「入力は以下の形式で与えられる」のような文言だけで、実際のフォーマットがない場合
189-
if (!content.contains('```')) {
215+
if (!content.contains('```') && !content.contains('\$')) {
190216
developer.log("入力形式の例がないため、preタグを直接探す");
191217

192218
// 入力例から入力形式を推測
@@ -207,9 +233,11 @@ class AtCoderService {
207233

208234
if (examplePre != null) {
209235
developer.log("入力例から形式を推測: ${examplePre.text}");
210-
contentBuffer.write('\n\n```\n');
211-
contentBuffer.write(examplePre.text.trim());
212-
contentBuffer.write('\n```\n\n');
236+
// 入力形式はTeX表示(コードブロック化しない)
237+
final processedText = _processTextWithMath(examplePre);
238+
contentBuffer.write('\n\n');
239+
contentBuffer.write(processedText);
240+
contentBuffer.write('\n\n');
213241

214242
// 入力形式の説明も追加
215243
contentBuffer.write('\n\n1行目は整数aが与えられる。');
@@ -222,23 +250,74 @@ class AtCoderService {
222250
final preText = pre.text.trim();
223251
if (preText.contains('a') && preText.contains('b c') && preText.contains('s')) {
224252
developer.log("入力形式のpreタグを直接発見: $preText");
225-
contentBuffer.write('\n\n```\n');
226-
contentBuffer.write(preText);
227-
contentBuffer.write('\n```\n\n');
253+
// 入力形式はTeX表示(コードブロック化しない)
254+
final processedText = _processTextWithMath(pre);
255+
contentBuffer.write('\n\n');
256+
contentBuffer.write(processedText);
257+
contentBuffer.write('\n\n');
228258
break;
229259
}
230260
}
231261
}
232262
}
233263
}
234264

235-
return contentBuffer.toString().trim();
265+
// すべてのセクションで余分な改行を削除
266+
content = _removeExcessiveNewlines(content);
267+
268+
return content;
236269
} catch (e) {
237270
developer.log("セクション内容抽出中にエラーが発生しました: $e");
238271
return '';
239272
}
240273
}
241274

275+
/// 入力セクションの内容をクリーンアップする
276+
String _cleanInputSectionContent(String content) {
277+
final lines = content.split('\n');
278+
final cleanedLines = <String>[];
279+
280+
for (var line in lines) {
281+
final trimmedLine = line.trim();
282+
283+
// 空行をスキップ
284+
if (trimmedLine.isEmpty) {
285+
continue;
286+
}
287+
288+
// 単純な数値のみの行をスキップ(入力例のデータの可能性)
289+
if (RegExp(r'^\d+$').hasMatch(trimmedLine)) {
290+
continue;
291+
}
292+
293+
// 入力例のパターンをスキップ(例:#..#.)
294+
if (RegExp(r'^[.#]+$').hasMatch(trimmedLine)) {
295+
continue;
296+
}
297+
298+
// 不要な「整数aが与えられる」などの汎用的な説明をスキップ
299+
if (trimmedLine.contains('行目は整数') && trimmedLine.contains('が与えられる')) {
300+
continue;
301+
}
302+
303+
cleanedLines.add(line);
304+
}
305+
306+
return cleanedLines.join('\n').trim();
307+
}
308+
309+
/// 余分な改行を削除する
310+
String _removeExcessiveNewlines(String content) {
311+
// 3つ以上連続する改行を2つに制限
312+
content = content.replaceAll(RegExp(r'\n{3,}'), '\n\n');
313+
314+
// 行末の空白を削除
315+
final lines = content.split('\n');
316+
final trimmedLines = lines.map((line) => line.trimRight()).toList();
317+
318+
return trimmedLines.join('\n').trim();
319+
}
320+
242321
/// HTMLテキストから数式を検出し、適切に$で囲む
243322
String _processTextWithMath(Element element) {
244323
String text = '';

0 commit comments

Comments
 (0)