From 0d2c64b64c6674611770d4020cc2bfeed188fd50 Mon Sep 17 00:00:00 2001 From: HN5107 <22e1259@andrew.ac.jp> Date: Sat, 10 Jan 2026 19:50:26 +0900 Subject: [PATCH] =?UTF-8?q?=E3=82=AD=E3=83=A3=E3=83=A9=E3=82=BB=E3=83=AA?= =?UTF-8?q?=E3=83=95=E7=A8=BC=E5=83=8D=E5=8F=AF=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../curation_train_app/AiReplyParser.kt | 50 ++- .../curation_train_app/AkaneReponder.kt | 3 + .../CharacterReplyManager.kt | 14 +- .../example/curation_train_app/DummyLines.kt | 175 ++++++++- .../curation_train_app/FollowSettings.kt | 11 + .../curation_train_app/HiyoriResponder.kt | 2 + .../example/curation_train_app/InfoType.kt | 4 +- .../LinePriorityActivity.kt | 36 ++ .../curation_train_app/LineSelectActivity.kt | 16 + .../curation_train_app/MainActivity.kt | 332 ++++++++++-------- .../curation_train_app/MarisaResponder.kt | 3 + .../curation_train_app/MomokaResponder.kt | 2 + .../example/curation_train_app/RailLine.kt | 7 + .../curation_train_app/RailLineData.kt | 17 + .../curation_train_app/ReimuResponder.kt | 4 + .../curation_train_app/SanaeResponder.kt | 3 + .../curation_train_app/SayakResponder.kt | 3 + .../curation_train_app/flandreResponder.kt | 2 + .../main/res/drawable/bg_comment_bubble.xml | 10 + .../res/layout/activity_line_priority.xml | 40 +++ app/src/main/res/layout/activity_main.xml | 81 ++--- .../res/layout/activity_region_select.xml | 16 +- 22 files changed, 593 insertions(+), 238 deletions(-) create mode 100644 app/src/main/java/com/example/curation_train_app/RailLine.kt create mode 100644 app/src/main/java/com/example/curation_train_app/RailLineData.kt create mode 100644 app/src/main/res/drawable/bg_comment_bubble.xml diff --git a/app/src/main/java/com/example/curation_train_app/AiReplyParser.kt b/app/src/main/java/com/example/curation_train_app/AiReplyParser.kt index 5042414..884e29d 100644 --- a/app/src/main/java/com/example/curation_train_app/AiReplyParser.kt +++ b/app/src/main/java/com/example/curation_train_app/AiReplyParser.kt @@ -1,24 +1,52 @@ package com.example.curation_train_app import org.json.JSONObject +import org.json.JSONArray object AiReplyParser { - fun parse(json: String): AiReply { - return try { + fun extractTextFromResponse(json: String): String { - val obj = JSONObject(json) + return try { + // 配列としてパース + val arr = JSONObject("{\"a\":$json}").getJSONArray("a") + val obj = arr.getJSONObject(0) - // GPT から返ってくるのは「text」だけ - val text = obj.optString("text", "(解析エラー)") + // textだけ取得 + var text = obj.getString("text") - // emotion は入っていないため、常に NORMAL を返す - val emotion = EmotionType.NORMAL + // ---- 余計なものを完全除去 ---- + text = text + .replace("text\":", "") // "text": + .replace("\"text\":\"", "") // "text":" + .replace("{\"text\":\"", "") // {"text":" + .replace("\"}", "") // "} + .replace("}", "") // } + .replace("{", "") // { + .replace("\\n", "") // 改行タグ + .replace("\n", "") + .replace("emotion", "") // emotion行 + .replace("normal", "") + .replace("happy", "") + .replace("angry", "") + .replace("surprised", "") + .replace("confused", "") + .replace("sleepy", "") + .replace("worry", "") + .replace("think", "") + .replace("“", "") + .replace("”", "") + .replace("\"", "") + .replace(",", "") + .replace(":", "") - AiReply(text, emotion) + .trim() - } catch (e: Exception) { - AiReply("(JSON解析エラー)", EmotionType.NORMAL) + text + + } catch (e: Exception) { + json + } } } -} + diff --git a/app/src/main/java/com/example/curation_train_app/AkaneReponder.kt b/app/src/main/java/com/example/curation_train_app/AkaneReponder.kt index 446c71b..d48f4b2 100644 --- a/app/src/main/java/com/example/curation_train_app/AkaneReponder.kt +++ b/app/src/main/java/com/example/curation_train_app/AkaneReponder.kt @@ -20,4 +20,7 @@ class AkaneResponder : CharacterResponder { "なんか気になる情報があるよねっ!気をつけていこーっ!" } } + + fun reply(text: String): String = respond(text, InfoType.NORMAL) + } diff --git a/app/src/main/java/com/example/curation_train_app/CharacterReplyManager.kt b/app/src/main/java/com/example/curation_train_app/CharacterReplyManager.kt index c934e60..fb27bb2 100644 --- a/app/src/main/java/com/example/curation_train_app/CharacterReplyManager.kt +++ b/app/src/main/java/com/example/curation_train_app/CharacterReplyManager.kt @@ -25,19 +25,15 @@ class CharacterReplyManager { ?: return "キャラが見つかりません。" return responder.respond(info, type) } - - fun replyWithAI(characterId: String, info: String, type: InfoType): AiReply { + fun replyWithAI(characterId: String, info: String, type: InfoType): String { val character = CharacterProfiles.getProfile(characterId) - ?: return AiReply("(エラー:キャラが不明です)", EmotionType.NORMAL) + ?: return "(エラー:キャラが不明です)" + val prompt = PromptBuilder.buildPrompt(character, info, type) - val ai = AiClient(apiKey = API_KEY) - val raw = ai.requestCharacterReply(prompt) - - // JSON パース - return AiReplyParser.parse(raw) + val ai = AiClient("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") + return ai.requestCharacterReply(prompt) } - } diff --git a/app/src/main/java/com/example/curation_train_app/DummyLines.kt b/app/src/main/java/com/example/curation_train_app/DummyLines.kt index f304527..14abf80 100644 --- a/app/src/main/java/com/example/curation_train_app/DummyLines.kt +++ b/app/src/main/java/com/example/curation_train_app/DummyLines.kt @@ -3,15 +3,172 @@ package com.example.curation_train_app object DummyLines { fun linesOf(region: String): List { - return when (region) { - "北海道" -> listOf("JR北海道全線", "札幌市営地下鉄", "道南いさりび鉄道") - "東北" -> listOf("JR東日本(東北)", "仙台市地下鉄", "青い森鉄道") - "関東" -> listOf("JR東日本(関東)", "東京メトロ", "京急", "東急", "小田急", "京王") - "中部" -> listOf("JR東海", "名鉄", "近鉄(名古屋)") - "関西" -> listOf("JR西日本(関西)", "大阪メトロ", "阪急", "阪神", "京阪", "南海", "近鉄(関西)") - "中国" -> listOf("JR西日本(中国)", "広島電鉄", "一畑電車") - "四国" -> listOf("JR四国") - "九州" -> listOf("JR九州", "西鉄") + return when(region) { + + // ------------------------- + // 北海道 + // ------------------------- + "hokkaido" -> listOf( + "JR北海道(函館本線)", + "JR北海道(千歳線)", + "JR北海道(札沼線・学園都市線)", + "JR北海道(根室本線)", + "JR北海道(宗谷本線)", + "札幌市営地下鉄 南北線", + "札幌市営地下鉄 東西線", + "札幌市営地下鉄 東豊線" + ) + + // ------------------------- + // 東北 + // ------------------------- + "tohoku" -> listOf( + "JR東日本(東北本線)", + "JR東日本(常磐線)", + "JR東日本(奥羽本線)", + "JR東日本(仙山線)", + "JR東日本(磐越西線)", + "仙台市地下鉄 南北線", + "仙台市地下鉄 東西線" + ) + + // ------------------------- + // 関東 + // ------------------------- + "kanto" -> listOf( + // JR + "JR東日本(山手線)", + "JR東日本(中央線快速)", + "JR東日本(総武線各停)", + "JR東日本(京浜東北線)", + "JR東日本(常磐線)", + "JR東日本(埼京線)", + "JR東日本(横須賀線)", + "JR東日本(湘南新宿ライン)", + "JR東日本(京葉線)", + "JR東日本(武蔵野線)", + + // 私鉄 + "東京メトロ(丸ノ内線)", + "東京メトロ(東西線)", + "東京メトロ(日比谷線)", + "東京メトロ(半蔵門線)", + "東京メトロ(南北線)", + "都営地下鉄(浅草線)", + "都営地下鉄(三田線)", + "東武東上線", + "東武伊勢崎線(スカイツリーライン)", + "西武池袋線", + "西武新宿線", + "小田急小田原線", + "京王京王線", + "東急東横線", + "東急田園都市線", + "京急本線", + "相鉄本線", + "つくばエクスプレス" + ) + + // ------------------------- + // 中部(東海) + // ------------------------- + "chubu" -> listOf( + // JR + "JR東海(東海道本線 静岡)", + "JR東海(東海道本線 名古屋)", + "JR東海(中央本線)", + "JR東海(関西本線)", + "JR東海(高山本線)", + "JR東海(御殿場線)", + + // 名古屋の私鉄 + "名古屋市営地下鉄 東山線", + "名古屋市営地下鉄 名城線", + "名古屋市営地下鉄 桜通線", + "名鉄名古屋本線", + "名鉄犬山線", + "名鉄常滑線", + "近鉄名古屋線" + ) + + + // ------------------------- + // 関西(あなたの本命) + // ------------------------- + "kansai" -> listOf( + // JR西日本 + "JR西日本(阪和線)", + "JR西日本(大阪環状線)", + "JR西日本(大和路線)", + "JR西日本(関空・紀州路快速)", + "JR西日本(京都線)", + "JR西日本(神戸線)", + "JR西日本(宝塚線)", + "JR西日本(琵琶湖線)", + + // 南海 + "南海本線", + "南海空港線", + "南海高野線", + "南海加太線", + + // 泉北高速 + "泉北高速鉄道線", + + // Osaka Metro + "Osaka Metro 御堂筋線", + "Osaka Metro 四つ橋線", + "Osaka Metro 谷町線", + "Osaka Metro 堺筋線", + + // 私鉄大手 + "近鉄奈良線", + "近鉄大阪線", + "京阪本線", + "阪急京都線", + "阪急神戸線", + "阪急宝塚線", + "阪神本線", + "阪神なんば線" + ) + + // ------------------------- + // 中国 + // ------------------------- + "chugoku" -> listOf( + "JR西日本(山陽本線)", + "JR西日本(可部線)", + "JR西日本(伯備線)", + "広島電鉄(市内線)", + "岡山電気軌道", + "一畑電車" + ) + + + // ------------------------- + // 四国 + // ------------------------- + "shikoku" -> listOf( + "JR四国(予讃線)", + "JR四国(高徳線)", + "JR四国(徳島線)", + "JR四国(土讃線)" + ) + + // ------------------------- + // 九州 + // ------------------------- + "kyushu" -> listOf( + "JR九州(鹿児島本線)", + "JR九州(長崎本線)", + "JR九州(日豊本線)", + "JR九州(久大本線)", + "福岡市地下鉄 空港線", + "福岡市地下鉄 箱崎線", + "福岡市地下鉄 七隈線", + "西鉄天神大牟田線" + ) + else -> listOf("該当する路線がありません") } } diff --git a/app/src/main/java/com/example/curation_train_app/FollowSettings.kt b/app/src/main/java/com/example/curation_train_app/FollowSettings.kt index fa2d09c..2408524 100644 --- a/app/src/main/java/com/example/curation_train_app/FollowSettings.kt +++ b/app/src/main/java/com/example/curation_train_app/FollowSettings.kt @@ -14,4 +14,15 @@ object FollowSettings { val prefs = context.getSharedPreferences("follow", Context.MODE_PRIVATE) prefs.edit().putStringSet("lines", lines.toSet()).apply() } + + fun loadNotifySettings(context: Context): Set { + val prefs = context.getSharedPreferences("follow", Context.MODE_PRIVATE) + return prefs.getStringSet("notify", emptySet()) ?: emptySet() + } + + fun saveNotifySettings(context: Context, types: Set) { + val prefs = context.getSharedPreferences("follow", Context.MODE_PRIVATE) + prefs.edit().putStringSet("notify", types).apply() + } + } diff --git a/app/src/main/java/com/example/curation_train_app/HiyoriResponder.kt b/app/src/main/java/com/example/curation_train_app/HiyoriResponder.kt index cc05ad7..0615ee5 100644 --- a/app/src/main/java/com/example/curation_train_app/HiyoriResponder.kt +++ b/app/src/main/java/com/example/curation_train_app/HiyoriResponder.kt @@ -20,4 +20,6 @@ class HiyoriResponder : CharacterResponder { "気になったことがあるの?よかったら教えてね。いっしょに見てみるよ。" } } + + fun reply(text: String): String = respond(text, InfoType.NORMAL) } diff --git a/app/src/main/java/com/example/curation_train_app/InfoType.kt b/app/src/main/java/com/example/curation_train_app/InfoType.kt index bb389ab..e4ca874 100644 --- a/app/src/main/java/com/example/curation_train_app/InfoType.kt +++ b/app/src/main/java/com/example/curation_train_app/InfoType.kt @@ -8,6 +8,8 @@ enum class InfoType { EVENT, // イベント・臨時列車 WEATHER, // 天候影響 NEW_TRAIN, // 新型車両関連 - OTHER // 分類できない場合 + OTHER, // 分類できない場合 + + NORMAL } diff --git a/app/src/main/java/com/example/curation_train_app/LinePriorityActivity.kt b/app/src/main/java/com/example/curation_train_app/LinePriorityActivity.kt index 0666d23..ffbf201 100644 --- a/app/src/main/java/com/example/curation_train_app/LinePriorityActivity.kt +++ b/app/src/main/java/com/example/curation_train_app/LinePriorityActivity.kt @@ -5,6 +5,7 @@ import android.widget.TextView import androidx.activity.ComponentActivity import android.content.Intent import android.widget.Button +import android.widget.CheckBox class LinePriorityActivity : ComponentActivity() { @@ -34,6 +35,20 @@ class LinePriorityActivity : ComponentActivity() { val boxes = listOf(box1, box2, box3, box4, box5, box6) + val saved = FollowSettings.loadNotifySettings(this) + + val cbDelay = findViewById(R.id.checkboxDelay) + val cbOuting = findViewById(R.id.checkboxOuting) + val cbCampaign = findViewById(R.id.checkboxCampaign) + val cbOther = findViewById(R.id.checkboxOther) + +// 保存済みの状態を反映 + cbDelay.isChecked = saved.contains("delay") + cbOuting.isChecked = saved.contains("outing") + cbCampaign.isChecked = saved.contains("campaign") + cbOther.isChecked = saved.contains("other") + + // ▼▼ 空き枠を探して路線名をセット ▼▼ for (box in boxes) { val t = box.text.toString() @@ -49,4 +64,25 @@ class LinePriorityActivity : ComponentActivity() { } // ▲▲ 空き枠を探してセット ▲▲ } + + override fun onPause() { + super.onPause() + + val selected = mutableSetOf() + + if (findViewById(R.id.checkboxDelay).isChecked) + selected.add("delay") + + if (findViewById(R.id.checkboxOuting).isChecked) + selected.add("outing") + + if (findViewById(R.id.checkboxCampaign).isChecked) + selected.add("campaign") + + if (findViewById(R.id.checkboxOther).isChecked) + selected.add("other") + + FollowSettings.saveNotifySettings(this, selected) + } + } diff --git a/app/src/main/java/com/example/curation_train_app/LineSelectActivity.kt b/app/src/main/java/com/example/curation_train_app/LineSelectActivity.kt index f4fe7c8..026db2d 100644 --- a/app/src/main/java/com/example/curation_train_app/LineSelectActivity.kt +++ b/app/src/main/java/com/example/curation_train_app/LineSelectActivity.kt @@ -2,6 +2,7 @@ package com.example.curation_train_app import android.content.Intent import android.os.Bundle +import android.widget.Button import android.widget.TextView import androidx.activity.ComponentActivity import androidx.recyclerview.widget.LinearLayoutManager @@ -13,6 +14,8 @@ class LineSelectActivity : ComponentActivity() { super.onCreate(savedInstanceState) setContentView(R.layout.activity_line_select) + + // ★ 地域名を受け取る val region = intent.getStringExtra("region") ?: "未指定" @@ -31,6 +34,19 @@ class LineSelectActivity : ComponentActivity() { } } + private fun onLineSelected(id: String) { + val lines = FollowSettings.loadLines(this).toMutableList() + + if (!lines.contains(id)) { + lines.add(id) + FollowSettings.saveLines(this, lines) + } + + finish() + } + + + // 優先度設定画面へ遷移 private fun openPriorityScreen(line: String) { val intent = Intent(this, LinePriorityActivity::class.java) diff --git a/app/src/main/java/com/example/curation_train_app/MainActivity.kt b/app/src/main/java/com/example/curation_train_app/MainActivity.kt index 2bbaec8..53af3f8 100644 --- a/app/src/main/java/com/example/curation_train_app/MainActivity.kt +++ b/app/src/main/java/com/example/curation_train_app/MainActivity.kt @@ -15,126 +15,40 @@ import retrofit2.Retrofit import retrofit2.converter.scalars.ScalarsConverterFactory import retrofit2.http.GET import retrofit2.Call +import org.json.JSONObject + class MainActivity : ComponentActivity() { + private var lastTrafficStatus: String = "" + private var rssList: List = emptyList() + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // --- キャラ初期画像 --- - val charId = CharacterSettings.loadCharacter(this) - val imageView = findViewById(R.id.imageCharacter) + setInitialCharacterImage() - val drawableId = when (charId) { - "reimu" -> R.drawable.reimu_normal - "marisa" -> R.drawable.marisa_normal - "flandre" -> R.drawable.flandre_normal - "sanae" -> R.drawable.sanae_normal - "akane" -> R.drawable.akane_normal - "momoka" -> R.drawable.momoka_normal - "sayaka" -> R.drawable.sayaka_normal - "hiyori" -> R.drawable.hiyori_normal - else -> R.drawable.reimu_normal - } - imageView.setImageResource(drawableId) - - // ----- キャラ応答ボタン ----- - val btn = findViewById