MyCSSVariables

index.html

<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="utf-8">
    <title>CSS変数</title>
    <link rel="stylesheet" href="css/styles.css">
</head>

<body>
    <h1>タイトル</h1>
    <p>こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。</p>
    <div class="btn">OK</div>
</body>

</html>

C:\MyCSSVariables\css

style.css

:root {
    /* --my-hue: 100; */
    /* --my-hue: 200; */
    --my-hue: 50;
}

body {
    background: hsl(var(--my-hue), 40%, 95%);
}

h1,
p {
    color: hsl(var(--my-hue), 35%, 55%);
}

.btn {
    color: #fff;
    width: 100px;
    padding: 8px;
    border-radius: 4px;
    text-align: center;
    /* background: hsl(var(--my-hue), 50%, 50%); */
    /* background: hsl(calc(var(--my-hue) + 180), 50%, 50%); */
    background: hsl(calc(var(--my-hue) + 60), 50%, 50%); }

Googleの人気記事を拾ってくるサイト

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <title>Googleニュース 人気記事アグリゲーター</title>
  <!-- Bootstrap CSS -->
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
  <style>
    body { background: #f8f9fa; padding-top: 20px; font-family: 'Arial', sans-serif; transition: background .3s, color .3s; }
    .dark-mode { background: #2c2c2c; color: #f1f1f1; }
    #controls { margin-bottom: 20px; }
    .card { border-radius: 10px; box-shadow: 0 4px 8px rgba(0,0,0,0.1); margin-bottom: 15px; transition: transform .2s, background .3s, color .3s; }
    .dark-mode .card { background: #3a3a3a; color: #f1f1f1; }
    .card:hover { transform: translateY(-3px); }
    .card-title { font-size: 1.25rem; margin-bottom: .5rem; }
    .meta { font-size: 0.85rem; color: #6c757d; margin-bottom: .5rem; }
    .dark-mode .meta { color: #ccc; }
    .thumbnail { width: 100%; height: auto; border-top-left-radius: 10px; border-top-right-radius: 10px; }
    #loading { display: none; font-size: 2rem; text-align: center; margin-top: 40px; }
    #error { display: none; color: red; text-align: center; margin-top: 20px; }
    @media (min-width: 768px) {
      #articles .col-md-6 { flex: 0 0 50%; max-width: 50%; }
    }
  </style>
</head>
<body>
  <div class="container">
    <div class="d-flex justify-content-between align-items-center mb-3">
      <h1>Googleニュース 人気記事</h1>
      <button id="darkModeToggle" class="btn btn-outline-secondary">ダークモード</button>
    </div>
    <div id="controls" class="d-flex flex-wrap justify-content-between align-items-end">
      <div class="form-group mb-2 mr-2">
        <label for="categorySelect">カテゴリ:</label>
        <select id="categorySelect" class="form-control">
          <option value="WORLD">世界</option>
          <option value="BUSINESS">ビジネス</option>
          <option value="TECHNOLOGY">テクノロジー</option>
          <option value="ENTERTAINMENT">エンタメ</option>
          <option value="SPORTS">スポーツ</option>
          <option value="SCIENCE">科学</option>
          <option value="HEALTH">健康</option>
        </select>
      </div>
      <div class="form-group mb-2 mr-2 flex-grow-1">
        <label for="searchInput">キーワード:</label>
        <input id="searchInput" type="text" class="form-control" placeholder="タイトルで絞り込み">
      </div>
      <div class="form-group mb-2 mr-2">
        <label for="maxItems">表示数:</label>
        <input id="maxItems" type="number" class="form-control" value="20" min="1" max="100">
      </div>
      <button id="refreshBtn" class="btn btn-primary mb-2">更新</button>
    </div>
    <div id="loading"><i class="fas fa-spinner fa-spin"></i> 読み込み中...</div>
    <div id="error"></div>
    <div id="articles" class="row"></div>
  </div>

  <!-- FontAwesome & jQuery & Bootstrap JS -->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/js/all.min.js"></script>
  <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
  <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.bundle.min.js"></script>
  <script>
    const controls = {
      category: document.getElementById('categorySelect'),
      search: document.getElementById('searchInput'),
      maxItems: document.getElementById('maxItems'),
      refresh: document.getElementById('refreshBtn'),
      darkToggle: document.getElementById('darkModeToggle')
    };
    const articlesContainer = document.getElementById('articles');
    const loading = document.getElementById('loading');
    const errorMsg = document.getElementById('error');
    const body = document.body;

    function getFeedUrl(topic) {
      return `https://news.google.com/rss/headlines/section/topic/${topic}?hl=ja&gl=JP&ceid=JP:ja`;
    }
    async function fetchArticles() {
      articlesContainer.innerHTML = '';
      errorMsg.style.display = 'none';
      loading.style.display = 'block';
      const topic = controls.category.value;
      const apiUrl = `https://api.rss2json.com/v1/api.json?rss_url=${encodeURIComponent(getFeedUrl(topic))}`;
      try {
        const res = await fetch(apiUrl);
        const data = await res.json();
        if (data.status !== 'ok') throw new Error('取得失敗');
        let items = data.items.map(item => ({
          title: item.title,
          link: item.link,
          date: new Date(item.pubDate),
          thumbnail: item.thumbnail || ''
        }));
        const kw = controls.search.value.trim();
        if (kw) items = items.filter(i => i.title.includes(kw));
        items = items.slice(0, parseInt(controls.maxItems.value) || items.length);
        render(items);
      } catch (e) {
        console.error(e);
        errorMsg.textContent = '記事の取得に失敗しました。';
        errorMsg.style.display = 'block';
      } finally {
        loading.style.display = 'none';
      }
    }
    function render(items) {
      if (!items.length) {
        articlesContainer.innerHTML = '<p class="text-center w-100">該当する記事がありません。</p>';
        return;
      }
      items.forEach(i => {
        const col = document.createElement('div'); col.className = 'col-12 col-md-6';
        const thumb = i.thumbnail ? `<img src="${i.thumbnail}" class="thumbnail" alt="サムネイル">` : '';
        col.innerHTML = `
          <div class="card">
            ${thumb}
            <div class="card-body">
              <h2 class="card-title"><a href="${i.link}" target="_blank">${i.title}</a></h2>
              <p class="meta">公開: ${i.date.toLocaleString()}</p>
            </div>
          </div>`;
        articlesContainer.appendChild(col);
      });
    }
    controls.refresh.addEventListener('click', fetchArticles);
    controls.darkToggle.addEventListener('click', () => {
      body.classList.toggle('dark-mode');
    });
    document.addEventListener('DOMContentLoaded', fetchArticles);
  </script>
</body>
</html>

C# 抽象クラス

using System;

// 抽象クラス
// User -> Japanese, American

abstract class User {
  public abstract void SayHi();
}

class Japanese: User {
  public override void SayHi() {
    Console.WriteLine("こんにちは!");
  }
}

class American: User {
  public override void SayHi() {
    Console.WriteLine("hi!");
  }
}

class MyApp {

  static void Main() {
    Japanese aki = new Japanese();
    aki.SayHi();
    American tom = new American();
    tom.SayHi();
  }

}

C# コンストラクタ

using System;

// コンストラクタ

class User {
  public string name;
  // public User() {
  //   this.name = "ME";
  // }
  public User(string name) {
    this.name = name;
  }
  // public User() { // オーバーロード
  //   this.name = "nobody";
  // }
  public User(): this("nobody") {
  }
  public void SayHi() {
    Console.WriteLine($"hi {name}");
  }
}

class MyApp {

  static void Main() {
    // User user = new User();
    // user.SayHi();
    User tom = new User("Tom");
    tom.SayHi();
    User user = new User();
    user.SayHi();
  }

}

note風WEBサービス

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>MiniNote - Note風ブログ with フィルタ・いいね・検索機能</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <style>
    body { font-family: sans-serif; background: #f9f9f9; margin: 0; }
    header { background: #2c3e50; color: white; padding: 1em; text-align: center; }
    nav { background: #34495e; text-align: center; padding: 0.5em; }
    nav button { margin: 0 8px; padding: 8px 20px; cursor: pointer; background: #ecf0f1; border: none; border-radius: 5px; }
    #main { max-width: 900px; margin: 2em auto; padding: 1em; background: white; border-radius: 10px; box-shadow: 0 4px 8px rgba(0,0,0,0.1); }
    article { padding: 1em; border-bottom: 1px solid #ddd; }
    h2 { margin: 0.5em 0; }
    .meta { font-size: 0.9em; color: #999; margin-bottom: 0.5em; }
    textarea, input[type="text"] { width: 100%; padding: 10px; margin: 10px 0; border-radius: 5px; border: 1px solid #ccc; }
    button.submit {
      background: #3498db; color: white; border: none;
      padding: 10px 20px; border-radius: 6px;
      cursor: pointer; font-weight: bold;
    }
    .hidden { display: none; }
    .tag { color: #3498db; margin-right: 5px; font-size: 0.9em; cursor: pointer; }
    .actions button { margin-right: 10px; }
    .like { color: #e74c3c; cursor: pointer; margin-left: 10px; }
  </style>
</head>
<body>

<header><h1>📘 MiniNote - あなたのNote風ブログ</h1></header>

<nav>
  <button onclick="showView('home')">🏠 ホーム</button>
  <button onclick="showView('new')">✍ 新規投稿</button>
  <input type="text" id="searchInput" placeholder="検索" oninput="renderPosts()" style="padding:5px; width: 200px;">
</nav>

<div id="main">
  <div id="homeView">
    <div id="postList"></div>
  </div>

  <div id="newView" class="hidden">
    <h2>新しい投稿を作成</h2>
    <input type="text" id="titleInput" placeholder="タイトル">
    <textarea id="contentInput" rows="8" placeholder="本文"></textarea>
    <input type="text" id="tagInput" placeholder="タグ(カンマ区切り)">
    <button class="submit" onclick="addPost()">投稿する</button>
  </div>

  <div id="detailView" class="hidden">
    <article>
      <h2 id="detailTitle"></h2>
      <div class="meta" id="detailDate"></div>
      <p id="detailContent"></p>
      <div id="detailTags"></div>
      <div class="like" id="likeDisplay" onclick="likePost(currentIndex)">❤️ <span id="likeCount">0</span></div>
    </article>
    <div class="actions">
      <button onclick="editPost(currentIndex)">✏ 編集</button>
      <button onclick="deletePost(currentIndex)">🗑 削除</button>
      <button onclick="showView('home')">← 戻る</button>
    </div>
  </div>
</div>

<script>
  let posts = JSON.parse(localStorage.getItem("posts") || "[]");
  let currentIndex = null;
  let filterTag = null;

  function showView(view) {
    document.querySelectorAll('#main > div').forEach(div => div.classList.add('hidden'));
    document.getElementById(view + "View").classList.remove("hidden");
    if (view === "home") renderPosts();
  }

  function addPost() {
    const title = document.getElementById("titleInput").value;
    const content = document.getElementById("contentInput").value;
    const tags = document.getElementById("tagInput").value.split(',').map(tag => tag.trim()).filter(Boolean);
    if (!title || !content) return alert("タイトルと本文を入力してください");

    const date = new Date().toLocaleString();
    posts.unshift({ title, content, date, tags, likes: 0 });
    localStorage.setItem("posts", JSON.stringify(posts));
    clearForm();
    showView("home");
  }

  function renderPosts() {
    const list = document.getElementById("postList");
    const search = document.getElementById("searchInput").value.toLowerCase();
    list.innerHTML = "";
    posts.filter(post => {
      const inSearch = post.title.toLowerCase().includes(search) || post.content.toLowerCase().includes(search);
      const inTag = !filterTag || post.tags.includes(filterTag);
      return inSearch && inTag;
    }).forEach((post, index) => {
      const el = document.createElement("article");
      el.innerHTML = `
        <h2>${post.title}</h2>
        <div class="meta">${post.date}</div>
        <p>${post.content.substring(0, 80)}...</p>
        <div>${post.tags.map(tag => `<span class='tag' onclick='filterByTag("${tag}")'>#${tag}</span>`).join(' ')}</div>
        <div class="like">❤️ ${post.likes}</div>
        <button onclick="showDetail(${index})">📖 詳細</button>
      `;
      list.appendChild(el);
    });
  }

  function filterByTag(tag) {
    filterTag = tag;
    renderPosts();
  }

  function showDetail(index) {
    const post = posts[index];
    currentIndex = index;
    document.getElementById("detailTitle").innerText = post.title;
    document.getElementById("detailDate").innerText = post.date;
    document.getElementById("detailContent").innerText = post.content;
    document.getElementById("detailTags").innerHTML = post.tags.map(tag => `<span class='tag'>#${tag}</span>`).join(' ');
    document.getElementById("likeCount").innerText = post.likes;
    showView("detail");
  }

  function likePost(index) {
    posts[index].likes++;
    localStorage.setItem("posts", JSON.stringify(posts));
    document.getElementById("likeCount").innerText = posts[index].likes;
    renderPosts();
  }

  function editPost(index) {
    const post = posts[index];
    document.getElementById("titleInput").value = post.title;
    document.getElementById("contentInput").value = post.content;
    document.getElementById("tagInput").value = post.tags.join(', ');
    posts.splice(index, 1);
    localStorage.setItem("posts", JSON.stringify(posts));
    showView("new");
  }

  function deletePost(index) {
    if (!confirm("本当に削除しますか?")) return;
    posts.splice(index, 1);
    localStorage.setItem("posts", JSON.stringify(posts));
    showView("home");
  }

  function clearForm() {
    document.getElementById("titleInput").value = "";
    document.getElementById("contentInput").value = "";
    document.getElementById("tagInput").value = "";
  }

  showView("home");
</script>

</body>
</html>

TRPGシナリオ自動生成&共有

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>TRPGシナリオ自動生成&共有</title>
  <style>
    body {
      font-family: 'Segoe UI', sans-serif;
      background: #f4f4f4;
      padding: 20px;
      max-width: 800px;
      margin: auto;
    }
    h1, h2 {
      text-align: center;
    }
    select, button, textarea {
      width: 100%;
      padding: 10px;
      margin-top: 10px;
      font-size: 1rem;
    }
    .box {
      background: #fff;
      padding: 15px;
      border-radius: 8px;
      margin-top: 20px;
      box-shadow: 0 2px 4px rgba(0,0,0,0.1);
    }
    .scenario {
      background: #f9f9f9;
      border-left: 5px solid #4CAF50;
      margin-bottom: 10px;
      padding: 10px;
      border-radius: 5px;
      position: relative;
    }
    .btns {
      margin-top: 10px;
      display: flex;
      gap: 10px;
    }
    .copy, .save, .delete {
      cursor: pointer;
      border: none;
      padding: 8px 12px;
      border-radius: 4px;
    }
    .copy { background: #2196F3; color: white; }
    .save { background: #4CAF50; color: white; }
    .delete { background: #f44336; color: white; }
  </style>
</head>
<body>
  <h1>🎲 TRPGシナリオ自動生成サイト</h1>

  <div class="box">
    <label>ジャンル選択:</label>
    <select id="genre">
      <option value="fantasy">ファンタジー</option>
      <option value="horror">ホラー</option>
      <option value="scifi">SF</option>
    </select>
    <button onclick="generateScenario()">📜 シナリオを生成する</button>
  </div>

  <div id="scenarioBox" class="box"></div>

  <h2>🗃 保存済みシナリオ</h2>
  <div id="savedScenarios" class="box"></div>

  <script>
    const data = {
      fantasy: {
        title: ["封印の迷宮", "聖騎士の試練", "魔王復活の予兆", "失われた王国"],
        world: ["中世の王国", "古代の神殿", "天空都市", "エルフの森"],
        incident: ["魔法の暴走", "伝説の剣の発見", "精霊の異変", "竜の襲撃"],
        npc: ["若き魔導士", "忠義の騎士", "隠者の賢者", "裏切り者の巫女"],
        goal: ["真実を解明せよ", "封印を強化せよ", "儀式を阻止せよ", "遺跡の謎を解け"]
      },
      horror: {
        title: ["呪われた村", "深夜の廃病院", "封印されたビデオ", "血塗られた儀式"],
        world: ["雨の山奥", "閉鎖された病院", "地下の儀式場", "忘れ去られた洋館"],
        incident: ["突然の失踪事件", "見えない何かの影", "不気味な手紙", "鏡の中の誰か"],
        npc: ["精神を病んだ神父", "警察官の幽霊", "語らぬ老婆", "首のない少女"],
        goal: ["脱出せよ", "謎を暴け", "呪いを解け", "儀式を止めろ"]
      },
      scifi: {
        title: ["星間戦争の火種", "機械反乱の夜", "消えた宇宙船", "記憶を失った地球"],
        world: ["宇宙コロニー", "月面都市", "異星の遺跡", "サイバーパンク都市"],
        incident: ["AIの暴走", "重力異常", "通信断絶", "テレポート事故"],
        npc: ["サイボーグ兵士", "記憶を失った博士", "企業スパイ", "異星の子供"],
        goal: ["原因を究明せよ", "AIを停止せよ", "人類を救え", "真実を暴け"]
      }
    };

    function generateScenario() {
      const genre = document.getElementById("genre").value;
      const g = data[genre];

      const title = rand(g.title);
      const world = rand(g.world);
      const incident = rand(g.incident);
      const npc = rand(g.npc);
      const goal = rand(g.goal);

      const scenarioText = `【タイトル】${title}\n【舞台】${world}\n【事件】${incident}\n【NPC】${npc}\n【目的】${goal}`;
      const html = `
        <div class="scenario">
          <pre>${scenarioText}</pre>
          <div class="btns">
            <button class="copy" onclick="copyText(\`${scenarioText.replace(/`/g, '\\`')}\`)">📋 コピー</button>
            <button class="save" onclick="saveScenario(\`${scenarioText.replace(/`/g, '\\`')}\`)">💾 保存</button>
          </div>
        </div>
      `;
      document.getElementById("scenarioBox").innerHTML = html;
    }

    function rand(arr) {
      return arr[Math.floor(Math.random() * arr.length)];
    }

    function copyText(text) {
      navigator.clipboard.writeText(text).then(() => {
        alert("コピーしました!");
      });
    }

    function saveScenario(text) {
      let saved = JSON.parse(localStorage.getItem("trpgScenarios") || "[]");
      saved.push(text);
      localStorage.setItem("trpgScenarios", JSON.stringify(saved));
      alert("保存しました!");
      showSaved();
    }

    function deleteScenario(index) {
      let saved = JSON.parse(localStorage.getItem("trpgScenarios") || "[]");
      saved.splice(index, 1);
      localStorage.setItem("trpgScenarios", JSON.stringify(saved));
      showSaved();
    }

    function showSaved() {
      const box = document.getElementById("savedScenarios");
      const saved = JSON.parse(localStorage.getItem("trpgScenarios") || "[]");
      if (saved.length === 0) {
        box.innerHTML = "<p>保存されているシナリオはありません。</p>";
        return;
      }
      box.innerHTML = saved.map((s, i) => `
        <div class="scenario">
          <pre>${s}</pre>
          <div class="btns">
            <button class="copy" onclick="copyText(\`${s.replace(/`/g, '\\`')}\`)">📋 コピー</button>
            <button class="delete" onclick="deleteScenario(${i})">🗑 削除</button>
          </div>
        </div>
      `).join("");
    }

    // 初回ロード
    showSaved();
  </script>
</body>
</html>

MyAOS.html

<!DOCTYPE html>
<html lang="ja">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>My Site</title>
  <link rel="stylesheet" href="https://unpkg.com/aos@next/dist/aos.css" />
  <link rel="stylesheet" href="style.css">
</head>

<body>
  <section>
    <h1>記事一覧</h1>
    <article>
      <img src="forest.png" width="240" height="160" data-aos="my-animation">
      <div class="text">
        <h2>タイトル</h2>
        <p>こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。</p>
      </div>
    </article>
    <article>
      <img src="forest.png" width="240" height="160">
      <div class="text">
        <h2>タイトル</h2>
        <p>こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。</p>
      </div>
    </article>
    <article>
      <img src="forest.png" width="240" height="160">
      <div class="text">
        <h2>タイトル</h2>
        <p>こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。</p>
      </div>
    </article>
  </section>

  <section>
    <h1>お客様の声</h1>
    <div class="voices">
      <section data-aos="fade-up">
        <h2>すばらしい</h2>
        <p>素晴らしいです。素晴らしいです。</p>
      </section>
      <section data-aos="fade-up" data-aos-delay="300">
        <h2>すばらしい</h2>
        <p>素晴らしいです。素晴らしいです。</p>
      </section>
      <section data-aos="fade-up" data-aos-delay="600">
        <h2>すばらしい</h2>
        <p>素晴らしいです。素晴らしいです。</p>
      </section>
    </div>
  </section>

  <footer id="footer">
    (c) dotinstall.com
  </footer>

  <a href="#" class="to-top" data-aos="fade-up" data-aos-anchor="#footer" data-aos-offset="0">先頭へ</a>

  <script src="https://unpkg.com/aos@next/dist/aos.js"></script>
  <script>
    AOS.init();
  </script>
</body>

</html>

style.css

@charset "utf-8";

body {
  margin: 0;
}

body>section {
  margin: 0 32px;
}

h1 {
  text-align: center;
  padding: 160px 0;
}

article {
  display: flex;
  gap: 16px;
  align-items: center;
}

article .text {
  flex: 1;
}

article h2 {
  margin: 0;
  font-size: 22px;
}

article+article {
  margin-top: 32px;
}

article:nth-child(even) {
  flex-direction: row-reverse;
}

.voices {
  display: flex;
  gap: 16px;
}

.voices>section {
  border-radius: 8px;
  border: 1px solid #ccc;
  padding: 16px 32px;
  text-align: center;
}

footer {
  margin-top: 160px;
  text-align: center;
  padding: 80px 0;
  background: #eee;
}

.to-top {
  position: fixed;
  bottom: 16px;
  right: 16px;
}

Z

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Z – 次世代ソーシャルネットワーク</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/aframe/1.5.0/aframe.min.js"></script>
<style>
:root{
  --primary:#1DA1F2;--background:#fff;--text:#000;--border:#E1E8ED;--card:#F7F9F9;--danger:#E0245E;
}
[data-theme="dark"]{--background:#15202B;--text:#fff;--border:#38444D;--card:#192734}
*{box-sizing:border-box;margin:0;padding:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif}
body{background:var(--background);color:var(--text);min-height:100vh;transition:.3s}
.hidden{display:none}
.wrapper{max-width:640px;margin-inline:auto;padding:20px}
.timeline{margin-top:2rem}
.timeline-item{background:var(--card);border-radius:12px;padding:1rem;margin-bottom:1rem;box-shadow:0 2px 6px rgba(0,0,0,.05)}
.timeline-item h3{margin:0 0 .5rem;font-size:1.1rem}
.timeline-item p{margin:0;white-space:pre-wrap;line-height:1.4}
.timeline-item small{display:block;margin-top:.5rem;font-size:.75rem;color:var(--border)}
.auth-box{background:var(--card);border-radius:12px;padding:1.5rem;margin-bottom:2rem}
.auth-box input{padding:.75rem;border:1px solid var(--border);border-radius:8px;width:100%;margin-bottom:.5rem}
.auth-box button{background:var(--primary);color:white;border:none;border-radius:8px;padding:.75rem;margin-top:.5rem;width:100%;cursor:pointer;font-weight:bold}
.profile-edit{background:var(--card);padding:1rem;border-radius:12px;margin-bottom:2rem}
.profile-edit h3{margin-bottom:.75rem}
.profile-edit input{width:100%;margin:.5rem 0;padding:.5rem;border:1px solid var(--border);border-radius:8px}
.follow-btn{background:#ccc;padding:.3rem .8rem;border-radius:8px;border:none;cursor:pointer;font-size:.85rem;margin-top:.5rem}
img.upload-preview{max-width:100px;border-radius:8px;margin-top:.5rem}
</style>
</head>
<body>
<div class="wrapper">
  <div id="authBox" class="auth-box">
    <h2>ログイン / 登録</h2>
    <input type="email" id="email" placeholder="メールアドレス">
    <input type="tel" id="phone" placeholder="電話番号">
    <input type="password" id="password" placeholder="パスワード">
    <input type="text" id="username" placeholder="ユーザー名">
    <button onclick="loginOrRegister()">ログイン / 登録</button>
  </div>
  <div id="mainBox" class="hidden">
    <h1 style="font-size:1.5rem;margin-bottom:1rem">Zタイムライン</h1>
    <div style="margin-bottom:1rem">ようこそ、<span id="userEmail"></span> さん!</div>
    <div class="profile-edit">
      <h3>プロフィール編集</h3>
      <input type="text" id="editName" placeholder="表示名を編集">
      <input type="text" id="editBio" placeholder="自己紹介を編集">
      <button onclick="saveProfile()">プロフィール保存</button>
    </div>
    <form id="timelineForm" style="display:flex;flex-direction:column;gap:.75rem;margin-bottom:2rem">
      <input id="timelineTitle" type="text" placeholder="タイトル" required>
      <textarea id="timelineContent" placeholder="投稿内容" required style="min-height:100px"></textarea>
      <input type="file" id="imageUpload" accept="image/*">
      <img id="preview" class="upload-preview hidden">
      <button type="submit">タイムラインに投稿</button>
    </form>
    <section id="timelineList" class="timeline"></section>
    <button onclick="logout()">ログアウト</button>
  </div>
</div>
<div id="vrScene" class="hidden" style="position:fixed;inset:0;z-index:9999"></div>
<button id="vrBtn" style="position:fixed;bottom:20px;right:20px;width:56px;height:56px;border-radius:50%;background:var(--primary);color:#fff;border:none;font-size:1.3rem;display:flex;align-items:center;justify-content:center;cursor:pointer;box-shadow:0 4px 12px rgba(0,0,0,.25)" onclick="enterVR()"><i class="fa-brands fa-vr-cardboard"></i></button>
<script>
let timeline = JSON.parse(localStorage.getItem('z_timeline')||'[]');
let feeds = JSON.parse(localStorage.getItem('z_feeds')||'[]');
let currentUser = JSON.parse(localStorage.getItem('z_user')||'null');
const authBox = document.getElementById('authBox');
const mainBox = document.getElementById('mainBox');
const timelineForm = document.getElementById('timelineForm');
const timelineList = document.getElementById('timelineList');
const userEmailSpan = document.getElementById('userEmail');
const previewImg = document.getElementById('preview');
const imageUpload = document.getElementById('imageUpload');
function loginOrRegister(){
  const email = document.getElementById('email').value.trim();
  const phone = document.getElementById('phone').value.trim();
  const pass = document.getElementById('password').value;
  const name = document.getElementById('username').value.trim();
  if(!email || !pass || !name){ alert('メール、パスワード、ユーザー名を入力してください'); return; }
  currentUser = {email, phone, name, bio:"", followers:[], following:[]};
  localStorage.setItem('z_user', JSON.stringify(currentUser));
  authBox.classList.add('hidden');
  mainBox.classList.remove('hidden');
  userEmailSpan.textContent = email;
  renderTimeline();
}
function logout(){ localStorage.removeItem('z_user'); location.reload(); }
function saveProfile(){
  const name = document.getElementById('editName').value;
  const bio = document.getElementById('editBio').value;
  if(name) currentUser.name = name;
  if(bio) currentUser.bio = bio;
  localStorage.setItem('z_user', JSON.stringify(currentUser));
  alert('プロフィールを保存しました');
}
function renderTimeline(){
  if(!timeline.length){ timelineList.innerHTML = '<p style="color:var(--border)">投稿がまだありません</p>'; return; }
  timelineList.innerHTML = timeline.map((t, index)=>{
    return `<div class="timeline-item">
      <h3>${t.title}</h3>
      <p>${t.content}</p>
      ${t.image ? `<img src="${t.image}" style="max-width:100%;margin-top:.5rem;border-radius:8px">` : ''}
      <small>${new Date(t.created).toLocaleString()}</small>
      <button onclick="followUser('${t.email}')" class="follow-btn">フォロー</button>
      <button onclick="deletePost(${index})" style="margin-top:.5rem;padding:.3rem .6rem;border:none;background:#eee;border-radius:6px;font-size:.8rem;cursor:pointer">削除</button>
    </div>`;
  }).join('');
}
function followUser(email){
  if(!currentUser.following.includes(email)){
    currentUser.following.push(email);
    localStorage.setItem('z_user', JSON.stringify(currentUser));
    alert(`${email} をフォローしました`);
  }
}
function deletePost(index){
  if(confirm('この投稿を削除しますか?')){
    timeline.splice(index,1);
    localStorage.setItem('z_timeline', JSON.stringify(timeline));
    renderTimeline();
  }
}
timelineForm.addEventListener('submit',e=>{
  e.preventDefault();
  const title = document.getElementById('timelineTitle').value.trim();
  const content = document.getElementById('timelineContent').value.trim();
  const file = imageUpload.files[0];
  if(!title || !content) return;
  const newPost = {title, content, image:null, created:new Date().toISOString(), email: currentUser.email};
  if(file){
    const reader = new FileReader();
    reader.onload = ()=>{
      newPost.image = reader.result;
      timeline.unshift(newPost);
      localStorage.setItem('z_timeline', JSON.stringify(timeline));
      renderTimeline();
    };
    reader.readAsDataURL(file);
  } else {
    timeline.unshift(newPost);
    localStorage.setItem('z_timeline', JSON.stringify(timeline));
    renderTimeline();
  }
  timelineForm.reset();
  previewImg.classList.add('hidden');
});
imageUpload.addEventListener('change',()=>{
  const file = imageUpload.files[0];
  if(file){
    const reader = new FileReader();
    reader.onload = ()=>{
      previewImg.src = reader.result;
      previewImg.classList.remove('hidden');
    };
    reader.readAsDataURL(file);
  }
});
function botAutoPost(){
  const phrases = ['こんにちは!', '今日も頑張ろう!', 'Zへようこそ!'];
  const msg = phrases[Math.floor(Math.random()*phrases.length)];
  timeline.unshift({title:'BOT投稿', content:msg, image:null, created:new Date().toISOString(), email:'bot@z.jp'});
  localStorage.setItem('z_timeline', JSON.stringify(timeline));
  renderTimeline();
}
setInterval(botAutoPost, 60000);
function fetchFeed(url){
  fetch(`https://api.rss2json.com/v1/api.json?rss_url=${encodeURIComponent(url)}`)
    .then(res=>res.json())
    .then(data=>{
      if(!data.items) return;
      data.items.slice(0,3).forEach(item=>{
        timeline.unshift({title:item.title, content:item.link, image:null, created:new Date().toISOString(), email:data.feed.title});
      });
      localStorage.setItem('z_timeline', JSON.stringify(timeline));
      renderTimeline();
    }).catch(e=>console.error('feed error',e));
}
feeds.forEach(fetchFeed);
function enterVR(){
  document.getElementById('vrScene').innerHTML = `
    <a-scene embedded>
      <a-sky color="#ECECEC"></a-sky>
      ${timeline.slice(0,10).map((p,i)=>`<a-entity text="value:${p.title}: ${p.content.replace(/\n/g,' ')};wrapCount:30" position="0 ${3-i*1.5} -3"></a-entity>`).join('')}
      <a-camera position="0 1.6 0"></a-camera>
    </a-scene>`;
  document.getElementById('vrScene').classList.remove('hidden');
  document.getElementById('vrBtn').classList.add('hidden');
}
document.addEventListener('keydown',e=>{
  if(e.key==='Escape' && !document.getElementById('vrScene').classList.contains('hidden')){
    document.getElementById('vrScene').classList.add('hidden');
    document.getElementById('vrBtn').classList.remove('hidden');
    document.getElementById('vrScene').innerHTML='';
  }
});
if(currentUser){
  authBox.classList.add('hidden');
  mainBox.classList.remove('hidden');
  userEmailSpan.textContent = currentUser.email;
  renderTimeline();
}
</script>
</body>
</html>

MusicPlayer.java

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;

import javazoom.jl.player.Player;     // JLayer

/** 超シンプル MP3 プレイヤー */
public class MusicPlayer extends JFrame {
    private static final long serialVersionUID = 1L;

    private JButton playBtn = new JButton("▶ 再生");
    private JButton stopBtn = new JButton("■ 停止");
    private JLabel  status  = new JLabel("ファイルを開いてください");
    private File    currentFile;
    private Player  player;           // 再生用スレッド
    private Thread  playThread;

    public MusicPlayer() {
        super("Java Swing Music Player");

        // 画面レイアウト
        JPanel ctrl = new JPanel();
        ctrl.add(playBtn);
        ctrl.add(stopBtn);
        add(ctrl, BorderLayout.CENTER);
        add(status, BorderLayout.SOUTH);

        // メニュー
        JMenuBar bar = new JMenuBar();
        JMenu     f  = new JMenu("ファイル");
        JMenuItem open = new JMenuItem("開く...");
        open.addActionListener(e -> chooseFile());
        f.add(open);
        bar.add(f);
        setJMenuBar(bar);

        // ボタン挙動
        playBtn.addActionListener(e -> play());
        stopBtn.addActionListener(e -> stop());

        // ウィンドウ設定
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        setSize(320, 120);
        setResizable(false);
        setLocationRelativeTo(null);
    }

    /** ファイル選択ダイアログ */
    private void chooseFile() {
        JFileChooser fc = new JFileChooser();
        fc.setFileFilter(new FileNameExtensionFilter("MP3 Audio", "mp3"));
        if (fc.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
            currentFile = fc.getSelectedFile();
            status.setText("選択中: " + currentFile.getName());
        }
    }

    /** 再生開始 */
    private void play() {
        if (currentFile == null) {
            JOptionPane.showMessageDialog(this, "まず MP3 を選択してください");
            return;
        }
        stop(); // 既に再生中なら停止
        playThread = new Thread(() -> {
            try (BufferedInputStream in = new BufferedInputStream(new FileInputStream(currentFile))) {
                player = new Player(in);
                status.setText("再生中: " + currentFile.getName());
                player.play();                  // ブロッキング
                SwingUtilities.invokeLater(() -> status.setText("停止"));
            } catch (Exception ex) {
                ex.printStackTrace();
                SwingUtilities.invokeLater(() -> status.setText("再生失敗"));
            }
        });
        playThread.start();
    }

    /** 再生停止 */
    private void stop() {
        if (player != null) {
            player.close();
        }
        if (playThread != null) {
            playThread.interrupt();
        }
        status.setText("停止");
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new MusicPlayer().setVisible(true));
    }
}

C:\java> dir jlayer-1.0.1.jar
2025/05/06 92,109 jlayer-1.0.1.jar ← この行が出れば OK
コンパイル
C:\java> javac -encoding UTF-8 -cp “.;jlayer-1.0.1.jar” MusicPlayer.java

小説投稿サイト

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>小説投稿サイト</title>
  <style>
    body {
      font-family: sans-serif;
      padding: 20px;
      max-width: 800px;
      margin: auto;
      background: #f2f2f2;
    }

    h1 {
      text-align: center;
    }

    form {
      background: white;
      padding: 20px;
      border-radius: 10px;
      margin-bottom: 30px;
      box-shadow: 0 0 10px rgba(0,0,0,0.1);
    }

    input, textarea {
      width: 100%;
      margin-bottom: 10px;
      padding: 10px;
      border-radius: 5px;
      border: 1px solid #ccc;
    }

    button {
      padding: 10px 20px;
      background-color: #007bff;
      color: white;
      border: none;
      border-radius: 5px;
      cursor: pointer;
    }

    .post {
      background: white;
      padding: 15px;
      border-left: 5px solid #007bff;
      margin-bottom: 20px;
      border-radius: 5px;
    }

    .post h2 {
      margin: 0 0 10px;
    }

    .meta {
      color: gray;
      font-size: 0.9em;
      margin-bottom: 10px;
    }

    .delete-btn {
      background-color: #dc3545;
      color: white;
      border: none;
      padding: 5px 10px;
      border-radius: 4px;
      float: right;
      cursor: pointer;
    }
  </style>
</head>
<body>
  <h1>小説投稿サイト</h1>

  <form id="novelForm">
    <input type="text" id="author" placeholder="著者名" required>
    <input type="text" id="title" placeholder="タイトル" required>
    <textarea id="content" rows="8" placeholder="本文" required></textarea>
    <button type="submit">投稿する</button>
  </form>

  <div id="postList"></div>

  <script>
    const form = document.getElementById('novelForm');
    const postList = document.getElementById('postList');
    let posts = JSON.parse(localStorage.getItem('novels')) || [];

    function saveAndRender() {
      localStorage.setItem('novels', JSON.stringify(posts));
      renderPosts();
    }

    function renderPosts() {
      postList.innerHTML = '';
      [...posts].reverse().forEach((post, index) => {
        const div = document.createElement('div');
        div.className = 'post';
        div.innerHTML = `
          <button class="delete-btn" onclick="deletePost(${index})">削除</button>
          <h2>${post.title}</h2>
          <div class="meta">著者: ${post.author} | 投稿日: ${post.date}</div>
          <p>${post.content.replace(/\n/g, '<br>')}</p>
        `;
        postList.appendChild(div);
      });
    }

    form.addEventListener('submit', e => {
      e.preventDefault();
      const title = document.getElementById('title').value;
      const content = document.getElementById('content').value;
      const author = document.getElementById('author').value;
      const date = new Date().toLocaleString();

      posts.push({ title, content, author, date });
      form.reset();
      saveAndRender();
    });

    window.deletePost = function(index) {
      posts.splice(posts.length - 1 - index, 1); // reverseしてるため
      saveAndRender();
    }

    renderPosts();
  </script>
</body>
</html>