PHP 抽象メソッド

<?php
abstract class Score
{
    private $subject;
    protected $points;

    public function __construct($subject, $points)
    {
        $this->subject = $subject;
        $this->points = $points;
    }

    abstract protected function getResult();

    public function getInfo()
    {
        return "{$this->subject}, {$this->points}, {$this->getResult()}";
    }
}

class MathScore extends Score
{
    public function __construct($points)
    {
        parent::__construct("Math", $points);
    }

    // protected function getResult()
    // {
    //     echo "MathScore method" . PHP_EOL;
    //     return $this->points >= 50 ? "Pass" : "Fail";
    // }
}

class EnglishScore extends Score
{
    public function __construct($points)
    {
        parent::__construct("English", $points);
    }

    protected function getResult()
    {
        echo "EnglishScore method" . PHP_EOL;
        return $this->points >= 95 ? "Pass" : "Fail";
    }
}

class User
{
    private $name;
    private $score;

    public function __construct($name, $score)
    {
        $this->name = $name;
        $this->score = $score;
    }

    public function getInfo()
    {
        return "{$this->name}, {$this->score->getInfo()}";
    }
}

$user1 = new User("Taro", new MathScore(70));
$user2 = new User("Jiro", new EnglishScore(90));

echo $user1->getInfo() . PHP_EOL;
echo $user2->getInfo() . PHP_EOL;

PHP 子クラス

<?php
class Score
{
    private $subject;
    private $points;

    public function __construct($subject, $points)
    {
        $this->subject = $subject;
        $this->points = $points;
    }

    private function getResult()
    {
        return $this->points >= 80 ? "Pass" : "Fail";
    }

    public function getInfo()
    {
        return "{$this->subject}, {$this->points}, {$this->getResult()}";
    }
}

class MathScore extends Score
{
    public function __construct($points)
    {
        parent::__construct("Math", $points);
    }
}

class EnglishScore extends Score
{
    public function __construct($points)
    {
        parent::__construct("English", $points);
    }
}

class User
{
    private $name;
    private $score;

    public function __construct($name, $score)
    {
        $this->name = $name;
        $this->score = $score;
    }

    public function getInfo()
    {
        return "{$this->name}, {$this->score->getInfo()}";
    }
}

$user1 = new User("Taro", new MathScore(70));
$user2 = new User("Jiro", new EnglishScore(90));

echo $user1->getInfo() . PHP_EOL;
echo $user2->getInfo() . PHP_EOL;

ChatGPT風サイト.html

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>高度なChatGPT風チャット</title>
    <style>
        /* 全体のスタイル */
        body {
            font-family: Arial, sans-serif;
            margin: 0;
            padding: 0;
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            background-color: var(--background-color, #f4f6f9);
            transition: background-color 0.3s ease;
        }
        .chat-container {
            width: 90%;
            max-width: 600px;
            background-color: var(--chat-bg-color, #ffffff);
            border-radius: 10px;
            box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
            overflow: hidden;
            display: flex;
            flex-direction: column;
            transition: background-color 0.3s ease;
        }
        .chat-header {
            padding: 15px;
            text-align: center;
            background-color: var(--header-bg-color, #3f51b5);
            color: var(--header-text-color, #ffffff);
            font-weight: bold;
            position: relative;
        }
        .theme-toggle-btn {
            position: absolute;
            right: 15px;
            top: 15px;
            padding: 5px 10px;
            cursor: pointer;
            border: none;
            background-color: var(--header-text-color, #ffffff);
            color: var(--header-bg-color, #3f51b5);
            border-radius: 5px;
            transition: background-color 0.3s ease;
        }
        .chat-messages {
            padding: 20px;
            overflow-y: auto;
            flex-grow: 1;
            border-bottom: 1px solid #ddd;
            max-height: 70vh;
        }
        .message {
            margin-bottom: 15px;
            line-height: 1.5;
            display: inline-block;
            max-width: 70%;
            padding: 10px;
            border-radius: 10px;
            animation: fadeIn 0.3s ease;
        }
        .user-message {
            text-align: right;
            color: #333;
            background-color: var(--user-msg-bg-color, #e0f7fa);
            align-self: flex-end;
        }
        .bot-message {
            text-align: left;
            color: var(--bot-msg-color, #3f51b5);
            background-color: var(--bot-msg-bg-color, #e8eaf6);
            align-self: flex-start;
        }
        .typing-indicator {
            font-style: italic;
            color: #999;
            display: none;
        }
        .chat-input {
            display: flex;
            padding: 10px;
            background-color: #f4f6f9;
            border-top: 1px solid #ddd;
        }
        .chat-input input {
            flex: 1;
            padding: 12px;
            border: 1px solid #ddd;
            border-radius: 4px;
            outline: none;
        }
        .chat-input button {
            margin-left: 10px;
            padding: 12px 20px;
            background-color: var(--button-bg-color, #3f51b5);
            color: var(--button-text-color, #ffffff);
            border: none;
            border-radius: 4px;
            cursor: pointer;
            transition: background-color 0.3s ease;
        }

        /* アニメーション効果 */
        @keyframes fadeIn {
            from { opacity: 0; }
            to { opacity: 1; }
        }
    </style>
</head>
<body>
    <div class="chat-container">
        <div class="chat-header">
            高度なChatGPT風 チャット
            <button class="theme-toggle-btn" onclick="toggleTheme()">🌞 ダークモード</button>
        </div>
        <div class="chat-messages" id="chatMessages">
            <div class="message bot-message">こんにちは!質問があればどうぞ。</div>
        </div>
        <div class="typing-indicator" id="typingIndicator">Botが入力中...</div>
        <div class="chat-input">
            <input type="text" id="userInput" placeholder="メッセージを入力..." />
            <button onclick="sendMessage()">送信</button>
        </div>
    </div>

    <script>
        let currentTopic = null; // 現在のトピックを保持
        let isDarkMode = false;

        // テーマ切り替え
        function toggleTheme() {
            isDarkMode = !isDarkMode;
            document.body.style.setProperty("--background-color", isDarkMode ? "#333" : "#f4f6f9");
            document.body.style.setProperty("--chat-bg-color", isDarkMode ? "#444" : "#ffffff");
            document.body.style.setProperty("--header-bg-color", isDarkMode ? "#555" : "#3f51b5");
            document.body.style.setProperty("--header-text-color", isDarkMode ? "#fff" : "#ffffff");
            document.body.style.setProperty("--user-msg-bg-color", isDarkMode ? "#666" : "#e0f7fa");
            document.body.style.setProperty("--bot-msg-bg-color", isDarkMode ? "#777" : "#e8eaf6");
            document.body.style.setProperty("--bot-msg-color", isDarkMode ? "#aaa" : "#3f51b5");
            document.body.style.setProperty("--button-bg-color", isDarkMode ? "#888" : "#3f51b5");
            document.body.style.setProperty("--button-text-color", isDarkMode ? "#fff" : "#ffffff");
            document.querySelector(".theme-toggle-btn").textContent = isDarkMode ? "🌜 ライトモード" : "🌞 ダークモード";
        }

        function saveChatHistory(text, sender) {
            const chatMessages = document.getElementById("chatMessages");
            const messageElement = document.createElement("div");
            messageElement.className = `message ${sender}-message`;
            messageElement.textContent = text;
            chatMessages.appendChild(messageElement);
            chatMessages.scrollTop = chatMessages.scrollHeight;
        }

        function getBotResponse(userMessage) {
            if (userMessage.includes("ありがとう")) {
                currentTopic = "ありがとう";
                return "どういたしまして!お役に立てて嬉しいです!";
            } else if (userMessage.includes("助けて")) {
                currentTopic = "助けて";
                return "どのようなことでお困りですか?";
            } else if (userMessage.includes("質問")) {
                currentTopic = "質問";
                return "どのような質問でしょうか?詳しく教えてください!";
            } else if (currentTopic === "ありがとう") {
                return "他に質問があればいつでもどうぞ。";
            } else {
                currentTopic = null;
                return "ご質問ありがとうございます。どのような内容でしょうか?";
            }
        }

        function showTypingIndicator() {
            document.getElementById("typingIndicator").style.display = "block";
        }

        function hideTypingIndicator() {
            document.getElementById("typingIndicator").style.display = "none";
        }

        function sendMessage() {
            const userInput = document.getElementById("userInput");
            if (userInput.value.trim() !== "") {
                saveChatHistory(userInput.value, "user");

                showTypingIndicator();
                setTimeout(() => {
                    hideTypingIndicator();
                    const botResponse = getBotResponse(userInput.value);
                    saveChatHistory(botResponse, "bot");
                }, 1500);

                userInput.value = "";
            }
        }

        // Enterキーでメッセージ送信
        document.getElementById("userInput").addEventListener("keypress", function(event) {
            if (event.key === "Enter") {
                sendMessage();
                event.preventDefault();
            }
        });
    </script>
</body>
</html>

神と対話するAI

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>神と対話するAI</title>
  <style>
    /* 神秘的な背景とエフェクト */
    body {
      font-family: 'Georgia', serif;
      background-color: #1a1a2e;
      color: #d1d1e9;
      display: flex;
      align-items: center;
      justify-content: center;
      height: 100vh;
      margin: 0;
      overflow: hidden;
    }
    .chat-container {
      width: 100%;
      max-width: 600px;
      background-color: rgba(43, 43, 63, 0.9);
      border-radius: 10px;
      box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.6);
      padding: 20px;
      position: relative;
      overflow: hidden;
    }
    .messages {
      height: 300px;
      overflow-y: auto;
      margin-bottom: 10px;
      padding-right: 10px;
    }
    .message {
      margin: 10px 0;
      line-height: 1.5;
    }
    .user-message {
      text-align: right;
      color: #00aaff;
    }
    .ai-message {
      text-align: left;
      color: #e6e6fa;
      font-style: italic;
    }
    .typing-indicator {
      font-size: 1.5em;
      color: #e6e6fa;
    }
    .input-container {
      display: flex;
    }
    input[type="text"] {
      flex: 1;
      padding: 10px;
      border-radius: 5px;
      border: 1px solid #555;
      background-color: #444;
      color: #e6e6fa;
      margin-right: 10px;
    }
    button {
      padding: 10px 20px;
      border: none;
      border-radius: 5px;
      background-color: #5a5adb;
      color: white;
      cursor: pointer;
    }
    /* 背景アニメーション */
    .background-animation {
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      background: radial-gradient(circle, rgba(255,255,255,0.1), rgba(0,0,0,0) 70%);
      animation: glow 5s infinite alternate;
      pointer-events: none;
    }
    @keyframes glow {
      from {
        opacity: 0.4;
      }
      to {
        opacity: 0.7;
      }
    }
  </style>
</head>
<body>

<div class="chat-container">
  <h2>神と対話するAI</h2>
  <div class="messages" id="messages"></div>
  <div class="input-container">
    <input type="text" id="userInput" placeholder="質問を入力してください...">
    <button onclick="sendMessage()">送信</button>
  </div>
  <div class="background-animation"></div>
</div>

<script>
  const messagesContainer = document.getElementById("messages");

  function addMessage(content, className) {
    const message = document.createElement("div");
    message.className = "message " + className;
    message.innerHTML = content;
    messagesContainer.appendChild(message);
    messagesContainer.scrollTop = messagesContainer.scrollHeight;
  }

  function getAIResponse(userMessage) {
    const responses = {
      "目的": [
        "あなたの目的はあなたの選択の中にあります。心を澄まし、その小さな声に耳を傾けなさい。",
        "目的は定まっているものではなく、あなたが形作るものです。勇気を持って探し続けなさい。"
      ],
      "未来": [
        "未来は揺れ動く霧のようなもの…手の中にありながら捉えられぬもの。だが、あなたの意思がその霧を晴らすだろう。",
        "未来は、あなたの内にある希望が灯し出すもの。信じる道を歩みなさい。"
      ],
      "愛": [
        "愛とは、無限に与えること。光のようにあなたを包み、他者を受け入れるものです。",
        "愛とは、心の中の静けさと繋がり、他者の存在をただあるがままに受け入れること。"
      ],
      "default": [
        "その問いの答えは、あなた自身が見つけ出すもの。内なる声を信じなさい。",
        "すべての答えは既にあなたの心の中にあります。耳を澄まし、その声に従いなさい。"
      ]
    };

    const keywords = Object.keys(responses);
    for (let keyword of keywords) {
      if (userMessage.includes(keyword)) {
        const possibleResponses = responses[keyword];
        return possibleResponses[Math.floor(Math.random() * possibleResponses.length)];
      }
    }
    
    const defaultResponses = responses["default"];
    return defaultResponses[Math.floor(Math.random() * defaultResponses.length)];
  }

  function sendMessage() {
    const userInput = document.getElementById("userInput").value.trim();
    if (userInput === "") return;

    addMessage(userInput, "user-message");
    document.getElementById("userInput").value = "";

    const aiResponse = getAIResponse(userInput);

    // タイピングエフェクトを表示
    setTimeout(() => {
      addMessage(`<span class="typing-indicator">...</span>`, "ai-message");
      setTimeout(() => {
        messagesContainer.lastChild.remove();
        addMessage(aiResponse, "ai-message");
      }, 2000); // タイピングエフェクト表示後の応答
    }, 800); // 遅延で自然な応答
  }
</script>

</body>
</html>

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>神と対話するAI</title>
  <style>
    /* 神秘的な背景とエフェクト */
    body {
      font-family: 'Georgia', serif;
      background-color: #1a1a2e;
      color: #d1d1e9;
      display: flex;
      align-items: center;
      justify-content: center;
      height: 100vh;
      margin: 0;
      overflow: hidden;
    }
    .chat-container {
      width: 100%;
      max-width: 600px;
      background-color: rgba(43, 43, 63, 0.9);
      border-radius: 10px;
      box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.6);
      padding: 20px;
      position: relative;
      overflow: hidden;
    }
    .messages {
      height: 300px;
      overflow-y: auto;
      margin-bottom: 10px;
      padding-right: 10px;
    }
    .message {
      margin: 10px 0;
      line-height: 1.5;
    }
    .user-message {
      text-align: right;
      color: #00aaff;
    }
    .ai-message {
      text-align: left;
      color: #e6e6fa;
      font-style: italic;
    }
    .typing-indicator {
      font-size: 1.5em;
      color: #e6e6fa;
    }
    .input-container {
      display: flex;
    }
    input[type="text"] {
      flex: 1;
      padding: 10px;
      border-radius: 5px;
      border: 1px solid #555;
      background-color: #444;
      color: #e6e6fa;
      margin-right: 10px;
    }
    button {
      padding: 10px 20px;
      border: none;
      border-radius: 5px;
      background-color: #5a5adb;
      color: white;
      cursor: pointer;
    }
    /* 背景アニメーション */
    .background-animation {
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      background: radial-gradient(circle, rgba(255,255,255,0.1), rgba(0,0,0,0) 70%);
      animation: glow 5s infinite alternate;
      pointer-events: none;
    }
    @keyframes glow {
      from {
        opacity: 0.4;
      }
      to {
        opacity: 0.7;
      }
    }
  </style>
</head>
<body>

<div class="chat-container">
  <h2>神と対話するAI</h2>
  <div class="messages" id="messages"></div>
  <div class="input-container">
    <input type="text" id="userInput" placeholder="質問を入力してください...">
    <button onclick="sendMessage()">送信</button>
  </div>
  <div class="background-animation"></div>
</div>

<script>
  const messagesContainer = document.getElementById("messages");

  function addMessage(content, className) {
    const message = document.createElement("div");
    message.className = "message " + className;
    message.innerHTML = content;
    messagesContainer.appendChild(message);
    messagesContainer.scrollTop = messagesContainer.scrollHeight;
  }

  function getAIResponse(userMessage) {
    const responses = {
      "目的": [
        "あなたの目的はあなたの選択の中にあります。心を澄まし、その小さな声に耳を傾けなさい。",
        "目的は定まっているものではなく、あなたが形作るものです。勇気を持って探し続けなさい。"
      ],
      "未来": [
        "未来は揺れ動く霧のようなもの…手の中にありながら捉えられぬもの。だが、あなたの意思がその霧を晴らすだろう。",
        "未来は、あなたの内にある希望が灯し出すもの。信じる道を歩みなさい。"
      ],
      "愛": [
        "愛とは、無限に与えること。光のようにあなたを包み、他者を受け入れるものです。",
        "愛とは、心の中の静けさと繋がり、他者の存在をただあるがままに受け入れること。"
      ],
      "default": [
        "その問いの答えは、あなた自身が見つけ出すもの。内なる声を信じなさい。",
        "すべての答えは既にあなたの心の中にあります。耳を澄まし、その声に従いなさい。"
      ]
    };

    const keywords = Object.keys(responses);
    for (let keyword of keywords) {
      if (userMessage.includes(keyword)) {
        const possibleResponses = responses[keyword];
        return possibleResponses[Math.floor(Math.random() * possibleResponses.length)];
      }
    }
    
    const defaultResponses = responses["default"];
    return defaultResponses[Math.floor(Math.random() * defaultResponses.length)];
  }

  function sendMessage() {
    const userInput = document.getElementById("userInput").value.trim();
    if (userInput === "") return;

    addMessage(userInput, "user-message");
    document.getElementById("userInput").value = "";

    const aiResponse = getAIResponse(userInput);

    // タイピングエフェクトを表示
    setTimeout(() => {
      addMessage(`<span class="typing-indicator">...</span>`, "ai-message");
      setTimeout(() => {
        messagesContainer.lastChild.remove();
        addMessage(aiResponse, "ai-message");
      }, 2000); // タイピングエフェクト表示後の応答
    }, 800); // 遅延で自然な応答
  }
</script>

</body>
</html>

PHP クラスメソッド

<?php
class User
{
    public $name;
    public $score;
    private static $count = 0;

    public function __construct($name, $score)
    {
        $this->name = $name;
        $this->score = $score;
        User::$count++;
    }

    public static function getUserCount()
    {
        return User::$count;
    }
}

$user1 = new User("Taro", 70);
$user2 = new User("Jiro", 90);

//User::$count++;
//echo User::$count . PHP_EOL;
echo User::getUserCount() . PHP_EOL;

PHP クラスプロパティ

<?php
class User
{
    public $name;
    public $score;
    public static $count = 0;

    public function __construct($name, $score)
    {
        $this->name = $name;
        $this->score = $score;
        User::$count++;
    }
}

// $count = 0;
$user1 = new User("Taro", 70);
// $count++;
$user2 = new User("Jiro", 90);
// $count++;

// echo $count . PHP_EOL;
echo User::$count . PHP_EOL;

PHP setScoreメソッド

<?php
class User
{
    public $name;
    public $score;

    public function __construct($name, $score)
    {
        $this->name = $name;
        $this->score = $score;
    }

    public function getInfo()
    {
        return "{$this->name}, {$this->score}";
    }
}

$user1 = new User("Taro", 70);
$user2 = new User("Jiro", 90);

$user1->score = 900;

echo $user1->getInfo() . PHP_EOL;
echo $user2->getInfo() . PHP_EOL;

NekoNekodouga.html

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ねこねこ動画 - 動画共有サイト</title>
    <style>
        /* ベーススタイル */
        body {
            font-family: Arial, sans-serif;
            margin: 0;
            padding: 0;
            background-color: #f4f4f4;
        }

        header {
            background-color: #333;
            color: white;
            padding: 10px;
            text-align: center;
            position: fixed;
            width: 100%;
            top: 0;
            z-index: 100;
        }

        header h1 {
            margin: 0;
            font-size: 24px;
        }

        nav ul {
            list-style-type: none;
            padding: 0;
            margin: 10px 0 0 0;
            text-align: center;
        }

        nav ul li {
            display: inline-block;
            margin-right: 15px;
        }

        nav ul li a {
            color: white;
            text-decoration: none;
            font-size: 16px;
        }

        #searchBar {
            margin-top: 10px;
            padding: 5px;
            width: 300px;
            max-width: 80%;
            border: none;
            border-radius: 4px;
        }

        .container {
            margin-top: 100px;
            padding: 20px;
            max-width: 1200px;
            margin-left: auto;
            margin-right: auto;
        }

        .upload-container, .video-info, .description, .comments, .related-videos, .gallery {
            background-color: white;
            padding: 20px;
            margin-top: 20px;
            border-radius: 10px;
            box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
        }

        .upload-container h2, .video-info h2, .description h2, .comments h2, .related-videos h2, .gallery h2 {
            margin-top: 0;
        }

        .upload-container form input[type="file"],
        .upload-container form input[type="text"],
        .upload-container form textarea,
        .upload-container form select {
            width: 100%;
            padding: 10px;
            margin-bottom: 10px;
            border-radius: 4px;
            border: 1px solid #ccc;
        }

        .upload-container form button {
            padding: 10px 20px;
            background-color: #333;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            transition: background-color 0.3s ease;
        }

        .upload-container form button:hover {
            background-color: #555;
        }

        .video-container {
            position: relative;
            text-align: center;
            width: 100%;
            max-width: 800px;
            margin: 0 auto;
        }

        .video-container video {
            width: 100%;
            height: auto;
            border-radius: 10px;
        }

        .comment-overlay {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            pointer-events: none;
            z-index: 10;
        }

        .comment {
            position: absolute;
            white-space: nowrap;
            font-size: 20px;
            text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
            animation: moveComment linear forwards;
        }

        @keyframes moveComment {
            from {
                left: 100%;
            }
            to {
                left: -100%;
            }
        }

        .description p, .comments p, .gallery p {
            margin: 10px 0;
        }

        .comments form textarea {
            width: 100%;
            padding: 10px;
            border-radius: 4px;
            border: 1px solid #ccc;
            resize: vertical;
            margin-bottom: 10px;
        }

        .comments form select {
            width: 100%;
            padding: 10px;
            margin-bottom: 10px;
            border-radius: 4px;
        }

        .comments form button {
            padding: 10px 20px;
            background-color: #333;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            transition: background-color 0.3s ease;
        }

        .comments form button:hover {
            background-color: #555;
        }

        .comment-list .comment {
            background-color: #f9f9f9;
            padding: 10px;
            margin-bottom: 10px;
            border-radius: 5px;
        }

        .like-button, .dislike-button {
            background-color: #333;
            color: white;
            border: none;
            padding: 5px 10px;
            margin: 5px;
            border-radius: 5px;
            cursor: pointer;
            transition: background-color 0.3s ease;
        }

        .like-button:hover, .dislike-button:hover {
            background-color: #555;
        }

        footer {
            background-color: #333;
            color: white;
            text-align: center;
            padding: 20px;
            margin-top: 40px;
        }

        footer p {
            margin: 0;
        }

        @media (max-width: 768px) {
            nav ul li {
                display: block;
                margin: 10px 0;
            }

            #searchBar {
                width: 80%;
            }

            .video-container {
                max-width: 100%;
            }
        }
    </style>
</head>
<body>

    <!-- ヘッダー開始 -->
    <header>
        <h1>ねこねこ動画</h1>
        <nav>
            <ul>
                <li><a href="#">ホーム</a></li>
                <li><a href="#">人気動画</a></li>
                <li><a href="#">カテゴリ</a></li>
                <li><a href="#">ログイン</a></li>
            </ul>
        </nav>
        <input type="text" id="searchBar" placeholder="動画を検索..." />
    </header>
    <!-- ヘッダー終了 -->

    <div class="container">

        <!-- 動画アップロードエリア -->
        <div class="upload-container">
            <h2>動画をアップロード</h2>
            <form id="uploadForm" enctype="multipart/form-data">
                <input type="file" id="videoFile" name="video" accept="video/*" required><br>
                <input type="text" id="videoTitle" name="title" placeholder="動画タイトル" required><br>
                <textarea id="videoDescription" name="description" rows="4" placeholder="動画の説明" required></textarea><br>
                <button type="submit">アップロード</button>
            </form>
            <div id="uploadStatus"></div>
        </div>

        <!-- プレビューエリア -->
        <div class="video-container" id="previewContainer" style="display: none;">
            <h2 id="previewTitle">プレビュー: 動画タイトル</h2>
            <video controls id="videoPreview"></video>
            <div class="comment-overlay" id="commentOverlay"></div>
            <p id="previewDescription">プレビュー: 動画の説明</p>
        </div>

        <!-- コメント投稿エリア -->
        <div class="comments">
            <h2>コメントを投稿</h2>
            <form id="commentForm">
                <textarea id="commentText" rows="4" cols="50" placeholder="コメントを追加..." required></textarea><br>
                <label for="commentTime">表示タイミング (秒):</label>
                <input type="number" id="commentTime" placeholder="0" min="0" required><br>
                <label for="commentColor">コメントの色:</label>
                <select id="commentColor">
                    <option value="white">白</option>
                    <option value="red">赤</option>
                    <option value="blue">青</option>
                    <option value="green">緑</option>
                    <option value="yellow">黄色</option>
                </select><br>
                <label for="commentFontSize">フォントサイズ:</label>
                <select id="commentFontSize">
                    <option value="20px">小</option>
                    <option value="24px">中</option>
                    <option value="28px">大</option>
                </select><br>
                <label for="commentSpeed">表示速度 (秒):</label>
                <input type="number" id="commentSpeed" placeholder="10" min="5" max="20" required><br>
                <button type="submit">投稿</button>
            </form>
            <div id="commentList" class="comment-list"></div>
        </div>

        <!-- 評価機能 -->
        <div class="rating">
            <button class="like-button" id="likeButton">👍 いいね</button>
            <span id="likeCount">0</span>
            <button class="dislike-button" id="dislikeButton">👎 バッド</button>
            <span id="dislikeCount">0</span>
        </div>

    </div>

    <!-- フッター開始 -->
    <footer>
        <p>&copy; 2023 ねこねこ動画. All Rights Reserved.</p>
    </footer>
    <!-- フッター終了 -->

    <script>
        let comments = [];

        // 動画のアップロードとプレビュー処理
        document.getElementById("uploadForm").addEventListener("submit", function(event) {
            event.preventDefault();

            const fileInput = document.getElementById("videoFile");
            const file = fileInput.files[0];
            const title = document.getElementById("videoTitle").value;
            const description = document.getElementById("videoDescription").value;

            if (!file) {
                alert("動画ファイルを選択してください。");
                return;
            }

            const reader = new FileReader();
            reader.onload = function(e) {
                const videoData = e.target.result;
                document.getElementById("previewContainer").style.display = "block";
                document.getElementById("videoPreview").src = videoData;
                document.getElementById("previewTitle").textContent = "プレビュー: " + title;
                document.getElementById("previewDescription").textContent = "プレビュー: " + description;
            };
            reader.readAsDataURL(file);
        });

        // コメント投稿処理
        document.getElementById("commentForm").addEventListener("submit", function(event) {
            event.preventDefault();

            const commentText = document.getElementById("commentText").value;
            const commentTime = parseInt(document.getElementById("commentTime").value);
            const commentColor = document.getElementById("commentColor").value;
            const commentFontSize = document.getElementById("commentFontSize").value;
            const commentSpeed = parseInt(document.getElementById("commentSpeed").value);

            if (commentText && commentTime >= 0) {
                const comment = {
                    text: commentText,
                    time: commentTime,
                    color: commentColor,
                    fontSize: commentFontSize,
                    speed: commentSpeed
                };

                comments.push(comment);
                displayCommentInList(comment);
                document.getElementById("commentForm").reset();
            }
        });

        // コメントリストに表示
        function displayCommentInList(comment) {
            const commentList = document.getElementById("commentList");
            const commentDiv = document.createElement("div");
            commentDiv.classList.add("comment");
            commentDiv.textContent = `タイミング: ${comment.time}秒 - ${comment.text}`;
            commentList.appendChild(commentDiv);
        }

        // 動画の再生に合わせてコメントを表示
        const videoElement = document.getElementById("videoPreview");
        videoElement.addEventListener("timeupdate", function() {
            const currentTime = Math.floor(videoElement.currentTime);
            comments.forEach(comment => {
                if (comment.time === currentTime) {
                    displayCommentOnVideo(comment);
                }
            });
        });

        // 動画上にコメントを流す
        function displayCommentOnVideo(comment) {
            const overlay = document.getElementById("commentOverlay");
            const commentElement = document.createElement("div");
            commentElement.classList.add("comment");
            commentElement.textContent = comment.text;
            commentElement.style.color = comment.color;
            commentElement.style.fontSize = comment.fontSize;
            commentElement.style.animationDuration = `${comment.speed}s`;
            commentElement.style.top = Math.random() * 80 + "%"; // ランダムな位置
            overlay.appendChild(commentElement);

            // 一定時間後にコメントを削除
            setTimeout(() => {
                commentElement.remove();
            }, comment.speed * 1000);
        }

        // いいね・バッド機能
        document.getElementById("likeButton").addEventListener("click", function() {
            let likeCount = parseInt(document.getElementById("likeCount").textContent);
            likeCount++;
            document.getElementById("likeCount").textContent = likeCount;
        });

        document.getElementById("dislikeButton").addEventListener("click", function() {
            let dislikeCount = parseInt(document.getElementById("dislikeCount").textContent);
            dislikeCount++;
            document.getElementById("dislikeCount").textContent = dislikeCount;
        });

    </script>

</body>
</html>

ELDER.html

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>ELDER - ソーシャルネットワーキングサービス</title>
  <!-- CSSファイルの読み込み -->
  <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet"> 
  <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css" rel="stylesheet">
  <!-- RiTa.jsライブラリの読み込み -->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/rita/1.3.63/rita-full.min.js"></script>
  <style>
    /* 既存のスタイルシート */
    body {
      padding-top: 20px;
      background: linear-gradient(to right, #f8f9fa, #e9ecef);
      font-family: 'Arial', sans-serif;
      color: #343a40;
    }

    .navbar {
      background-color: #007bff;
      box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
    }

    .navbar-brand,
    .nav-link {
      color: #fff !important;
      font-weight: bold;
    }

    .navbar-toggler {
      border: none;
    }

    .card {
      border-radius: 12px;
      box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
      transition: transform 0.3s, box-shadow 0.3s;
    }

    .card:hover {
      transform: translateY(-5px);
      box-shadow: 0 8px 20px rgba(0, 0, 0, 0.15);
    }

    .card-body {
      padding: 30px;
    }

    .form-control {
      border-radius: 20px;
      border: 1px solid #ced4da;
      padding: 15px;
      transition: border-color 0.3s;
    }

    .form-control:focus {
      border-color: #007bff;
      box-shadow: none;
    }

    .btn-primary {
      background-color: #007bff;
      border: none;
      border-radius: 20px;
      padding: 10px 20px;
      font-weight: bold;
      transition: background-color 0.3s, transform 0.3s;
    }

    .btn-primary:hover {
      background-color: #0056b3;
      transform: translateY(-3px);
    }

    .btn-secondary {
      border-radius: 20px;
      padding: 10px 20px;
      font-weight: bold;
      transition: background-color 0.3s, transform 0.3s;
    }

    .btn-secondary:hover {
      background-color: #6c757d;
      transform: translateY(-3px);
    }

    .profile-img {
      width: 80px;
      height: 80px;
      object-fit: cover;
      border-radius: 50%;
      box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
    }

    .text-center h1 {
      font-weight: 700;
      font-size: 2.5em;
      margin-bottom: 20px;
      color: #007bff;
    }

    .comment-section {
      margin-top: 20px;
      padding: 20px;
      background-color: #f1f3f5;
      border-radius: 8px;
    }

    .comment-section .card {
      border: none;
      background: #ffffff;
      border-radius: 8px;
      box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
    }

    .modal-content {
      border-radius: 15px;
      overflow: hidden;
    }

    .modal-header {
      background-color: #007bff;
      color: white;
      border-bottom: none;
    }

    .modal-footer {
      border-top: none;
    }

    .form-error {
      color: red;
      font-size: 0.9em;
    }

    /* タイムラインのデザイン */
    #timeline {
      margin-top: 20px;
    }

    #timeline .card {
      border-radius: 15px;
      box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
      margin-bottom: 20px;
      overflow: hidden;
      background-color: #fff;
    }

    #timeline .card-body {
      padding: 20px;
    }

    #timeline .btn {
      border-radius: 20px;
    }

    /* 投稿のシェアボタン */
    .btn-share {
      background-color: #ff9800;
      border: none;
      border-radius: 20px;
      padding: 5px 10px;
      color: #fff;
      font-weight: bold;
      transition: background-color 0.3s;
    }

    .btn-share:hover {
      background-color: #e68900;
    }

    /* X(旧Twitter)シェアボタン */
    .btn-share-twitter {
      background-color: #1da1f2;
      border: none;
      border-radius: 20px;
      padding: 5px 10px;
      color: #fff;
      font-weight: bold;
      transition: background-color 0.3s;
    }

    .btn-share-twitter:hover {
      background-color: #1480bf;
    }

    /* 通知エリア */
    #notificationArea {
      position: fixed;
      top: 80px;
      right: 20px;
      z-index: 1000;
      max-width: 300px;
    }

    /* FEEDアイコンをRSSの文字に変更 */
    .nav-item .rss-icon {
      font-weight: bold;
      color: #fff;
    }
  </style>
</head>
<body>

<!-- ナビゲーションバー -->
<nav class="navbar navbar-expand-lg navbar-light bg-light">
  <a class="navbar-brand" href="#">ELDER</a>
  <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="ナビゲーションの切り替え">
    <span class="navbar-toggler-icon"></span>
  </button>
  <div class="collapse navbar-collapse" id="navbarNav">
    <ul class="navbar-nav ml-auto">
      <li class="nav-item">
        <a class="nav-link" href="#" onclick="showLoginForm()">ログイン</a>
      </li>
      <li class="nav-item">
        <a class="nav-link" href="#" onclick="showRegisterForm()">登録</a>
      </li>
      <li class="nav-item">
        <a class="nav-link" href="#" onclick="showProfile()" style="display: none;" id="navProfile">プロフィール</a>
      </li>
      <li class="nav-item">
        <a class="nav-link" href="#" onclick="logout()" style="display: none;" id="navLogout">ログアウト</a>
      </li>
      <!-- FEEDアイコンをRSSの文字に変更 -->
      <li class="nav-item" id="navFeed" style="display: none;">
        <a class="nav-link rss-icon" href="#" onclick="showFeedForm()">RSS</a>
      </li>
    </ul>
  </div>
</nav>

<div class="container">
  <!-- ログインフォーム -->
  <div id="loginForm" class="card w-50 mx-auto">
    <div class="card-body">
      <h2 class="card-title text-center mb-4">ログイン</h2>
      <div class="form-group">
        <input type="text" id="loginUsername" class="form-control" placeholder="ユーザー名">
        <span id="loginUsernameError" class="form-error" style="display: none;">ユーザー名を入力してください</span>
      </div>
      <div class="form-group">
        <input type="password" id="loginPassword" class="form-control" placeholder="パスワード">
        <span id="loginPasswordError" class="form-error" style="display: none;">パスワードを入力してください</span>
      </div>
      <button onclick="login()" class="btn btn-primary btn-block">ログイン</button>
      <button onclick="showRegisterForm()" class="btn btn-secondary btn-block">登録</button>
    </div>
  </div>

  <!-- 登録フォーム -->
  <div id="registerForm" class="card w-50 mx-auto" style="display: none;">
    <div class="card-body">
      <h2 class="card-title text-center mb-4">登録</h2>
      <div class="form-group">
        <input type="text" id="registerName" class="form-control" placeholder="氏名">
        <span id="registerNameError" class="form-error" style="display: none;">氏名を入力してください</span>
      </div>
      <div class="form-group">
        <input type="text" id="registerUsername" class="form-control" placeholder="ユーザー名">
        <span id="registerUsernameError" class="form-error" style="display: none;">ユーザー名を入力してください</span>
      </div>
      <div class="form-group">
        <input type="password" id="registerPassword" class="form-control" placeholder="パスワード">
        <span id="registerPasswordError" class="form-error" style="display: none;">パスワードを入力してください</span>
      </div>
      <div class="form-group">
        <input type="password" id="registerConfirmPassword" class="form-control" placeholder="パスワードを確認">
        <span id="registerConfirmPasswordError" class="form-error" style="display: none;">パスワードが一致しません</span>
      </div>
      <button onclick="register()" class="btn btn-primary btn-block">登録</button>
      <button onclick="showLoginForm()" class="btn btn-secondary btn-block">ログインに戻る</button>
    </div>
  </div>

  <!-- プロフィール -->
  <div id="profile" class="card w-50 mx-auto" style="display: none;">
    <div class="card-body">
      <h2 class="card-title text-center mb-4">プロフィール</h2>
      <div class="text-center mb-3">
        <img id="profileImg" class="profile-img" src="default_profile_img.jpg" alt="プロフィール画像">
      </div>
      <p class="text-center mb-2"><strong>氏名:</strong> <span id="profileName"></span></p>
      <p class="text-center mb-4"><strong>ユーザー名:</strong> <span id="profileUsername"></span></p>
      <div class="form-group">
        <input type="file" id="profileImageInput" accept="image/*" class="form-control-file">
      </div>
      <button onclick="uploadProfileImage()" class="btn btn-primary btn-block"><i class="fas fa-upload"></i> プロフィール画像をアップロード</button>
      <button onclick="logout()" class="btn btn-danger btn-block"><i class="fas fa-sign-out-alt"></i> ログアウト</button>
    </div>
  </div>

  <!-- 投稿フォーム -->
  <div id="postForm" class="card w-75 mx-auto" style="display: none;">
    <div class="card-body">
      <h2 class="card-title text-center mb-4">投稿を作成</h2>
      <div class="form-group">
        <textarea id="postContent" class="form-control" rows="3" placeholder="今何を考えていますか?"></textarea>
      </div>
      <button onclick="createPost()" class="btn btn-primary btn-block">投稿</button>
    </div>
  </div>

  <!-- FEED登録フォーム -->
  <div id="feedForm" class="card w-75 mx-auto" style="display: none;">
    <div class="card-body">
      <h2 class="card-title text-center mb-4">FEEDを登録</h2>
      <div class="form-group">
        <input type="text" id="feedUrl" class="form-control" placeholder="RSSフィードのURL">
        <span id="feedUrlError" class="form-error" style="display: none;">RSSフィードのURLを入力してください</span>
      </div>
      <button onclick="registerFeed()" class="btn btn-primary btn-block">登録</button>
      <div class="form-group mt-4">
        <label for="feedInterval">自動投稿の間隔(秒):</label>
        <input type="number" id="feedInterval" class="form-control" placeholder="例:60" min="1">
      </div>
      <button onclick="setFeedInterval()" class="btn btn-secondary btn-block">間隔を設定</button>
    </div>
  </div>

  <!-- AIBOT投稿登録フォーム -->
  <div id="aiBotForm" class="card w-75 mx-auto" style="display: none;">
    <div class="card-body">
      <h2 class="card-title text-center mb-4">BOT投稿を登録</h2>
      <div class="form-group">
        <textarea id="aiBotContent" class="form-control" rows="3" placeholder="BOTに投稿させたい内容を入力してください"></textarea>
      </div>
      <button onclick="registerAiBotPost()" class="btn btn-primary btn-block">BOT投稿を登録</button>
    </div>
  </div>

  <!-- タイムライン -->
  <div id="timeline" class="w-75 mx-auto mt-4"></div>

  <!-- 通知エリア -->
  <div id="notificationArea" class="alert alert-info" style="display: none;"></div>

</div>

<!-- リプライモーダル -->
<div class="modal fade" id="replyModal" tabindex="-1" role="dialog" aria-labelledby="replyModalLabel" aria-hidden="true">
  <div class="modal-dialog" role="document">
    <div class="modal-content">
      <!-- モーダルの内容は後ほどJavaScriptで制御します -->
      <div class="modal-header">
        <h5 class="modal-title" id="replyModalLabel">投稿に返信</h5>
        <button type="button" class="close" data-dismiss="modal" aria-label="閉じる">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body">
        <textarea id="replyContent" class="form-control" rows="3" placeholder="返信をここに書いてください..."></textarea>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-dismiss="modal">閉じる</button>
        <button type="button" onclick="postReply()" class="btn btn-primary">返信</button>
      </div>
    </div>
  </div>
</div>

<!-- スクリプトの読み込み -->
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
<!-- BootstrapのJavaScript -->
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
<!-- RiTa.jsライブラリの読み込み(既にhead内で読み込み済み) -->
<script>
  // ユーザー、投稿、フィード、チャット関連のデータ
  let currentUser = null;
  let users = [];
  let posts = [];
  let feeds = [];
  let notifications = [];
  let aiBotPosts = [];
  let feedFetchInterval = 60000; // デフォルトは60,000ミリ秒(60秒)
  let feedFetchTimer;
  let markovBotInterval = 60000; // マルコフ連鎖BOTの投稿間隔

  // ローカルストレージの読み込み・保存関連の関数
  function saveUsersToLocalStorage() {
    localStorage.setItem('users', JSON.stringify(users));
  }

  function savePostsToLocalStorage() {
    localStorage.setItem('posts', JSON.stringify(posts));
  }

  function saveFeedsToLocalStorage() {
    localStorage.setItem('feeds', JSON.stringify(feeds));
  }

  function saveAiBotPostsToLocalStorage() {
    localStorage.setItem('aiBotPosts', JSON.stringify(aiBotPosts));
  }

  function saveCurrentUserToLocalStorage() {
    if (currentUser) {
      localStorage.setItem('currentUser', JSON.stringify(currentUser));
    } else {
      localStorage.removeItem('currentUser');
    }
  }

  function loadUsersFromLocalStorage() {
    const storedUsers = localStorage.getItem('users');
    if (storedUsers) {
      users = JSON.parse(storedUsers);
    }
  }

  function loadPostsFromLocalStorage() {
    const storedPosts = localStorage.getItem('posts');
    if (storedPosts) {
      posts = JSON.parse(storedPosts);
    }
  }

  function loadFeedsFromLocalStorage() {
    const storedFeeds = localStorage.getItem('feeds');
    if (storedFeeds) {
      feeds = JSON.parse(storedFeeds);
    }
  }

  function loadAiBotPostsFromLocalStorage() {
    const storedAiBotPosts = localStorage.getItem('aiBotPosts');
    if (storedAiBotPosts) {
      aiBotPosts = JSON.parse(storedAiBotPosts);
    }
  }

  function loadCurrentUserFromLocalStorage() {
    const storedCurrentUser = localStorage.getItem('currentUser');
    if (storedCurrentUser) {
      currentUser = JSON.parse(storedCurrentUser);
    }
  }

  // フォームの表示・非表示
  function hideAll() {
    document.getElementById('loginForm').style.display = 'none';
    document.getElementById('registerForm').style.display = 'none';
    document.getElementById('profile').style.display = 'none';
    document.getElementById('postForm').style.display = 'none';
    document.getElementById('feedForm').style.display = 'none';
    document.getElementById('aiBotForm').style.display = 'none';
  }

  function showLoginForm() {
    hideAll();
    document.getElementById('loginForm').style.display = 'block';
    document.getElementById('navProfile').style.display = 'none';
    document.getElementById('navLogout').style.display = 'none';
    document.getElementById('navFeed').style.display = 'none';
  }

  function showRegisterForm() {
    hideAll();
    document.getElementById('registerForm').style.display = 'block';
  }

  function showProfile() {
    hideAll();
    document.getElementById('profile').style.display = 'block';
    document.getElementById('profileName').textContent = currentUser.name;
    document.getElementById('profileUsername').textContent = currentUser.username;
    document.getElementById('postForm').style.display = 'block';
    document.getElementById('feedForm').style.display = 'block';
    document.getElementById('aiBotForm').style.display = 'block';
    loadProfileImage(); // プロフィール画像をロード
    displayTimeline(); // タイムラインを表示
    document.getElementById('navProfile').style.display = 'block';
    document.getElementById('navLogout').style.display = 'block';
    document.getElementById('navFeed').style.display = 'block'; // RSSナビゲーションを表示
  }

  function showFeedForm() {
    hideAll();
    document.getElementById('feedForm').style.display = 'block';
  }

  // ユーザー認証関連の関数
  function validateLoginForm() {
    let valid = true;
    const username = document.getElementById('loginUsername').value;
    const password = document.getElementById('loginPassword').value;

    if (!username) {
      document.getElementById('loginUsernameError').style.display = 'block';
      valid = false;
    } else {
      document.getElementById('loginUsernameError').style.display = 'none';
    }

    if (!password) {
      document.getElementById('loginPasswordError').style.display = 'block';
      valid = false;
    } else {
      document.getElementById('loginPasswordError').style.display = 'none';
    }

    return valid;
  }

  function login() {
    if (!validateLoginForm()) {
      return;
    }

    const username = document.getElementById('loginUsername').value;
    const password = document.getElementById('loginPassword').value;
    const user = users.find(u => u.username === username && u.password === password);
    if (user) {
      currentUser = user;
      saveCurrentUserToLocalStorage(); // currentUserを保存
      showProfile();
    } else {
      alert('ユーザー名またはパスワードが間違っています。');
    }
  }

  function logout() {
    currentUser = null;
    saveCurrentUserToLocalStorage(); // currentUserを削除
    hideAll();
    showLoginForm();
  }

  function validateRegisterForm() {
    let valid = true;
    const name = document.getElementById('registerName').value;
    const username = document.getElementById('registerUsername').value;
    const password = document.getElementById('registerPassword').value;
    const confirmPassword = document.getElementById('registerConfirmPassword').value;

    if (!name) {
      document.getElementById('registerNameError').style.display = 'block';
      valid = false;
    } else {
      document.getElementById('registerNameError').style.display = 'none';
    }

    if (!username) {
      document.getElementById('registerUsernameError').style.display = 'block';
      valid = false;
    } else {
      document.getElementById('registerUsernameError').style.display = 'none';
    }

    // ユーザー名の重複チェック
    if (users.find(u => u.username === username)) {
      document.getElementById('registerUsernameError').textContent = 'このユーザー名は既に使用されています';
      document.getElementById('registerUsernameError').style.display = 'block';
      valid = false;
    } else {
      document.getElementById('registerUsernameError').style.display = 'none';
    }

    if (!password) {
      document.getElementById('registerPasswordError').style.display = 'block';
      valid = false;
    } else {
      document.getElementById('registerPasswordError').style.display = 'none';
    }

    if (password !== confirmPassword) {
      document.getElementById('registerConfirmPasswordError').style.display = 'block';
      valid = false;
    } else {
      document.getElementById('registerConfirmPasswordError').style.display = 'none';
    }

    return valid;
  }

  function register() {
    if (!validateRegisterForm()) {
      return;
    }

    const name = document.getElementById('registerName').value;
    const username = document.getElementById('registerUsername').value;
    const password = document.getElementById('registerPassword').value;

    users.push({ name, username, password, profileImage: null });
    saveUsersToLocalStorage(); // ユーザー情報を保存
    alert('登録が完了しました!ログインしてください。');
    showLoginForm();
  }

  // プロフィール画像の処理
  function loadProfileImage() {
    const profileImg = document.getElementById('profileImg');
    // プロフィール画像が設定されている場合はその画像を表示
    if (currentUser.profileImage) {
      profileImg.src = currentUser.profileImage;
    } else {
      // デフォルトのプロフィール画像を表示
      profileImg.src = 'default_profile_img.jpg';
    }
  }

  function uploadProfileImage() {
    const input = document.getElementById('profileImageInput');
    const file = input.files[0];
    if (file) {
      // FileReaderを使用して画像を読み込む
      const reader = new FileReader();
      reader.onload = function(e) {
        // 読み込んだ画像をプロフィール画像として設定
        currentUser.profileImage = e.target.result;
        // プロフィール画像を更新して表示
        loadProfileImage();
        saveUsersToLocalStorage(); // プロフィール画像を保存
        saveCurrentUserToLocalStorage(); // currentUserを更新
      }
      reader.readAsDataURL(file);
    }
  }

  // AIBOT投稿を登録
  function registerAiBotPost() {
    const content = document.getElementById('aiBotContent').value;
    if (content.trim() !== '') {
      aiBotPosts.push(content);
      saveAiBotPostsToLocalStorage();
      alert("BOTの投稿が登録されました!");
      document.getElementById('aiBotContent').value = ''; // 入力欄を空にする
    }
  }

  // AIBOTが定期的に投稿
  function postAiBotContent() {
    if (aiBotPosts.length > 0) {
      const content = aiBotPosts[Math.floor(Math.random() * aiBotPosts.length)];
      const aiUser = {
        name: 'BOT',
        username: 'bot',
        profileImage: 'default_ai_profile_img.jpg'
      };
      const post = {
        id: Date.now(),
        content: content,
        author: aiUser.name,
        authorUsername: aiUser.username,
        authorProfileImage: aiUser.profileImage,
        likes: 0,
        comments: []
      };
      posts.unshift(post);
      savePostsToLocalStorage();
      displayTimeline();
    }
  }

  setInterval(postAiBotContent, 500000); // 50,000ミリ秒 = 50秒

  // マルコフ連鎖を使用した自動投稿BOT
  function generateMarkovChainText(order = 2) {
    const allTexts = posts.map(post => post.content).join(' ');
    if (allTexts.length < 100) return null; // テキストが短すぎる場合は生成しない

    const markov = new RiTa.Markov(order);
    markov.addText(allTexts);
    const sentences = markov.generate(1);
    return sentences[0];
  }

  function postMarkovBotContent() {
    const generatedText = generateMarkovChainText(3); // 階数を3に設定
    if (generatedText) {
      const botUser = {
        name: 'MarkovBot',
        username: 'markovbot',
        profileImage: 'markov_bot_profile_img.jpg'
      };
      const post = {
        id: Date.now(),
        content: generatedText,
        author: botUser.name,
        authorUsername: botUser.username,
        authorProfileImage: botUser.profileImage,
        likes: 0,
        comments: []
      };
      posts.unshift(post);
      savePostsToLocalStorage();
      displayTimeline();
    }
  }

  setInterval(postMarkovBotContent, markovBotInterval); // マルコフ連鎖BOTの投稿間隔

  // 投稿関連の関数
  function createPost() {
    const postContent = document.getElementById('postContent').value;
    if (postContent.trim() !== '') {
      const post = {
        id: Date.now(),
        content: postContent,
        author: currentUser.name,
        authorUsername: currentUser.username,
        authorProfileImage: currentUser.profileImage,
        likes: 0,
        comments: [],
        shares: 0
      };
      posts.unshift(post); // 最新の投稿を先頭に追加
      savePostsToLocalStorage(); // 投稿を保存
      displayTimeline();
      document.getElementById('postContent').value = ''; // 投稿後、入力欄を空にする
    }
  }

  function displayTimeline() {
    const timeline = document.getElementById('timeline');
    timeline.innerHTML = '';
    posts.forEach(post => {
      const postElement = document.createElement('div');
      postElement.classList.add('card', 'mb-3');
      postElement.innerHTML = `
        <div class="card-body">
          <div class="d-flex align-items-center mb-3">
            <img src="${post.authorProfileImage || 'default_profile_img.jpg'}" class="profile-img mr-2" alt="プロフィール画像">
            <div>
              <strong>${post.author}</strong> (@${post.authorUsername})
              ${post.shared ? '<span class="badge badge-info ml-2">シェア</span>' : ''}
            </div>
          </div>
          <p class="card-text">${post.content}</p>
          ${post.link ? `<a href="${post.link}" target="_blank" class="btn btn-link">続きを読む</a>` : ''}
          <div class="d-flex justify-content-between">
            <div>
              <button onclick="likePost(${post.id})" class="btn btn-primary btn-sm"><i class="fas fa-thumbs-up"></i> いいね (${post.likes})</button>
              <button onclick="toggleComments(${post.id})" class="btn btn-secondary btn-sm"><i class="fas fa-comments"></i> コメント (${post.comments.length})</button>
              <button onclick="replyToPost(${post.id})" class="btn btn-info btn-sm"><i class="fas fa-reply"></i> 返信</button>
              <button onclick="sharePost(${post.id})" class="btn btn-share btn-sm"><i class="fas fa-share"></i> シェア (${post.shares || 0})</button>
              <button onclick="shareToTwitter(${post.id})" class="btn btn-share-twitter btn-sm"><i class="fab fa-twitter"></i> Xでシェア</button>
            </div>
            <small class="text-muted">${new Date(post.id).toLocaleString()}</small>
          </div>
          <div id="comments-${post.id}" class="comment-section mt-3" style="display: none;">
            ${post.comments.map(comment => `
              <div class="card mb-2">
                <div class="card-body">
                  <p><strong>${comment.author}</strong>: ${comment.content}</p>
                </div>
              </div>
            `).join('')}
          </div>
        </div>
      `;
      timeline.appendChild(postElement);
    });
  }

  // いいね機能
  function likePost(postId) {
    const post = posts.find(p => p.id === postId);
    post.likes++;
    savePostsToLocalStorage();
    displayTimeline();
  }

  // コメント表示切替
  function toggleComments(postId) {
    const commentSection = document.getElementById(`comments-${postId}`);
    commentSection.style.display = commentSection.style.display === 'none' ? 'block' : 'none';
  }

  // リプライ機能
  function replyToPost(postId) {
    const modal = document.getElementById('replyModal');
    modal.dataset.postId = postId;
    $('#replyModal').modal('show');
  }

  function postReply() {
    const postId = parseInt(document.getElementById('replyModal').dataset.postId);
    const post = posts.find(p => p.id === postId);
    const replyContent = document.getElementById('replyContent').value;
    if (replyContent.trim() !== '') {
      post.comments.push({ author: currentUser.name, content: replyContent });
      $('#replyModal').modal('hide');
      savePostsToLocalStorage();
      displayTimeline();
    } else {
      alert('返信を入力してください。');
    }
  }

  // 投稿のシェア機能
  function sharePost(postId) {
    const post = posts.find(p => p.id === postId);
    if (post) {
      const sharedPost = {
        ...post,
        id: Date.now(),
        author: currentUser.name,
        authorUsername: currentUser.username,
        authorProfileImage: currentUser.profileImage,
        shared: true,
        likes: 0,
        comments: [],
        shares: post.shares ? post.shares + 1 : 1
      };
      posts.unshift(sharedPost);
      savePostsToLocalStorage();
      displayTimeline();
      alert('投稿をシェアしました。');
    }
  }

  // X(旧Twitter)にシェアする機能
  function shareToTwitter(postId) {
    const post = posts.find(p => p.id === postId);
    if (post) {
      let shareText = post.content;
      if (post.link) {
        shareText += ' ' + post.link;
      }
      const shareUrl = `https://twitter.com/intent/tweet?text=${encodeURIComponent(shareText)}&url=${encodeURIComponent(window.location.href)}`;
      window.open(shareUrl, '_blank');
    }
  }

  // FEEDの登録と自動投稿機能
  function registerFeed() {
    const feedUrl = document.getElementById('feedUrl').value;
    if (feedUrl.trim() !== '') {
      feeds.push(feedUrl);
      saveFeedsToLocalStorage(); // フィード情報を保存
      alert('RSSフィードが登録されました!');
      document.getElementById('feedUrl').value = ''; // 登録後、入力欄を空にする
    } else {
      document.getElementById('feedUrlError').style.display = 'block';
    }
  }

  function fetchFeeds() {
    feeds.forEach(feedUrl => {
      fetch(`https://api.rss2json.com/v1/api.json?rss_url=${encodeURIComponent(feedUrl)}`)
        .then(response => response.json())
        .then(data => {
          data.items.forEach(item => {
            // 同じ投稿が既に存在するかチェック
            if (!posts.some(p => p.link === item.link)) {
              const post = {
                id: Date.now() + Math.random(), // 重複しないIDを生成
                content: item.title,
                link: item.link, // リンクを追加
                author: 'FEEDBOT',
                authorUsername: 'feedbot',
                authorProfileImage: 'feedbot_profile_img.jpg', // FEEDBOTのプロフィール画像を設定
                likes: 0,
                comments: []
              };
              posts.unshift(post); // 最新の投稿を先頭に追加
              savePostsToLocalStorage(); // 投稿を保存
            }
          });
          displayTimeline(); // タイムラインを表示
        })
        .catch(error => console.error('RSSフィードの取得エラー:', error));
    });
  }

  function setFeedInterval() {
    const intervalInput = document.getElementById('feedInterval').value;
    if (intervalInput && parseInt(intervalInput) > 0) {
      feedFetchInterval = parseInt(intervalInput) * 1000; // ミリ秒に変換
      clearInterval(feedFetchTimer);
      feedFetchTimer = setInterval(fetchFeeds, feedFetchInterval);
      alert(`自動投稿の間隔が${intervalInput}秒に設定されました。`);
    } else {
      alert('有効な間隔を入力してください(1以上の数字)。');
    }
  }

  // ページロード時にフィードの自動取得を開始
  function startFeedFetch() {
    feedFetchTimer = setInterval(fetchFeeds, feedFetchInterval);
  }

  // 初期化
  function init() {
    loadUsersFromLocalStorage();
    loadPostsFromLocalStorage();
    loadFeedsFromLocalStorage();
    loadAiBotPostsFromLocalStorage();
    loadCurrentUserFromLocalStorage();

    if (currentUser) {
      showProfile();
    } else {
      hideAll();
      document.getElementById('loginForm').style.display = 'block';
    }

    displayTimeline();
    startFeedFetch(); // フィードの自動取得を開始
  }

  // ページロード時に初期化
  window.onload = init;

</script>

</body>
</html>