add code check uaing static analys with ---KEY_TEXT--- in content

master
a2nr 2026-01-18 06:44:46 +07:00
parent f5b33c458d
commit 767678bb51
10 changed files with 1022 additions and 189 deletions

View File

@ -804,3 +804,54 @@ class NewLanguageCompiler(BaseCompiler):
- File extensions are automatically adjusted based on the selected language - File extensions are automatically adjusted based on the selected language
- The system maintains backward compatibility with existing C lessons - The system maintains backward compatibility with existing C lessons
- All language compilation follows the same security and timeout constraints - All language compilation follows the same security and timeout constraints
## Static Code Analysis Feature
The system includes a static code analysis feature that validates student code against required keywords before compilation. This prevents students from hardcoding outputs without using proper algorithms or variables.
### How It Works
1. Teachers define required keywords in lesson files using the `---KEY_TEXT---` and `---END_KEY_TEXT---` markers
2. When students submit code, the system checks if their code contains all required keywords
3. Students only receive success notifications and lesson completion credit if both:
- Their output matches the expected output (if specified)
- Their code contains all required keywords from the KEY_TEXT section
### Adding Static Analysis to Lessons
To add static analysis to a lesson, include the `---KEY_TEXT---` section in your lesson file:
```markdown
---KEY_TEXT---
int counter
counter = 5
printf
---END_KEY_TEXT---
```
This example would require students to use an integer variable named `counter`, initialize it to 5, and use the `printf` function in their code.
### Advanced Pattern Matching
The system supports both literal keyword matching and regex patterns:
- For literal keywords, just list them (one per line)
- For regex patterns, enclose them in forward slashes: `/int\s+\w+\s*=\s*\d+/`
Example with regex:
```markdown
---KEY_TEXT---
int counter
/counter\s*=\s*\d+/
printf
---END_KEY_TEXT---
```
This would require an integer variable named counter, an assignment to a numeric value, and the printf function.
### Behavior
- If static analysis fails, the success message is hidden and progress is not tracked
- No explicit error messages are shown to students to maintain a clean user experience
- The code still gets compiled and executed normally, but success criteria are not met
- Both output correctness and keyword presence are required for lesson completion

34
app.py
View File

@ -394,6 +394,7 @@ def render_markdown_content(file_path):
initial_code = "" initial_code = ""
solution_code = "" solution_code = ""
expected_output = "" expected_output = ""
key_text = ""
# Look for expected output separator - format: [content] ---EXPECTED_OUTPUT--- [output] ---END_EXPECTED_OUTPUT--- [content] # Look for expected output separator - format: [content] ---EXPECTED_OUTPUT--- [output] ---END_EXPECTED_OUTPUT--- [content]
if '---EXPECTED_OUTPUT---' in lesson_content and '---END_EXPECTED_OUTPUT---' in lesson_content: if '---EXPECTED_OUTPUT---' in lesson_content and '---END_EXPECTED_OUTPUT---' in lesson_content:
@ -407,6 +408,18 @@ def render_markdown_content(file_path):
# Remove the expected output section from the lesson content # Remove the expected output section from the lesson content
lesson_content = lesson_content[:start_idx] + lesson_content[end_idx + len('---END_EXPECTED_OUTPUT---'):] lesson_content = lesson_content[:start_idx] + lesson_content[end_idx + len('---END_EXPECTED_OUTPUT---'):]
# Look for key text separator - format: [content] ---KEY_TEXT--- [keywords] ---END_KEY_TEXT--- [content]
if '---KEY_TEXT---' in lesson_content and '---END_KEY_TEXT---' in lesson_content:
start_idx = lesson_content.find('---KEY_TEXT---')
end_idx = lesson_content.find('---END_KEY_TEXT---')
if start_idx != -1 and end_idx != -1 and end_idx > start_idx:
# Extract the key text between the separators
key_start = start_idx + len('---KEY_TEXT---')
key_text = lesson_content[key_start:end_idx].strip()
# Remove the key text section from the lesson content
lesson_content = lesson_content[:start_idx] + lesson_content[end_idx + len('---END_KEY_TEXT---'):]
# Look for lesson info separator - format: ---LESSON_INFO--- [info] ---END_LESSON_INFO--- [content] # Look for lesson info separator - format: ---LESSON_INFO--- [info] ---END_LESSON_INFO--- [content]
if '---LESSON_INFO---' in lesson_content and '---END_LESSON_INFO---' in lesson_content: if '---LESSON_INFO---' in lesson_content and '---END_LESSON_INFO---' in lesson_content:
start_idx = lesson_content.find('---LESSON_INFO---') + len('---LESSON_INFO---') start_idx = lesson_content.find('---LESSON_INFO---') + len('---LESSON_INFO---')
@ -458,7 +471,7 @@ def render_markdown_content(file_path):
exercise_html = markdown.markdown(exercise_content, extensions=['fenced_code', 'codehilite', 'tables']) if exercise_content else "" exercise_html = markdown.markdown(exercise_content, extensions=['fenced_code', 'codehilite', 'tables']) if exercise_content else ""
lesson_info_html = markdown.markdown(lesson_info, extensions=['fenced_code', 'codehilite', 'tables']) if lesson_info else "" lesson_info_html = markdown.markdown(lesson_info, extensions=['fenced_code', 'codehilite', 'tables']) if lesson_info else ""
return lesson_html, exercise_html, expected_output, lesson_info_html, initial_code, solution_code return lesson_html, exercise_html, expected_output, lesson_info_html, initial_code, solution_code, key_text
@app.route('/') @app.route('/')
def index(): def index():
@ -524,7 +537,7 @@ def lesson(filename):
if not os.path.exists(file_path): if not os.path.exists(file_path):
return "Lesson not found", 404 return "Lesson not found", 404
lesson_html, exercise_html, expected_output, lesson_info, initial_code, solution_code = render_markdown_content(file_path) lesson_html, exercise_html, expected_output, lesson_info, initial_code, solution_code, key_text = render_markdown_content(file_path)
# If no initial code is provided, use a default template # If no initial code is provided, use a default template
if not initial_code: if not initial_code:
@ -585,6 +598,7 @@ int main() {
lesson_info=lesson_info, lesson_info=lesson_info,
initial_code=initial_code, initial_code=initial_code,
solution_code=solution_code, solution_code=solution_code,
key_text=key_text,
lesson_title=filename.replace('.md', '').replace('_', ' ').title(), lesson_title=filename.replace('.md', '').replace('_', ' ').title(),
token=token, token=token,
progress=progress, progress=progress,
@ -599,6 +613,22 @@ int main() {
language_display_name=language_display_name) language_display_name=language_display_name)
@app.route('/get-key-text/<filename>')
def get_key_text(filename):
"""Get the key text for a specific lesson"""
file_path = os.path.join(CONTENT_DIR, filename)
if not os.path.exists(file_path):
return jsonify({'success': False, 'error': 'Lesson not found'}), 404
# Extract key text from the lesson file
_, _, _, _, _, _, key_text = render_markdown_content(file_path)
return jsonify({
'success': True,
'key_text': key_text
})
@app.route('/compile', methods=['POST']) @app.route('/compile', methods=['POST'])
def compile_code(): def compile_code():
"""Compile and run code submitted by the user in the selected programming language""" """Compile and run code submitted by the user in the selected programming language"""

View File

@ -0,0 +1,326 @@
---LESSON_INFO---
**Learning Objectives:**
- Memahami berbagai tipe data dalam bahasa C
- Mengenal tipe data karakter, angka bulat, dan angka desimal
- Belajar menggunakan operator sizeof() untuk mengetahui ukuran tipe data
- Memahami penggunaan tipe data dalam konteks nyata
- Mengenal tipe data extended (lebih lanjut)
**Prerequisites:**
- Dasar-dasar pemrograman
- Pemahaman tentang program Halo Dunia
- Pemahaman tentang variabel
---END_LESSON_INFO---
# Tipe Data dalam C
**Tipe data dalam bahasa C** menentukan jenis nilai yang bisa disimpan dalam variabel, serta ukuran dan rentang nilai yang bisa ditampung. Setiap variabel dalam C harus memiliki tipe data yang dideklarasikan.
## Mengapa Tipe Data Penting?
**Tipe data** penting karena:
- Menentukan **jumlah memori** yang dialokasikan untuk variabel
- Menentukan **jenis nilai** yang bisa disimpan (angka, karakter, dll.)
- Menentukan **operasi** yang bisa dilakukan pada variabel tersebut
## Tipe Data Karakter
**Tipe data `char`** digunakan untuk menyimpan **satu karakter**. Karakter harus ditempatkan di dalam tanda petik tunggal `' '`.
```c
char myGrade = 'A';
char letter = 'x';
char symbol = '@';
```
**Format specifier** untuk `char` adalah `%c`:
```c
char myGrade = 'A';
printf("My grade is: %c\n", myGrade); // Output: My grade is: A
```
## Tipe Data Angka Bulat
**Tipe data `int`** digunakan untuk menyimpan **bilangan bulat** (angka tanpa desimal).
```c
int myNum = 5; // Bilangan positif
int myNegativeNum = -5; // Bilangan negatif
int zero = 0; // Nol
```
**Format specifier** untuk `int` adalah `%d` atau `%i`:
```c
int myNum = 5;
printf("My number is: %d\n", myNum); // Output: My number is: 5
```
### Tipe Data Integer Lainnya
C juga menyediakan tipe data integer lainnya:
- `short` - versi pendek dari int (biasanya 2 byte)
- `long` - versi panjang dari int (biasanya 8 byte)
- `unsigned int` - versi int tanpa tanda (hanya nilai positif dan nol)
## Tipe Data Desimal
**Tipe data `float`** digunakan untuk menyimpan **bilangan desimal** dengan presisi tunggal.
```c
float myFloat = 9.99;
float scientific = 3e5; // 300000
float negative = -3.99;
```
**Format specifier** untuk `float` adalah `%f`:
```c
float myFloat = 9.99;
printf("My float is: %f\n", myFloat); // Output: My float is: 9.990000
```
**Tipe data `double`** digunakan untuk menyimpan **bilangan desimal** dengan presisi ganda (lebih akurat dari float).
```c
double myDouble = 19.99;
double precise = 3.141592653589793;
```
**Format specifier** untuk `double` adalah `%lf`:
```c
double myDouble = 19.99;
printf("My double is: %lf\n", myDouble); // Output: My double is: 19.990000
```
## Mengetahui Ukuran Tipe Data
Anda bisa menggunakan **operator `sizeof()`** untuk mengetahui ukuran tipe data dalam byte:
```c
#include <stdio.h>
int main() {
printf("Size of char: %zu byte(s)\n", sizeof(char));
printf("Size of int: %zu byte(s)\n", sizeof(int));
printf("Size of float: %zu byte(s)\n", sizeof(float));
printf("Size of double: %zu byte(s)\n", sizeof(double));
return 0;
}
```
**Output (dapat bervariasi tergantung sistem):**
```
Size of char: 1 byte(s)
Size of int: 4 byte(s)
Size of float: 4 byte(s)
Size of double: 8 byte(s)
```
## Tipe Data Extended
C juga menyediakan tipe data extended untuk kebutuhan spesifik:
### Tipe Data Unsigned
- `unsigned char` - karakter tanpa tanda (0 hingga 255)
- `unsigned int` - integer tanpa tanda (0 hingga 4,294,967,295)
- `unsigned short` - short integer tanpa tanda
- `unsigned long` - long integer tanpa tanda
### Tipe Data Signed
- `signed char` - karakter dengan tanda (-128 hingga 127)
- `signed int` - integer dengan tanda (sama seperti int biasa)
## Contoh Nyata Penggunaan Tipe Data
Berikut adalah contoh penggunaan berbagai tipe data dalam situasi nyata:
```c
#include <stdio.h>
int main() {
// Tipe data karakter
char initial = 'J';
// Tipe data angka bulat
int age = 25;
unsigned int population = 1000000;
// Tipe data desimal
float temperature = 36.6;
double preciseValue = 3.141592653589793238;
// Menampilkan informasi
printf("Initial: %c\n", initial);
printf("Age: %d years old\n", age);
printf("Population: %u people\n", population);
printf("Temperature: %.1f°C\n", temperature);
printf("Pi: %.10lf\n", preciseValue);
// Menampilkan ukuran tipe data
printf("\nSize of age variable: %zu bytes\n", sizeof(age));
printf("Size of temperature variable: %zu bytes\n", sizeof(temperature));
return 0;
}
```
**Output:**
```
Initial: J
Age: 25 years old
Population: 1000000 people
Temperature: 36.6°C
Pi: 3.1415926535
Size of age variable: 4 bytes
Size of temperature variable: 4 bytes
```
## Konstanta dalam C
**Konstanta** dalam bahasa C adalah nilai tetap yang tidak dapat diubah selama eksekusi program. Konstanta juga dikenal sebagai **literal** karena nilainya langsung ditulis dalam kode program.
### Jenis-Jenis Konstanta
Ada beberapa jenis konstanta dalam bahasa C:
#### 1. Konstanta Integer
Nilai bilangan bulat yang tidak memiliki bagian desimal:
```c
const int MAX_STUDENTS = 100;
int count = 50;
```
#### 2. Konstanta Floating-Point
Nilai bilangan desimal:
```c
const double PI = 3.14159;
float tax_rate = 0.08;
```
#### 3. Konstanta Karakter
Satu karakter yang diapit oleh tanda petik tunggal:
```c
const char NEWLINE = '\n';
char grade = 'A';
```
#### 4. Konstanta String
Rangkaian karakter yang diapit oleh tanda petik ganda:
```c
const char *GREETING = "Hello, World!";
char message[] = "Welcome to C programming";
```
### Keyword `const`
Anda bisa membuat variabel menjadi konstan dengan menggunakan **keyword `const`**. Setelah dideklarasikan sebagai konstan, nilai variabel tersebut tidak bisa diubah:
```c
const int AGE = 25;
// AGE = 30; // Ini akan menyebabkan error karena AGE adalah konstan
```
### Preprocessor `#define`
Alternatif lain untuk membuat konstanta adalah dengan menggunakan **preprocessor directive `#define`**:
```c
#define PI 3.14159
#define MAX_SIZE 100
#define NAME "John Doe"
int main() {
double area = PI * 5 * 5; // Menghitung luas lingkaran dengan jari-jari 5
printf("Area of circle: %.2f\n", area);
return 0;
}
```
**Tips:**
- Gunakan tipe data yang **tepat** untuk kebutuhan Anda
- Perhatikan **rentang nilai** yang bisa ditampung oleh masing-masing tipe data
- Gunakan `unsigned` jika Anda yakin nilai tidak akan negatif
- Gunakan `double` jika Anda membutuhkan presisi tinggi
**Referensi:**
- [https://www.w3schools.com/c/c_data_types.php](https://www.w3schools.com/c/c_data_types.php)
- [https://www.w3schools.com/c/c_data_types_characters.php](https://www.w3schools.com/c/c_data_types_characters.php)
- [https://www.w3schools.com/c/c_data_types_numbers.php](https://www.w3schools.com/c/data_types_numbers.php)
- [https://www.w3schools.com/c/c_data_types_dec.php](https://www.w3schools.com/c/c_data_types_dec.php)
- [https://www.w3schools.com/c/c_data_types_sizeof.php](https://www.w3schools.com/c/c_data_types_sizeof.php)
- [https://www.w3schools.com/c/c_data_types_reallife.php](https://www.w3schools.com/c/c_data_types_reallife.php)
- [https://www.w3schools.com/c/c_data_types_extended.php](https://www.w3schools.com/c/c_data_types_extended.php)
- [Hello, World!](lesson/hello_world.md)
- [Variables in C](lesson/variables.md)
---EXERCISE---
# Latihan: Menggunakan Tipe Data
Dalam latihan ini, Anda akan membuat program sederhana yang menggunakan berbagai tipe data untuk menyimpan informasi buku dan menampilkannya.
**Requirements:**
- Buat variabel `title` untuk menyimpan judul buku (gunakan tipe data char array)
- Buat variabel `pages` untuk menyimpan jumlah halaman (gunakan tipe data int)
- Buat variabel `price` untuk menyimpan harga buku (gunakan tipe data float)
- Buat variabel `rating` untuk menyimpan rating buku (gunakan tipe data double)
- Tampilkan informasi buku menggunakan printf dengan format specifier yang sesuai
- Tampilkan ukuran dari variabel pages menggunakan sizeof()
**Expected Output:**
```
Book Title: The Art of Programming
Pages: 450
Price: $49.99
Rating: 4.75
Size of pages variable: 4 byte(s)
```
Try writing your solution in the code editor below!
---EXPECTED_OUTPUT---
Book Title: The Art of Programming
Pages: 450
Price: $49.99
Rating: 4.75
Size of pages variable: 4 byte(s)
---END_EXPECTED_OUTPUT---
---INITIAL_CODE---
#include <stdio.h>
int main() {
// Deklarasi variabel di sini
// Tampilkan informasi buku di sini
printf("Book Title: \n");
printf("Pages: \n");
printf("Price: $\n");
printf("Rating: \n");
printf("Size of pages variable: byte(s)\n");
return 0;
}
---END_INITIAL_CODE---
---SOLUTION_CODE---
#include <stdio.h>
int main() {
// Deklarasi variabel
char title[] = "The Art of Programming";
int pages = 450;
float price = 49.99;
double rating = 4.75;
// Tampilkan informasi buku
printf("Book Title: %s\n", title);
printf("Pages: %d\n", pages);
printf("Price: $%.2f\n", price);
printf("Rating: %.2lf\n", rating);
printf("Size of pages variable: %zu byte(s)\n", sizeof(pages));
return 0;
}
---END_SOLUTION_CODE---

View File

@ -0,0 +1,231 @@
---LESSON_INFO---
**Learning Objectives:**
- Memahami struktur dasar program C
- Mengenal fungsi main() sebagai titik awal eksekusi program
- Belajar menggunakan perintah printf untuk menampilkan output
- Memahami konsep header file dan direktif include
**Prerequisites:**
- Tidak ada persyaratan khusus
- Cocok untuk pemula dalam pemrograman C
---END_LESSON_INFO---
# Program Pertama C: Halo, Dunia!
**Bahasa pemrograman C** adalah bahasa pemrograman umum yang berhubungan erat dengan cara mesin bekerja. **Memahami cara kerja memori komputer** adalah aspek penting dari bahasa pemrograman C. Meskipun C bisa dianggap sebagai "sulit dipelajari", sebenarnya C adalah bahasa yang sangat sederhana, dengan kemampuan yang sangat kuat.
C adalah **bahasa yang sangat umum**, dan merupakan bahasa dari banyak aplikasi seperti Windows, interpreter Python, Git, dan banyak lagi.
**C adalah bahasa yang dikompilasi** - yang berarti bahwa untuk menjalankannya, **kompiler** (misalnya, GCC atau Visual Studio) harus mengambil kode yang kita tulis, memprosesnya, lalu membuat file yang dapat dieksekusi. File ini kemudian dapat dijalankan, dan akan melakukan apa yang kita maksudkan agar program tersebut lakukan.
## Program pertama kita
Setiap program C menggunakan **pustaka**, yang memberikan kemampuan untuk mengeksekusi fungsi-fungsi yang diperlukan. Sebagai contoh, fungsi paling dasar yang disebut `printf`, yang mencetak ke layar, didefinisikan dalam **file header `stdio.h`**.
Untuk menambahkan kemampuan menjalankan perintah `printf` ke program kita, kita harus menambahkan **direktif include** berikut ke baris pertama kode kita:
```c
#include <stdio.h>
```
Bagian kedua dari kode adalah kode aktual yang akan kita tulis. **Kode pertama yang akan dijalankan selalu berada di fungsi `main`**.
```c
int main() {
... kode kita ada di sini
}
```
**Kata kunci `int`** menunjukkan bahwa fungsi `main` akan mengembalikan bilangan bulat - angka sederhana. Angka yang akan dikembalikan oleh fungsi menunjukkan apakah program yang kita tulis berjalan dengan benar. Jika kita ingin mengatakan bahwa kode kita berjalan dengan sukses, kita akan mengembalikan angka 0. Angka lebih besar dari 0 akan berarti bahwa program yang kita tulis gagal. Untuk tutorial ini, kita akan mengembalikan 0 untuk menunjukkan bahwa program kita berhasil:
```c
return 0;
```
**Perhatikan bahwa setiap pernyataan dalam C harus diakhiri dengan titik koma**, sehingga kompiler tahu bahwa pernyataan baru telah dimulai.
Terakhir tetapi tidak kalah pentingnya, kita perlu memanggil fungsi `printf` untuk mencetak kalimat kita.
## Sintaks Dasar dalam C
**Sintaks dalam bahasa C** merujuk pada aturan dan struktur yang menentukan bagaimana program ditulis. Berikut adalah beberapa konsep penting dalam sintaks C:
### Struktur Program C
**Program C memiliki struktur tertentu** yang harus diikuti:
- **Header files** (menggunakan `#include`)
- **Fungsi `main()` sebagai titik awal eksekusi**
- **Deklarasi variabel** (jika ada)
- **Pernyataan-pernyataan program**
- **Pengembalian nilai dari fungsi `main()`**
### Case Sensitivity
**Bahasa C bersifat *case-sensitive***, artinya huruf besar dan kecil dibedakan. Misalnya, `variable`, `Variable`, dan `VARIABLE` adalah tiga nama yang berbeda.
### Titik Koma (;)
**Setiap pernyataan dalam C harus diakhiri dengan titik koma**. Ini memberi tahu kompiler bahwa pernyataan tersebut telah selesai.
### Blok Kode
**Blok kode dalam C didefinisikan dengan kurung kurawal `{` dan `}`**. Semua kode yang berada di antara kurung kurawal ini dianggap sebagai satu unit.
## Pernyataan dalam C
**Pernyataan dalam bahasa C adalah instruksi** yang memberi tahu komputer untuk melakukan tindakan tertentu. Ada beberapa jenis pernyataan dalam C:
### Pernyataan Ekspresi
Pernyataan yang terdiri dari ekspresi dan diakhiri dengan titik koma:
```c
x = 5;
y = x + 3;
hasil = a * b + c;
```
### Pernyataan Kompoun (Blok)
Sejumlah pernyataan yang dikelompokkan bersama dalam kurung kurawal:
```c
{
int a = 10;
int b = 20;
int sum = a + b;
}
```
## Output dalam C
**Output dalam bahasa C biasanya dilakukan menggunakan fungsi `printf()`** dari pustaka `stdio.h`. Fungsi ini memungkinkan kita untuk menampilkan teks dan nilai variabel ke layar.
### Format Specifier
**Fungsi `printf()` menggunakan format specifier** untuk menentukan tipe data yang akan dicetak:
- **`%d` atau `%i` untuk bilangan bulat (integer)**
- **`%f` untuk bilangan desimal (float/double)**
- **`%c` untuk karakter**
- **`%s` untuk string**
Contoh:
```c
int usia = 25;
float tinggi = 175.5;
char inisial = 'J';
printf("Usia saya %d tahun\n", usia);
printf("Tinggi saya %.1f cm\n", tinggi);
printf("Inisial saya %c\n", inisial);
```
## Baris Baru dalam C
**Untuk membuat baris baru dalam output C, kita menggunakan karakter escape `\n`**. Karakter ini memberi tahu kompiler untuk pindah ke baris berikutnya.
Contoh:
```c
printf("Baris pertama\nBaris kedua\nBaris ketiga");
```
Output:
```
Baris pertama
Baris kedua
Baris ketiga
```
**Selain `\n`, ada beberapa karakter escape lain dalam C**:
- **`\t` untuk tab**
- **`\\` untuk backslash**
- **`\"` untuk tanda kutip ganda**
## Komentar dalam C
**Komentar adalah teks yang ditulis dalam kode program tetapi tidak akan dieksekusi**. Komentar digunakan untuk menjelaskan kode dan membuatnya lebih mudah dipahami.
### Komentar Satu Baris
**Komentar satu baris dimulai dengan `//`**:
```c
// Ini adalah komentar satu baris
int x = 5; // komentar setelah pernyataan
```
### Komentar Lebih dari Satu Baris
**Komentar yang lebih dari satu baris dimulai dengan `/*` dan diakhiri dengan `*/`**:
```c
/*
Ini adalah komentar
yang mencakup lebih dari
satu baris
*/
int y = 10;
```
**Komentar sangat penting untuk dokumentasi kode** dan membantu programmer lain (atau diri sendiri di masa depan) memahami maksud dari kode yang ditulis.
---
## Tabel Fungsi Dasar dalam stdio.h
| Fungsi | Deskripsi | Contoh |
|--------|-----------|--------|
| printf() | Mencetak output ke layar | `printf("Halo Dunia\\n");` |
| scanf() | Membaca input dari pengguna | `scanf("%d", &angka);` |
| getchar() | Membaca satu karakter | `char c = getchar();` |
| putchar() | Mencetak satu karakter | `putchar('A');` |
**Referensi:**
- [https://www.w3schools.com/c/c_syntax.php](https://www.w3schools.com/c/c_syntax.php)
- [https://www.w3schools.com/c/c_statements.php](https://www.w3schools.com/c/c_statements.php)
- [https://www.w3schools.com/c/c_output.php](https://www.w3schools.com/c/c_output.php)
- [https://www.w3schools.com/c/c_newline.php](https://www.w3schools.com/c/c_newline.php)
- [https://www.w3schools.com/c/c_comments.php](https://www.w3schools.com/c/c_comments.php)
- [Variables in C](lesson/variables.md)
- [Data Types in C](lesson/data_types.md)
---EXERCISE---
# Latihan: Program Halo, Dunia! dan Penggunaan Dasar C
Latih pemahamanmu tentang sintaks dasar C dengan menyelesaikan program berikut. Tambahkan komentar, gunakan format specifier, dan karakter escape sesuai permintaan.
**Requirements:**
- Ganti teks "Goodbye, World!" menjadi "Hello, World!"
- Tambahkan komentar satu baris sebelum fungsi main() menjelaskan tujuan program
- Tambahkan komentar lebih dari satu baris di dalam fungsi main() untuk menjelaskan apa yang dilakukan oleh printf
- Gunakan format specifier untuk mencetak usia kamu (sebagai integer) setelah "Hello, World!"
- Tambahkan karakter escape untuk membuat baris baru sebelum mencetak usia
- Pastikan program berjalan tanpa error
**Expected Output:**
```
Hello, World!
Saya berusia 20 tahun
```
Try writing your solution in the code editor below!
---EXPECTED_OUTPUT---
Hello, World!
Saya berusia 20 tahun
---END_EXPECTED_OUTPUT---
---KEY_TEXT---
Hello,
\n
---END_KEY_TEXT---
---INITIAL_CODE---
#include <stdio.h>
int main() {
printf("Goodbye, World!");
return 0;
}
---END_INITIAL_CODE---
---SOLUTION_CODE---
#include <stdio.h>
// Program ini mencetak pesan sambutan dan usia
int main() {
/*
* Fungsi printf digunakan untuk mencetak output ke layar
* Dalam contoh ini, kita mencetak Hello, World! dan usia
*/
printf("Hello, World!\nSaya berusia 20 tahun");
return 0;
}
---END_SOLUTION_CODE---

View File

@ -28,6 +28,7 @@ Happy coding!
---Available_Lessons--- ---Available_Lessons---
1. [Introduction to C Programming](lesson/introduction_to_c.md) 1. [Hello World](lesson/hello_world.md)
2. [Variables and Data Types in C](lesson/variables_and_data_types.md) 2. [variables](lesson/variable.md)
3. [data type](lesson/data_type.md)

View File

@ -1,52 +0,0 @@
# 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---

View File

@ -0,0 +1,218 @@
---LESSON_INFO---
**Learning Objectives:**
- Memahami konsep variabel dalam bahasa C
- Belajar mendeklarasikan dan menginisialisasi variabel
- Mengenal aturan penamaan variabel dalam C
- Memahami cara mengubah nilai variabel
- Mengenal format specifier untuk berbagai tipe data
- Belajar mendeklarasikan beberapa variabel sekaligus
- Memahami penggunaan variabel dalam konteks nyata
**Prerequisites:**
- Dasar-dasar pemrograman
- Pemahaman tentang program Halo Dunia
---END_LESSON_INFO---
# Variabel dalam C
**Variabel dalam bahasa C** adalah bagian memori bernama yang digunakan untuk menyimpan data dan mengaksesnya kapan saja diperlukan. Variabel memungkinkan kita menggunakan memori tanpa harus mengingat alamat memori yang tepat.
## Apa itu Variabel?
**Variabel** dalam bahasa C adalah **wadah (kontainer)** untuk menyimpan nilai data. Seperti halnya kotak yang bisa kita beri label dan isi dengan nilai tertentu. Setiap variabel memiliki **nama** (identifier) dan **nilai**.
## Deklarasi dan Inisialisasi Variabel
Untuk membuat variabel dalam C, kita harus menentukan **tipe data** dan **nama** yang akan disimpan. Setiap variabel harus dideklarasikan sebelum digunakan.
### Deklarasi Variabel
**Deklarasi variabel** adalah proses membuat variabel dengan menentukan tipe data dan nama:
```c
int myNum;
```
### Inisialisasi Variabel
**Inisialisasi variabel** adalah proses memberikan nilai awal ke variabel:
```c
int myNum = 15;
```
Contoh lengkap deklarasi dan inisialisasi:
```c
// Deklarasi dan inisialisasi sekaligus
int age = 20;
float price = 19.99;
char grade = 'A';
// Deklarasi terlebih dahulu, kemudian inisialisasi
int score;
score = 100;
```
## Format Specifier untuk Variabel
**Format specifier** digunakan dalam fungsi `printf()` untuk menentukan tipe data yang akan dicetak:
- `%d` atau `%i` untuk bilangan bulat (integer)
- `%f` untuk bilangan desimal (float/double)
- `%c` untuk karakter
- `%s` untuk string
Contoh:
```c
int myNum = 5;
float myFloatNum = 5.99;
char myLetter = 'D';
printf("Number: %d\n", myNum);
printf("Float: %f\n", myFloatNum);
printf("Letter: %c\n", myLetter);
```
## Mengubah Nilai Variabel
Setelah variabel dideklarasikan, kita bisa **mengubah nilainya** kapan saja dengan menggunakan operator penugasan (`=`):
```c
int myNum = 15;
printf("Original value: %d\n", myNum); // Output: 15
myNum = 20;
printf("New value: %d\n", myNum); // Output: 20
```
**Catatan penting:** Anda tidak bisa mengganti tipe data dari variabel yang sudah dideklarasikan. Jika sebuah variabel dideklarasikan sebagai `int`, Anda hanya bisa menyimpan bilangan bulat di dalamnya.
## Deklarasi Beberapa Variabel
Anda bisa **mendeklarasikan beberapa variabel sekaligus** dengan tipe data yang sama menggunakan koma:
```c
int x, y, z;
x = y = z = 50;
```
Atau deklarasi dan inisialisasi sekaligus:
```c
int x = 10, y = 20, z = 30;
```
## Aturan Penamaan Variabel
**Aturan untuk memberi nama variabel dalam C:**
1. Nama variabel hanya boleh mengandung **huruf**, **angka**, dan **garis bawah**
2. Harus **dimulai dengan huruf atau garis bawah**, tidak bisa dimulai dengan angka
3. **Tidak diperbolehkan spasi** dalam nama variabel
4. Nama **tidak boleh merupakan kata kunci** atau reserved word
5. Nama harus **unik dalam program**
6. Bahasa C bersifat **case-sensitive** (huruf besar dan kecil berbeda)
Contoh nama variabel yang **valid**: `myVar`, `_count`, `totalAmount`, `student_id`
Contoh nama variabel yang **tidak valid**: `2count`, `first name`, `int`
## Contoh Nyata Penggunaan Variabel
Berikut adalah contoh penggunaan variabel dalam situasi nyata:
```c
#include <stdio.h>
int main() {
// Informasi pelanggan
char firstName[] = "John";
char lastName[] = "Doe";
int age = 30;
float salary = 2500.50;
// Menampilkan informasi
printf("Name: %s %s\n", firstName, lastName);
printf("Age: %d years old\n", age);
printf("Salary: $%.2f\n", salary);
return 0;
}
```
**Output:**
```
Name: John Doe
Age: 30 years old
Salary: $2500.50
```
**Tips:**
- Gunakan nama variabel yang **deskriptif** agar kode lebih mudah dipahami
- Gunakan **camelCase** atau **snake_case** untuk nama variabel yang terdiri dari beberapa kata
- Hindari nama variabel yang terlalu singkat kecuali untuk variabel loop (seperti `i`, `j`, `k`)
**Referensi:**
- [https://www.w3schools.com/c/c_variables.php](https://www.w3schools.com/c/c_variables.php)
- [https://www.w3schools.com/c/c_variables_format.php](https://www.w3schools.com/c/c_variables_format.php)
- [https://www.w3schools.com/c/c_variables_change.php](https://www.w3schools.com/c/c_variables_change.php)
- [https://www.w3schools.com/c/c_variables_multiple.php](https://www.w3schools.com/c/c_variables_multiple.php)
- [https://www.w3schools.com/c/c_variables_names.php](https://www.w3schools.com/c/c_variables_names.php)
- [https://www.w3schools.com/c/c_variables_reallife.php](https://www.w3schools.com/c/c_variables_reallife.php)
- [Hello, World!](lesson/hello_world.md)
- [Data Types in C](lesson/data_types.md)
---EXERCISE---
# Latihan: Menggunakan Variabel
Dalam latihan ini, Anda akan membuat program sederhana yang menggunakan beberapa variabel untuk menyimpan informasi produk dan menampilkannya.
**Requirements:**
- Buat variabel `productName` untuk menyimpan nama produk (gunakan tipe data char array)
- Buat variabel `quantity` untuk menyimpan jumlah produk (gunakan tipe data int)
- Buat variabel `price` untuk menyimpan harga produk (gunakan tipe data float)
- Tampilkan informasi produk menggunakan printf dengan format specifier yang sesuai
**Expected Output:**
```
Product: Laptop
Quantity: 5
Price: $1200.00
```
Try writing your solution in the code editor below!
---EXPECTED_OUTPUT---
Product: Laptop
Quantity: 5
Price: $1200.00
---END_EXPECTED_OUTPUT---
---INITIAL_CODE---
#include <stdio.h>
int main() {
// Deklarasi variabel di sini
// Tampilkan informasi produk di sini
printf("Product: \n");
printf("Quantity: \n");
printf("Price: $\n");
return 0;
}
---END_INITIAL_CODE---
---SOLUTION_CODE---
#include <stdio.h>
int main() {
// Deklarasi variabel
char productName[] = "Laptop";
int quantity = 5;
float price = 1200.00;
// Tampilkan informasi produk
printf("Product: %s\n", productName);
printf("Quantity: %d\n", quantity);
printf("Price: $%.2f\n", price);
return 0;
}
---END_SOLUTION_CODE---

View File

@ -1,121 +0,0 @@
---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---

View File

@ -4,6 +4,8 @@ services:
elemes: elemes:
build: . build: .
container_name: elemes container_name: elemes
ports:
5000:5000
volumes: volumes:
- ../content:/app/content - ../content:/app/content
- ./static:/app/static - ./static:/app/static

View File

@ -232,6 +232,7 @@
const initialCode = {{ initial_code | tojson }}; const initialCode = {{ initial_code | tojson }};
const solutionCode = {{ solution_code | tojson }}; const solutionCode = {{ solution_code | tojson }};
const expectedOutput = {{ expected_output | tojson }}; const expectedOutput = {{ expected_output | tojson }};
const keyText = {{ key_text | tojson }};
// Get DOM elements // Get DOM elements
const runButton = document.getElementById('run-code'); const runButton = document.getElementById('run-code');
@ -563,6 +564,51 @@
return; return;
} }
// Perform static analysis first
let staticAnalysisPassed = true;
let staticAnalysisMessage = '';
if (keyText && keyText !== "None" && keyText !== "") {
// Parse the key text to get required keywords
const requiredKeywords = keyText.split('\n').filter(keyword => keyword.trim() !== '');
// Perform static analysis
staticAnalysisPassed = true;
staticAnalysisMessage = '';
for (const keyword of requiredKeywords) {
if (keyword.trim() !== '') {
// Check if the keyword contains regex patterns (enclosed in slashes)
const trimmedKeyword = keyword.trim();
if (trimmedKeyword.startsWith('/') && trimmedKeyword.endsWith('/')) {
// This is a regex pattern
try {
const regexPattern = trimmedKeyword.slice(1, -1); // Remove the leading and trailing slashes
const regex = new RegExp(regexPattern, 'g');
if (!regex.test(code)) {
staticAnalysisPassed = false;
staticAnalysisMessage += `Missing pattern: "${trimmedKeyword}"\n`;
}
} catch (e) {
// If regex is malformed, treat as literal string
if (!code.includes(trimmedKeyword)) {
staticAnalysisPassed = false;
staticAnalysisMessage += `Missing required keyword: "${trimmedKeyword}"\n`;
}
}
} else {
// Simple check: see if the literal keyword exists in the code
if (!code.includes(trimmedKeyword)) {
staticAnalysisPassed = false;
staticAnalysisMessage += `Missing required keyword: "${trimmedKeyword}"\n`;
}
}
}
}
}
// Show loading state // Show loading state
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;
@ -591,10 +637,12 @@
outputContent.textContent = data.output || 'Program executed successfully with no output.'; outputContent.textContent = data.output || 'Program executed successfully with no output.';
outputContent.className = 'output-success'; outputContent.className = 'output-success';
// Check if output matches expected output (if available) // Check if output matches expected output (if available) AND static analysis passed
if (expectedOutput && expectedOutput !== "None" && expectedOutput !== "") { if (expectedOutput && expectedOutput !== "None" && expectedOutput !== "") {
const actualOutput = data.output || ''; const actualOutput = data.output || '';
if (actualOutput.trim() === expectedOutput.trim()) {
// Both output match and static analysis pass are required for success
if (actualOutput.trim() === expectedOutput.trim() && staticAnalysisPassed) {
// Show success message card if element exists // Show success message card if element exists
const successElement = document.getElementById('success-message'); const successElement = document.getElementById('success-message');
if (successElement) { if (successElement) {
@ -691,29 +739,128 @@
}); });
} }
} else { } else {
// Hide success message if output doesn't match // Hide success message if output doesn't match OR static analysis failed
const successElement = document.getElementById('success-message'); const successElement = document.getElementById('success-message');
if (successElement) { if (successElement) {
successElement.classList.add('d-none'); successElement.classList.add('d-none');
} }
// Hide solution button if output doesn't match // Hide solution button if output doesn't match OR static analysis failed
if (solutionButton) { if (solutionButton) {
solutionButton.classList.add('d-none'); solutionButton.classList.add('d-none');
} }
} }
} else { } else {
// Hide success message if no expected output // For lessons without expected output, check only static analysis
if (staticAnalysisPassed) {
// Show success message card if element exists
const successElement = document.getElementById('success-message');
if (successElement) {
// Remove d-none to show the element
successElement.classList.remove('d-none');
// Hide the success message after 10 seconds
setTimeout(function() {
successElement.classList.add('d-none');
}, 10000);
}
// Show solution button if solution code exists
if (solutionButton && solutionCode && solutionCode !== "None" && solutionCode !== "") {
solutionButton.classList.remove('d-none');
}
// Track progress if student is logged in
const savedToken = localStorage.getItem('student_token');
if (savedToken) {
// Extract lesson name from the URL
const pathParts = window.location.pathname.split('/');
let lessonFilename = pathParts[pathParts.length - 1];
// Handle the case where the URL might include query parameters
if (lessonFilename.includes('?')) {
lessonFilename = lessonFilename.split('?')[0];
}
// Extract just the lesson name without .md extension
const lessonName = lessonFilename.replace('.md', '');
// Send progress to server
fetch('/track-progress', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
token: savedToken,
lesson_name: lessonName,
status: 'completed'
})
})
.then(response => response.json())
.then(data => {
if (data.success) {
console.log('Progress tracked successfully for lesson:', lessonName);
// Update the UI to reflect the new status
document.querySelectorAll('.lesson-card').forEach(card => {
const link = card.querySelector('a');
if (link && link.href.includes(lessonFilename)) {
const statusBadge = card.querySelector('.badge');
if (statusBadge) {
statusBadge.className = 'badge bg-success float-end';
statusBadge.title = 'Completed';
statusBadge.innerHTML = '<i class="fas fa-check-circle"></i> Completed';
}
const btn = card.querySelector('.btn-primary');
if (btn) {
btn.textContent = btn.textContent.replace('Start Learning', 'Review');
}
}
});
// Update the current lesson status in the sidebar
const statusElement = document.querySelector('.card-body p strong + p span');
if (statusElement) {
statusElement.className = 'badge bg-success';
statusElement.innerHTML = '<i class="fas fa-check-circle"></i> Completed';
}
// Update the lesson in the "All Lessons" sidebar
document.querySelectorAll('.list-group-item').forEach(item => {
if (item.href && item.href.includes(lessonFilename)) {
let badge = item.querySelector('.badge');
if (!badge) {
badge = document.createElement('span');
badge.className = 'badge bg-success float-end';
badge.innerHTML = '<i class="fas fa-check-circle"></i>';
item.appendChild(badge);
} else {
badge.className = 'badge bg-success float-end';
badge.innerHTML = '<i class="fas fa-check-circle"></i>';
}
}
});
} else {
console.error('Failed to track progress:', data.message);
}
})
.catch(error => {
console.error('Error tracking progress:', error);
});
}
} else {
// Hide success message if static analysis failed
const successElement = document.getElementById('success-message'); const successElement = document.getElementById('success-message');
if (successElement) { if (successElement) {
successElement.classList.add('d-none'); successElement.classList.add('d-none');
} }
// Hide solution button if no expected output // Hide solution button if static analysis failed
if (solutionButton) { if (solutionButton) {
solutionButton.classList.add('d-none'); solutionButton.classList.add('d-none');
} }
} }
}
} else { } else {
outputContent.textContent = data.error || data.output || 'An error occurred.'; outputContent.textContent = data.error || data.output || 'An error occurred.';
outputContent.className = 'output-error'; outputContent.className = 'output-error';