diff options
| -rw-r--r-- | static/css/main.css | 361 | ||||
| -rw-r--r-- | static/js/app.js | 285 |
2 files changed, 646 insertions, 0 deletions
diff --git a/static/css/main.css b/static/css/main.css new file mode 100644 index 0000000..655f0c4 --- /dev/null +++ b/static/css/main.css @@ -0,0 +1,361 @@ +* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+body {
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
+ background: #1e1e1e;
+ color: #d4d4d4;
+ height: 100vh;
+ overflow: hidden;
+}
+
+.container {
+ display: flex;
+ flex-direction: column;
+ height: 100vh;
+}
+
+header {
+ background: #252526;
+ padding: 16px 24px;
+ border-bottom: 1px solid #3e3e42;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ flex-shrink: 0;
+}
+
+h1 {
+ font-size: 20px;
+ font-weight: 600;
+ color: #fff;
+ display: flex;
+ align-items: center;
+ gap: 12px;
+}
+
+.logo {
+ width: 32px;
+ height: 32px;
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ border-radius: 8px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-weight: bold;
+ color: white;
+}
+
+.main-content {
+ display: flex;
+ flex: 1;
+ overflow: hidden;
+ min-height: 0;
+}
+
+.editor-panel {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ border-right: 1px solid #3e3e42;
+ min-width: 0;
+}
+
+.toolbar {
+ background: #252526;
+ padding: 12px 16px;
+ border-bottom: 1px solid #3e3e42;
+ display: flex;
+ gap: 12px;
+ align-items: center;
+ flex-shrink: 0;
+ flex-wrap: wrap;
+}
+
+.language-select {
+ padding: 8px 16px;
+ background: #3e3e42;
+ border: 1px solid #505050;
+ border-radius: 6px;
+ color: #d4d4d4;
+ font-size: 14px;
+ cursor: pointer;
+ outline: none;
+}
+
+.language-select:hover {
+ background: #4e4e52;
+}
+
+.analyze-btn {
+ margin-left: auto;
+ padding: 8px 24px;
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ border: none;
+ border-radius: 6px;
+ color: white;
+ font-size: 14px;
+ font-weight: 600;
+ cursor: pointer;
+ transition: transform 0.2s;
+}
+
+.analyze-btn:hover {
+ transform: translateY(-1px);
+}
+
+.analyze-btn:active {
+ transform: translateY(0);
+}
+
+.analyze-btn:disabled {
+ opacity: 0.5;
+ cursor: not-allowed;
+}
+
+#editor {
+ flex: 1;
+ width: 100%;
+ min-height: 0;
+}
+
+.results-panel {
+ width: 400px;
+ min-width: 400px;
+ max-width: 400px;
+ flex-shrink: 0;
+ background: #252526;
+ display: flex;
+ flex-direction: column;
+ overflow-y: auto;
+}
+
+.results-header {
+ padding: 16px 20px;
+ border-bottom: 1px solid #3e3e42;
+}
+
+.results-header h2 {
+ font-size: 16px;
+ font-weight: 600;
+ color: #fff;
+}
+
+.results-content {
+ padding: 20px;
+}
+
+.empty-state {
+ text-align: center;
+ padding: 60px 20px;
+ color: #858585;
+}
+
+.result-section {
+ margin-bottom: 24px;
+}
+
+.result-section h3 {
+ font-size: 14px;
+ font-weight: 600;
+ color: #fff;
+ margin-bottom: 12px;
+}
+
+.complexity-badge {
+ display: inline-block;
+ padding: 6px 12px;
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ border-radius: 6px;
+ font-size: 18px;
+ font-weight: bold;
+ color: white;
+ font-family: 'Courier New', monospace;
+}
+
+.info-list {
+ list-style: none;
+ padding: 0;
+}
+
+.info-list li {
+ padding: 8px 12px;
+ background: #1e1e1e;
+ border-radius: 4px;
+ margin-bottom: 8px;
+ font-size: 13px;
+}
+
+.chart-container {
+ background: #1e1e1e;
+ padding: 16px;
+ border-radius: 8px;
+ height: 300px;
+ position: relative;
+}
+
+.loading {
+ display: none;
+ padding: 20px;
+ text-align: center;
+}
+
+.loading.active {
+ display: block;
+}
+
+.spinner {
+ border: 3px solid #3e3e42;
+ border-top: 3px solid #667eea;
+ border-radius: 50%;
+ width: 40px;
+ height: 40px;
+ animation: spin 1s linear infinite;
+ margin: 0 auto 12px;
+}
+
+@keyframes spin {
+ 0% {
+ transform: rotate(0deg);
+ }
+
+ 100% {
+ transform: rotate(360deg);
+ }
+}
+
+/* Tablet */
+@media (max-width: 1024px) {
+ .results-panel {
+ width: 350px;
+ min-width: 350px;
+ max-width: 350px;
+ }
+
+ header {
+ padding: 12px 16px;
+ }
+
+ h1 {
+ font-size: 18px;
+ }
+}
+
+/* Mobile */
+@media (max-width: 768px) {
+ .main-content {
+ flex-direction: column;
+ }
+
+ .editor-panel {
+ border-right: none;
+ border-bottom: 1px solid #3e3e42;
+ min-height: 50vh;
+ max-height: 50vh;
+ }
+
+ .results-panel {
+ width: 100%;
+ min-width: 100%;
+ max-width: 100%;
+ flex: 1;
+ }
+
+ header {
+ padding: 12px 16px;
+ }
+
+ h1 {
+ font-size: 16px;
+ }
+
+ .logo {
+ width: 28px;
+ height: 28px;
+ font-size: 14px;
+ }
+
+ .toolbar {
+ padding: 8px 12px;
+ gap: 8px;
+ }
+
+ .language-select {
+ padding: 6px 12px;
+ font-size: 13px;
+ }
+
+ .analyze-btn {
+ padding: 6px 16px;
+ font-size: 13px;
+ margin-left: auto;
+ }
+
+ .results-content {
+ padding: 16px;
+ }
+
+ .result-section {
+ margin-bottom: 20px;
+ }
+
+ .complexity-badge {
+ font-size: 16px;
+ padding: 4px 10px;
+ }
+
+ .info-list li {
+ font-size: 12px;
+ padding: 6px 10px;
+ }
+
+ .chart-container {
+ height: 200px;
+ padding: 12px;
+ }
+
+ .empty-state {
+ padding: 40px 16px;
+ font-size: 14px;
+ }
+}
+
+/* Small mobile */
+@media (max-width: 480px) {
+ header {
+ padding: 10px 12px;
+ }
+
+ h1 {
+ font-size: 14px;
+ gap: 8px;
+ }
+
+ .logo {
+ width: 24px;
+ height: 24px;
+ font-size: 12px;
+ }
+
+ .toolbar {
+ flex-direction: column;
+ align-items: stretch;
+ }
+
+ .analyze-btn {
+ margin-left: 0;
+ width: 100%;
+ }
+
+ .editor-panel {
+ min-height: 40vh;
+ max-height: 40vh;
+ }
+
+ .chart-container {
+ height: 180px;
+ }
+}
\ No newline at end of file diff --git a/static/js/app.js b/static/js/app.js new file mode 100644 index 0000000..5cde1b7 --- /dev/null +++ b/static/js/app.js @@ -0,0 +1,285 @@ +let editor;
+let currentLanguage = 'javascript';
+let chart = null;
+let loadingInterval = null;
+let loadingMessageIndex = 0;
+
+const loadingMessages = [
+ "Parsing code structure...",
+ "Analyzing algorithm patterns...",
+ "Detecting time complexity...",
+ "Identifying nested loops...",
+ "Checking for recursion...",
+ "Examining data structures...",
+ "Loading execution environment...",
+ "Compiling test cases...",
+ "Generating test data...",
+ "Running performance benchmarks...",
+ "Measuring execution time...",
+ "Testing with small inputs...",
+ "Testing with large inputs...",
+ "Analyzing growth patterns...",
+ "Calculating complexity metrics...",
+ "Fitting complexity curves...",
+ "Validating results...",
+ "Finalizing analysis..."
+];
+
+const irregularIntervals = [2400, 3800, 4500, 1000, 2900, 4300, 1100, 3400, 950, 2250, 850, 3200, 2050, 1200, 1400, 1800, 900, 1300];
+
+require.config({
+ paths: {
+ vs: 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.44.0/min/vs'
+ }
+});
+
+require(['vs/editor/editor.main'], function () {
+ editor = monaco.editor.create(document.getElementById('editor'), {
+ value: '// Write your algorithm here\nfunction algorithm(arr) {\n // Your code\n return arr;\n}',
+ language: 'javascript',
+ theme: 'vs-dark',
+ fontSize: 14,
+ minimap: { enabled: false },
+ scrollBeyondLastLine: false,
+ automaticLayout: true,
+ lineNumbers: 'on',
+ roundedSelection: false,
+ scrollbar: {
+ vertical: 'visible',
+ horizontal: 'visible'
+ }
+ });
+
+ setupEventListeners();
+});
+
+function setupEventListeners() {
+ // Language selector
+ document.getElementById('languageSelect').addEventListener('change', (e) => {
+ currentLanguage = e.target.value;
+ monaco.editor.setModelLanguage(editor.getModel(), currentLanguage);
+
+ // default code template
+ const templates = {
+ javascript: '// Write your algorithm here\nfunction algorithm(arr) {\n // Your code\n return arr;\n}',
+ python: '# Write your algorithm here\ndef algorithm(arr):\n # Your code\n return arr',
+ go: '// Write your algorithm here\nfunc algorithm(arr []int) []int {\n // Your code\n return arr\n}'
+ };
+ editor.setValue(templates[currentLanguage]);
+ });
+
+ // Analyze button
+ document.getElementById('analyzeBtn').addEventListener('click', analyzeCode);
+}
+
+function startDynamicLoading() {
+ loadingMessageIndex = 0;
+ const loadingText = document.querySelector('#loadingState p');
+
+ function updateMessage() {
+ if (loadingMessageIndex < loadingMessages.length) {
+ loadingText.textContent = loadingMessages[loadingMessageIndex];
+
+ if (loadingMessageIndex < loadingMessages.length - 1) {
+ const nextInterval = irregularIntervals[loadingMessageIndex];
+ loadingMessageIndex++;
+ loadingInterval = setTimeout(updateMessage, nextInterval);
+ } else {
+ loadingMessageIndex++;
+ }
+ }
+ }
+
+ updateMessage();
+}
+
+function stopDynamicLoading() {
+ if (loadingInterval) {
+ clearTimeout(loadingInterval);
+ loadingInterval = null;
+ }
+}
+
+async function analyzeCode() {
+ const code = editor.getValue();
+
+ if (!code.trim()) {
+ alert('Please enter code to analyze');
+ return;
+ }
+
+ showLoading();
+ startDynamicLoading();
+
+ const analyzeBtn = document.getElementById('analyzeBtn');
+ analyzeBtn.disabled = true;
+
+ try {
+ const response = await fetch('/api/analyze', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({
+ code: code,
+ language: currentLanguage
+ })
+ });
+
+ const result = await response.json();
+
+ if (!response.ok) {
+ throw new Error(result.error || 'Analysis failed');
+ }
+
+ displayResults(result);
+ } catch (error) {
+ displayError(error.message);
+ } finally {
+ stopDynamicLoading();
+ analyzeBtn.disabled = false;
+ }
+}
+
+function showLoading() {
+ document.getElementById('resultsContent').style.display = 'none';
+ document.getElementById('loadingState').classList.add('active');
+}
+
+function displayResults(result) {
+ stopDynamicLoading();
+ document.getElementById('loadingState').classList.remove('active');
+ document.getElementById('resultsContent').style.display = 'block';
+
+ const resultsHTML = `
+ <div class="result-section">
+ <h3>Detected Complexity</h3>
+ <div class="complexity-badge">${result.complexity}</div>
+ <p style="margin-top: 8px; font-size: 12px; color: #858585;">
+ Confidence: ${result.confidence.toFixed(1)}%
+ </p>
+ </div>
+
+ <div class="result-section">
+ <h3>Static Analysis</h3>
+ <ul class="info-list">
+ ${result.staticAnalysis.map(item => `<li>${item}</li>`).join('')}
+ </ul>
+ </div>
+
+ <div class="result-section">
+ <h3>Performance Graph</h3>
+ <div class="chart-container">
+ <canvas id="performanceChart"></canvas>
+ </div>
+ </div>
+
+ <div class="result-section">
+ <h3>Execution Timings</h3>
+ <ul class="info-list">
+ ${result.performanceData.map(t =>
+ `<li>n = ${t.size}: ${t.time.toFixed(3)}ms</li>`
+ ).join('')}
+ </ul>
+ </div>
+ `;
+
+ document.getElementById('resultsContent').innerHTML = resultsHTML;
+
+ renderChart(result.performanceData, result.complexity);
+}
+
+function renderChart(data, complexity) {
+ if (typeof Chart === 'undefined') {
+ console.error('Chart.js is not available');
+ return;
+ }
+
+ const ctx = document.getElementById('performanceChart');
+
+ // Destroy previous chart if exists
+ if (chart) {
+ chart.destroy();
+ }
+
+ chart = new Chart(ctx, {
+ type: 'line',
+ data: {
+ labels: data.map(d => d.size),
+ datasets: [{
+ label: `Execution Time (${complexity})`,
+ data: data.map(d => d.time),
+ borderColor: '#667eea',
+ backgroundColor: 'rgba(102, 126, 234, 0.1)',
+ borderWidth: 2,
+ pointRadius: 4,
+ pointBackgroundColor: '#667eea',
+ tension: 0.4
+ }]
+ },
+ options: {
+ responsive: true,
+ maintainAspectRatio: false,
+ plugins: {
+ legend: {
+ labels: { color: '#d4d4d4' }
+ },
+ tooltip: {
+ backgroundColor: '#252526',
+ titleColor: '#fff',
+ bodyColor: '#d4d4d4',
+ borderColor: '#3e3e42',
+ borderWidth: 1
+ }
+ },
+ scales: {
+ x: {
+ title: {
+ display: true,
+ text: 'Input Size (n)',
+ color: '#d4d4d4'
+ },
+ ticks: { color: '#858585' },
+ grid: { color: '#3e3e42' }
+ },
+ y: {
+ title: {
+ display: true,
+ text: 'Time (ms)',
+ color: '#d4d4d4'
+ },
+ ticks: { color: '#858585' },
+ grid: { color: '#3e3e42' }
+ }
+ }
+ }
+ });
+}
+
+function displayError(message) {
+ stopDynamicLoading();
+ document.getElementById('loadingState').classList.remove('active');
+ document.getElementById('resultsContent').style.display = 'block';
+ document.getElementById('resultsContent').innerHTML = `
+ <div class="result-section">
+ <h3 style="color: #f48771;">Error</h3>
+ <div style="background: #1e1e1e; padding: 12px; border-radius: 4px; color: #f48771;">
+ ${message}
+ </div>
+ </div>
+ `;
+}
+
+// Initialize app when DOM is ready
+if (document.readyState === 'loading') {
+ document.addEventListener('DOMContentLoaded', initApp);
+} else {
+ initApp();
+}
+
+function initApp() {
+ if (typeof Chart === 'undefined') {
+ console.error('Chart.js failed to load');
+ alert('Failed to load required libraries. Please refresh the page.');
+ }
+}
\ No newline at end of file |
