import javax.swing.*;
import javax.swing.undo.UndoManager;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.awt.dnd.*;
import java.awt.datatransfer.*;
public class AdvancedTextEditor extends JFrame implements ActionListener {
JTabbedPane tabbedPane;
JTextArea textArea;
JMenuBar menuBar;
JMenu fileMenu, editMenu, formatMenu, themeMenu;
JMenuItem newItem, openItem, saveItem, saveAllItem, closeItem;
JMenuItem cutItem, copyItem, pasteItem, findItem, replaceItem, undoItem, redoItem;
JMenuItem fontItem, lightThemeItem, darkThemeItem;
JFileChooser fileChooser;
JLabel statusBar;
UndoManager undoManager = new UndoManager();
JPopupMenu contextMenu;
public AdvancedTextEditor() {
setTitle("Advanced Text Editor");
setSize(800, 600);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
tabbedPane = new JTabbedPane();
add(tabbedPane, BorderLayout.CENTER);
statusBar = new JLabel("Status: Ready | Line: 1, Column: 1");
add(statusBar, BorderLayout.SOUTH);
menuBar = new JMenuBar();
// ファイルメニューの作成
fileMenu = new JMenu("File");
newItem = new JMenuItem("New");
openItem = new JMenuItem("Open");
saveItem = new JMenuItem("Save");
saveAllItem = new JMenuItem("Save All");
closeItem = new JMenuItem("Close");
fileMenu.add(newItem);
fileMenu.add(openItem);
fileMenu.add(saveItem);
fileMenu.add(saveAllItem);
fileMenu.add(closeItem);
// 編集メニューの作成
editMenu = new JMenu("Edit");
cutItem = new JMenuItem("Cut");
copyItem = new JMenuItem("Copy");
pasteItem = new JMenuItem("Paste");
undoItem = new JMenuItem("Undo");
redoItem = new JMenuItem("Redo");
findItem = new JMenuItem("Find");
replaceItem = new JMenuItem("Replace");
editMenu.add(cutItem);
editMenu.add(copyItem);
editMenu.add(pasteItem);
editMenu.add(undoItem);
editMenu.add(redoItem);
editMenu.add(findItem);
editMenu.add(replaceItem);
// フォーマットメニューの作成
formatMenu = new JMenu("Format");
fontItem = new JMenuItem("Change Font");
formatMenu.add(fontItem);
// テーマメニューの作成
themeMenu = new JMenu("Themes");
lightThemeItem = new JMenuItem("Light Theme");
darkThemeItem = new JMenuItem("Dark Theme");
themeMenu.add(lightThemeItem);
themeMenu.add(darkThemeItem);
// メニューバーにメニューを追加
menuBar.add(fileMenu);
menuBar.add(editMenu);
menuBar.add(formatMenu);
menuBar.add(themeMenu);
setJMenuBar(menuBar);
// アクションリスナーの設定
newItem.addActionListener(this);
openItem.addActionListener(this);
saveItem.addActionListener(this);
saveAllItem.addActionListener(this);
closeItem.addActionListener(this);
cutItem.addActionListener(this);
copyItem.addActionListener(this);
pasteItem.addActionListener(this);
undoItem.addActionListener(this);
redoItem.addActionListener(this);
findItem.addActionListener(this);
replaceItem.addActionListener(this);
fontItem.addActionListener(this);
lightThemeItem.addActionListener(this);
darkThemeItem.addActionListener(this);
// ドラッグ&ドロップ対応
new DropTarget(tabbedPane, new FileDropHandler());
// コンテキストメニューの設定
contextMenu = new JPopupMenu();
contextMenu.add(cutItem);
contextMenu.add(copyItem);
contextMenu.add(pasteItem);
}
// アクションリスナーの処理
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == newItem) {
addNewTab();
}
// 他のアクションもここに追加
}
// 新しいタブを追加するメソッド
private void addNewTab() {
JTextArea textArea = new JTextArea();
JScrollPane scrollPane = new JScrollPane(textArea);
tabbedPane.add("Untitled", scrollPane);
tabbedPane.setSelectedComponent(scrollPane);
textArea.getDocument().addUndoableEditListener(e -> undoManager.addEdit(e.getEdit()));
}
// ファイルドロップハンドラ
@SuppressWarnings("unchecked")
class FileDropHandler extends DropTargetAdapter {
@Override
public void drop(DropTargetDropEvent dtde) {
dtde.acceptDrop(DnDConstants.ACTION_COPY);
try {
java.util.List<File> droppedFiles = (java.util.List<File>) dtde.getTransferable()
.getTransferData(DataFlavor.javaFileListFlavor);
for (File file : droppedFiles) {
openFile(file);
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
// ファイルを開くメソッド
private void openFile(File file) {
try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
JTextArea textArea = new JTextArea();
textArea.read(reader, null);
JScrollPane scrollPane = new JScrollPane(textArea);
tabbedPane.add(file.getName(), scrollPane);
tabbedPane.setSelectedComponent(scrollPane);
} catch (IOException ex) {
ex.printStackTrace();
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
AdvancedTextEditor editor = new AdvancedTextEditor();
editor.setVisible(true);
});
}
}
カテゴリー: programming
ブックマークサイト.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>
:root {
--bg-color: #f4f4f9;
--text-color: #000;
--link-color: #007bff;
--btn-bg-color: #007bff;
--btn-hover-color: #0056b3;
--delete-btn-bg-color: #dc3545;
--delete-btn-hover-color: #c82333;
}
[data-theme="dark"] {
--bg-color: #2e2e2e;
--text-color: #fff;
--link-color: #66b2ff;
--btn-bg-color: #0056b3;
--btn-hover-color: #007bff;
--delete-btn-bg-color: #c82333;
--delete-btn-hover-color: #dc3545;
}
body {
font-family: Arial, sans-serif;
margin: 20px;
padding: 0;
background-color: var(--bg-color);
color: var(--text-color);
transition: background-color 0.3s, color 0.3s;
}
.container {
max-width: 800px;
margin: auto;
padding: 20px;
background: #fff;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
border-radius: 8px;
background-color: var(--bg-color);
color: var(--text-color);
transition: background-color 0.3s, color 0.3s;
}
.bookmark-form {
display: flex;
flex-direction: column;
gap: 10px;
margin-bottom: 20px;
}
.bookmark-form input, .bookmark-form select {
padding: 10px;
font-size: 16px;
border: 1px solid #ddd;
border-radius: 5px;
background-color: var(--bg-color);
color: var(--text-color);
}
.bookmark-form button {
padding: 10px;
font-size: 16px;
background-color: var(--btn-bg-color);
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
}
.bookmark-form button:hover {
background-color: var(--btn-hover-color);
}
.bookmark-list {
list-style-type: none;
padding: 0;
}
.bookmark-item {
display: flex;
justify-content: space-between;
align-items: center;
margin: 10px 0;
padding: 10px;
border: 1px solid #ddd;
border-radius: 5px;
background-color: #fafafa;
background-color: var(--bg-color);
color: var(--text-color);
}
.bookmark-item a {
text-decoration: none;
color: var(--link-color);
}
.bookmark-item button {
padding: 5px 10px;
font-size: 14px;
background-color: var(--delete-btn-bg-color);
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
}
.bookmark-item button:hover {
background-color: var(--delete-btn-hover-color);
}
.controls {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
</style>
</head>
<body data-theme="light">
<div class="container">
<h1>ブックマークサイト</h1>
<div class="controls">
<input type="text" id="search-bar" placeholder="ブックマークを検索" oninput="filterBookmarks()">
<select id="category-filter" onchange="filterByCategory()">
<option value="all">すべてのカテゴリー</option>
</select>
<button onclick="toggleTheme()">ダークモード切り替え</button>
</div>
<div class="bookmark-form">
<input type="text" id="bookmark-title" placeholder="タイトルを入力してください" required>
<input type="url" id="bookmark-url" placeholder="URLを入力してください" required>
<input type="text" id="bookmark-category" placeholder="カテゴリーを入力してください">
<button onclick="addBookmark()">ブックマークを追加</button>
</div>
<ul id="bookmark-list" class="bookmark-list"></ul>
</div>
<script>
document.addEventListener('DOMContentLoaded', loadBookmarks);
function loadBookmarks() {
const bookmarks = JSON.parse(localStorage.getItem('bookmarks')) || [];
const categories = new Set();
bookmarks.forEach(bookmark => {
renderBookmark(bookmark);
categories.add(bookmark.category);
});
updateCategoryFilter(Array.from(categories));
}
function addBookmark() {
const titleInput = document.getElementById('bookmark-title');
const urlInput = document.getElementById('bookmark-url');
const categoryInput = document.getElementById('bookmark-category');
const title = titleInput.value.trim();
const url = urlInput.value.trim();
const category = categoryInput.value.trim();
if (title === '' || url === '') {
alert('タイトルとURLを入力してください。');
return;
}
const bookmark = { title, url, category };
saveBookmark(bookmark);
renderBookmark(bookmark);
titleInput.value = '';
urlInput.value = '';
categoryInput.value = '';
updateCategoryFilter([category]);
}
function saveBookmark(bookmark) {
const bookmarks = JSON.parse(localStorage.getItem('bookmarks')) || [];
bookmarks.push(bookmark);
localStorage.setItem('bookmarks', JSON.stringify(bookmarks));
}
function renderBookmark(bookmark) {
const bookmarkList = document.getElementById('bookmark-list');
const listItem = document.createElement('li');
listItem.className = 'bookmark-item';
listItem.innerHTML = `
<span>${bookmark.title} (${bookmark.category})</span>
<div>
<a href="${bookmark.url}" target="_blank">訪問</a>
<button onclick="editBookmark('${bookmark.url}')">編集</button>
<button onclick="deleteBookmark('${bookmark.url}')">削除</button>
</div>
`;
bookmarkList.appendChild(listItem);
}
function deleteBookmark(url) {
let bookmarks = JSON.parse(localStorage.getItem('bookmarks')) || [];
bookmarks = bookmarks.filter(bookmark => bookmark.url !== url);
localStorage.setItem('bookmarks', JSON.stringify(bookmarks));
refreshBookmarkList();
}
function editBookmark(url) {
let bookmarks = JSON.parse(localStorage.getItem('bookmarks')) || [];
const bookmark = bookmarks.find(bookmark => bookmark.url === url);
if (bookmark) {
document.getElementById('bookmark-title').value = bookmark.title;
document.getElementById('bookmark-url').value = bookmark.url;
document.getElementById('bookmark-category').value = bookmark.category;
deleteBookmark(url); // 編集のために一旦削除
}
}
function refreshBookmarkList() {
const bookmarkList = document.getElementById('bookmark-list');
bookmarkList.innerHTML = '';
loadBookmarks();
}
function filterBookmarks() {
const query = document.getElementById('search-bar').value.toLowerCase();
const bookmarkItems = document.querySelectorAll('.bookmark-item');
bookmarkItems.forEach(item => {
const title = item.querySelector('span').innerText.toLowerCase();
item.style.display = title.includes(query) ? 'flex' : 'none';
});
}
function filterByCategory() {
const category = document.getElementById('category-filter').value;
const bookmarkItems = document.querySelectorAll('.bookmark-item');
bookmarkItems.forEach(item => {
const itemCategory = item.querySelector('span').innerText.split(' (')[1].slice(0, -1);
item.style.display = (category === 'all' || itemCategory === category) ? 'flex' : 'none';
});
}
function updateCategoryFilter(categories) {
const filter = document.getElementById('category-filter');
categories.forEach(category => {
if (![...filter.options].some(option => option.value === category)) {
const option = document.createElement('option');
option.value = category;
option.textContent = category;
filter.appendChild(option);
}
});
}
function toggleTheme() {
const body = document.body;
const currentTheme = body.getAttribute('data-theme');
const newTheme = currentTheme === 'light' ? 'dark' : 'light';
body.setAttribute('data-theme', newTheme);
}
</script>
</body>
</html>
Javascript 日時を更新してみよう
main.js
'use strict';
{
// 2000 4 11
// const d = new Date(2000, 3, 11);
// 2000 2 ??
const d = new Date(2000, 3, 0);
d.setDate(d.getDate() + 100);
console.log(d.toLocaleString());
}
index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My JavaScript</title>
</head>
<body>
<script src="main.js"></script>
</body>
</html>
Here’s a brief overview of C++, one of the most powerful and widely used programming languages, especially in areas like game development, system programming, and high-performance applications:
Here’s a brief overview of C++, one of the most powerful and widely used programming languages, especially in areas like game development, system programming, and high-performance applications:
Overview of C++
- History: C++ was developed by Bjarne Stroustrup starting in 1979 at Bell Labs. It was designed as an extension of the C programming language, adding object-oriented, generic, and functional features.
- Key Features:
- Object-Oriented Programming (OOP): Supports encapsulation, inheritance, and polymorphism.
- Templates: Allows for generic programming, which is crucial for creating reusable code.
- Standard Template Library (STL): Provides a rich set of algorithms, containers, and iterators.
- Memory Management: Direct control over memory with new and delete, though modern C++ encourages smart pointers for safety.
- Performance: Known for its efficiency, close to the hardware, making it ideal for performance-critical applications.
- Syntax and Structure:
- C++ retains C’s syntax but adds features like classes, templates, and exceptions.
- Example of a simple C++ program:
cpp#include <iostream> int main() { std::cout << "Hello, World!" << std::endl; return 0; }
- Modern C++ (C++11, C++14, C++17, C++20):
- Introduced many features like auto, lambda expressions, move semantics, and more expressive syntax for containers and algorithms.
- Example of using auto and a lambda:
cpp#include <vector> #include <algorithm> int main() { std::vector<int> numbers = {1, 2, 3, 4, 5}; auto result = std::find_if(numbers.begin(), numbers.end(), [](int x) { return x > 3; }); if (result != numbers.end()) { std::cout << "First number greater than 3: " << *result << std::endl; } return 0; }
- Use Cases:
- Game Development: Used in engines like Unreal Engine.
- System Software: Operating systems, device drivers.
- High-Performance Computing: Scientific simulations, financial systems.
- Embedded Systems: Due to its efficiency and control over hardware.
- Learning C++:
- Start with basic C programming concepts.
- Learn object-oriented programming principles.
- Dive into templates and the STL.
- Understand modern C++ features for safer, more expressive code.
- Challenges:
- Complexity: C++ is vast with many features, which can be overwhelming for beginners.
- Memory Management: Manual memory handling can lead to bugs if not managed correctly.
If you have any specific questions about C++ or need help with a particular aspect of the language, feel free to ask!
Solve the Two Sum problem in Python
Solve the Two Sum problem in Python
回答
Certainly, I’ll provide a solution to the Two Sum problem in Python. This problem is a common interview question where you’re given an array of integers and a target sum, and you need to find two numbers in the array that add up to the target.
Here’s a step-by-step approach:
- Use a Hash Map: This approach allows for O(n) time complexity, where n is the number of elements in the array.
- Iterate Through the Array: For each number, calculate what the other number should be to reach the target sum.
- Check if the Complement Exists: If the complement exists in the hash map, return the indices of both numbers.
Here’s the implementation:
python
def two_sum(nums, target):
# Dictionary to store the number and its index
num_dict = {}
# Iterate through the list
for i, num in enumerate(nums):
# Calculate the complement
complement = target - num
# If the complement exists in the dictionary, return the indices
if complement in num_dict:
return [num_dict[complement], i]
# If not, add the current number and its index to the dictionary
num_dict[num] = i
# If no solution is found, return an empty list or raise an exception
return [] # or raise ValueError("No two sum solution")
# Example usage
nums = [2, 7, 11, 15]
target = 9
result = two_sum(nums, target)
print(result) # Should print [0, 1] because nums[0] + nums[1] == 9
Explanation:
- We use a dictionary (num_dict) to keep track of numbers we’ve seen and their indices.
- As we iterate through the list:
- We calculate what number, when added to the current number, would give us the target.
- If this number exists in our dictionary, we’ve found our pair, and we return their indices.
- If not, we add the current number and its index to the dictionary.
This solution ensures that we only traverse the list once, making it efficient with a time complexity of O(n). The space complexity is also O(n) in the worst case where all numbers are unique.
ruby 数当てゲーム
数当てゲーム
class NumberGuessingGame
attr_accessor :player_name, :target_number, :guess, :attempts, :difficulty, :games_played, :total_attempts
def initialize
@player_name = “”
@target_number = 0
@guess = nil
@attempts = 0
@difficulty = “easy”
@games_played = 0
@total_attempts = 0
end
def start
welcome_message
get_player_name
loop do
set_difficulty
setup_game
play_round
display_result
update_statistics
break unless play_again?
end
display_statistics
farewell_message
end
def welcome_message
puts “数当てゲームへようこそ!”
end
def get_player_name
print “あなたの名前を入力してください: “
@player_name = gets.chomp
end
def set_difficulty
puts “難易度を選択してください: easy, medium, hard”
@difficulty = gets.chomp.downcase
end
def setup_game
@target_number = case @difficulty
when “medium”
rand(1..500)
when “hard”
rand(1..1000)
else
rand(1..100)
end
@attempts = 0
end
def play_round
until @guess == @target_number
print “数を予想してください: “
@guess = gets.to_i
@attempts += 1
give_hint
end
end
def give_hint
if @guess < @target_number puts “もっと大きい数です。” elsif @guess > @target_number
puts “もっと小さい数です。”
else
puts “正解です!”
end
end
def display_result
puts “#{@player_name}さん、おめでとうございます!”
puts “#{@attempts}回目で正解です!”
end
def play_again?
print “もう一度プレイしますか?(yes/no): “
answer = gets.chomp.downcase
answer == ‘yes’
end
def update_statistics
@games_played += 1
@total_attempts += @attempts
end
def display_statistics
puts “統計情報:”
puts “プレイしたゲーム数: #{@games_played}”
puts “総試行回数: #{@total_attempts}”
puts “平均試行回数: #{@total_attempts / @games_played}” if @games_played > 0
end
def farewell_message
puts “ゲームをプレイしていただきありがとうございました!またお会いしましょう!”
end
end
ゲーム開始
game = NumberGuessingGame.new
game.start
機能概要
難易度選択: プレイヤーはeasy, medium, hardのいずれかの難易度を選択でき、難易度によって予想する数の範囲が変わります。
easy: 1-100
medium: 1-500
hard: 1-1000
プレイ統計の表示: プレイしたゲーム数、総試行回数、平均試行回数を表示します。
再プレイ機能: プレイヤーはゲーム終了後、再度プレイするかどうかを選択できます。
実行方法
上記のコードをファイル(例: number_guessing_game_extended.rb)として保存します。
ターミナル(コマンドプロンプト)を開き、そのファイルがあるディレクトリに移動します。
以下のコマンドを実行してゲームを開始します。
bash
ruby number_guessing_game_extended.rb
この拡張版では、より多くの機能を楽しむことができ、プレイヤーは複数回のゲームプレイを通じて自分のパフォーマンスを追跡することができます。
PHP 変数
<?php
// echo 150 * 120 . PHP_EOL;
// echo 150 * 130 . PHP_EOL;
// echo 150 * 140 . PHP_EOL;
$price = 150;
echo $price * 120 . PHP_EOL;
echo $price * 130 . PHP_EOL;
echo $price * 140 . PHP_EOL;
PHP 数値
<?php
echo 10 + 3 . PHP_EOL;
echo 10 - 3 . PHP_EOL;
echo 10 * 3 . PHP_EOL;
echo 10 ** 3 . PHP_EOL;
echo 10 / 3 . PHP_EOL;
echo 10 % 3 . PHP_EOL;
echo 10 + 2 * 3 . PHP_EOL;
echo (10 + 2) * 3 . PHP_EOL;
Unity C# 変数
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Test : MonoBehaviour
{
int HP = 100, ATK = 100;
int DEF = 50;
//
string name = "";
//少数
float f = 0.1f;
bool isDead = false;
// Start is called before the first frame update
void Start()
{
HP = 1000;
f = 1000;
name = "名前は勇者" + "です";
isDead = true;
HP = 200;
UnityEngine.Debug.Log("HP" + HP);
HP = 100;
UnityEngine.Debug.Log("HP" + HP);
}
private void FixedUpdate()
{
}
// Update is called once per frame
void Update()
{
}
}
ELDER
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ELDER</title>
<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">
<style>
body {
padding-top: 20px;
background-color: #f8f9fa;
}
.card {
margin-bottom: 20px;
}
.profile-img {
width: 50px;
height: 50px;
object-fit: cover;
border-radius: 50%;
}
.comment-section {
margin-top: 20px;
}
.navbar {
margin-bottom: 20px;
}
.form-error {
color: red;
font-size: 0.9em;
}
</style>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<a class="navbar-brand" href="#">SNS</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<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>
</ul>
</div>
</nav>
<div class="container">
<h1 class="text-center mb-4">ソーシャルネットワーキングサービス</h1>
<!-- ログインフォーム -->
<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 id="followButton" onclick="toggleFollow()" class="btn btn-primary btn-block"></button>
<button id="messageButton" onclick="openDirectMessageModal()" class="btn btn-primary btn-block">ダイレクトメッセージを送信</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>
</div>
<!-- タイムライン -->
<div id="timeline" class="w-75 mx-auto mt-4"></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">
<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">×</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>
<!-- ダイレクトメッセージモーダル -->
<div class="modal fade" id="directMessageModal" tabindex="-1" role="dialog" aria-labelledby="directMessageModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="directMessageModalLabel">ダイレクトメッセージを送信</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="閉じる">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<select id="recipient" class="form-control">
<option value="">送信先を選択</option>
<!-- ユーザーリストがここに追加される -->
</select>
<textarea id="directMessageContent" class="form-control mt-2" rows="3" placeholder="メッセージをここに書いてください..."></textarea>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">閉じる</button>
<button type="button" onclick="sendDirectMessage()" class="btn btn-primary">送信</button>
</div>
</div>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.5.4/dist/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
<script>
let currentUser = null; // 現在のログインユーザー
let users = []; // ユーザーの配列
let posts = []; // 投稿の配列
let feeds = []; // フィードの配列
// ローカルストレージにユーザー情報を保存
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 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 showLoginForm() {
hideAll();
document.getElementById('loginForm').style.display = 'block';
}
function showRegisterForm() {
hideAll();
document.getElementById('registerForm').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;
showProfile();
} else {
alert('ユーザー名またはパスワードが間違っています。');
}
}
function logout() {
currentUser = null;
hideAll();
document.getElementById('loginForm').style.display = 'block';
document.getElementById('navProfile').style.display = 'none';
document.getElementById('navLogout').style.display = 'none';
}
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 (!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, following: false });
saveUsersToLocalStorage(); // ユーザー情報を保存
alert('登録が完了しました!ログインしてください。');
showLoginForm();
}
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';
loadProfileImage(); // プロフィール画像をロード
displayTimeline(); // タイムラインを表示
updateFollowButton(); // フォローボタンの表示を更新
loadDirectMessageRecipients(); // ダイレクトメッセージの送信先をロード
document.getElementById('navProfile').style.display = 'block';
document.getElementById('navLogout').style.display = 'block';
}
// プロフィール画像をロード
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(); // プロフィール画像を保存
}
reader.readAsDataURL(file);
}
}
// フォローボタンの更新
function updateFollowButton() {
const followButton = document.getElementById('followButton');
if (currentUser.following) {
followButton.textContent = 'フォロー解除';
} else {
followButton.textContent = 'フォロー';
}
saveUsersToLocalStorage(); // フォロー状態を保存
}
// フォローの切り替え
function toggleFollow() {
currentUser.following = !currentUser.following;
updateFollowButton();
}
// ダイレクトメッセージの送信先をロード
function loadDirectMessageRecipients() {
const select = document.getElementById('recipient');
select.innerHTML = '<option value="">送信先を選択</option>';
users.forEach(user => {
if (user !== currentUser) {
const option = document.createElement('option');
option.value = user.username;
option.textContent = user.name;
select.appendChild(option);
}
});
}
// ダイレクトメッセージのモーダルを開く
function openDirectMessageModal() {
$('#directMessageModal').modal('show');
}
// ダイレクトメッセージを送信
function sendDirectMessage() {
const recipientUsername = document.getElementById('recipient').value;
const messageContent = document.getElementById('directMessageContent').value;
if (recipientUsername && messageContent.trim() !== '') {
const recipient = users.find(user => user.username === recipientUsername);
if (recipient) {
alert(`メッセージを${recipient.name}に送信しました: ${messageContent}`);
$('#directMessageModal').modal('hide');
} else {
alert('送信先が見つかりません。');
}
} else {
alert('送信先を選択し、メッセージを入力してください。');
}
}
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: []
};
posts.unshift(post); // 最新の投稿を先頭に追加
savePostsToLocalStorage(); // 投稿を保存
displayTimeline();
document.getElementById('postContent').value = ''; // 投稿後、入力欄を空にする
}
}
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 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})
</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>
</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 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 => {
const post = {
id: Date.now() + Math.random(), // 重複しないIDを生成
content: item.title,
link: item.link, // リンクを追加
author: 'RSSフィード',
authorUsername: 'rssfeed',
authorProfileImage: 'default_profile_img.jpg', // プロフィール画像を設定
likes: 0,
comments: []
};
posts.unshift(post); // 最新の投稿を先頭に追加
savePostsToLocalStorage(); // 投稿を保存
});
displayTimeline(); // タイムラインを表示
})
.catch(error => console.error('Error fetching RSS feed:', error));
});
}
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';
}
// 初期データをローカルストレージから読み込む
loadUsersFromLocalStorage();
loadPostsFromLocalStorage();
loadFeedsFromLocalStorage();
// 初期ログイン画面表示
hideAll();
document.getElementById('loginForm').style.display = 'block';
// 1時間ごとにRSSフィードをフェッチして自動投稿
setInterval(fetchFeeds, 5); // 3600000ミリ秒 = 1時間
</script>
</body>
</html>
RSSの機能を使えるようにしました
