Skip to main content
Glama

Poker Task Management MCP

by Hirao-Y
enhanced_level1_classes.js28.4 kB
// =============== クラス定義 =============== // 学習進捗管理システム (強化版) class EnhancedLearningProgressManager { constructor() { this.currentStage = 1; this.totalStages = 4; this.stageProgress = [0, 0, 0, 0]; // 各段階の進捗率 this.completedObjectives = {}; this.startTime = Date.now(); this.stageStartTimes = {}; this.calculationCount = 0; this.scenarioExperience = { medical: false, research: false, nuclear: false, industrial: false }; this.updateUI(); } nextStage() { if (this.currentStage < this.totalStages) { this.stageProgress[this.currentStage - 1] = 100; this.currentStage++; this.stageStartTimes[this.currentStage] = Date.now(); this.updateStageContent(); this.updateUI(); this.resetObjectives(); } else { this.completeLevel(); } } updateObjective(objectiveIndex, completed = true) { const stageKey = `stage${this.currentStage}`; if (!this.completedObjectives[stageKey]) { this.completedObjectives[stageKey] = {}; } this.completedObjectives[stageKey][objectiveIndex] = completed; // UIを更新 const objectiveElement = document.getElementById(`objective-${objectiveIndex}`); if (objectiveElement) { objectiveElement.textContent = completed ? '✓' : '◯'; objectiveElement.className = completed ? 'objective-item completed' : 'objective-item'; objectiveElement.textContent += ' ' + stageData[this.currentStage].objectives[objectiveIndex - 1]; } // 段階進捗の更新 this.updateStageProgress(); } updateStageProgress() { const stageKey = `stage${this.currentStage}`; const objectives = this.completedObjectives[stageKey] || {}; const completed = Object.values(objectives).filter(v => v).length; const total = stageData[this.currentStage].objectives.length; this.stageProgress[this.currentStage - 1] = (completed / total) * 100; this.updateUI(); // 段階完了チェック if (completed === total) { this.showStageCompletion(); } } showStageCompletion() { const completionElement = document.getElementById('stage-completion'); if (completionElement) { completionElement.style.display = 'block'; } } updateUI() { // ステージインジケーター更新 const indicators = document.querySelectorAll('.stage-indicator'); indicators.forEach((indicator, index) => { indicator.classList.remove('active', 'completed'); if (index + 1 < this.currentStage) { indicator.classList.add('completed'); } else if (index + 1 === this.currentStage) { indicator.classList.add('active'); } }); // ステージラベル更新 const labels = document.querySelectorAll('.stage-label'); labels.forEach((label, index) => { label.classList.remove('active'); if (index + 1 === this.currentStage) { label.classList.add('active'); } }); // 現在ステージ表示更新 const currentStageData = stageData[this.currentStage]; const stageTitle = currentStageData.title.split(':')[1]?.trim() || currentStageData.title; document.getElementById('current-stage-display').textContent = `Stage ${this.currentStage}/${this.totalStages}: ${stageTitle}`; // ナビゲーションボタン更新 document.getElementById('prev-btn').disabled = this.currentStage === 1; document.getElementById('next-btn').style.display = this.currentStage === this.totalStages ? 'none' : 'flex'; } updateStageContent() { const stage = stageData[this.currentStage]; // アイコンとタイトル更新 document.getElementById('stage-icon').textContent = stage.icon; document.getElementById('stage-title').textContent = stage.title; // プロセスステップ更新 const processSteps = document.querySelectorAll('.process-step'); processSteps.forEach((step, index) => { step.classList.remove('active', 'completed'); if (index + 1 < this.currentStage) { step.classList.add('completed'); } else if (index + 1 === this.currentStage) { step.classList.add('active'); } }); // 可視化パネルの目標更新 document.getElementById('viz-stage-display').textContent = `Stage ${this.currentStage}: ${stage.title.split(':')[0]}`; // CSS変数でカラーテーマ更新 document.documentElement.style.setProperty('--current-stage-color', stage.color); // ステージ固有のコンテンツ更新 this.updateStageSpecificContent(); // ステージ完了表示を隠す const completionElement = document.getElementById('stage-completion'); if (completionElement) { completionElement.style.display = 'none'; } } updateStageSpecificContent() { const stage = stageData[this.currentStage]; const scenario = scenarioData[currentScenario]; // 学習コンテンツの更新 const contentSection = document.querySelector('.content-section'); if (contentSection) { const titleElement = contentSection.querySelector('.section-title span:last-child'); if (titleElement) { titleElement.textContent = stage.content.title; } const descElement = contentSection.querySelector('p'); if (descElement) { descElement.innerHTML = stage.content.description; } } // ステージ別の数式・概念の更新 this.updateStageEquations(); } updateStageEquations() { const eq = equationDatabase[this.currentStage]?.primary; const equationBox = document.querySelector('.equation-box'); if (equationBox && eq) { equationBox.querySelector('.main-equation').innerHTML = eq.formula; equationBox.querySelector('.equation-description').textContent = eq.description; } } resetObjectives() { const stageKey = `stage${this.currentStage}`; this.completedObjectives[stageKey] = {}; // UI目標リセット for (let i = 1; i <= 4; i++) { const objective = document.getElementById(`objective-${i}`); if (objective) { const objectiveText = stageData[this.currentStage].objectives[i-1] || ''; objective.textContent = `◯ ${objectiveText}`; objective.className = 'objective-item'; } } } trackCalculation() { this.calculationCount++; this.updateObjective(3, true); // 計算実行の目標完了 } trackScenarioExperience() { this.scenarioExperience[currentScenario] = true; } completeLevel() { const completionTime = (Date.now() - this.startTime) / 1000; const experiencedScenarios = Object.values(this.scenarioExperience).filter(v => v).length; alert(`🎉 Level 1 完了おめでとうございます! 📊 学習成果: • 完了時間: ${Math.round(completionTime)}秒 • 実行計算: ${this.calculationCount}回 • 体験シナリオ: ${experiencedScenarios}/4分野 • 習得概念: 4段階学習プロセス完了 🎯 達成度評価: • 基礎理論: 完全習得 • 材料特性: 完全理解 • 設計手法: 実践完了 • 評価最適化: マスター 🚀 次のステップ: Level 2: 実用設計チャレンジ Level 3: 高度解析・MCNP連携 放射線遮蔽の段階的学習を完全にマスターしました! 実際の研究・業務でぜひご活用ください。`); } } // シナリオ管理システム class ScenarioManager { constructor() { this.currentScenario = 'medical'; this.bindEvents(); } switchScenario(newScenario) { if (this.currentScenario === newScenario) return; this.currentScenario = newScenario; currentScenario = newScenario; // UI更新 this.updateScenarioUI(); this.updateScenarioContent(); this.updateScenarioDefaults(); this.updateVisualization(); // 学習進捗に記録 if (progressManager) { progressManager.trackScenarioExperience(); } } updateScenarioUI() { const scenario = scenarioData[this.currentScenario]; // テーマクラス更新 document.getElementById('body').className = scenario.theme; // タブの状態更新 document.querySelectorAll('.scenario-tab').forEach(tab => { tab.classList.remove('active'); if (tab.dataset.scenario === this.currentScenario) { tab.classList.add('active'); } }); // CSS変数更新 document.documentElement.style.setProperty('--scenario-color', scenario.color); document.documentElement.style.setProperty('--scenario-rgb', scenario.rgb); } updateScenarioContent() { const scenario = scenarioData[this.currentScenario]; // シナリオコンテキスト更新 document.getElementById('scenario-context-title').innerHTML = `<span>${scenario.icon}</span><span>${scenario.context.title}</span>`; document.getElementById('scenario-description').innerHTML = scenario.context.description; // 線量限度更新 document.getElementById('scenario-specific-limits').textContent = `⚡ ${scenario.name}の線量限度(ICRP 146, 2022)`; document.getElementById('dose-limits-content').innerHTML = scenario.context.limits; // パラメータセクション更新 document.getElementById('scenario-params-title').innerHTML = `<span>${scenario.icon}</span><span>${scenario.context.params.title}</span>`; document.getElementById('scenario-params-description').textContent = scenario.context.params.description; // 可視化ヘッダー更新 const nuclideText = document.getElementById('nuclide-select').options[document.getElementById('nuclide-select').selectedIndex].text; document.getElementById('current-scenario-display').textContent = `${scenario.name}用${nuclideText}`; } updateScenarioDefaults() { const defaults = scenarioDefaults[this.currentScenario]; const scenario = scenarioData[this.currentScenario]; // 核種選択肢の更新 const nuclideSelect = document.getElementById('nuclide-select'); Array.from(nuclideSelect.options).forEach(option => { option.style.display = scenario.nuclides.includes(option.value) ? 'block' : 'none'; }); // デフォルト値の設定 document.getElementById('nuclide-select').value = defaults.nuclide; document.getElementById('activity-slider').value = defaults.activity; document.getElementById('material-select').value = defaults.material; document.getElementById('thickness-slider').value = defaults.thickness; document.getElementById('distance-slider').value = defaults.distance; // スライダー表示更新 updateSliderDisplays(); } updateVisualization() { if (visualizer) { const material = document.getElementById('material-select').value; const thickness = parseFloat(document.getElementById('thickness-slider').value); visualizer.updateShield(material, thickness); visualizer.updateScenarioColors(this.currentScenario); } } bindEvents() { document.querySelectorAll('.scenario-tab').forEach(tab => { tab.addEventListener('click', () => { this.switchScenario(tab.dataset.scenario); }); }); } } // 3D可視化システム(強化版) class Enhanced3DVisualizer { constructor(container) { this.container = container; this.isAnimating = false; this.particleSystem = null; this.init(); this.createObjects(); this.animate(); this.setupEventListeners(); } init() { // シーン作成 scene = new THREE.Scene(); scene.background = new THREE.Color(0xf8fafc); // カメラ設定 camera = new THREE.PerspectiveCamera(75, this.container.clientWidth / this.container.clientHeight, 0.1, 1000); camera.position.set(5, 5, 8); camera.lookAt(0, 0, 0); // レンダラー設定 renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setSize(this.container.clientWidth, this.container.clientHeight); renderer.shadowMap.enabled = true; renderer.shadowMap.type = THREE.PCFSoftShadowMap; this.container.appendChild(renderer.domElement); // ライティング const ambientLight = new THREE.AmbientLight(0xffffff, 0.6); scene.add(ambientLight); const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8); directionalLight.position.set(5, 5, 5); directionalLight.castShadow = true; directionalLight.shadow.mapSize.width = 2048; directionalLight.shadow.mapSize.height = 2048; scene.add(directionalLight); // 座標軸 const axesHelper = new THREE.AxesHelper(3); scene.add(axesHelper); // マウスコントロール this.setupMouseControls(); } setupMouseControls() { let isMouseDown = false; let mouseX = 0, mouseY = 0; let targetRotationX = 0, targetRotationY = 0; let rotationX = 0, rotationY = 0; this.container.addEventListener('mousedown', (event) => { isMouseDown = true; mouseX = event.clientX; mouseY = event.clientY; }); this.container.addEventListener('mousemove', (event) => { if (!isMouseDown) return; const deltaX = event.clientX - mouseX; const deltaY = event.clientY - mouseY; targetRotationY += deltaX * 0.01; targetRotationX += deltaY * 0.01; mouseX = event.clientX; mouseY = event.clientY; }); this.container.addEventListener('mouseup', () => { isMouseDown = false; }); // スムーズな回転 const updateRotation = () => { rotationX += (targetRotationX - rotationX) * 0.05; rotationY += (targetRotationY - rotationY) * 0.05; const radius = 10; camera.position.x = radius * Math.sin(rotationY) * Math.cos(rotationX); camera.position.y = radius * Math.sin(rotationX); camera.position.z = radius * Math.cos(rotationY) * Math.cos(rotationX); camera.lookAt(0, 0, 0); requestAnimationFrame(updateRotation); }; updateRotation(); } createObjects() { // 線源 (赤い球) const sourceGeom = new THREE.SphereGeometry(0.3, 32, 32); const sourceMat = new THREE.MeshLambertMaterial({ color: 0xff4444, emissive: 0x220000 }); sourceObject = new THREE.Mesh(sourceGeom, sourceMat); sourceObject.position.set(-3, 0, 0); sourceObject.castShadow = true; scene.add(sourceObject); // 遮蔽材(可変) this.updateShield('concrete', 1.0); // 検出器 (緑の点) const detectorGeom = new THREE.SphereGeometry(0.2, 16, 16); const detectorMat = new THREE.MeshLambertMaterial({ color: 0x44ff44, emissive: 0x002200 }); detectorObject = new THREE.Mesh(detectorGeom, detectorMat); detectorObject.position.set(3, 0, 0); scene.add(detectorObject); // 距離ライン this.createDistanceLine(); // 床面 const floorGeometry = new THREE.PlaneGeometry(20, 20); const floorMaterial = new THREE.MeshLambertMaterial({ color: 0xf0f0f0, transparent: true, opacity: 0.5 }); const floor = new THREE.Mesh(floorGeometry, floorMaterial); floor.rotation.x = -Math.PI / 2; floor.position.y = -2; floor.receiveShadow = true; scene.add(floor); // 放射線パーティクルシステム this.createParticleSystem(); } updateShield(material, thickness) { // 既存の遮蔽材削除 if (shieldObject) { scene.remove(shieldObject); } if (thickness > 0) { const materialData = physicsDatabase.materials[material]; const shieldGeom = new THREE.BoxGeometry(thickness, 2, 2); const shieldMat = new THREE.MeshLambertMaterial({ color: materialData.color, transparent: true, opacity: 0.7 }); shieldObject = new THREE.Mesh(shieldGeom, shieldMat); shieldObject.position.set(0, 0, 0); shieldObject.castShadow = true; shieldObject.receiveShadow = true; scene.add(shieldObject); } this.createDistanceLine(); } updateDetectorPosition(distance) { if (detectorObject) { detectorObject.position.x = (distance / 100) * 3; // スケール調整 this.createDistanceLine(); } } createDistanceLine() { // 既存のライン削除 const existingLine = scene.getObjectByName('distanceLine'); if (existingLine) scene.remove(existingLine); // 新しいライン作成 if (sourceObject && detectorObject) { const points = [ sourceObject.position.clone(), detectorObject.position.clone() ]; const geometry = new THREE.BufferGeometry().setFromPoints(points); const material = new THREE.LineDashedMaterial({ color: 0x888888, dashSize: 0.2, gapSize: 0.1 }); const line = new THREE.Line(geometry, material); line.computeLineDistances(); line.name = 'distanceLine'; scene.add(line); } } createParticleSystem() { if (!sourceObject) return; const particleCount = 100; const geometry = new THREE.BufferGeometry(); const positions = new Float32Array(particleCount * 3); const velocities = new Float32Array(particleCount * 3); for (let i = 0; i < particleCount; i++) { const i3 = i * 3; // 線源位置からスタート positions[i3] = sourceObject.position.x; positions[i3 + 1] = sourceObject.position.y + (Math.random() - 0.5) * 0.2; positions[i3 + 2] = sourceObject.position.z + (Math.random() - 0.5) * 0.2; // 速度設定 velocities[i3] = 0.05 + Math.random() * 0.03; velocities[i3 + 1] = (Math.random() - 0.5) * 0.01; velocities[i3 + 2] = (Math.random() - 0.5) * 0.01; } geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3)); geometry.setAttribute('velocity', new THREE.BufferAttribute(velocities, 3)); const material = new THREE.PointsMaterial({ color: 0xff6666, size: 0.1, transparent: true, opacity: 0.8 }); this.particleSystem = new THREE.Points(geometry, material); scene.add(this.particleSystem); } toggleAnimation() { this.isAnimating = !this.isAnimating; const btn = document.getElementById('animation-toggle'); if (btn) { btn.textContent = this.isAnimating ? '⏸️' : '▶️'; btn.title = this.isAnimating ? '停止' : '放射線アニメーション'; } } updateScenarioColors(scenario) { const scenarioConfig = scenarioData[scenario]; if (sourceObject) { sourceObject.material.emissive.setHex(0x220000); } if (detectorObject) { detectorObject.material.emissive.setHex(0x002200); } } animate() { const render = () => { requestAnimationFrame(render); // 線源回転 if (sourceObject) { sourceObject.rotation.y += 0.01; } // パーティクルアニメーション if (this.particleSystem && this.isAnimating) { this.updateParticles(); } renderer.render(scene, camera); }; render(); } updateParticles() { if (!this.particleSystem || !sourceObject || !detectorObject) return; const positions = this.particleSystem.geometry.attributes.position.array; const velocities = this.particleSystem.geometry.attributes.velocity.array; for (let i = 0; i < positions.length; i += 3) { // パーティクル移動 positions[i] += velocities[i]; positions[i + 1] += velocities[i + 1]; positions[i + 2] += velocities[i + 2]; // 範囲外になったらリセット if (positions[i] > detectorObject.position.x + 1) { positions[i] = sourceObject.position.x; positions[i + 1] = sourceObject.position.y + (Math.random() - 0.5) * 0.2; positions[i + 2] = sourceObject.position.z + (Math.random() - 0.5) * 0.2; } } this.particleSystem.geometry.attributes.position.needsUpdate = true; } setupEventListeners() { // リサイズ対応 window.addEventListener('resize', () => { camera.aspect = this.container.clientWidth / this.container.clientHeight; camera.updateProjectionMatrix(); renderer.setSize(this.container.clientWidth, this.container.clientHeight); }); } } // 計算エンジン(強化版) class EnhancedShieldingCalculator { constructor() { this.safetyLimit = 2.5; // μSv/h (デフォルト) } setSafetyLimit(limit) { this.safetyLimit = limit; } calculate(nuclide, activity, material, thickness, distance) { const nuclideData = physicsDatabase.nuclides[nuclide]; const materialData = physicsDatabase.materials[material]; // 基本計算 const mu = materialData.muMass * materialData.density; const buildup = this.calculateBuildup(mu, thickness); const geometricFactor = 1 / (4 * Math.PI * Math.pow(distance / 100, 2)); // cm to m const initialDoseRate = (activity / 37) * nuclideData.gammaConstant * geometricFactor; const finalDoseRate = initialDoseRate * Math.exp(-mu * thickness) * buildup; // 追加計算 const hvl = Math.log(2) / mu; const tvl = Math.log(10) / mu; const attenuationFactor = Math.exp(-mu * thickness); // 安全性評価 const safetyStatus = this.evaluateSafety(finalDoseRate); const safetyMargin = finalDoseRate <= this.safetyLimit ? ((this.safetyLimit - finalDoseRate) / this.safetyLimit * 100) : 0; return { initialDoseRate: Math.max(initialDoseRate, 0.001), finalDoseRate: Math.max(finalDoseRate, 0.001), attenuationFactor: attenuationFactor, attenuationPercent: (1 - attenuationFactor) * 100, buildup: buildup, hvl: hvl, tvl: tvl, safetyStatus: safetyStatus, safetyMargin: safetyMargin, requiredThickness: this.calculateRequiredThickness(initialDoseRate, mu, buildup), costEstimate: this.estimateCost(material, thickness) }; } calculateBuildup(mu, thickness) { const mut = mu * thickness; if (mut < 0.1) return 1.0; // Taylor buildup approximation const b = 2.5; // typical value for gamma rays return 1 + (b - 1) * mut * Math.exp(-mut); } evaluateSafety(doseRate) { if (doseRate <= this.safetyLimit) return 'safe'; if (doseRate <= this.safetyLimit * 2) return 'warning'; return 'danger'; } calculateRequiredThickness(initialDoseRate, mu, buildup) { if (initialDoseRate <= this.safetyLimit) return 0; // 反復計算で必要厚さを求める let thickness = 0; let step = 1; for (let i = 0; i < 100; i++) { const testBuildup = this.calculateBuildup(mu, thickness); const testDoseRate = initialDoseRate * Math.exp(-mu * thickness) * testBuildup; if (testDoseRate <= this.safetyLimit) { break; } thickness += step; if (thickness > 200) break; // 安全装置 } return thickness; } estimateCost(material, thickness) { const materialData = physicsDatabase.materials[material]; const volume = thickness * 2 * 2 / 1000; // m³に変換(仮定サイズ) return volume * materialData.cost * 1000; // 相対コスト } } // チャート管理(強化版) class EnhancedChartManager { constructor() { this.chart = null; this.initializeChart(); } initializeChart() { const ctx = document.getElementById('comparison-chart').getContext('2d'); this.chart = new Chart(ctx, { type: 'bar', data: { labels: ['遮蔽前', '遮蔽後', '基準値'], datasets: [{ label: '線量率 (μSv/h)', data: [0, 0, 2.5], backgroundColor: [ 'rgba(239, 68, 68, 0.8)', 'rgba(34, 197, 94, 0.8)', 'rgba(234, 179, 8, 0.8)' ], borderColor: [ 'rgba(239, 68, 68, 1)', 'rgba(34, 197, 94, 1)', 'rgba(234, 179, 8, 1)' ], borderWidth: 2 }] }, options: { responsive: true, maintainAspectRatio: false, scales: { y: { beginAtZero: true, type: 'logarithmic', title: { display: true, text: '線量率 (μSv/h)' } } }, plugins: { legend: { display: false }, title: { display: true, text: '遮蔽効果の比較', font: { size: 14, weight: 'bold' } } } } }); } updateChart(initialDoseRate, finalDoseRate, safetyLimit) { if (this.chart) { this.chart.data.datasets[0].data = [ Math.max(initialDoseRate, 0.001), Math.max(finalDoseRate, 0.001), safetyLimit || 2.5 ]; this.chart.update(); } } }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Hirao-Y/poker_mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server