From eefe1419b1c0ada67de1385b1c7da8e195379e79 Mon Sep 17 00:00:00 2001 From: EP Date: Thu, 6 Mar 2025 15:12:15 -0500 Subject: [PATCH] Enhanced UI with cyber-garden theme and dataset management --- .DS_Store | Bin 0 -> 6148 bytes README.md | 60 +++++++ data_manager.js | 104 ++++++++++++ datasets.html | 295 +++++++++++++++++++++++++++++++++ index.html | 433 ++++++++++++++++++++++++++++++++++++++++++++++++ script.js | 329 ++++++++++++++++++++++++++++++++++++ styles.css | 178 ++++++++++++++++++++ 7 files changed, 1399 insertions(+) create mode 100644 .DS_Store create mode 100644 README.md create mode 100644 data_manager.js create mode 100644 datasets.html create mode 100644 index.html create mode 100644 script.js create mode 100644 styles.css diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..addf938417cb54557fbf183095329dd8de056881 GIT binary patch literal 6148 zcmeHK!Ab)$5S`HqD}wasF~871SW9{=is{9h)IvRMyH(Khet~!Y#j~H__xL6=LKlO@ zi-?_p*&!kxKQ2Z@Ln5ls1X%_J5p{9tz>JT8ocEZ}lmcDS6bla{r8hm`;Wxr};oHy+pcGdF>9pAsco$vNp{Mcu6w;fjw z@7p|{(!;uG*Gt5Lcje*?I0MdrGqA@D*ga64>@f$Px-;Mmlo^ooA)pD?hMi(QI?&}3 z062g;3&v7Qh)*!A4Le1wKv-RY>dIDPu)0GZ%&s=<6xE&BiVwCYe-|wjfj$F=IvvXWKfxzcEb{v a + b, 0) + }); + + // Keep only last 50 datasets in the list + if (datasets.length > 50) { + datasets.shift(); + } + + localStorage.setItem('roots-datasets', JSON.stringify(datasets)); + this.updateDatasetDisplay(); + } + + updateDatasetDisplay() { + const datasetList = document.getElementById('dataset-list'); + if (!datasetList) return; + + const datasets = JSON.parse(localStorage.getItem('roots-datasets') || '[]'); + datasetList.innerHTML = datasets.reverse().slice(0, 5).map(dataset => ` +
+
+ ${dataset.filename} + + Words: ${dataset.wordCount} | + Submissions: ${dataset.totalSubmissions} + +
+
+ ${new Date(dataset.timestamp).toLocaleString()} +
+
+ `).join(''); + } + + startAutoBackup() { + // Initial backup + setTimeout(() => this.saveDataset(), 5000); + + // Regular backups + setInterval(() => this.saveDataset(), this.backupInterval); + } +} + +// Initialize data manager when document is ready +document.addEventListener('DOMContentLoaded', () => { + window.dataManager = new DataManager(); +}); diff --git a/datasets.html b/datasets.html new file mode 100644 index 0000000..32fa93f --- /dev/null +++ b/datasets.html @@ -0,0 +1,295 @@ + + + + + + R00TS - Dataset Manager + + + + +
+ ← Back to Garden + +
+

R00TS Dataset Manager

+
+ +
+ +
+ +
+
+ +
+
+
+ + + + diff --git a/index.html b/index.html new file mode 100644 index 0000000..d27299b --- /dev/null +++ b/index.html @@ -0,0 +1,433 @@ + + + + + + R00TS - AI Word Seeding + + + + + + + + +
+
+
+

R00TS

+

Plant the seeds of artificial intelligence by contributing words you think are important

+
+ +
+
+
+ + +
+ +
+
+ +
+
+

Total Words

+

0

+
+
+

Unique Words

+

0

+
+
+ +
+ +
+
+

Recent Datasets

+ View All Datasets +
+
+ +
+
+ + +
+ + + + \ No newline at end of file diff --git a/script.js b/script.js new file mode 100644 index 0000000..457e4a3 --- /dev/null +++ b/script.js @@ -0,0 +1,329 @@ +// R00TS - Plant the seeds of artificial intelligence +// Main application functionality + +document.addEventListener('DOMContentLoaded', function() { + // Initialize particles + initParticles(); + + // Load words from storage + loadWords(); + + // Set up automatic updates + setInterval(loadWords, 5000); +}); + +function initParticles() { + particlesJS('particles-js', { + particles: { + number: { + value: 80, + density: { + enable: true, + value_area: 800 + } + }, + color: { + value: '#00ff9d' + }, + shape: { + type: 'circle' + }, + opacity: { + value: 0.5, + random: true, + animation: { + enable: true, + speed: 1, + opacity_min: 0.1, + sync: false + } + }, + size: { + value: 3, + random: true, + animation: { + enable: true, + speed: 2, + size_min: 0.1, + sync: false + } + }, + line_linked: { + enable: true, + distance: 150, + color: '#00ff9d', + opacity: 0.2, + width: 1 + }, + move: { + enable: true, + speed: 1, + direction: 'none', + random: true, + straight: false, + out_mode: 'out', + bounce: false + } + }, + interactivity: { + detect_on: 'canvas', + events: { + onhover: { + enable: true, + mode: 'grab' + }, + resize: true + }, + modes: { + grab: { + distance: 140, + line_linked: { + opacity: 0.5 + } + } + } + }, + retina_detect: true + }); +} + +function loadWords() { + // In a real implementation, this would be an API call + // For demo purposes, we're using localStorage + let words = JSON.parse(localStorage.getItem('roots-words')) || {}; + + // Update the visualization + updateWordCloud(words); + + // Update statistics + updateStats(words); +} + +function updateStats(words) { + const totalSubmissions = Object.values(words).reduce((a, b) => a + b, 0); + const uniqueWords = Object.keys(words).length; + + document.getElementById('submission-count').textContent = totalSubmissions; + document.getElementById('unique-count').textContent = uniqueWords; +} + +function submitWord(word) { + word = word.trim().toLowerCase(); + + if (!word) return false; + + // Create a particle burst effect + createParticleBurst(); + + // For demo purposes, we're using localStorage + let words = JSON.parse(localStorage.getItem('roots-words')) || {}; + words[word] = (words[word] || 0) + 1; + localStorage.setItem('roots-words', JSON.stringify(words)); + + // Update UI with animation + gsap.to('.stat-box', { + scale: 1.1, + duration: 0.2, + yoyo: true, + repeat: 1, + ease: 'power2.out' + }); + + loadWords(); + return true; +} + +function createParticleBurst() { + const container = document.querySelector('.input-area'); + const rect = container.getBoundingClientRect(); + const centerX = rect.left + rect.width / 2; + const centerY = rect.top + rect.height / 2; + + for (let i = 0; i < 20; i++) { + const particle = document.createElement('div'); + particle.style.cssText = ` + position: fixed; + width: 8px; + height: 8px; + background: #00ff9d; + border-radius: 50%; + pointer-events: none; + z-index: 1000; + `; + document.body.appendChild(particle); + + const angle = (i / 20) * Math.PI * 2; + const velocity = 2 + Math.random() * 2; + const dx = Math.cos(angle) * velocity; + const dy = Math.sin(angle) * velocity; + + gsap.fromTo(particle, + { + x: centerX, + y: centerY, + scale: 1, + opacity: 1 + }, + { + duration: 1 + Math.random(), + x: centerX + dx * 50, + y: centerY + dy * 50, + scale: 0, + opacity: 0, + ease: 'power2.out', + onComplete: () => particle.remove() + } + ); + } +} + +function updateWordCloud(words) { + const container = document.getElementById('word-cloud-container'); + if (!container) return; + + container.innerHTML = ''; + + const width = container.offsetWidth; + const height = container.offsetHeight; + + const wordData = Object.entries(words).map(([text, value]) => ({ text, value })); + + // Sort by frequency + wordData.sort((a, b) => b.value - a.value); + + // Take top 100 words + const topWords = wordData.slice(0, 100); + + if (topWords.length === 0) { + container.innerHTML = '

Plant some words to see them grow here!

'; + return; + } + + // Calculate min/max for scaling + const minCount = Math.min(...topWords.map(d => d.value)) || 1; + const maxCount = Math.max(...topWords.map(d => d.value)) || 1; + + // Create SVG + const svg = d3.select('#word-cloud-container') + .append('svg') + .attr('width', width) + .attr('height', height) + .append('g') + .attr('transform', `translate(${width/2}, ${height * 0.8})`); + + // Create tree trunk + const trunk = svg.append('path') + .attr('d', `M0,0 L0,-${height * 0.6}`) + .attr('stroke', '#00ff9d') + .attr('stroke-width', 8) + .attr('fill', 'none') + .style('opacity', 0) + .transition() + .duration(1000) + .style('opacity', 1); + + // Create branches function + function createBranch(startX, startY, length, angle, depth) { + if (depth <= 0) return; + + const endX = startX + length * Math.sin(angle); + const endY = startY - length * Math.cos(angle); + + svg.append('path') + .attr('d', `M${startX},${startY} L${endX},${endY}`) + .attr('stroke', '#00ff9d') + .attr('stroke-width', Math.max(1, depth)) + .attr('fill', 'none') + .style('opacity', 0) + .transition() + .delay(1000 + (5 - depth) * 300) + .duration(500) + .style('opacity', 0.5); + + createBranch(endX, endY, length * 0.7, angle + 0.5, depth - 1); + createBranch(endX, endY, length * 0.7, angle - 0.5, depth - 1); + } + + // Create initial branches + createBranch(0, -height * 0.6, height * 0.2, -Math.PI/4, 5); + createBranch(0, -height * 0.6, height * 0.2, Math.PI/4, 5); + + // Create a force simulation for the words + const simulation = d3.forceSimulation(topWords) + .force('charge', d3.forceManyBody().strength(5)) + .force('collide', d3.forceCollide(d => fontSize(d) / 2 + 2)) + .force('x', d3.forceX(d => { + const angle = (d.index / topWords.length) * Math.PI - Math.PI/2; + return Math.cos(angle) * (height * 0.3); + })) + .force('y', d3.forceY(d => { + const angle = (d.index / topWords.length) * Math.PI - Math.PI/2; + return Math.sin(angle) * (height * 0.3) - height * 0.4; + })); + + // Create word elements + const words = svg.selectAll('.word') + .data(topWords) + .enter() + .append('text') + .attr('class', 'word') + .style('fill', d => d3.interpolateGreenYellow(d.value / maxCount)) + .style('font-size', d => `${fontSize(d)}px`) + .style('font-family', '"Space Grotesk", sans-serif') + .style('cursor', 'pointer') + .text(d => d.text) + .style('opacity', 0) + .on('mouseover', function(event, d) { + d3.select(this) + .transition() + .duration(200) + .style('fill', '#39ff14') + .style('font-size', d => `${fontSize(d) * 1.2}px`) + .style('text-shadow', '0 0 10px rgba(57, 255, 20, 0.5)'); + }) + .on('mouseout', function(event, d) { + d3.select(this) + .transition() + .duration(200) + .style('fill', d3.interpolateGreenYellow(d.value / maxCount)) + .style('font-size', d => `${fontSize(d)}px`) + .style('text-shadow', 'none'); + }); + + // Add transition for words appearing + words.transition() + .delay((d, i) => 2000 + i * 50) + .duration(500) + .style('opacity', 1); + + // Update word positions on each tick + simulation.on('tick', () => { + words + .attr('x', d => d.x) + .attr('y', d => d.y) + .attr('text-anchor', 'middle') + .attr('alignment-baseline', 'middle'); + }); +} +} + +// Function to share words +function shareResults() { + const words = JSON.parse(localStorage.getItem('roots-words')) || {}; + const totalWords = Object.values(words).reduce((a, b) => a + b, 0); + const uniqueWords = Object.keys(words).length; + + const topWords = Object.entries(words) + .sort((a, b) => b[1] - a[1]) + .slice(0, 5) + .map(([word, count]) => word) + .join(', '); + + const shareText = `I've planted ${totalWords} words (${uniqueWords} unique) to help grow the future of AI with R00TS! Top contributions: ${topWords}`; + + // In a real implementation, this would integrate with social sharing APIs + // For demo purposes, we'll just copy to clipboard + navigator.clipboard.writeText(shareText) + .then(() => alert('Share text copied to clipboard!')) + .catch(err => console.error('Failed to copy: ', err)); +} \ No newline at end of file diff --git a/styles.css b/styles.css new file mode 100644 index 0000000..accbb03 --- /dev/null +++ b/styles.css @@ -0,0 +1,178 @@ +/* R00TS - Core Styles */ +body { + font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; + background-color: #f0f2f5; + color: #212529; + margin: 0; + padding: 0; + line-height: 1.6; +} + +.container { + max-width: 800px; + margin: 0 auto; + padding: 20px; +} + +/* Header Styles */ +.header { + text-align: center; + margin-bottom: 30px; + padding: 20px 0; +} + +.header h1 { + font-weight: 700; + color: #2e2e2e; + margin-bottom: 10px; + font-size: 3rem; +} + +.r00ts-brand { + font-family: monospace; + font-weight: bold; + letter-spacing: 1px; +} + +.header .lead { + color: #555; + font-size: 1.2rem; +} + +/* Input Area Styles */ +.input-area { + background-color: #ffffff; + padding: 20px; + border-radius: 10px; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); + margin-bottom: 30px; +} + +.input-area label { + font-weight: 600; + color: #495057; +} + +.form-control:focus { + border-color: #80bdff; + box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25); +} + +/* Word Cloud Styles */ +.word-cloud { + width: 100%; + height: 400px; + margin-top: 30px; + background-color: #ffffff; + border-radius: 10px; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); + overflow: hidden; + position: relative; +} + +.word-item { + transition: all 0.2s ease; + cursor: pointer; +} + +/* Statistics Styles */ +.stats-area { + display: flex; + justify-content: space-around; + margin: 20px 0; +} + +.stat-box { + text-align: center; + padding: 10px; + background-color: #ffffff; + border-radius: 10px; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); + flex: 1; + margin: 0 10px; +} + +.stat-box h3 { + margin: 0; + font-size: 1rem; + color: #6c757d; +} + +.stat-box p { + margin: 5px 0 0; + font-size: 1.5rem; + font-weight: 700; + color: #4a6fa5; +} + +/* Footer Styles */ +.footer { + text-align: center; + margin-top: 30px; + padding: 20px 0; + color: #6c757d; + font-size: 0.9rem; + border-top: 1px solid #dee2e6; +} + +/* Button Styles */ +.btn-primary { + background-color: #4a6fa5; + border: none; + padding: 10px 20px; + transition: background-color 0.2s; +} + +.btn-primary:hover { + background-color: #3a5a8c; +} + +/* Responsive Adjustments */ +@media (max-width: 576px) { + .container { + padding: 10px; + } + + .word-cloud { + height: 300px; + } + + .stats-area { + flex-direction: column; + } + + .stat-box { + margin: 5px 0; + } + + .header h1 { + font-size: 2.5rem; + } +} + +/* Share button */ +.share-btn { + display: inline-block; + background-color: #4a6fa5; + color: white; + border: none; + border-radius: 50px; + padding: 8px 20px; + margin-top: 10px; + cursor: pointer; + transition: background-color 0.2s; +} + +.share-btn:hover { + background-color: #3a5a8c; +} + +/* Animation for word addition */ +@keyframes grow { + 0% { transform: scale(0); opacity: 0; } + 100% { transform: scale(1); opacity: 1; } +} + +.word-added { + animation: grow 0.5s ease-out; +} \ No newline at end of file