/
glrbbir
/
ShedulerOS
Обзор
Документация
Войти
/
glrbbir
/
ShedulerOS
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
ui/queue-visualizer.js
256 строк
7 KB
Gleb
project
12 июн 2026, 19:15
12 июн 2026, 19:15
9180c5a
Код
Авторство
О чём код?
class QueueVisualizer { constructor() { this.container = null; this.canvas = null; this.ctx = null; this.currentQueueState = null; this.threadColorMap = {}; this.queueConfig = null; this.padding = 20; this.cpuHeight = 60; this.queueHeight = 50; this.queueSpacing = 15; this.threadSize = 35; this.threadSpacing = 8; this.fontSize = 12; } init(containerElement, threads = [], queueConfig = null) { this.container = containerElement; this.queueConfig = queueConfig; if (!this.canvas) { this.canvas = document.createElement('canvas'); this.canvas.id = 'queueCanvas'; this.canvas.style.border = '1px solid #ddd'; this.canvas.style.borderRadius = '4px'; this.canvas.style.backgroundColor = '#f9fafb'; this.canvas.style.display = 'block'; this.canvas.style.margin = '10px 0'; this.container.appendChild(this.canvas); window.addEventListener('resize', () => { if (this.canvas && this.canvas.style.display !== 'none') { this.draw(); } }); } this.ctx = this.canvas.getContext('2d'); threads.forEach(t => { this.threadColorMap[t.id] = t.color; }); this._resizeCanvas(); } updateState(queueStates, currentTime, threads = []) { if (!queueStates || queueStates.length === 0) { this.currentQueueState = null; this.clear(); return; } const intTime = Math.floor(currentTime); let targetState = null; for (let i = queueStates.length - 1; i >= 0; i--) { if (queueStates[i].time <= intTime) { targetState = queueStates[i]; break; } } if (!targetState) targetState = queueStates[0]; this.currentQueueState = targetState; threads.forEach(t => { this.threadColorMap[t.id] = t.color; }); this.draw(); } clear() { if (!this.ctx) return; this._resizeCanvas(); const dpr = window.devicePixelRatio || 1; const width = this.canvas.width / dpr; const height = this.canvas.height / dpr; this.ctx.fillStyle = '#f9fafb'; this.ctx.fillRect(0, 0, width, height); this.ctx.fillStyle = '#999'; this.ctx.font = '14px Arial'; this.ctx.textAlign = 'center'; this.ctx.fillText('Симуляция не запущена', width / 2, height / 2); } draw() { this._resizeCanvas(); if (!this.ctx || !this.currentQueueState) { this.clear(); return; } const dpr = window.devicePixelRatio || 1; const width = this.canvas.width / dpr; const height = this.canvas.height / dpr; this.ctx.fillStyle = '#f9fafb'; this.ctx.fillRect(0, 0, width, height); let currentY = this.padding; this._drawCPU(currentY); currentY += this.cpuHeight + this.queueSpacing; if (this.currentQueueState.queues && this.currentQueueState.queues.length > 0) { for (const queue of this.currentQueueState.queues) { this._drawQueue(queue, currentY); currentY += this.queueHeight + this.queueSpacing; } } } _drawCPU(y) { const dpr = window.devicePixelRatio || 1; const width = (this.canvas.width / dpr) - 2 * this.padding; const x = this.padding; this.ctx.strokeStyle = '#333'; this.ctx.lineWidth = 2; this.ctx.strokeRect(x, y, width, this.cpuHeight); this.ctx.fillStyle = '#333'; this.ctx.font = 'bold 14px Arial'; this.ctx.textAlign = 'left'; this.ctx.textBaseline = 'top'; this.ctx.fillText('CPU:', x + 10, y + 10); if (this.currentQueueState.cpu) { const { threadId, queue, color } = this.currentQueueState.cpu; const threadX = x + 80; const threadY = y + (this.cpuHeight - this.threadSize) / 2; this.ctx.fillStyle = color || '#999'; this.ctx.fillRect(threadX, threadY, this.threadSize, this.threadSize); this.ctx.strokeStyle = '#333'; this.ctx.lineWidth = 1; this.ctx.strokeRect(threadX, threadY, this.threadSize, this.threadSize); this.ctx.fillStyle = '#fff'; this.ctx.font = 'bold 12px Arial'; this.ctx.textAlign = 'center'; this.ctx.textBaseline = 'middle'; this.ctx.fillText(threadId, threadX + this.threadSize / 2, threadY + this.threadSize / 2); this.ctx.fillStyle = '#666'; this.ctx.font = '11px Arial'; this.ctx.textAlign = 'left'; this.ctx.textBaseline = 'top'; this.ctx.fillText(`Q${queue}`, threadX + this.threadSize + 10, threadY + 5); } else { this.ctx.fillStyle = '#999'; this.ctx.font = '12px Arial'; this.ctx.textAlign = 'left'; this.ctx.textBaseline = 'middle'; this.ctx.fillText('(пусто)', x + 80, y + this.cpuHeight / 2); } } _drawQueue(queue, y) { const dpr = window.devicePixelRatio || 1; const width = (this.canvas.width / dpr) - 2 * this.padding; const x = this.padding; this.ctx.strokeStyle = '#ccc'; this.ctx.lineWidth = 1; this.ctx.strokeRect(x, y, width, this.queueHeight); this.ctx.fillStyle = '#f0f0f0'; this.ctx.fillRect(x, y, width, this.queueHeight); this.ctx.fillStyle = '#333'; this.ctx.font = 'bold 12px Arial'; this.ctx.textAlign = 'left'; this.ctx.textBaseline = 'top'; this.ctx.fillText(queue.label, x + 10, y + 8); if (queue.threads && queue.threads.length > 0) { let threadX = x + 150; const threadY = y + (this.queueHeight - this.threadSize) / 2; for (const threadId of queue.threads) { if (threadX + this.threadSize > width + x - 10) break; const color = this.threadColorMap[threadId] || '#999'; this.ctx.fillStyle = color; this.ctx.fillRect(threadX, threadY, this.threadSize, this.threadSize); this.ctx.strokeStyle = '#333'; this.ctx.lineWidth = 1; this.ctx.strokeRect(threadX, threadY, this.threadSize, this.threadSize); this.ctx.fillStyle = '#fff'; this.ctx.font = 'bold 11px Arial'; this.ctx.textAlign = 'center'; this.ctx.textBaseline = 'middle'; this.ctx.fillText(threadId, threadX + this.threadSize / 2, threadY + this.threadSize / 2); threadX += this.threadSize + this.threadSpacing; } } else { this.ctx.fillStyle = '#999'; this.ctx.font = '11px Arial'; this.ctx.textAlign = 'left'; this.ctx.textBaseline = 'middle'; this.ctx.fillText('(пусто)', x + 150, y + this.queueHeight / 2); } } _resizeCanvas() { if (!this.container) return; const containerWidth = this.container.clientWidth || 800; const numQueues = this.queueConfig?.queues?.length || 3; const calculatedHeight = this.padding + this.cpuHeight + this.queueSpacing + (numQueues * (this.queueHeight + this.queueSpacing)) + this.padding; const dpr = window.devicePixelRatio || 1; const targetWidth = containerWidth * dpr; const targetHeight = calculatedHeight * dpr; if (this.canvas.width !== targetWidth || this.canvas.height !== targetHeight) { this.canvas.style.width = `${containerWidth}px`; this.canvas.style.height = `${calculatedHeight}px`; this.canvas.width = targetWidth; this.canvas.height = targetHeight; this.ctx.setTransform(1, 0, 0, 1, 0, 0); this.ctx.scale(dpr, dpr); } } hide() { if (this.canvas) this.canvas.style.display = 'none'; } show() { if (this.canvas) { this.canvas.style.display = 'block'; this.draw(); } } }