update multi language programing (currently c and python)
parent
869870a598
commit
4939c4edd5
70
README.md
70
README.md
|
|
@ -5,12 +5,14 @@ A web-based learning management system for C programming with interactive exerci
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- View lessons written in Markdown format
|
- View lessons written in Markdown format
|
||||||
- Interactive C code editor with compilation and execution
|
- Interactive code editor with compilation and execution for multiple programming languages
|
||||||
- Real-time feedback on code compilation and execution
|
- Real-time feedback on code compilation and execution
|
||||||
- No database required - content stored as Markdown files
|
- No database required - content stored as Markdown files
|
||||||
- Student token-based progress tracking system
|
- Student token-based progress tracking system
|
||||||
- No authentication required - ready to use out of the box
|
- No authentication required - ready to use out of the box
|
||||||
- Containerized with Podman for easy deployment
|
- Containerized with Podman for easy deployment
|
||||||
|
- Support for multiple programming languages (C, Python, and extensible for others)
|
||||||
|
- Configurable default programming language via environment variables
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
|
|
@ -747,18 +749,58 @@ Monitor the LMS server's resource usage (CPU, memory, disk I/O) during load test
|
||||||
- Database performance (if one is added in the future)
|
- Database performance (if one is added in the future)
|
||||||
- Container resource limits
|
- Container resource limits
|
||||||
|
|
||||||
The included `locustfile.py` simulates the following user behaviors:
|
## Multi-Language Programming Support
|
||||||
- Browsing the home page
|
|
||||||
- Viewing lessons
|
|
||||||
- Compiling C code
|
|
||||||
- Validating student tokens
|
|
||||||
- Logging in with tokens
|
|
||||||
- Tracking student progress
|
|
||||||
|
|
||||||
### Monitoring Performance
|
The system now supports multiple programming languages with a modular compiler architecture. Currently supports C and Python with easy extensibility for additional languages.
|
||||||
|
|
||||||
Monitor the LMS server's resource usage (CPU, memory, disk I/O) during load testing to identify potential bottlenecks. Pay attention to:
|
### Supported Languages
|
||||||
- Response times for API requests
|
|
||||||
- Compilation performance under load
|
- **C**: Compiled using GCC with standard compilation and execution workflow
|
||||||
- Database performance (if one is added in the future)
|
- **Python**: Interpreted using Python 3 with syntax checking and execution
|
||||||
- Container resource limits
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
The default programming language can be configured via environment variables in your `.env` file:
|
||||||
|
|
||||||
|
```
|
||||||
|
# To use C as default language (default setting)
|
||||||
|
DEFAULT_PROGRAMMING_LANGUAGE=c
|
||||||
|
|
||||||
|
# To use Python as default language
|
||||||
|
DEFAULT_PROGRAMMING_LANGUAGE=python
|
||||||
|
```
|
||||||
|
|
||||||
|
### Extending to Additional Languages
|
||||||
|
|
||||||
|
The system is designed to be easily extended with additional programming languages:
|
||||||
|
|
||||||
|
1. Create a new compiler class that inherits from `BaseCompiler` in the `compiler/` directory
|
||||||
|
2. Implement the `compile()` and `run()` methods for your language
|
||||||
|
3. Register the new compiler in the `CompilerFactory` in `compiler/__init__.py`
|
||||||
|
4. Update the UI if needed to support the new language
|
||||||
|
|
||||||
|
Example structure for a new language compiler:
|
||||||
|
```python
|
||||||
|
# compiler/new_language_compiler.py
|
||||||
|
from .base_compiler import BaseCompiler
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
class NewLanguageCompiler(BaseCompiler):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__("NewLanguage", ".nl") # Replace with appropriate extension
|
||||||
|
|
||||||
|
def compile(self, file_path, timeout=10):
|
||||||
|
# Implement compilation logic for your language
|
||||||
|
pass
|
||||||
|
|
||||||
|
def run(self, file_path, timeout=5):
|
||||||
|
# Implement execution logic for your language
|
||||||
|
pass
|
||||||
|
```
|
||||||
|
|
||||||
|
### Language-Specific Features
|
||||||
|
|
||||||
|
- The code editor header now dynamically displays the active programming language
|
||||||
|
- File extensions are automatically adjusted based on the selected language
|
||||||
|
- The system maintains backward compatibility with existing C lessons
|
||||||
|
- All language compilation follows the same security and timeout constraints
|
||||||
|
|
|
||||||
78
app.py
78
app.py
|
|
@ -22,6 +22,9 @@ app = Flask(__name__)
|
||||||
# Configure logging
|
# Configure logging
|
||||||
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
||||||
|
|
||||||
|
# Import compiler module after app initialization to avoid circular imports
|
||||||
|
from compiler import compiler_factory
|
||||||
|
|
||||||
# Load configuration from environment variables with defaults
|
# Load configuration from environment variables with defaults
|
||||||
CONTENT_DIR = os.environ.get('CONTENT_DIR', 'content')
|
CONTENT_DIR = os.environ.get('CONTENT_DIR', 'content')
|
||||||
STATIC_DIR = os.environ.get('STATIC_DIR', 'static')
|
STATIC_DIR = os.environ.get('STATIC_DIR', 'static')
|
||||||
|
|
@ -571,6 +574,10 @@ int main() {
|
||||||
# Get ordered lessons for the sidebar
|
# Get ordered lessons for the sidebar
|
||||||
ordered_lessons = get_ordered_lessons_with_learning_objectives(progress)
|
ordered_lessons = get_ordered_lessons_with_learning_objectives(progress)
|
||||||
|
|
||||||
|
# Get the programming language from environment variable
|
||||||
|
programming_language = os.environ.get('DEFAULT_PROGRAMMING_LANGUAGE', 'c').lower()
|
||||||
|
language_display_name = compiler_factory.get_language_display_name(programming_language)
|
||||||
|
|
||||||
return render_template('lesson.html',
|
return render_template('lesson.html',
|
||||||
lesson_content=lesson_html,
|
lesson_content=lesson_html,
|
||||||
exercise_content=exercise_html,
|
exercise_content=exercise_html,
|
||||||
|
|
@ -587,20 +594,25 @@ int main() {
|
||||||
ordered_lessons=ordered_lessons,
|
ordered_lessons=ordered_lessons,
|
||||||
app_bar_title=APP_BAR_TITLE,
|
app_bar_title=APP_BAR_TITLE,
|
||||||
copyright_text=COPYRIGHT_TEXT,
|
copyright_text=COPYRIGHT_TEXT,
|
||||||
page_title_suffix=PAGE_TITLE_SUFFIX)
|
page_title_suffix=PAGE_TITLE_SUFFIX,
|
||||||
|
language=programming_language,
|
||||||
|
language_display_name=language_display_name)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/compile', methods=['POST'])
|
@app.route('/compile', methods=['POST'])
|
||||||
def compile_code():
|
def compile_code():
|
||||||
"""Compile and run C code submitted by the user"""
|
"""Compile and run code submitted by the user in the selected programming language"""
|
||||||
try:
|
try:
|
||||||
code = None
|
code = None
|
||||||
|
language = None
|
||||||
|
|
||||||
# Try to get code from JSON data
|
# Try to get code and language from JSON data
|
||||||
if request.content_type and 'application/json' in request.content_type:
|
if request.content_type and 'application/json' in request.content_type:
|
||||||
try:
|
try:
|
||||||
json_data = request.get_json(force=True)
|
json_data = request.get_json(force=True)
|
||||||
if json_data and 'code' in json_data:
|
if json_data:
|
||||||
code = json_data['code']
|
code = json_data.get('code', '')
|
||||||
|
language = json_data.get('language', '') # Get language from request
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# Log the error for debugging
|
# Log the error for debugging
|
||||||
print(f"JSON parsing error: {e}")
|
print(f"JSON parsing error: {e}")
|
||||||
|
|
@ -609,6 +621,7 @@ def compile_code():
|
||||||
# If not found in JSON, try form data
|
# If not found in JSON, try form data
|
||||||
if not code:
|
if not code:
|
||||||
code = request.form.get('code', '')
|
code = request.form.get('code', '')
|
||||||
|
language = request.form.get('language', '') # Get language from form
|
||||||
|
|
||||||
if not code:
|
if not code:
|
||||||
return jsonify({
|
return jsonify({
|
||||||
|
|
@ -617,58 +630,11 @@ def compile_code():
|
||||||
'error': 'No code provided'
|
'error': 'No code provided'
|
||||||
})
|
})
|
||||||
|
|
||||||
# Create a temporary file for the C code
|
# Get the appropriate compiler based on the language
|
||||||
with tempfile.NamedTemporaryFile(mode='w', suffix='.c', delete=False) as temp_c:
|
compiler = compiler_factory.get_compiler(language)
|
||||||
temp_c.write(code)
|
|
||||||
temp_c_path = temp_c.name
|
|
||||||
|
|
||||||
# Create a temporary file for the executable
|
# Compile and run the code using the selected compiler
|
||||||
temp_exe_path = temp_c_path.replace('.c', '')
|
result = compiler.compile_and_run(code)
|
||||||
|
|
||||||
# Compile the C code
|
|
||||||
compile_result = subprocess.run(
|
|
||||||
['gcc', temp_c_path, '-o', temp_exe_path],
|
|
||||||
capture_output=True,
|
|
||||||
text=True,
|
|
||||||
timeout=10
|
|
||||||
)
|
|
||||||
|
|
||||||
if compile_result.returncode != 0:
|
|
||||||
# Compilation failed
|
|
||||||
result = {
|
|
||||||
'success': False,
|
|
||||||
'output': compile_result.stdout, # Include any stdout if available
|
|
||||||
'error': compile_result.stderr # Show GCC error messages
|
|
||||||
}
|
|
||||||
else:
|
|
||||||
# Compilation succeeded, run the program
|
|
||||||
try:
|
|
||||||
run_result = subprocess.run(
|
|
||||||
[temp_exe_path],
|
|
||||||
capture_output=True,
|
|
||||||
text=True,
|
|
||||||
timeout=5
|
|
||||||
)
|
|
||||||
|
|
||||||
result = {
|
|
||||||
'success': True,
|
|
||||||
'output': run_result.stdout,
|
|
||||||
'error': run_result.stderr if run_result.stderr else None
|
|
||||||
}
|
|
||||||
except subprocess.TimeoutExpired:
|
|
||||||
result = {
|
|
||||||
'success': False,
|
|
||||||
'output': '',
|
|
||||||
'error': 'Program execution timed out'
|
|
||||||
}
|
|
||||||
|
|
||||||
# Clean up temporary files
|
|
||||||
try:
|
|
||||||
os.remove(temp_c_path)
|
|
||||||
if os.path.exists(temp_exe_path):
|
|
||||||
os.remove(temp_exe_path)
|
|
||||||
except:
|
|
||||||
pass # Ignore cleanup errors
|
|
||||||
|
|
||||||
return jsonify(result)
|
return jsonify(result)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
"""
|
||||||
|
Compiler Factory for managing different language compilers
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
from .c_compiler import CCompiler
|
||||||
|
from .python_compiler import PythonCompiler
|
||||||
|
|
||||||
|
|
||||||
|
class CompilerFactory:
|
||||||
|
"""
|
||||||
|
Factory class to create and manage different language compilers
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.compilers = {
|
||||||
|
'c': CCompiler(),
|
||||||
|
'python': PythonCompiler()
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get default language from environment variable
|
||||||
|
default_language = os.environ.get('DEFAULT_PROGRAMMING_LANGUAGE', 'c').lower()
|
||||||
|
self.default_compiler = self.compilers.get(default_language, self.compilers['c'])
|
||||||
|
|
||||||
|
def get_compiler(self, language=None):
|
||||||
|
"""
|
||||||
|
Get a compiler instance for the specified language
|
||||||
|
:param language: Language identifier ('c', 'python', etc.)
|
||||||
|
:return: Compiler instance
|
||||||
|
"""
|
||||||
|
if language is None:
|
||||||
|
return self.default_compiler
|
||||||
|
|
||||||
|
language = language.lower()
|
||||||
|
if language in self.compilers:
|
||||||
|
return self.compilers[language]
|
||||||
|
else:
|
||||||
|
# Return default compiler if requested language is not available
|
||||||
|
return self.default_compiler
|
||||||
|
|
||||||
|
def get_available_languages(self):
|
||||||
|
"""
|
||||||
|
Get list of available programming languages
|
||||||
|
:return: List of available language identifiers
|
||||||
|
"""
|
||||||
|
return list(self.compilers.keys())
|
||||||
|
|
||||||
|
def get_language_display_name(self, language):
|
||||||
|
"""
|
||||||
|
Get display name for a language
|
||||||
|
:param language: Language identifier
|
||||||
|
:return: Display name for the language
|
||||||
|
"""
|
||||||
|
display_names = {
|
||||||
|
'c': 'C',
|
||||||
|
'python': 'Python'
|
||||||
|
}
|
||||||
|
return display_names.get(language, language.capitalize())
|
||||||
|
|
||||||
|
|
||||||
|
# Global compiler factory instance
|
||||||
|
compiler_factory = CompilerFactory()
|
||||||
|
|
@ -0,0 +1,69 @@
|
||||||
|
"""
|
||||||
|
Base compiler class for the modular compilation system
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import tempfile
|
||||||
|
from abc import ABC, abstractmethod
|
||||||
|
|
||||||
|
|
||||||
|
class BaseCompiler(ABC):
|
||||||
|
"""
|
||||||
|
Abstract base class for all compilers
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, language, file_extension):
|
||||||
|
self.language = language
|
||||||
|
self.file_extension = file_extension
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def compile(self, code, timeout=10):
|
||||||
|
"""
|
||||||
|
Compile the code and return the result
|
||||||
|
:param code: Source code to compile
|
||||||
|
:param timeout: Compilation timeout in seconds
|
||||||
|
:return: Dictionary with success, output, and error fields
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def run(self, file_path, timeout=5):
|
||||||
|
"""
|
||||||
|
Run the compiled code and return the result
|
||||||
|
:param file_path: Path to the compiled file
|
||||||
|
:param timeout: Execution timeout in seconds
|
||||||
|
:return: Dictionary with success, output, and error fields
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def compile_and_run(self, code, compile_timeout=10, run_timeout=5):
|
||||||
|
"""
|
||||||
|
Compile and run the code in one step
|
||||||
|
:param code: Source code to compile and run
|
||||||
|
:param compile_timeout: Compilation timeout in seconds
|
||||||
|
:param run_timeout: Execution timeout in seconds
|
||||||
|
:return: Dictionary with success, output, and error fields
|
||||||
|
"""
|
||||||
|
# Create a temporary file for the source code
|
||||||
|
with tempfile.NamedTemporaryFile(mode='w', suffix=self.file_extension, delete=False) as temp_source:
|
||||||
|
temp_source.write(code)
|
||||||
|
temp_source_path = temp_source.name
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Compile the code
|
||||||
|
compile_result = self.compile(temp_source_path, compile_timeout)
|
||||||
|
|
||||||
|
if not compile_result['success']:
|
||||||
|
return compile_result
|
||||||
|
|
||||||
|
# Run the code
|
||||||
|
run_result = self.run(temp_source_path, run_timeout)
|
||||||
|
return run_result
|
||||||
|
|
||||||
|
finally:
|
||||||
|
# Clean up temporary files
|
||||||
|
try:
|
||||||
|
os.remove(temp_source_path)
|
||||||
|
except:
|
||||||
|
pass # Ignore cleanup errors
|
||||||
|
|
@ -0,0 +1,114 @@
|
||||||
|
"""
|
||||||
|
C Compiler implementation for the modular compilation system
|
||||||
|
"""
|
||||||
|
|
||||||
|
import subprocess
|
||||||
|
import os
|
||||||
|
from .base_compiler import BaseCompiler
|
||||||
|
|
||||||
|
|
||||||
|
class CCompiler(BaseCompiler):
|
||||||
|
"""
|
||||||
|
Compiler class for C programming language
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__("C", ".c")
|
||||||
|
|
||||||
|
def compile(self, file_path, timeout=10):
|
||||||
|
"""
|
||||||
|
Compile C code
|
||||||
|
:param file_path: Path to the C source file
|
||||||
|
:param timeout: Compilation timeout in seconds
|
||||||
|
:return: Dictionary with success, output, and error fields
|
||||||
|
"""
|
||||||
|
# Create a temporary file for the executable
|
||||||
|
temp_exe_path = file_path.replace('.c', '')
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Compile the C code
|
||||||
|
compile_result = subprocess.run(
|
||||||
|
['gcc', file_path, '-o', temp_exe_path],
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
timeout=timeout
|
||||||
|
)
|
||||||
|
|
||||||
|
if compile_result.returncode != 0:
|
||||||
|
# Compilation failed
|
||||||
|
return {
|
||||||
|
'success': False,
|
||||||
|
'output': compile_result.stdout,
|
||||||
|
'error': compile_result.stderr
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
# Compilation succeeded
|
||||||
|
return {
|
||||||
|
'success': True,
|
||||||
|
'output': compile_result.stdout,
|
||||||
|
'error': compile_result.stderr if compile_result.stderr else None,
|
||||||
|
'executable_path': temp_exe_path
|
||||||
|
}
|
||||||
|
except subprocess.TimeoutExpired:
|
||||||
|
return {
|
||||||
|
'success': False,
|
||||||
|
'output': '',
|
||||||
|
'error': 'Compilation timed out'
|
||||||
|
}
|
||||||
|
except Exception as e:
|
||||||
|
return {
|
||||||
|
'success': False,
|
||||||
|
'output': '',
|
||||||
|
'error': f'Compilation error: {str(e)}'
|
||||||
|
}
|
||||||
|
|
||||||
|
def run(self, file_path, timeout=5):
|
||||||
|
"""
|
||||||
|
Run compiled C program
|
||||||
|
:param file_path: Path to the C source file (executable will be derived)
|
||||||
|
:param timeout: Execution timeout in seconds
|
||||||
|
:return: Dictionary with success, output, and error fields
|
||||||
|
"""
|
||||||
|
temp_exe_path = file_path.replace('.c', '')
|
||||||
|
|
||||||
|
if not os.path.exists(temp_exe_path):
|
||||||
|
return {
|
||||||
|
'success': False,
|
||||||
|
'output': '',
|
||||||
|
'error': 'Executable not found'
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Run the compiled program
|
||||||
|
run_result = subprocess.run(
|
||||||
|
[temp_exe_path],
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
timeout=timeout
|
||||||
|
)
|
||||||
|
|
||||||
|
result = {
|
||||||
|
'success': True,
|
||||||
|
'output': run_result.stdout,
|
||||||
|
'error': run_result.stderr if run_result.stderr else None
|
||||||
|
}
|
||||||
|
|
||||||
|
# Clean up the executable
|
||||||
|
try:
|
||||||
|
os.remove(temp_exe_path)
|
||||||
|
except:
|
||||||
|
pass # Ignore cleanup errors
|
||||||
|
|
||||||
|
return result
|
||||||
|
except subprocess.TimeoutExpired:
|
||||||
|
return {
|
||||||
|
'success': False,
|
||||||
|
'output': '',
|
||||||
|
'error': 'Program execution timed out'
|
||||||
|
}
|
||||||
|
except Exception as e:
|
||||||
|
return {
|
||||||
|
'success': False,
|
||||||
|
'output': '',
|
||||||
|
'error': f'Runtime error: {str(e)}'
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,85 @@
|
||||||
|
"""
|
||||||
|
Python Compiler/Interpreter implementation for the modular compilation system
|
||||||
|
"""
|
||||||
|
|
||||||
|
import subprocess
|
||||||
|
import tempfile
|
||||||
|
import os
|
||||||
|
from .base_compiler import BaseCompiler
|
||||||
|
|
||||||
|
|
||||||
|
class PythonCompiler(BaseCompiler):
|
||||||
|
"""
|
||||||
|
Compiler/Interpreter class for Python programming language
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__("Python", ".py")
|
||||||
|
|
||||||
|
def compile(self, file_path, timeout=10):
|
||||||
|
"""
|
||||||
|
Check Python syntax (simulate compilation)
|
||||||
|
:param file_path: Path to the Python source file
|
||||||
|
:param timeout: Compilation timeout in seconds
|
||||||
|
:return: Dictionary with success, output, and error fields
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
# Use Python's compile function to check syntax
|
||||||
|
with open(file_path, 'r', encoding='utf-8') as f:
|
||||||
|
code = f.read()
|
||||||
|
|
||||||
|
# Attempt to compile the code to check for syntax errors
|
||||||
|
compile(code, file_path, 'exec')
|
||||||
|
|
||||||
|
# If we reach this point, syntax is valid
|
||||||
|
return {
|
||||||
|
'success': True,
|
||||||
|
'output': '',
|
||||||
|
'error': None
|
||||||
|
}
|
||||||
|
except SyntaxError as e:
|
||||||
|
return {
|
||||||
|
'success': False,
|
||||||
|
'output': '',
|
||||||
|
'error': f"SyntaxError: {e.msg} at line {e.lineno}"
|
||||||
|
}
|
||||||
|
except Exception as e:
|
||||||
|
return {
|
||||||
|
'success': False,
|
||||||
|
'output': '',
|
||||||
|
'error': f'Syntax check error: {str(e)}'
|
||||||
|
}
|
||||||
|
|
||||||
|
def run(self, file_path, timeout=5):
|
||||||
|
"""
|
||||||
|
Run Python code
|
||||||
|
:param file_path: Path to the Python source file
|
||||||
|
:param timeout: Execution timeout in seconds
|
||||||
|
:return: Dictionary with success, output, and error fields
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
# Run the Python script
|
||||||
|
run_result = subprocess.run(
|
||||||
|
['python3', file_path],
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
timeout=timeout
|
||||||
|
)
|
||||||
|
|
||||||
|
return {
|
||||||
|
'success': True,
|
||||||
|
'output': run_result.stdout,
|
||||||
|
'error': run_result.stderr if run_result.stderr else None
|
||||||
|
}
|
||||||
|
except subprocess.TimeoutExpired:
|
||||||
|
return {
|
||||||
|
'success': False,
|
||||||
|
'output': '',
|
||||||
|
'error': 'Program execution timed out'
|
||||||
|
}
|
||||||
|
except Exception as e:
|
||||||
|
return {
|
||||||
|
'success': False,
|
||||||
|
'output': '',
|
||||||
|
'error': f'Runtime error: {str(e)}'
|
||||||
|
}
|
||||||
|
|
@ -19,6 +19,10 @@ APP_BAR_TITLE=Belajar Pemrograman C
|
||||||
COPYRIGHT_TEXT=Sistem Pembelajaran Pemrograman C © 2025
|
COPYRIGHT_TEXT=Sistem Pembelajaran Pemrograman C © 2025
|
||||||
PAGE_TITLE_SUFFIX=Belajar Pemrograman C
|
PAGE_TITLE_SUFFIX=Belajar Pemrograman C
|
||||||
|
|
||||||
|
# Programming Language Configuration
|
||||||
|
DEFAULT_PROGRAMMING_LANGUAGE=c
|
||||||
|
# To use Python as default language instead, uncomment the line below:
|
||||||
|
# DEFAULT_PROGRAMMING_LANGUAGE=python
|
||||||
|
|
||||||
# Server Configuration
|
# Server Configuration
|
||||||
HOST=0.0.0.0
|
HOST=0.0.0.0
|
||||||
|
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
# Welcome to C Programming Learning System
|
|
||||||
|
|
||||||
This is a comprehensive learning platform designed to help you master the C programming language through interactive lessons and exercises.
|
|
||||||
|
|
||||||
## Learning Objectives
|
|
||||||
|
|
||||||
| Module | Objective | Skills Acquired |
|
|
||||||
|--------|-----------|-----------------|
|
|
||||||
| Introduction to C | Understand basic syntax and structure | Writing first C program |
|
|
||||||
| Variables & Data Types | Learn about different data types | Proper variable declaration |
|
|
||||||
| Control Structures | Master conditional statements and loops | Logic implementation |
|
|
||||||
| Functions | Create and use functions | Code organization |
|
|
||||||
| Arrays & Pointers | Work with complex data structures | Memory management |
|
|
||||||
|
|
||||||
## How to Use This System
|
|
||||||
|
|
||||||
1. **Browse Lessons**: Select from the available lessons on the left
|
|
||||||
2. **Read Content**: Study the lesson materials and examples
|
|
||||||
3. **Practice Coding**: Use the integrated code editor to write and test C code
|
|
||||||
4. **Complete Exercises**: Apply your knowledge to solve programming challenges
|
|
||||||
5. **Get Feedback**: See immediate results of your code execution
|
|
||||||
|
|
||||||
## Getting Started
|
|
||||||
|
|
||||||
Start with the "Introduction to C" lesson to begin your journey in C programming. Each lesson builds upon the previous one, so it's recommended to follow them in order.
|
|
||||||
|
|
||||||
Happy coding!
|
|
||||||
|
|
||||||
---Available_Lessons---
|
|
||||||
|
|
||||||
1. [Introduction to C Programming](lesson/introduction_to_c.md)
|
|
||||||
2. [Variables and Data Types in C](lesson/variables_and_data_types.md)
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
# Python Introduction Lesson
|
||||||
|
|
||||||
|
This lesson introduces the basics of Python programming.
|
||||||
|
|
||||||
|
## Variables and Data Types
|
||||||
|
|
||||||
|
Python is a high-level programming language known for its simplicity and readability.
|
||||||
|
|
||||||
|
```python
|
||||||
|
# This is a comment in Python
|
||||||
|
name = "John" # String variable
|
||||||
|
age = 25 # Integer variable
|
||||||
|
height = 5.9 # Float variable
|
||||||
|
is_student = True # Boolean variable
|
||||||
|
|
||||||
|
print(f"Name: {name}, Age: {age}, Height: {height}, Student: {is_student}")
|
||||||
|
```
|
||||||
|
|
||||||
|
## Basic Operations
|
||||||
|
|
||||||
|
You can perform basic arithmetic operations in Python:
|
||||||
|
|
||||||
|
```python
|
||||||
|
a = 10
|
||||||
|
b = 5
|
||||||
|
|
||||||
|
addition = a + b
|
||||||
|
subtraction = a - b
|
||||||
|
multiplication = a * b
|
||||||
|
division = a / b
|
||||||
|
|
||||||
|
print(f"Addition: {addition}")
|
||||||
|
print(f"Subtraction: {subtraction}")
|
||||||
|
print(f"Multiplication: {multiplication}")
|
||||||
|
print(f"Division: {division}")
|
||||||
|
```
|
||||||
|
|
||||||
|
---EXERCISE---
|
||||||
|
|
||||||
|
Write a Python program that prints "Hello, Python!" to the console.
|
||||||
|
|
||||||
|
---INITIAL_CODE---
|
||||||
|
print("Write your Python code here")
|
||||||
|
---END_INITIAL_CODE---
|
||||||
|
|
||||||
|
---EXPECTED_OUTPUT---
|
||||||
|
Hello, Python!
|
||||||
|
---END_EXPECTED_OUTPUT---
|
||||||
|
|
||||||
|
---SOLUTION_CODE---
|
||||||
|
print("Hello, Python!")
|
||||||
|
---END_SOLUTION_CODE---
|
||||||
|
|
@ -0,0 +1,121 @@
|
||||||
|
---LESSON_INFO---
|
||||||
|
**Learning Objectives:**
|
||||||
|
- Memahami berbagai tipe data dalam bahasa C
|
||||||
|
- Belajar mendeklarasikan dan menginisialisasi variabel
|
||||||
|
- Mengenal batas-batas masing-masing tipe data
|
||||||
|
- Memahami perbedaan antara tipe data signed dan unsigned
|
||||||
|
|
||||||
|
**Prerequisites:**
|
||||||
|
- Dasar-dasar pemrograman
|
||||||
|
- Pemahaman tentang program Halo Dunia
|
||||||
|
|
||||||
|
---END_LESSON_INFO---
|
||||||
|
# Tipe Data dan Variabel dalam C
|
||||||
|
|
||||||
|
C memiliki beberapa jenis variabel, tetapi ada beberapa tipe dasar:
|
||||||
|
|
||||||
|
* Bilangan Bulat - bilangan bulat yang bisa positif atau negatif. Didefinisikan menggunakan `char`, `int`, `short`, `long` atau `long long`.
|
||||||
|
* Bilangan Bulat Tak Bertanda - bilangan bulat yang hanya bisa positif. Didefinisikan menggunakan `unsigned char`, `unsigned int`, `unsigned short`, `unsigned long` atau `unsigned long long`.
|
||||||
|
* Bilangan Pecahan - bilangan real (bilangan dengan pecahan). Didefinisikan menggunakan `float` dan `double`.
|
||||||
|
* Struktur - akan dijelaskan nanti, di bagian Struktur.
|
||||||
|
|
||||||
|
## Tipe Data dalam C
|
||||||
|
|
||||||
|
Jenis-jenis variabel yang berbeda menentukan batas-batasnya. Sebuah `char` bisa dari -128 hingga 127, sedangkan sebuah `long` bisa dari -2,147,483,648 hingga 2,147,483,647 (`long` dan tipe data numerik lainnya mungkin memiliki rentang lain di komputer yang berbeda, misalnya - dari –9,223,372,036,854,775,808 hingga 9,223,372,036,854,775,807 di komputer 64-bit).
|
||||||
|
|
||||||
|
Perhatikan bahwa C _tidak_ memiliki tipe boolean. Biasanya, itu didefinisikan menggunakan notasi berikut:
|
||||||
|
|
||||||
|
```c
|
||||||
|
#define BOOL char
|
||||||
|
#define FALSE 0
|
||||||
|
#define TRUE 1
|
||||||
|
```
|
||||||
|
|
||||||
|
C menggunakan array karakter untuk mendefinisikan string, dan akan dijelaskan di bagian String.
|
||||||
|
|
||||||
|
## Mendefinisikan variabel
|
||||||
|
Untuk angka, kita biasanya akan menggunakan tipe `int`. Di kebanyakan komputer saat ini, itu adalah bilangan 32-bit, yang berarti angkanya bisa dari -2,147,483,648 hingga 2,147,483,647.
|
||||||
|
|
||||||
|
Untuk mendefinisikan variabel `foo` dan `bar`, kita perlu menggunakan sintaks berikut:
|
||||||
|
|
||||||
|
```c
|
||||||
|
int foo;
|
||||||
|
int bar = 1;
|
||||||
|
```
|
||||||
|
|
||||||
|
Variabel `foo` bisa digunakan, tetapi karena kita tidak menginisialisasinya, kita tidak tahu apa yang ada di dalamnya. Variabel `bar` berisi angka 1.
|
||||||
|
|
||||||
|
Sekarang, kita bisa melakukan beberapa operasi matematika. Dengan mengasumsikan `a`, `b`, `c`, `d`, dan `e` adalah variabel, kita bisa menggunakan operator penjumlahan, pengurangan dan perkalian dalam notasi berikut, dan memberikan nilai baru ke `a`:
|
||||||
|
|
||||||
|
```c
|
||||||
|
int a = 0, b = 1, c = 2, d = 3, e = 4;
|
||||||
|
a = b - c + d * e;
|
||||||
|
printf("%d", a); /* akan mencetak 1-2+3*4 = 11 */
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Tabel Tipe Data dalam C
|
||||||
|
|
||||||
|
| Tipe | Ukuran (bit) | Rentang Nilai | Contoh |
|
||||||
|
|------|--------------|---------------|--------|
|
||||||
|
| char | 8 | -128 hingga 127 | `char grade = 'A';` |
|
||||||
|
| int | 32 | -2,147,483,648 hingga 2,147,483,647 | `int age = 25;` |
|
||||||
|
| short | 16 | -32,768 hingga 32,767 | `short year = 2023;` |
|
||||||
|
| long | 64 | -9,223,372,036,854,775,808 hingga 9,223,372,036,854,775,807 | `long population = 1000000L;` |
|
||||||
|
| float | 32 | ~7 digit desimal | `float price = 19.99f;` |
|
||||||
|
| double | 64 | ~15 digit desimal | `double pi = 3.14159;` |
|
||||||
|
| unsigned char | 8 | 0 hingga 255 | `unsigned char count = 100;` |
|
||||||
|
|
||||||
|
---EXERCISE---
|
||||||
|
|
||||||
|
# Latihan: Menjumlahkan Variabel
|
||||||
|
|
||||||
|
Di latihan berikutnya, Anda perlu membuat program yang mencetak jumlah dari angka `a`, `b`, dan `c`.
|
||||||
|
|
||||||
|
**Requirements:**
|
||||||
|
- Hitung jumlah dari variabel a, b, dan c
|
||||||
|
- Simpan hasilnya dalam variabel sum
|
||||||
|
- Pastikan tipe data yang digunakan sesuai
|
||||||
|
|
||||||
|
**Expected Output:**
|
||||||
|
```
|
||||||
|
The sum of a, b, and c is 12.750000.
|
||||||
|
```
|
||||||
|
|
||||||
|
Try writing your solution in the code editor below!
|
||||||
|
|
||||||
|
---EXPECTED_OUTPUT---
|
||||||
|
The sum of a, b, and c is 12.750000.
|
||||||
|
---END_EXPECTED_OUTPUT---
|
||||||
|
|
||||||
|
---INITIAL_CODE---
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
int a = 3;
|
||||||
|
float b = 4.5;
|
||||||
|
double c = 5.25;
|
||||||
|
float sum;
|
||||||
|
|
||||||
|
/* Kode Anda di sini */
|
||||||
|
|
||||||
|
printf("The sum of a, b, and c is %f.", sum);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
---END_INITIAL_CODE---
|
||||||
|
|
||||||
|
---SOLUTION_CODE---
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
int a = 3;
|
||||||
|
float b = 4.5;
|
||||||
|
double c = 5.25;
|
||||||
|
float sum;
|
||||||
|
|
||||||
|
sum = a + b + c;
|
||||||
|
printf("The sum of a, b, and c is %f.", sum);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
---END_SOLUTION_CODE---
|
||||||
|
|
@ -4,6 +4,8 @@ services:
|
||||||
elemes:
|
elemes:
|
||||||
build: .
|
build: .
|
||||||
container_name: elemes
|
container_name: elemes
|
||||||
|
ports:
|
||||||
|
- "5000:5000" # Expose port 5000 to the host
|
||||||
volumes:
|
volumes:
|
||||||
- ../content:/app/content
|
- ../content:/app/content
|
||||||
- ./static:/app/static
|
- ./static:/app/static
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@
|
||||||
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header d-flex justify-content-between align-items-center" style="background-color: #4a76a8; color: white;">
|
<div class="card-header d-flex justify-content-between align-items-center" style="background-color: #4a76a8; color: white;">
|
||||||
<span><i class="fas fa-file-code me-2"></i>C code.c</span>
|
<span><i class="fas fa-file-code me-2"></i>{{ language_display_name }} code.{{ 'py' if language == 'python' else 'c' }}</span>
|
||||||
<div>
|
<div>
|
||||||
<button id="theme-toggle" class="btn btn-sm btn-outline-light me-2">
|
<button id="theme-toggle" class="btn btn-sm btn-outline-light me-2">
|
||||||
<i class="fas fa-moon"></i> Dark
|
<i class="fas fa-moon"></i> Dark
|
||||||
|
|
@ -366,7 +366,7 @@
|
||||||
const code = codeEditor.value;
|
const code = codeEditor.value;
|
||||||
|
|
||||||
if (!code.trim()) {
|
if (!code.trim()) {
|
||||||
alert('Please enter some C code to run.');
|
alert('Please enter some code to run.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -374,13 +374,21 @@
|
||||||
runButton.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Running...';
|
runButton.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Running...';
|
||||||
runButton.disabled = true;
|
runButton.disabled = true;
|
||||||
|
|
||||||
// Create form data to send to the server
|
// Get language from environment/config - default to C for backward compatibility
|
||||||
const formData = new FormData();
|
const language = '{{ language | default("c") }}'; // This would be passed from the backend
|
||||||
formData.append('code', code);
|
|
||||||
|
// Prepare data to send to the server
|
||||||
|
const requestData = {
|
||||||
|
code: code,
|
||||||
|
language: language
|
||||||
|
};
|
||||||
|
|
||||||
fetch('/compile', {
|
fetch('/compile', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: formData
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify(requestData)
|
||||||
})
|
})
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue