From b0598c555ebf1a670cdd030272439f4bf0294a1e Mon Sep 17 00:00:00 2001 From: dawood Date: Sun, 29 Mar 2026 10:23:22 +0300 Subject: [PATCH 1/3] =?UTF-8?q?v1:=20listele=20komutu=20eklendi,=20SPEC=20?= =?UTF-8?q?ve=20README=20g=C3=BCncellendi?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 187 ++++++++-------------------------------------- SPEC.txt | 112 +++++++++++++++++++++++++++ mini-grades-v1.py | 133 +++++++++++++++++++++++++++++++++ 3 files changed, 277 insertions(+), 155 deletions(-) create mode 100644 SPEC.txt create mode 100644 mini-grades-v1.py diff --git a/README.md b/README.md index 665ded57..80d49e15 100644 --- a/README.md +++ b/README.md @@ -1,180 +1,57 @@ -
- Which Language Banner - - # 🚀 The AI Native Language Initiative - - **AI doesn't just write code—it speaks it. But which language does it speak best?** - - [![Join the Movement](https://img.shields.io/badge/Join-The_Movement-blue?style=for-the-badge&logo=github)](./AGENT.md) - [![Codexes](https://img.shields.io/badge/Supported_Codexes-5-success?style=for-the-badge)](#-supported-codexes) - [![Problems](https://img.shields.io/badge/Benchmarks-2-orange?style=for-the-badge)](#-the-arena-problems) - - *We are on a mission to map the "native tongue" of Large Language Models. Join us in benchmarking Claude, Gemini, OpenAI, and more across every programming language known to humanity.* -
+# mini-grades ---- - -## 🌟 The Vision - -When we ask an AI to build a system from scratch, the language we choose matters. Does an LLM reason better in the strict, typed world of **Rust**, or the dynamic flexibility of **Python**? Does it write better **Ruby** than **Go**? - -This isn't just another benchmarking tool. It's an **exploratory movement** to understand the cognitive alignment between Artificial Intelligence and programming paradigms. We are building the definitive matrix comparing **AI coding systems** (Codexes) against **Programming Languages** through standardized real-world **Problems**. - -Be part of the discovery. Help us find the ultimate AI-native programming language. - -> 🧠 **Explore Deeper:** Internals → [CLAUDE.md](./CLAUDE.md) · Architecture → [program.md](./program.md) · Roadmap → [plan.md](./plan.md) +Komut satırı tabanlı öğrenci not yönetim sistemi. +Veriler `grades.txt` dosyasında saklanır. --- -## ⚡ Quick Start: Join the Arena +## Kullanım -You don't need to be an expert to contribute. You can run your first benchmark in less than 2 minutes and join the movement. +``` +python mini-grades-v1.py [argümanlar] +``` -### 1️⃣ Gear Up -You'll need `ruby`, toolchains for your target languages, and at least one API key or active tool (Claude CLI, Gemini API, or OpenAI API). +## Komutlar -### 2️⃣ Configure Your AI -Create `config/codexes.local.yml` (this will be gitignored to protect your keys): +| Komut | Açıklama | +|-------|----------| +| `init` | `grades.txt` dosyasını oluşturur | +| `ogrenci-ekle ` | Yeni öğrenci ekler | +| `not-gir ` | Öğrenciye not ekler (0-100) | +| `listele` | Tüm öğrencileri listeler | -```yaml -codexes: - gemini: - enabled: true - config: - api_key: "${GOOGLE_API_KEY}" -``` -```bash -export GOOGLE_API_KEY="your-key-here" -``` +## Örnek -### 3️⃣ Run Your First Benchmark -Test the waters with a lightning-fast dry run: -```bash -bin/which-language run gemini minigit --dry-run --lang python --trials 1 ``` -Or unleash the full power for a real benchmark: -```bash -bin/which-language run gemini minigit --lang python --trials 1 +python mini-grades-v1.py init +python mini-grades-v1.py ogrenci-ekle "Ali Veli" +python mini-grades-v1.py not-gir 1 85 +python mini-grades-v1.py listele ``` -*Your pristine outputs, including raw data, markdown reports, and gorgeous PNG graphs will be waiting for you in the `artifacts/` directory. You are now officially a benchmark runner!* - -**Platform Setup Shortcuts:** -- **Windows**: `.\scripts\install_windows.ps1` (run as Administrator) -- **macOS**: `chmod +x scripts/install_mac.sh && bash scripts/install_mac.sh` - --- -## 🧩 The Matrix Model +## Sürüm Geçmişi -Think of this initiative as a living, breathing matrix. Every benchmark run is an intersection of three dimensions: +### v0 +- `init`, `ogrenci-ekle`, `not-gir` komutları eklendi +- Temel dosya okuma/yazma ve ID yönetimi -| Dimension | Defined by | Example | -|----------|------------|---------| -| 🎯 **Problem** | `problems//problem.json` + assets | `minigit`, `minigrades` | -| 🧠 **Codex** | `lib/codexes/*.rb` + `config/codexes*.yml` | `claude`, `gemini`, `openai` | -| 🗣️ **Language**| `config/languages.yml` | `python`, `rust`, `ruby/steep` | +### v1 +- `listele` komutu eklendi (`while` döngüsü ile satır satır okuma) +- Bilinmeyen komut hatası eklendi +- SPEC v1 olarak güncellendi --- -## 📊 Current State of the Matrix - -We are constantly expanding our coverage. Here is where the initiative stands today: - -### 🧠 Supported Codexes -| Codex | Status | Notes | -|------|:---:|-------| -| **Claude Code** | ✅ | Default CLI adapter | -| **Gemini** | ✅ | API adapter, Flash-Lite/Pro | -| **OpenAI** | ✅ | Responses API, cost accounting | -| **Groq** | ✅ | API adapter, robust parsing | -| **Aider** | 🚧 | CLI adapter, *needs validation* | - -*More warriors (DeepSeek, Qwen, Grok, Cline) are entering the arena soon. See [plan.md](./plan.md).* - -### 🗣️ Supported Languages -- **Dynamic:** `python`, `ruby`, `javascript`, `perl`, `lua` -- **Static:** `rust`, `go`, `c`, `typescript`, `java` -- **Functional:** `scheme`, `ocaml`, `haskell` -- **Typed Variants:** `python/mypy`, `ruby/steep` - -### 🎯 The Arena (Problems) -- 💾 **minigit** — Minimal version control system -- 🎓 **minigrades** — Student grade manager -- 🎵 **miniplaylist** — Playlist management system - ---- +## Veri Formatı -## 🛠️ Power User Commands - -Command the benchmarking pipeline like a pro: - -```bash -# 🔥 Full pipeline (benchmark + report + figures) -bin/which-language run gemini minigit --lang python --trials 1 - -# 🏃 Benchmark only -bin/which-language benchmark gemini minigit --lang python --trials 1 - -# ⚔️ Epic Codex Battles (Compare systems head-to-head) -bin/which-language run claude minigit --lang python --trials 3 -bin/which-language run gemini minigit --lang python --trials 3 ``` - ---- - -## 🏆 Hall of Fame - -This project thrives on the brilliant minds driving it forward. We celebrate every contribution! Here are the legends who have shaped the initiative: - -
- -| [
mame](https://github.com/mame) | [
berkevnl](https://github.com/berkevnl) | [
Ahmetngz](https://github.com/Ahmetngz) | -| :---: | :---: | :---: | -| 🚀 Visionary | 💻 Core Architect | 💻 Core Architect | - -
- -### Become a Legend -Want your face on the Hall of Fame? See our strict but fair [Contributor Protocol (AGENT.md)](./AGENT.md). We are actively hunting for: -- **Codex Whisperers:** Implement new adapters in `lib/codexes` -- **Data Scientists:** Run benchmarks on your machines and submit results -- **Problem Architects:** Design new, brutal testing scenarios in `problems/` -- **Linguists:** Add support for new programming languages to `config/languages.yml` - ---- - -## 🏗️ Repository Layout - -For the curious minds, here is how our engine is built: - -```text -. -├── bin/ # CLI Application binaries (which-language) -├── src/ # Core application scripts (benchmark, report, plot) -├── problems/ # The arena: problem definitions -├── lib/codexes/ # The minds: codex adapters -├── config/codexes.yml # Codex configuration layer -├── config/languages.yml # Languages and toolchain configuration -├── scripts/ # Productivity accelerators (installers) -├── program.md # Agent entry point -├── AGENT.md # Contributor protocol & rules -├── plan.md # Living iteration roadmap -├── walkthrough.md # Proof-of-work documentation -├── CLAUDE.md # Technical internals and secrets -└── artifacts/ # The spoils: benchmark outputs +STUDENT|1|Ali Veli +GRADE|1|85 +GRADE|1|90 ``` --- -## 🏛️ Historical Context - -This entire movement was ignited by a single, powerful question: *Which Programming Language Is Best for Claude Code?* - -- 📖 [Read the original publication that started it all](https://dev.to/mame/which-programming-language-is-best-for-claude-code-508a) -- 🇯🇵 [Japanese version available here](https://zenn.dev/mametter/articles/3e8580ec034201) - -## 🌌 The Multiverse (Similar Projects) -We proudly stand alongside other incredible benchmarking initiatives: -- [AutoCodeBench](https://autocodebench.github.io) -- [LiveCodeBench](https://livecodebench.github.io) +Geliştirici: Davud Kılıç — 251478023 diff --git a/SPEC.txt b/SPEC.txt new file mode 100644 index 00000000..acd633dd --- /dev/null +++ b/SPEC.txt @@ -0,0 +1,112 @@ +PROJECT: mini-grades +AUTHOR: Davud Kılıç - 251478023 +VERSION: v1 +DATE: 2026-03-28 + +======================================== +OVERVIEW +======================================== + +mini-grades is a command-line student grade manager. +It stores student records and their grades in a plain text file +and supports adding students, entering grades, calculating +averages, generating reports, and deleting students. + +All data is persisted in a file called grades.txt +in the current working directory. + +======================================== +COMMANDS +======================================== + +--- init --- +Usage: python grades.py init +Creates an empty grades.txt file. +If grades.txt already exists, print "Already initialized" and exit. + +--- ogrenci-ekle --- +Usage: python grades.py ogrenci-ekle "Ali Veli" +Adds a new student with no grades yet. +Each student has: id , name. +Prints "Added student #: " + +--- not-gir --- +Usage: python grades.py not-gir 1 85 +Appends a grade for student #1. +Valid grades are integers between 0 and 100. +Prints "Grade 85 added for student #1." +If student does not exist, prints "Student #1 not found." +If grade is not between 0 and 100, prints "Invalid grade: . Must be between 0 and 100." + +--- listele --- +Usage: python grades.py listele +Lists all students in the file, one per line. +Format: # - +Example output: + #1 - Ali Veli + #2 - Ayse Kaya +If no students exist, prints "No students found." +NOTE: This is a v1 intermediate command. "rapor" will replace/extend it in a future version. + +--- ortalama --- +Usage: python grades.py ortalama 1 +Calculates and prints the average of all grades for student #1. +Prints "Student #1 () average: " +Average is rounded to 2 decimal places. +If student has no grades, prints "Student #1 has no grades yet." +If student does not exist, prints "Student #1 not found." +STATUS: Not yet implemented. + +--- rapor --- +Usage: python grades.py rapor +Prints all students and their averages, one per line: + [1] Ali Veli - Average: 87.50 (3 grades) + [2] Ayse Kaya - No grades yet. +If no students exist, prints "No students found." +STATUS: Not yet implemented. + +--- ogrenci-sil --- +Usage: python grades.py ogrenci-sil 1 +Removes student #1 and all their grades from grades.txt. +Prints "Deleted student #1: " +If student does not exist, prints "Student #1 not found." +STATUS: Not yet implemented. + +======================================== +DATA FORMAT +======================================== + +File: grades.txt +Format: One record per line, fields separated by | +Student record: STUDENT|| +Grade record: GRADE|| + +Example: +STUDENT|1|Ali Veli +GRADE|1|85 +GRADE|1|90 +STUDENT|2|Ayse Kaya +GRADE|2|70 + +======================================== +ERROR HANDLING +======================================== + +- Running any command before "init": print "Not initialized. Run: python grades.py init" +- Invalid command: print "Unknown command: " +- Missing arguments: print "Usage: python grades.py [args]" +- Non-integer grade input: print "Invalid grade: . Must be an integer." +- Non-integer student ID input: print "Invalid ID: . Must be an integer." + +======================================== +CHANGELOG +======================================== + +v0 (2026-03-13) + - init, ogrenci-ekle, not-gir komutlari eklendi. + - Temel dosya I/O ve ID yonetimi implemente edildi. + +v1 (2026-03-28) + - listele komutu eklendi. + - while dongusu ile dosyadan satir satir okuma implemente edildi. + - Unknown command hatasi eklendi. diff --git a/mini-grades-v1.py b/mini-grades-v1.py new file mode 100644 index 00000000..0bd13845 --- /dev/null +++ b/mini-grades-v1.py @@ -0,0 +1,133 @@ +""" +mini-grades v1 - Basitlestirilmis implementasyon +Ogrenci: Davud Kılıç - 251478023 + +V1 Degisiklikleri: + - listele komutu eklendi (while dongusu ile dosyadan satir satir okuma) + +Kapsam: init, ogrenci-ekle, not-gir, listele komutlari. + - ortalama/rapor/ogrenci-sil henuz implemente edilmedi + - ID hesabi dosyadaki STUDENT satiri sayisina gore yapiliyor +""" + +# V1 Görev Listesi: +# 1. listele komutu eklendi (while ile satır satır okuma) +# 2. Bilinmeyen komut hatası eklendi +# 3. SPEC v1 olarak güncellendi + +import os +import sys + +DATA_FILE = "grades.txt" + + +def init(): # İlgili ".txt" dosyası yoksa oluşturur, varsa uyarır. + + if os.path.exists(DATA_FILE): + return "Already initialized" + f = open(DATA_FILE, "x", encoding="utf-8") + f.close() + return "Initialized. grades.txt created." + + +def add_student(name): # Öğrenci ad-soyad bilgisi alır. Türkçe karakterlerde sorun çıkmaz. + + if not os.path.exists(DATA_FILE): + return "Not initialized. Run: python mini-grades-v1.py init" + + f = open(DATA_FILE, "r", encoding="utf-8") + content = f.read() + f.close() + + student_count = content.count("STUDENT|") + new_id = student_count + 1 + + f = open(DATA_FILE, "a", encoding="utf-8") + f.write(f"STUDENT|{new_id}|{name}\n") + f.close() + return f"Added student #{new_id}: {name}" + + +def add_grade(ids, grade_str): # Öğrenciye not ekler. Geçerlilik kontrolü yapar, dosyaya yazar. + + if not os.path.exists(DATA_FILE): + return "Not initialized. Run: python mini-grades-v1.py init" + + if not grade_str.lstrip("-").isdigit(): + return f"Invalid grade: {grade_str}. Must be an integer." + + grade = int(grade_str) + + if not 0 <= grade <= 100: + return f"Invalid grade: {grade_str}. Must be between 0 and 100." + + f = open(DATA_FILE, "r", encoding="utf-8") + content = f.read() + f.close() + + if f"STUDENT|{ids}|" not in content: + return f"Student #{ids} not found." + + f = open(DATA_FILE, "a", encoding="utf-8") + f.write(f"GRADE|{ids}|{grade}\n") + f.close() + + return f"Grade {grade} added for student #{ids}." + + +def list_students(): # Tüm öğrencileri sırayla ekrana basar. + + if not os.path.exists(DATA_FILE): + return "Not initialized. Run: python mini-grades-v1.py init" + + f = open(DATA_FILE, "r", encoding="utf-8") + lines = f.readlines() + f.close() + + result = "" + i = 0 + while i < len(lines): + line = lines[i].strip() + if line.startswith("STUDENT|"): + parts = line.split("|") + result += f"#{parts[1]} - {parts[2]}\n" + i += 1 + + if result == "": + return "No students found." + + return result.strip() + + +def average(): + return "Command 'ortalama' will be implemented in future weeks." + + +def del_student(): + return "Command 'ogrenci-sil' will be implemented in future weeks." + + +def rapor(): + return "Command 'rapor' will be implemented in future weeks." + + +#-----------------------------------------------------------------------# + +if len(sys.argv) < 2: + print("Usage: python mini-grades-v1.py [args]") +elif sys.argv[1] == "init": + print(init()) +elif sys.argv[1] == "ogrenci-ekle": + if len(sys.argv) < 3: + print("Usage: python mini-grades-v1.py ogrenci-ekle ") + else: + print(add_student(sys.argv[2])) +elif sys.argv[1] == "not-gir": + if len(sys.argv) < 4: + print("Usage: python mini-grades-v1.py not-gir ") + else: + print(add_grade(sys.argv[2], sys.argv[3])) +elif sys.argv[1] == "listele": + print(list_students()) +else: + print(f"Unknown command: {sys.argv[1]}") \ No newline at end of file From 15556aa156f7cdaa9d4b35db8b97ce2f72ce2174 Mon Sep 17 00:00:00 2001 From: dawood Date: Mon, 20 Apr 2026 06:03:17 +0300 Subject: [PATCH 2/3] [minigrades] Add v2: ara, ortalama, not-listele commands with tests --- README.md | 23 ++++- SPEC.txt | 31 +++++- mini-grades-v1.py | 133 -------------------------- mini-grades-v2.py | 235 ++++++++++++++++++++++++++++++++++++++++++++++ test_grades.py | 176 ++++++++++++++++++++++++++++++++++ 5 files changed, 456 insertions(+), 142 deletions(-) delete mode 100644 mini-grades-v1.py create mode 100644 mini-grades-v2.py create mode 100644 test_grades.py diff --git a/README.md b/README.md index 80d49e15..70567d75 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Veriler `grades.txt` dosyasında saklanır. ## Kullanım ``` -python mini-grades-v1.py [argümanlar] +python mini-grades-v2.py [argümanlar] ``` ## Komutlar @@ -19,14 +19,21 @@ python mini-grades-v1.py [argümanlar] | `ogrenci-ekle ` | Yeni öğrenci ekler | | `not-gir ` | Öğrenciye not ekler (0-100) | | `listele` | Tüm öğrencileri listeler | +| `ara ` | İsme göre öğrenci arar (büyük/küçük harf duyarsız) | +| `ortalama ` | Öğrencinin not ortalamasını hesaplar | +| `not-listele ` | Öğrencinin tüm notlarını listeler | ## Örnek ``` -python mini-grades-v1.py init -python mini-grades-v1.py ogrenci-ekle "Ali Veli" -python mini-grades-v1.py not-gir 1 85 -python mini-grades-v1.py listele +python mini-grades-v2.py init +python mini-grades-v2.py ogrenci-ekle "Ali Veli" +python mini-grades-v2.py not-gir 1 85 +python mini-grades-v2.py not-gir 1 90 +python mini-grades-v2.py ara "Ali" +python mini-grades-v2.py ortalama 1 +python mini-grades-v2.py not-listele 1 +python mini-grades-v2.py listele ``` --- @@ -42,6 +49,12 @@ python mini-grades-v1.py listele - Bilinmeyen komut hatası eklendi - SPEC v1 olarak güncellendi +### v2 +- `ara` komutu eklendi: isim araması (`for` döngüsü + string `in` operatörü) +- `ortalama` komutu eklendi: `for` döngüsü ile not toplama ve ortalama hesabı +- `not-listele` komutu eklendi: belirli öğrencinin notlarını `for` ile listeler +- SPEC v2 olarak güncellendi + --- ## Veri Formatı diff --git a/SPEC.txt b/SPEC.txt index acd633dd..0d86571e 100644 --- a/SPEC.txt +++ b/SPEC.txt @@ -1,7 +1,7 @@ PROJECT: mini-grades AUTHOR: Davud Kılıç - 251478023 -VERSION: v1 -DATE: 2026-03-28 +VERSION: v2 +DATE: 2026-04-19 ======================================== OVERVIEW @@ -46,7 +46,16 @@ Example output: #1 - Ali Veli #2 - Ayse Kaya If no students exist, prints "No students found." -NOTE: This is a v1 intermediate command. "rapor" will replace/extend it in a future version. +NOTE: Intermediate command. "rapor" will replace/extend it in a future version. + +--- ara --- +Usage: python grades.py ara +Searches all students whose name contains the given keyword (case-insensitive). +Prints matching students one per line in the same format as listele. +If no match found, prints "No students found matching ''." +Example: + python grades.py ara Ali + -> #1 - Ali Veli --- ortalama --- Usage: python grades.py ortalama 1 @@ -55,7 +64,16 @@ Prints "Student #1 () average: " Average is rounded to 2 decimal places. If student has no grades, prints "Student #1 has no grades yet." If student does not exist, prints "Student #1 not found." -STATUS: Not yet implemented. + +--- not-listele --- +Usage: python grades.py not-listele 1 +Lists all grades for student #1, numbered. +Format: + Student #1 () grades: + 1. 85 + 2. 90 +If student has no grades, prints "Student #1 () has no grades yet." +If student does not exist, prints "Student #1 not found." --- rapor --- Usage: python grades.py rapor @@ -110,3 +128,8 @@ v1 (2026-03-28) - listele komutu eklendi. - while dongusu ile dosyadan satir satir okuma implemente edildi. - Unknown command hatasi eklendi. + +v2 (2026-04-19) + - ara komutu eklendi (string 'in' operatoru + for dongusu ile isim araması). + - ortalama komutu eklendi (for dongusu ile not toplama ve hesaplama). + - not-listele komutu eklendi (belirli bir ogrencinin notlarini for dongusu ile listeler). diff --git a/mini-grades-v1.py b/mini-grades-v1.py deleted file mode 100644 index 0bd13845..00000000 --- a/mini-grades-v1.py +++ /dev/null @@ -1,133 +0,0 @@ -""" -mini-grades v1 - Basitlestirilmis implementasyon -Ogrenci: Davud Kılıç - 251478023 - -V1 Degisiklikleri: - - listele komutu eklendi (while dongusu ile dosyadan satir satir okuma) - -Kapsam: init, ogrenci-ekle, not-gir, listele komutlari. - - ortalama/rapor/ogrenci-sil henuz implemente edilmedi - - ID hesabi dosyadaki STUDENT satiri sayisina gore yapiliyor -""" - -# V1 Görev Listesi: -# 1. listele komutu eklendi (while ile satır satır okuma) -# 2. Bilinmeyen komut hatası eklendi -# 3. SPEC v1 olarak güncellendi - -import os -import sys - -DATA_FILE = "grades.txt" - - -def init(): # İlgili ".txt" dosyası yoksa oluşturur, varsa uyarır. - - if os.path.exists(DATA_FILE): - return "Already initialized" - f = open(DATA_FILE, "x", encoding="utf-8") - f.close() - return "Initialized. grades.txt created." - - -def add_student(name): # Öğrenci ad-soyad bilgisi alır. Türkçe karakterlerde sorun çıkmaz. - - if not os.path.exists(DATA_FILE): - return "Not initialized. Run: python mini-grades-v1.py init" - - f = open(DATA_FILE, "r", encoding="utf-8") - content = f.read() - f.close() - - student_count = content.count("STUDENT|") - new_id = student_count + 1 - - f = open(DATA_FILE, "a", encoding="utf-8") - f.write(f"STUDENT|{new_id}|{name}\n") - f.close() - return f"Added student #{new_id}: {name}" - - -def add_grade(ids, grade_str): # Öğrenciye not ekler. Geçerlilik kontrolü yapar, dosyaya yazar. - - if not os.path.exists(DATA_FILE): - return "Not initialized. Run: python mini-grades-v1.py init" - - if not grade_str.lstrip("-").isdigit(): - return f"Invalid grade: {grade_str}. Must be an integer." - - grade = int(grade_str) - - if not 0 <= grade <= 100: - return f"Invalid grade: {grade_str}. Must be between 0 and 100." - - f = open(DATA_FILE, "r", encoding="utf-8") - content = f.read() - f.close() - - if f"STUDENT|{ids}|" not in content: - return f"Student #{ids} not found." - - f = open(DATA_FILE, "a", encoding="utf-8") - f.write(f"GRADE|{ids}|{grade}\n") - f.close() - - return f"Grade {grade} added for student #{ids}." - - -def list_students(): # Tüm öğrencileri sırayla ekrana basar. - - if not os.path.exists(DATA_FILE): - return "Not initialized. Run: python mini-grades-v1.py init" - - f = open(DATA_FILE, "r", encoding="utf-8") - lines = f.readlines() - f.close() - - result = "" - i = 0 - while i < len(lines): - line = lines[i].strip() - if line.startswith("STUDENT|"): - parts = line.split("|") - result += f"#{parts[1]} - {parts[2]}\n" - i += 1 - - if result == "": - return "No students found." - - return result.strip() - - -def average(): - return "Command 'ortalama' will be implemented in future weeks." - - -def del_student(): - return "Command 'ogrenci-sil' will be implemented in future weeks." - - -def rapor(): - return "Command 'rapor' will be implemented in future weeks." - - -#-----------------------------------------------------------------------# - -if len(sys.argv) < 2: - print("Usage: python mini-grades-v1.py [args]") -elif sys.argv[1] == "init": - print(init()) -elif sys.argv[1] == "ogrenci-ekle": - if len(sys.argv) < 3: - print("Usage: python mini-grades-v1.py ogrenci-ekle ") - else: - print(add_student(sys.argv[2])) -elif sys.argv[1] == "not-gir": - if len(sys.argv) < 4: - print("Usage: python mini-grades-v1.py not-gir ") - else: - print(add_grade(sys.argv[2], sys.argv[3])) -elif sys.argv[1] == "listele": - print(list_students()) -else: - print(f"Unknown command: {sys.argv[1]}") \ No newline at end of file diff --git a/mini-grades-v2.py b/mini-grades-v2.py new file mode 100644 index 00000000..081e43d2 --- /dev/null +++ b/mini-grades-v2.py @@ -0,0 +1,235 @@ +""" +mini-grades v2 - Basitlestirilmis implementasyon +Ogrenci: Davud Kılıç - 251478023 + +V2 Degisiklikleri: + - ara komutu eklendi (string icinde arama, for dongusu ile) + - ortalama komutu eklendi (for dongusu ile not toplama) + - not-listele komutu eklendi (belirli bir ogrencinin notlarini listeler) + +Kapsam: init, ogrenci-ekle, not-gir, listele, ara, ortalama, not-listele komutlari. + - rapor/ogrenci-sil henuz implemente edilmedi + - ID hesabi dosyadaki STUDENT satiri sayisina gore yapiliyor +""" + +# V2 Görev Listesi: +# 1. ara komutu: isim araması (string in / for döngüsü ile) +# 2. ortalama komutu: öğrenci notlarının ortalaması (for döngüsü ile) +# 3. not-listele komutu: bir öğrencinin tüm notlarını listeler (for döngüsü ile) + +import os +import sys + +DATA_FILE = "grades.txt" + + +def init(): + if os.path.exists(DATA_FILE): + return "Already initialized" + f = open(DATA_FILE, "x", encoding="utf-8") + f.close() + return "Initialized. grades.txt created." + + +def add_student(name): + if not os.path.exists(DATA_FILE): + return "Not initialized. Run: python mini-grades-v2.py init" + + f = open(DATA_FILE, "r", encoding="utf-8") + content = f.read() + f.close() + + student_count = content.count("STUDENT|") + new_id = student_count + 1 + + f = open(DATA_FILE, "a", encoding="utf-8") + f.write(f"STUDENT|{new_id}|{name}\n") + f.close() + return f"Added student #{new_id}: {name}" + + +def add_grade(ids, grade_str): + if not os.path.exists(DATA_FILE): + return "Not initialized. Run: python mini-grades-v2.py init" + + if not grade_str.lstrip("-").isdigit(): + return f"Invalid grade: {grade_str}. Must be an integer." + + grade = int(grade_str) + + if not 0 <= grade <= 100: + return f"Invalid grade: {grade_str}. Must be between 0 and 100." + + f = open(DATA_FILE, "r", encoding="utf-8") + content = f.read() + f.close() + + if f"STUDENT|{ids}|" not in content: + return f"Student #{ids} not found." + + f = open(DATA_FILE, "a", encoding="utf-8") + f.write(f"GRADE|{ids}|{grade}\n") + f.close() + + return f"Grade {grade} added for student #{ids}." + + +def list_students(): + if not os.path.exists(DATA_FILE): + return "Not initialized. Run: python mini-grades-v2.py init" + + f = open(DATA_FILE, "r", encoding="utf-8") + lines = f.readlines() + f.close() + + result = "" + i = 0 + while i < len(lines): + line = lines[i].strip() + if line.startswith("STUDENT|"): + parts = line.split("|") + result += f"#{parts[1]} - {parts[2]}\n" + i += 1 + + if result == "": + return "No students found." + + return result.strip() + + +def search_student(keyword): + """İsim araması. for döngüsü + string 'in' operatörü kullanır.""" + if not os.path.exists(DATA_FILE): + return "Not initialized. Run: python mini-grades-v2.py init" + + f = open(DATA_FILE, "r", encoding="utf-8") + lines = f.readlines() + f.close() + + result = "" + for line in lines: + line = line.strip() + if line.startswith("STUDENT|"): + parts = line.split("|") + name = parts[2] + if keyword.lower() in name.lower(): + result += f"#{parts[1]} - {name}\n" + + if result == "": + return f"No students found matching '{keyword}'." + + return result.strip() + + +def average(ids): + """Bir öğrencinin not ortalamasını hesaplar. for döngüsü ile not toplama.""" + if not os.path.exists(DATA_FILE): + return "Not initialized. Run: python mini-grades-v2.py init" + + f = open(DATA_FILE, "r", encoding="utf-8") + lines = f.readlines() + f.close() + + student_name = None + grades = [] + + for line in lines: + line = line.strip() + if line.startswith(f"STUDENT|{ids}|"): + parts = line.split("|") + student_name = parts[2] + elif line.startswith(f"GRADE|{ids}|"): + parts = line.split("|") + grades.append(int(parts[2])) + + if student_name is None: + return f"Student #{ids} not found." + + if len(grades) == 0: + return f"Student #{ids} has no grades yet." + + total = 0 + for g in grades: + total += g + avg = round(total / len(grades), 2) + + return f"Student #{ids} ({student_name}) average: {avg}" + + +def list_grades(ids): + """Bir öğrencinin tüm notlarını listeler. for döngüsü ile filtreleme.""" + if not os.path.exists(DATA_FILE): + return "Not initialized. Run: python mini-grades-v2.py init" + + f = open(DATA_FILE, "r", encoding="utf-8") + lines = f.readlines() + f.close() + + student_name = None + grades = [] + + for line in lines: + line = line.strip() + if line.startswith(f"STUDENT|{ids}|"): + parts = line.split("|") + student_name = parts[2] + elif line.startswith(f"GRADE|{ids}|"): + parts = line.split("|") + grades.append(parts[2]) + + if student_name is None: + return f"Student #{ids} not found." + + if len(grades) == 0: + return f"Student #{ids} ({student_name}) has no grades yet." + + result = f"Student #{ids} ({student_name}) grades:\n" + for i, g in enumerate(grades): + result += f" {i + 1}. {g}\n" + + return result.strip() + + +def del_student(): + return "Command 'ogrenci-sil' will be implemented in future weeks." + + +def rapor(): + return "Command 'rapor' will be implemented in future weeks." + + +#-----------------------------------------------------------------------# + +if len(sys.argv) < 2: + print("Usage: python mini-grades-v2.py [args]") +elif sys.argv[1] == "init": + print(init()) +elif sys.argv[1] == "ogrenci-ekle": + if len(sys.argv) < 3: + print("Usage: python mini-grades-v2.py ogrenci-ekle ") + else: + print(add_student(sys.argv[2])) +elif sys.argv[1] == "not-gir": + if len(sys.argv) < 4: + print("Usage: python mini-grades-v2.py not-gir ") + else: + print(add_grade(sys.argv[2], sys.argv[3])) +elif sys.argv[1] == "listele": + print(list_students()) +elif sys.argv[1] == "ara": + if len(sys.argv) < 3: + print("Usage: python mini-grades-v2.py ara ") + else: + print(search_student(sys.argv[2])) +elif sys.argv[1] == "ortalama": + if len(sys.argv) < 3: + print("Usage: python mini-grades-v2.py ortalama ") + else: + print(average(sys.argv[2])) +elif sys.argv[1] == "not-listele": + if len(sys.argv) < 3: + print("Usage: python mini-grades-v2.py not-listele ") + else: + print(list_grades(sys.argv[2])) +else: + print(f"Unknown command: {sys.argv[1]}") diff --git a/test_grades.py b/test_grades.py new file mode 100644 index 00000000..8f4f4f4b --- /dev/null +++ b/test_grades.py @@ -0,0 +1,176 @@ +""" +mini-grades SPEC test senaryolari +Ogrenci: Davud Kılıç 251478023 +Proje: mini-grades +""" +import subprocess +import os + +# --- Yardimci Fonksiyon --- +def run_cmd(args): + """Komutu calistir, stdout dondur.""" + result = subprocess.run( + ["python", "mini-grades-v2.py"] + args, + capture_output=True, + text=True + ) + return result.stdout.strip() + +def setup(): + """Her testten once grades.txt'yi sil, temiz baslangic.""" + if os.path.exists("grades.txt"): + os.remove("grades.txt") + +# --- init testleri --- +def test_init_creates_file(): + setup() + run_cmd(["init"]) + assert os.path.exists("grades.txt"), "grades.txt olusturulmali" + +def test_init_already_exists(): + setup() + run_cmd(["init"]) + output = run_cmd(["init"]) + assert "Already initialized" in output + +# --- ogrenci-ekle testleri --- +def test_add_student_success(): + setup() + run_cmd(["init"]) + output = run_cmd(["ogrenci-ekle", "Ali Veli"]) + assert "Added student #1" in output + assert "Ali Veli" in output + +def test_add_student_id_increments(): + setup() + run_cmd(["init"]) + run_cmd(["ogrenci-ekle", "Ali Veli"]) + output = run_cmd(["ogrenci-ekle", "Ayse Kaya"]) + assert "#2" in output + +def test_add_student_saved_to_file(): + setup() + run_cmd(["init"]) + run_cmd(["ogrenci-ekle", "Ali Veli"]) + f = open("grades.txt", "r", encoding="utf-8") + content = f.read() + f.close() + assert "STUDENT|1|Ali Veli" in content + +def test_add_student_turkish_chars(): + setup() + run_cmd(["init"]) + output = run_cmd(["ogrenci-ekle", "Şükrü Çelik"]) + assert "Şükrü Çelik" in output + +def test_add_student_before_init(): + setup() + output = run_cmd(["ogrenci-ekle", "Ali Veli"]) + assert "Not initialized" in output + +def test_add_student_missing_arg(): + setup() + run_cmd(["init"]) + output = run_cmd(["ogrenci-ekle"]) + assert "Usage" in output + +# --- genel hata testleri --- +def test_no_command(): + setup() + output = run_cmd([]) + assert "Usage" in output + +def test_unknown_command(): + setup() + run_cmd(["init"]) + output = run_cmd(["ucur"]) + assert "Unknown command" in output + +# --- ara testleri (v2) --- +def test_search_finds_student(): + setup() + run_cmd(["init"]) + run_cmd(["ogrenci-ekle", "Ali Veli"]) + run_cmd(["ogrenci-ekle", "Ayse Kaya"]) + output = run_cmd(["ara", "Ali"]) + assert "Ali Veli" in output + assert "Ayse Kaya" not in output + +def test_search_case_insensitive(): + setup() + run_cmd(["init"]) + run_cmd(["ogrenci-ekle", "Ali Veli"]) + output = run_cmd(["ara", "ali"]) + assert "Ali Veli" in output + +def test_search_no_match(): + setup() + run_cmd(["init"]) + run_cmd(["ogrenci-ekle", "Ali Veli"]) + output = run_cmd(["ara", "Zeynep"]) + assert "No students found" in output + +def test_search_missing_arg(): + setup() + run_cmd(["init"]) + output = run_cmd(["ara"]) + assert "Usage" in output + +# --- ortalama testleri (v2) --- +def test_average_correct(): + setup() + run_cmd(["init"]) + run_cmd(["ogrenci-ekle", "Ali Veli"]) + run_cmd(["not-gir", "1", "80"]) + run_cmd(["not-gir", "1", "90"]) + output = run_cmd(["ortalama", "1"]) + assert "85.0" in output + +def test_average_no_grades(): + setup() + run_cmd(["init"]) + run_cmd(["ogrenci-ekle", "Ali Veli"]) + output = run_cmd(["ortalama", "1"]) + assert "no grades" in output + +def test_average_student_not_found(): + setup() + run_cmd(["init"]) + output = run_cmd(["ortalama", "99"]) + assert "not found" in output + +def test_average_missing_arg(): + setup() + run_cmd(["init"]) + output = run_cmd(["ortalama"]) + assert "Usage" in output + +# --- not-listele testleri (v2) --- +def test_list_grades_success(): + setup() + run_cmd(["init"]) + run_cmd(["ogrenci-ekle", "Ali Veli"]) + run_cmd(["not-gir", "1", "75"]) + run_cmd(["not-gir", "1", "90"]) + output = run_cmd(["not-listele", "1"]) + assert "75" in output + assert "90" in output + +def test_list_grades_no_grades(): + setup() + run_cmd(["init"]) + run_cmd(["ogrenci-ekle", "Ali Veli"]) + output = run_cmd(["not-listele", "1"]) + assert "no grades" in output + +def test_list_grades_student_not_found(): + setup() + run_cmd(["init"]) + output = run_cmd(["not-listele", "5"]) + assert "not found" in output + +def test_list_grades_missing_arg(): + setup() + run_cmd(["init"]) + output = run_cmd(["not-listele"]) + assert "Usage" in output From 43a4d0ab3540d1f481cb73c940e707976707ae9e Mon Sep 17 00:00:00 2001 From: dawood Date: Tue, 21 Apr 2026 07:00:04 +0300 Subject: [PATCH 3/3] [minigrades] Move v2 files to problems/minigrades/ --- SPEC.txt => problems/minigrades/SPEC.txt | 0 mini-grades-v2.py => problems/minigrades/mini-grades-v2.py | 0 test_grades.py => problems/minigrades/test_grades.py | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename SPEC.txt => problems/minigrades/SPEC.txt (100%) rename mini-grades-v2.py => problems/minigrades/mini-grades-v2.py (100%) rename test_grades.py => problems/minigrades/test_grades.py (100%) diff --git a/SPEC.txt b/problems/minigrades/SPEC.txt similarity index 100% rename from SPEC.txt rename to problems/minigrades/SPEC.txt diff --git a/mini-grades-v2.py b/problems/minigrades/mini-grades-v2.py similarity index 100% rename from mini-grades-v2.py rename to problems/minigrades/mini-grades-v2.py diff --git a/test_grades.py b/problems/minigrades/test_grades.py similarity index 100% rename from test_grades.py rename to problems/minigrades/test_grades.py