{"id":26088,"date":"2025-07-06T06:02:22","date_gmt":"2025-07-05T21:02:22","guid":{"rendered":"http:\/\/www.tyosuke20xx.com\/blog\/?p=26088"},"modified":"2025-07-06T06:02:24","modified_gmt":"2025-07-05T21:02:24","slug":"%e3%81%b2%e3%81%a8%e3%81%93%e3%81%a8%e5%b1%a5%e6%ad%b4%e6%9b%b8","status":"publish","type":"post","link":"http:\/\/www.tyosuke20xx.com\/blog\/?p=26088","title":{"rendered":"\u3072\u3068\u3053\u3068\u5c65\u6b74\u66f8"},"content":{"rendered":"\n<pre class=\"wp-block-code\"><code>\n&lt;!DOCTYPE html>\n&lt;html lang=\"ja\">\n&lt;head>\n  &lt;meta charset=\"UTF-8\">\n  &lt;title>\u3072\u3068\u3053\u3068\u5c65\u6b74\u66f8 Ultra&lt;\/title>\n  &lt;script src=\"https:\/\/cdn.jsdelivr.net\/npm\/chart.js\">&lt;\/script>\n  &lt;style>\n    body {\n      font-family: \"Helvetica Neue\", sans-serif;\n      background: #f0f0f0;\n      padding: 30px;\n      max-width: 900px;\n      margin: auto;\n    }\n    h1 {\n      text-align: center;\n      margin-bottom: 20px;\n    }\n    textarea, input&#91;type=\"date\"], input&#91;type=\"text\"] {\n      width: 100%;\n      padding: 10px;\n      font-size: 1rem;\n      margin-bottom: 10px;\n    }\n    .emotion-btn {\n      font-size: 20px;\n      padding: 6px 12px;\n      border: 2px solid #ccc;\n      background: white;\n      cursor: pointer;\n      border-radius: 6px;\n    }\n    .emotion-btn.selected {\n      border-color: #4caf50;\n      background: #e8f5e9;\n    }\n    button.add {\n      background: #4caf50;\n      color: white;\n      border: none;\n      border-radius: 6px;\n      padding: 10px 20px;\n      cursor: pointer;\n      font-size: 1rem;\n      margin-top: 10px;\n    }\n    button.export {\n      background: #2196f3;\n      margin-left: 10px;\n    }\n    .entry {\n      background: white;\n      padding: 10px;\n      border-left: 5px solid #ccc;\n      margin: 10px 0;\n      border-radius: 6px;\n    }\n    .section-date {\n      font-weight: bold;\n      margin-top: 30px;\n    }\n    .entry .meta {\n      font-size: 0.8em;\n      color: #666;\n    }\n    #stats {\n      margin: 20px 0;\n      background: #fff;\n      padding: 10px;\n      border-radius: 8px;\n      box-shadow: 0 0 3px rgba(0,0,0,0.1);\n    }\n  &lt;\/style>\n&lt;\/head>\n&lt;body>\n\n&lt;h1>\u3072\u3068\u3053\u3068\u5c65\u6b74\u66f8 Ultra&lt;\/h1>\n\n&lt;textarea id=\"entryInput\" placeholder=\"\u4eca\u65e5\u306e\u4e00\u8a00\u3092\u8a18\u9332\u3057\u3088\u3046\uff01\">&lt;\/textarea>\n&lt;input type=\"date\" id=\"entryDate\">\n&lt;div>\n  &lt;button class=\"emotion-btn\" data-emotion=\"\ud83d\ude0a\">\ud83d\ude0a \u559c&lt;\/button>\n  &lt;button class=\"emotion-btn\" data-emotion=\"\ud83d\ude22\">\ud83d\ude22 \u54c0&lt;\/button>\n  &lt;button class=\"emotion-btn\" data-emotion=\"\ud83d\ude20\">\ud83d\ude20 \u6012&lt;\/button>\n  &lt;button class=\"emotion-btn\" data-emotion=\"\ud83d\ude10\">\ud83d\ude10 \u4e2d\u7acb&lt;\/button>\n&lt;\/div>\n&lt;button class=\"add\" onclick=\"addEntry()\">\u8a18\u9332&lt;\/button>\n&lt;button class=\"add export\" onclick=\"exportCSV()\">CSV\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9&lt;\/button>\n\n&lt;input type=\"text\" id=\"searchBox\" placeholder=\"\u30ad\u30fc\u30ef\u30fc\u30c9\u691c\u7d22\uff08\u4f8b\uff1a\u5b09\u3057\u3044\u3001\u7f8e\u8853\u9928\uff09\">\n&lt;div id=\"stats\">&lt;\/div>\n&lt;canvas id=\"emotionChart\" height=\"200\">&lt;\/canvas>\n&lt;div id=\"entryList\">&lt;\/div>\n\n&lt;script>\nconst input = document.getElementById(\"entryInput\");\nconst dateInput = document.getElementById(\"entryDate\");\nconst searchBox = document.getElementById(\"searchBox\");\nconst entryList = document.getElementById(\"entryList\");\nconst stats = document.getElementById(\"stats\");\nconst emotionButtons = document.querySelectorAll(\".emotion-btn\");\nlet selectedEmotion = \"\ud83d\ude0a\";\ndateInput.valueAsDate = new Date();\n\nemotionButtons.forEach(btn => {\n  btn.addEventListener(\"click\", () => {\n    emotionButtons.forEach(b => b.classList.remove(\"selected\"));\n    btn.classList.add(\"selected\");\n    selectedEmotion = btn.dataset.emotion;\n  });\n});\n\nfunction addEntry() {\n  const text = input.value.trim();\n  const date = dateInput.value;\n  if (!text || !date || !selectedEmotion) return;\n  const entries = JSON.parse(localStorage.getItem(\"entries\") || \"&#91;]\");\n  entries.push({ text, date, emotion: selectedEmotion, timestamp: new Date().toISOString() });\n  localStorage.setItem(\"entries\", JSON.stringify(entries));\n  input.value = \"\";\n  renderEntries();\n}\n\nfunction exportCSV() {\n  const entries = JSON.parse(localStorage.getItem(\"entries\") || \"&#91;]\");\n  let csv = \"\u65e5\u4ed8,\u611f\u60c5,\u30c6\u30ad\u30b9\u30c8,\u8a18\u9332\u65e5\u6642\\n\";\n  entries.forEach(e => {\n    csv += `${e.date},${e.emotion},\"${e.text.replace(\/\"\/g, '\"\"')}\",${e.timestamp}\\n`;\n  });\n  const blob = new Blob(&#91;csv], { type: \"text\/csv\" });\n  const url = URL.createObjectURL(blob);\n  const a = document.createElement(\"a\");\n  a.href = url;\n  a.download = \"hitokoto_entries.csv\";\n  a.click();\n  URL.revokeObjectURL(url);\n}\n\nfunction groupByDate(entries) {\n  const grouped = {};\n  entries.forEach(entry => {\n    if (!grouped&#91;entry.date]) grouped&#91;entry.date] = &#91;];\n    grouped&#91;entry.date].push(entry);\n  });\n  return grouped;\n}\n\nfunction renderEntries() {\n  const entries = JSON.parse(localStorage.getItem(\"entries\") || \"&#91;]\").reverse();\n  const keyword = searchBox.value.trim();\n  const filtered = keyword\n    ? entries.filter(e => e.text.includes(keyword))\n    : entries;\n\n  const grouped = groupByDate(filtered);\n  const emotionCounts = { \"\ud83d\ude0a\": 0, \"\ud83d\ude22\": 0, \"\ud83d\ude20\": 0, \"\ud83d\ude10\": 0 };\n\n  entryList.innerHTML = \"\";\n  let totalTextLength = 0;\n\n  for (const date in grouped) {\n    const section = document.createElement(\"div\");\n    section.innerHTML = `&lt;div class=\"section-date\">\ud83d\udcc5 ${date}&lt;\/div>`;\n    grouped&#91;date].forEach(entry => {\n      emotionCounts&#91;entry.emotion]++;\n      totalTextLength += entry.text.length;\n      const div = document.createElement(\"div\");\n      div.className = \"entry\";\n      div.innerHTML = `\n        &lt;div>${entry.emotion} ${entry.text}&lt;\/div>\n        &lt;div class=\"meta\">${new Date(entry.timestamp).toLocaleString()}&lt;\/div>\n      `;\n      section.appendChild(div);\n    });\n    entryList.appendChild(section);\n  }\n\n  const total = filtered.length;\n  const avgLen = total ? Math.round(totalTextLength \/ total) : 0;\n  stats.innerHTML = `\ud83d\udccc \u7dcf\u6295\u7a3f\u6570: ${total} \u4ef6\uff5c\u5e73\u5747\u6587\u5b57\u6570: ${avgLen} \u5b57`;\n\n  renderChart(emotionCounts);\n}\n\nfunction renderChart(counts) {\n  const ctx = document.getElementById(\"emotionChart\").getContext(\"2d\");\n  if (window.myChart) window.myChart.destroy();\n  window.myChart = new Chart(ctx, {\n    type: \"pie\",\n    data: {\n      labels: &#91;\"\ud83d\ude0a \u559c\", \"\ud83d\ude22 \u54c0\", \"\ud83d\ude20 \u6012\", \"\ud83d\ude10 \u4e2d\u7acb\"],\n      datasets: &#91;{\n        data: &#91;\n          counts&#91;\"\ud83d\ude0a\"],\n          counts&#91;\"\ud83d\ude22\"],\n          counts&#91;\"\ud83d\ude20\"],\n          counts&#91;\"\ud83d\ude10\"]\n        ],\n        backgroundColor: &#91;\"gold\", \"skyblue\", \"tomato\", \"gray\"]\n      }]\n    },\n    options: {\n      plugins: { legend: { position: \"bottom\" } }\n    }\n  });\n}\n\nsearchBox.addEventListener(\"input\", renderEntries);\nrenderEntries();\n&lt;\/script>\n\n&lt;\/body>\n&lt;\/html>\n<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"footnotes":""},"categories":[80,96],"tags":[],"class_list":["post-26088","post","type-post","status-publish","format-standard","hentry","category-html","category-web"],"aioseo_notices":[],"jetpack_featured_media_url":"","_links":{"self":[{"href":"http:\/\/www.tyosuke20xx.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/26088","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.tyosuke20xx.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.tyosuke20xx.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.tyosuke20xx.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.tyosuke20xx.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=26088"}],"version-history":[{"count":1,"href":"http:\/\/www.tyosuke20xx.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/26088\/revisions"}],"predecessor-version":[{"id":26089,"href":"http:\/\/www.tyosuke20xx.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/26088\/revisions\/26089"}],"wp:attachment":[{"href":"http:\/\/www.tyosuke20xx.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=26088"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.tyosuke20xx.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=26088"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.tyosuke20xx.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=26088"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}