Menu
CoddyTech

Nền tảng học trực tuyến

Thuộc phần Lập trình hướng đối tượng trong hành trình GO của Coddy. Bài học 105 trên 107.

challenge icon

Thử thách

Dễ

Hãy cùng xây dựng một nền tảng học trực tuyến để quản lý các khóa học, học viên và theo dõi tiến độ học tập! Bạn sẽ kết hợp các struct, interface, composition và polymorphism để tạo nên một hệ thống thống nhất, nơi học viên có thể đăng ký khóa học và hoàn thành bài học.

Bạn sẽ sắp xếp code trong năm tệp:

  • lesson.go: Định nghĩa struct Lesson để biểu diễn từng đơn vị học tập. Mỗi bài học có ID, Title và Duration (tính bằng phút). Thêm hàm khởi tạo NewLesson trả về một con trỏ đến Lesson.
  • course.go: Tạo struct Course gồm ID, Title, Instructor và một slice chứa các con trỏ *Lesson. Thêm hàm khởi tạo NewCourse và phương thức AddLesson. Đồng thời triển khai phương thức TotalDuration() int trả về tổng thời lượng của tất cả bài học trong khóa học.
  • student.go: Định nghĩa struct Student với các trường ID, Name và Email. Thêm hàm khởi tạo NewStudent.
  • enrollment.go: Đây là nơi phần theo dõi tiến độ phát huy tác dụng. Tạo struct Enrollment liên kết một học viên với một khóa học và theo dõi những bài học họ đã hoàn thành. Struct này cần có:
    • Một con trỏ đến Student
    • Một con trỏ đến Course
    • Một map CompletedLessons (ID bài học ánh xạ đến giá trị boolean)

    Định nghĩa interface Progressable với phương thức Progress() float64 trả về tỷ lệ phần trăm (từ 0.0 đến 100.0).

    Triển khai các phương thức sau cho Enrollment:

    • NewEnrollment(student *Student, course *Course) *Enrollment: hàm khởi tạo tạo một map bài học đã hoàn thành rỗng
    • CompleteLesson(lessonID string) string: đánh dấu một bài học là đã hoàn thành. Trả về lesson not found nếu bài học không tồn tại trong khóa học, already completed nếu bài học đã hoàn thành, hoặc completed nếu thành công
    • Progress() float64: trả về tỷ lệ phần trăm bài học đã hoàn thành (số bài đã hoàn thành/tổng số bài * 100), hoặc 0.0 nếu khóa học không có bài học
  • main.go: Xây dựng nền tảng và xử lý các thao tác đăng ký.

    Đọc ID, tiêu đề và giảng viên của khóa học. Sau đó đọc số lượng bài học cùng ID, tiêu đề và thời lượng của từng bài. Đọc ID, tên và email của học viên. Tạo một lượt đăng ký liên kết học viên với khóa học.

    Sau đó đọc số lượng thao tác. Mỗi thao tác là complete [lessonID] hoặc progress. Với thao tác hoàn thành, hãy in thông báo kết quả. Với thao tác xem tiến độ, hãy in tiến độ với một chữ số thập phân, theo sau là dấu phần trăm.

Đầu vào sẽ có dạng như sau:

  • ID khóa học, tiêu đề, giảng viên (3 dòng)
  • Số lượng bài học, sau đó là ID, tiêu đề, thời lượng của từng bài học (mỗi bài 3 dòng)
  • ID, tên, email học viên (3 dòng)
  • Số lượng thao tác, sau đó là từng thao tác (mỗi thao tác 1 dòng)

Ví dụ, với đầu vào:

C001
Go Fundamentals
Jane Smith
3
L001
Variables
30
L002
Functions
45
L003
Structs
60
S001
Alice
alice@learn.com
5
progress
complete L001
progress
complete L001
complete L002

Kết quả đầu ra sẽ là:

0.0%
completed
33.3%
already completed
completed

Và với đầu vào:

C100
Python Basics
Bob Teacher
2
L100
Intro
20
L101
Loops
40
S100
Charlie
charlie@edu.com
4
complete L999
complete L100
complete L101
progress

Kết quả đầu ra sẽ là:

lesson not found
completed
completed
100.0%

Lưu ý cách struct Enrollment dùng composition để liên kết học viên với khóa học, còn interface Progressable cho phép mọi kiểu báo cáo trạng thái hoàn thành. Thiết kế này giúp bạn dễ dàng mở rộng. Bạn có thể thêm tính năng theo dõi tiến độ cho từng bài học hoặc toàn bộ lộ trình học bằng cùng interface!

Tự làm thử

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

func main() {
	scanner := bufio.NewScanner(os.Stdin)

	// Hàm (function) hỗ trợ đọc một dòng
	readLine := func() string {
		scanner.Scan()
		return strings.TrimSpace(scanner.Text())
	}

	// Đọc thông tin khóa học
	courseID := readLine()
	courseTitle := readLine()
	courseInstructor := readLine()

	// TODO: Tạo khóa học bằng NewCourse
	_ = courseID
	_ = courseTitle
	_ = courseInstructor

	// Đọc số lượng bài học
	numLessons, _ := strconv.Atoi(readLine())

	// TODO: Đọc từng bài học và thêm vào khóa học
	for i := 0; i < numLessons; i++ {
		lessonID := readLine()
		lessonTitle := readLine()
		lessonDuration, _ := strconv.Atoi(readLine())

		// TODO: Tạo bài học và thêm vào khóa học
		_ = lessonID
		_ = lessonTitle
		_ = lessonDuration
	}

	// Đọc thông tin học viên
	studentID := readLine()
	studentName := readLine()
	studentEmail := readLine()

	// TODO: Tạo học viên bằng NewStudent
	_ = studentID
	_ = studentName
	_ = studentEmail

	// TODO: Tạo bản ghi đăng ký liên kết học viên với khóa học

	// Đọc số lượng thao tác
	numOps, _ := strconv.Atoi(readLine())

	// Xử lý từng thao tác
	for i := 0; i < numOps; i++ {
		operation := readLine()

		if operation == "progress" {
			// TODO: Gọi Progress() và in ra theo định dạng "%.1f%%"
			fmt.Println("0.0%") // Thay bằng tiến độ thực tế
		} else if strings.HasPrefix(operation, "complete ") {
			lessonID := strings.TrimPrefix(operation, "complete ")
			// TODO: Gọi CompleteLesson và in ra kết quả
			_ = lessonID
			fmt.Println("") // Thay bằng kết quả thực tế
		}
	}
}

Tất cả bài học trong Lập trình hướng đối tượng

Tự luyện tập: Trình biên dịch Go online