159 lines
5.4 KiB
Python
159 lines
5.4 KiB
Python
"""
|
|
Token and student progress operations backed by CSV file.
|
|
"""
|
|
|
|
import csv
|
|
import logging
|
|
import os
|
|
|
|
from config import TOKENS_FILE
|
|
|
|
|
|
def get_teacher_token():
|
|
"""Return the teacher token (first data row in CSV)."""
|
|
if not os.path.exists(TOKENS_FILE):
|
|
return None
|
|
|
|
with open(TOKENS_FILE, 'r', newline='', encoding='utf-8') as csvfile:
|
|
reader = csv.DictReader(csvfile, delimiter=';')
|
|
for row in reader:
|
|
return row['token']
|
|
|
|
return None
|
|
|
|
|
|
def is_teacher_token(token):
|
|
"""Check if the given token belongs to the teacher (first row)."""
|
|
return token == get_teacher_token()
|
|
|
|
|
|
def validate_token(token):
|
|
"""Validate if a token exists in the CSV file and return student info."""
|
|
if not os.path.exists(TOKENS_FILE):
|
|
return None
|
|
|
|
with open(TOKENS_FILE, 'r', newline='', encoding='utf-8') as csvfile:
|
|
reader = csv.DictReader(csvfile, delimiter=';')
|
|
for row in reader:
|
|
if row['token'] == token:
|
|
return {
|
|
'token': row['token'],
|
|
'student_name': row['nama_siswa'],
|
|
'is_teacher': is_teacher_token(token),
|
|
}
|
|
|
|
return None
|
|
|
|
|
|
def get_student_progress(token):
|
|
"""Get the progress of a student based on their token."""
|
|
if not os.path.exists(TOKENS_FILE):
|
|
return None
|
|
|
|
with open(TOKENS_FILE, 'r', newline='', encoding='utf-8') as csvfile:
|
|
reader = csv.DictReader(csvfile, delimiter=';')
|
|
for row in reader:
|
|
if row['token'] == token:
|
|
return row
|
|
|
|
return None
|
|
|
|
|
|
def update_student_progress(token, lesson_name, status="completed"):
|
|
"""Update the progress of a student for a specific lesson."""
|
|
if not os.path.exists(TOKENS_FILE):
|
|
logging.warning(f"Tokens file {TOKENS_FILE} does not exist")
|
|
return False
|
|
|
|
rows = []
|
|
with open(TOKENS_FILE, 'r', newline='', encoding='utf-8') as csvfile:
|
|
reader = csv.DictReader(csvfile, delimiter=';')
|
|
fieldnames = reader.fieldnames
|
|
rows = list(reader)
|
|
|
|
updated = False
|
|
for row in rows:
|
|
if row['token'] == token:
|
|
if lesson_name in fieldnames:
|
|
row[lesson_name] = status
|
|
updated = True
|
|
logging.info(f"Updating progress for token {token}, lesson {lesson_name}, status {status}")
|
|
else:
|
|
logging.warning(f"Lesson '{lesson_name}' not found in CSV columns: {fieldnames}")
|
|
break
|
|
|
|
if updated:
|
|
with open(TOKENS_FILE, 'w', newline='', encoding='utf-8') as csvfile:
|
|
writer = csv.DictWriter(csvfile, fieldnames=fieldnames, delimiter=';')
|
|
writer.writeheader()
|
|
writer.writerows(rows)
|
|
logging.info(f"Updated progress for token {token}, lesson {lesson_name}, status {status}")
|
|
else:
|
|
logging.warning(f"Failed to update progress for token {token}, lesson {lesson_name}")
|
|
|
|
return updated
|
|
|
|
|
|
def initialize_tokens_file(lesson_names):
|
|
"""Initialize the tokens CSV file with headers and lesson columns."""
|
|
if not os.path.exists(TOKENS_FILE):
|
|
headers = ['token', 'nama_siswa'] + lesson_names
|
|
with open(TOKENS_FILE, 'w', newline='', encoding='utf-8') as csvfile:
|
|
writer = csv.writer(csvfile, delimiter=';')
|
|
writer.writerow(headers)
|
|
print(f"Created new tokens file: {TOKENS_FILE} with headers: {headers}")
|
|
|
|
|
|
def calculate_student_completion(student_data, all_lessons):
|
|
"""Calculate the number of completed lessons for a student."""
|
|
completed_count = 0
|
|
for lesson in all_lessons:
|
|
if isinstance(lesson, dict) and 'filename' in lesson:
|
|
lesson_key = lesson['filename'].replace('.md', '')
|
|
else:
|
|
lesson_key = lesson.replace('.md', '')
|
|
|
|
if lesson_key in student_data and student_data[lesson_key] == 'completed':
|
|
completed_count += 1
|
|
return completed_count
|
|
|
|
|
|
def get_all_students_progress(all_lessons_func):
|
|
"""Get all students' progress data for the progress report.
|
|
|
|
Returns (all_students_progress, ordered_lessons).
|
|
"""
|
|
all_students_progress = []
|
|
ordered_lessons = []
|
|
lesson_headers = []
|
|
|
|
if not os.path.exists(TOKENS_FILE):
|
|
return all_students_progress, ordered_lessons
|
|
|
|
with open(TOKENS_FILE, 'r', newline='', encoding='utf-8') as csvfile:
|
|
reader = csv.DictReader(csvfile, delimiter=';')
|
|
lesson_headers = [field for field in reader.fieldnames if field not in ['token', 'nama_siswa']]
|
|
|
|
all_lessons_dict = {}
|
|
for lesson in all_lessons_func():
|
|
lesson_key = lesson['filename'].replace('.md', '')
|
|
all_lessons_dict[lesson_key] = lesson
|
|
|
|
for lesson_header in lesson_headers:
|
|
if lesson_header in all_lessons_dict:
|
|
ordered_lessons.append(all_lessons_dict[lesson_header])
|
|
else:
|
|
ordered_lessons.append({
|
|
'filename': f"{lesson_header}.md",
|
|
'title': lesson_header.replace('_', ' ').title(),
|
|
'description': 'Lesson information not available',
|
|
})
|
|
|
|
for row in reader:
|
|
student_data = dict(row)
|
|
del student_data['token']
|
|
student_data['completed_count'] = calculate_student_completion(student_data, ordered_lessons)
|
|
all_students_progress.append(student_data)
|
|
|
|
return all_students_progress, ordered_lessons
|