Bỏ qua menu, tới nội dung
Thành viên The MONA Group
Thành viên The MONA Group
Sản phẩm và viết theo yêu cầu
1900 636 648Tư vấn miễn phí, 8h–22h
MONA OS 2.0Hệ thống quản trị MONA tự phát triển, nối 7 phần mềm nội bộ về một dữ liệu, có Gấu Quản Trị trả lời câu hỏi điều hành.7 phần mềm1 trục dữ liệu8 AI AgentXem MONA OS hoạt động
Dự án giáo dụcThe IELTS WorkshopPhần mềm quản lý chuỗi 11 cơ sở luyện thi, kèm app cho học viên20238 tháng12 ngườiXem hồ sơ dự án Xem thêm dự án Khoa Y
Dự án bán lẻHình minh hoạ gấu MONA bán trang sức tại quầy kính, cạnh màn hình bán hàng và tồn khoNgọc Thành JewelryPhần mềm quản lý chuỗi cửa hàng trang sức, tích hợp xuất hoá đơn20246 tháng7 ngườiXem hồ sơ dự án
Dự án sản xuấtHình minh hoạ gấu MONA hướng dẫn công nhân học bài trên phần mềm đào tạo trong phòng họp nhà máyPolytex Far Eastern Việt NamPhần mềm đào tạo công nhân viên chạy trong mạng nội bộ nhà máy20234 tháng8 ngườiXem hồ sơ dự án
Dự án nhân sựHình minh hoạ gấu MONA đứng lớp đào tạo cho bác sĩ, điều dưỡng bằng phần mềm học trực tuyếnBệnh viện Hoàn Mỹ Sài GònViệc đào tạo nhân sự chuyển từ Excel sang phần mềm MONA viết riêng20247 tuần13 moduleXem hồ sơ dự án
Sản phẩm có sẵnHình minh hoạ gấu MONA phục vụ bàn, khách quét mã QR trên bàn để gọi mónnhahang.aiGọi món tại bàn bằng mã QR, kết nối bếp, quản lý bàn, định lượng nguyên liệuNhà hàngQuán ănChuỗi ăn uốngXem nhahang.ai
Sản phẩm có sẵnMONA HouseTự lập hoá đơn tiền phòng, gửi mã QR qua Zalo, báo có khi khách chuyển khoảnNhà trọCăn hộ cho thuêXem MONA House
Sản phẩm có sẵnMONA NHTQĐặt hàng Taobao, 1688, Tmall, ví khách hàng và theo dõi vận đơn cho công ty nhập hàngTaobao1688TmallXem MONA NHTQ
Tư vấn miễn phí, 8h–22h mỗi ngày
Kiến thức phần mềm

Quy đổi điểm 10 sang điểm chữ và thang 4, tính điểm trung bình học kỳ trong phần mềm đào tạo

Lê Minh NhựtCập nhật · Đăng · 19 phút đọc

Quy đổi điểm 10 sang điểm chữ và thang 4, tính điểm trung bình học kỳ trong phần mềm đào tạo

Theo Thông tư 56/2026/TT-BGDĐT của Bộ Giáo dục và Đào tạo (ký ngày 07/07/2026), điểm học phần thang 10 được làm tròn đến phần trăm rồi xếp loại như sau. A từ 8,50 đến 10 (quy đổi thành 4), B từ 7,00 đến 8,49 (3), C từ 5,50 đến 6,99 (2), D từ 4,00 đến 5,49 (1) và F dưới 4,00 (0). Điểm trung bình học kỳ bằng tổng của điểm thang 4 nhân số tín chỉ, chia cho tổng tín chỉ của các học phần được tính, làm tròn đến phần trăm. Văn bản và số liệu trong bài tra ngày 03/11/2026 trên bản PDF có chữ ký của moet.gov.vn. Bài đọc khung quốc gia; quy chế của từng trường có thể khác ở các điểm mà Điều 12 khoản 6 giao cho trường quy định (ngưỡng điểm đạt cao hơn, thêm mức điểm chữ, thi lại, học lại để cải thiện và quy tắc chọn điểm khi điểm lần sau thấp hơn); vì vậy mọi con số bên dưới nằm trong cấu hình, không viết cứng vào mã.

Điểm làm tròn là chỗ phần mềm hay sai nhất. Ba điểm thành phần 8,0 (20%), 8,5 (30%) và 8,69 (50%) cho đúng 8,495: làm tròn lên khi phần dư từ 5 (ROUND_HALF_UP) ra A, cắt bỏ phần dư (ROUND_DOWN) ra B. Thông tư chỉ ghi “làm tròn đến phần trăm” mà không nêu kiểu làm tròn, người viết phần mềm phải chọn và ghi rõ lựa chọn đó. Bộ hàm Python 3.9 dùng module decimal bên dưới đã chạy thật, và mọi kết quả in ra là kết quả của lần chạy đó.

Thông tư nào đang có hiệu lực và áp dụng cho khóa nào

Thông tư 56/2026/TT-BGDĐT ban hành Quy chế đào tạo trình độ đại học. Điều 2 của thông tư ghi hiệu lực từ ngày 07/7/2026 và thay thế Thông tư 08/2021/TT-BGDĐT (18/3/2021) cùng Thông tư 28/2023/TT-BGDĐT (28/12/2023, đào tạo từ xa). Tra ngày 03/11/2026, MONA không thấy văn bản nào thay thế hay sửa đổi thông tư mới này. Quy chế gồm 27 điều, và bài dùng ba điều: Điều 12 (điểm học phần), Điều 13 (điểm trung bình và xếp loại) và Điều 27 (chuyển tiếp).

Điều 2 Thông tư 56/2026 nêu hiệu lực tháng 7/2026 và thay Thông tư 08/2021
Trang đầu bản PDF ký của Thông tư 56/2026/TT-BGDĐT: ngày ký 07/07/2026, Điều 2 nêu hiệu lực và hai thông tư bị thay thế. Nguồn: moet.gov.vn, chụp ngày 03/11/2026.

Điều 27 quyết định khóa nào dùng quy chế nào, nên phần mềm phải lưu quy chế theo khóa tuyển sinh, không đặt một hằng số cho cả hệ thống:

Đối tượng Quy chế áp dụng Căn cứ
Khóa tuyển sinh năm 2026, học từ năm học 2026 – 2027 Thông tư 56/2026 Điều 27 khoản 1
Khóa đã có thông báo tuyển sinh trước ngày thông tư có hiệu lực Quy chế có hiệu lực lúc thông báo tuyển sinh Điều 27 khoản 2
Trường chọn dùng sớm quy định mới có lợi hơn cho người học Được phép trong thời gian chuyển tiếp, phải bảo đảm chất lượng và trách nhiệm giải trình Điều 27 khoản 4
Quy chế nội bộ của trường Rà soát và ban hành trước ngày 31/12/2026 Điều 27 khoản 4

MONA chưa mở được bản gốc của Thông tư 08/2021 (liên kết vbpl.vn trả lỗi 404, các trang luật chặn công cụ tải tự động), vì vậy bài không trích điều khoản nào của thông tư cũ. Cách tính theo khung cũ chỉ xuất hiện ở dạng quy chế của một trường làm theo khung đó: Quy chế đào tạo trình độ đại học của Trường Đại học Nguyễn Tất Thành (Quyết định 859/QĐ-NTT, 26/07/2021), tra ngày 03/11/2026. Quy chế này dùng cùng bảng A đến F nhưng làm tròn điểm học phần đến một chữ số thập phân ở Điều 15 khoản 2.

Bảng quy đổi điểm 10, điểm chữ và thang 4 để nhập vào cấu hình

Điều 12 khoản 4 xếp điểm học phần thành năm mức, và Điều 13 khoản 2 quy đổi mỗi mức ra thang 4. Hai khoản cùng nằm trên bản PDF có chữ ký, ảnh chụp hai trang đó đặt ngay dưới bảng:

Điểm chữ Thang 10 (đã làm tròn) Thang 4 Tính vào điểm trung bình
A 8,50 đến 10,0 4 Có
B 7,00 đến 8,49 3 Có
C 5,50 đến 6,99 2 Có
D 4,00 đến 5,49 1 Có
F Dưới 4,00 0 Có, tính là 0
P Từ 5,00, học phần chỉ yêu cầu đạt Không quy đổi Không
I, X, R Hoãn thi (I), chưa đủ dữ liệu (X), miễn học và công nhận tín chỉ (R) Không quy đổi Không
Khoản 4 Điều 12 Thông tư 56/2026 xếp điểm học phần thành mức A, B, C, D
Khoản 3 và 4 Điều 12: vắng thi không lý do nhận 0, điểm học phần làm tròn đến phần trăm, bốn mức đạt có phân mức. Nguồn: bản PDF ký của Thông tư 56/2026 trên moet.gov.vn, chụp ngày 03/11/2026.
Khoản 2 và 3 Điều 13 Thông tư 56/2026 quy đổi điểm chữ sang thang 4
Khoản 2 và 3 Điều 13: A đến F quy đổi thành 4 đến 0, điểm chữ ngoài danh sách và học phần ngoài chương trình không tính vào điểm trung bình. Nguồn: bản PDF ký của Thông tư 56/2026 trên moet.gov.vn, chụp ngày 03/11/2026.

Bảng nằm trong mã dưới dạng dữ liệu, mỗi dòng chỉ giữ cận dưới của thang 10. Giữ cận dưới thì không có khoảng hở giữa 8,49 và 8,50 cho một điểm như 8,495 lọt vào, và đổi sang quy chế khác chỉ cần đổi dữ liệu. Điều 13 khoản 2 cho phép trường quy định thêm điểm chữ nhiều mức hơn; khi đó thêm dòng vào danh sách với điểm thang 4 do trường quy định. Hàm tra bảng duyệt từ trên xuống và dừng ở dòng đầu tiên có cận dưới nhỏ hơn hoặc bằng điểm, nên danh sách phải xếp từ cao xuống thấp. Danh sách xếp loại học lực của Điều 13 khoản 5 cũng để dạng dữ liệu vì cũng chỉ có cận dưới. Học phần P không xếp vào A đến D: Điều 12 khoản 4 điểm b dành P cho học phần chỉ yêu cầu đạt, ngưỡng đạt 5,00, còn D vẫn là mức đạt có phân mức của học phần được tính điểm.

from decimal import Decimal as D, ROUND_HALF_UP, ROUND_HALF_EVEN, ROUND_DOWN

# Bảng quy đổi là dữ liệu: (điểm chữ, cận dưới của thang 10, điểm thang 4). Thứ tự từ cao xuống thấp.
BANDS_TT56 = [("A", D("8.50"), D(4)), ("B", D("7.00"), D(3)), ("C", D("5.50"), D(2)),
              ("D", D("4.00"), D(1)), ("F", D("0.00"), D(0))]        # TT 56/2026 Điều 12 k4, Điều 13 k2

# Mỗi cấu hình quy chế: làm tròn mấy chữ số, theo kiểu nào, dùng bảng nào.
SCHEME_TT56 = {"places": 2, "rounding": ROUND_HALF_UP, "bands": BANDS_TT56}
SCHEME_ONE_DECIMAL = {"places": 1, "rounding": ROUND_HALF_UP, "bands": BANDS_TT56}  # quy chế trường làm tròn 1 chữ số

# Xếp loại học lực theo điểm trung bình thang 4 (TT 56/2026 Điều 13 khoản 5a).
RANKS_4 = [(D("3.60"), "Xuất sắc"), (D("3.20"), "Giỏi"), (D("2.50"), "Khá"),
           (D("2.00"), "Trung bình"), (D("1.00"), "Yếu"), (D("0.00"), "Kém")]

Tính điểm học phần từ điểm thành phần và trọng số

Điều 12 khoản 1 yêu cầu mỗi học phần có ít nhất ba điểm thành phần, trong đó điểm thi cuối kỳ có trọng số từ 50%. Học phần dưới 2 tín chỉ được có hai điểm, đồ án hoặc khóa luận tốt nghiệp được có một điểm. Khoản 3 quy định sinh viên vắng không có lý do chính đáng nhận 0, còn vắng có lý do thì thi đợt khác và được tính là điểm lần đầu. Hàm check_components kiểm các điều kiện về số điểm và trọng số trước khi cho nhập điểm; quy ước trong mã là mục cuối của danh sách thành phần chính là điểm thi cuối kỳ. Hàm chỉ kiểm học phần có từ hai điểm thành phần; đồ án và khóa luận tốt nghiệp, được phép có một điểm, cần một nhánh kiểm riêng. Cách trộn đề trắc nghiệm để các thí sinh cùng phòng nhận đề khác nhau có ở bài trộn đề thi trắc nghiệm.

def quantum(places):
    return D(1).scaleb(-places)                  # places=2 -> Decimal('0.01')

def course_score(components, scheme):
    """components: [(điểm thang 10 dạng chuỗi, trọng số dạng chuỗi), ...] -> điểm học phần đã làm tròn."""
    total = sum(D(s) * D(w) for s, w in components)
    return total.quantize(quantum(scheme["places"]), rounding=scheme["rounding"])

def letter_and_point(score, scheme):
    for letter, low, point in scheme["bands"]:
        if score >= low:
            return letter, point
    raise ValueError(f"điểm {score} nằm ngoài thang 0 đến 10")

def check_components(components, credits):
    """Trả về danh sách lỗi theo TT 56/2026 Điều 12 khoản 1 (rỗng là hợp lệ)."""
    errors, weights = [], [D(w) for _, w in components]
    if sum(weights) != D(1):
        errors.append(f"tổng trọng số {sum(weights)}, phải bằng 1")
    if len(components) < 3 and D(credits) >= 2:
        errors.append(f"{len(components)} điểm thành phần, học phần từ 2 tín chỉ cần ít nhất 3")
    if D(components[-1][1]) < D("0.5"):
        errors.append(f"điểm thi cuối kỳ (mục cuối) có trọng số {components[-1][1]}, phải từ 0.5")
    return errors

Năm ca kiểm trọng số cho học phần 3 tín chỉ và 1 tín chỉ, rồi chín điểm quanh các cận của bảng:

Kiểm trọng số điểm thành phần
đủ 3 điểm, thi cuối 50%: hợp lệ
thi cuối 40%: ['điểm thi cuối kỳ (mục cuối) có trọng số 0.4, phải từ 0.5']
chỉ 2 điểm, học phần 3 tín chỉ: ['2 điểm thành phần, học phần từ 2 tín chỉ cần ít nhất 3']
chỉ 2 điểm, học phần 1 tín chỉ: hợp lệ
tổng trọng số 0.9: ['tổng trọng số 0.9, phải bằng 1']
Điểm học phần, điểm chữ, điểm thang 4
10.00 ('A', Decimal('4'))
8.50 ('A', Decimal('4'))
8.49 ('B', Decimal('3'))
7.00 ('B', Decimal('3'))
6.99 ('C', Decimal('2'))
5.50 ('C', Decimal('2'))
4.00 ('D', Decimal('1'))
3.99 ('F', Decimal('0'))
0.00 ('F', Decimal('0'))

Điểm 8,49 ra B, 8,50 ra A, 3,99 ra F và 4,00 ra D: hàm so sánh điểm đã làm tròn với cận dưới, không so điểm chưa làm tròn.

Làm tròn: cùng một điểm, hai quy tắc, hai điểm chữ

Điều 12 khoản 4 chỉ nói điểm học phần “được làm tròn đến phần trăm”. Tài liệu Python liệt kê từng kiểu làm tròn một câu: ROUND_HALF_UP đưa điểm nằm đúng giữa hai số về phía xa số 0, ROUND_HALF_EVEN đưa về số chẵn gần nhất, ROUND_DOWN cắt về phía số 0. Mặc định của module decimal là ROUND_HALF_EVEN.

Tài liệu Python 3.9 liệt kê các kiểu làm tròn của module decimal như ROUND_HALF_UP và ROUND_DOWN
Danh sách hằng số làm tròn của module decimal trong tài liệu Python 3.9. Nguồn: docs.python.org, chụp ngày 03/11/2026.

MONA chọn ROUND_HALF_UP cho điểm học phần: phần dư đúng bằng 5 thì làm tròn lên. Đây là lựa chọn của MONA, thông tư không quy định. Với điểm thành phần 8,0 (20%), 8,5 (30%) và 8,69 (50%), tổng đúng bằng 8,495:

comps = [("8.0", "0.2"), ("8.5", "0.3"), ("8.69", "0.5")]
exact = sum(D(s) * D(w) for s, w in comps)
print("tổng chính xác:", exact)
for name, rounding in [("ROUND_HALF_UP (quy tròn)", ROUND_HALF_UP), ("ROUND_HALF_EVEN (mặc định của decimal)", ROUND_HALF_EVEN), ("ROUND_DOWN (cắt bỏ)", ROUND_DOWN)]:
    sc = dict(SCHEME_TT56, rounding=rounding)
    score = course_score(comps, sc)
    print(f"{name}: {score} -> {letter_and_point(score, sc)[0]}")
f = 8.0 * 0.2 + 8.5 * 0.3 + 8.69 * 0.5
print("float:", repr(f), "round(f, 2) =", round(f, 2))
Biên A/B: thành phần 8.0 (20%), 8.5 (30%), 8.69 (50%)
tổng chính xác: 8.495
ROUND_HALF_UP (quy tròn): 8.50 -> A
ROUND_HALF_EVEN (mặc định của decimal): 8.50 -> A
ROUND_DOWN (cắt bỏ): 8.49 -> B
float: 8.495000000000001 round(f, 2) = 8.5

ROUND_HALF_UP và ROUND_HALF_EVEN cùng cho 8,50 nên ra A, còn ROUND_DOWN cho 8,49 nên ra B. Trường nào ghi trong quy chế là cắt bỏ thì đặt rounding của cấu hình thành ROUND_DOWN và cùng điểm đó thành B. Kiểu làm tròn là một khóa riêng của từng quy chế, đổi kiểu không phải sửa hàm tính. Ở bốn cận của bảng (8,495; 6,995; 5,495; 3,995) chữ số đứng trước số 5 luôn là 9, nên ROUND_HALF_EVEN cho kết quả giống ROUND_HALF_UP; kết quả chạy ở mục tiếp theo xác nhận điều đó.

Biến điểm sang float gây lỗi ở đúng các cận này. Python lưu 0,15 hay 6,8 dưới dạng nhị phân gần đúng, và tài liệu decimal nêu ví dụ 1,1 + 2,2 hiển thị là 3,3000000000000003. Ca kiểm với thành phần 4,1 (15%), 6,8 (35%) và 8,0 (50%):

comps4 = [("4.1", "0.15"), ("6.8", "0.35"), ("8.0", "0.5")]
print("Decimal, tổng chính xác:", sum(D(s) * D(w) for s, w in comps4))
sc = SCHEME_TT56
score = course_score(comps4, sc)
print("Decimal:", score, "->", letter_and_point(score, sc)[0])
f4 = 4.1 * 0.15 + 6.8 * 0.35 + 8.0 * 0.5
print("float:", repr(f4), "-> round(f, 2) =", round(f4, 2), "->", letter_and_point(D(str(round(f4, 2))), sc)[0])
print("ROUND_HALF_EVEN cho 8.495, 6.995, 5.495, 3.995:",
      [str(D(x).quantize(D("0.01"), rounding=ROUND_HALF_EVEN)) for x in ["8.495", "6.995", "5.495", "3.995"]])
Biên B/C với float: thành phần 4.1 (15%), 6.8 (35%), 8.0 (50%)
Decimal, tổng chính xác: 6.995
Decimal: 7.00 -> B
float: 6.994999999999999 -> round(f, 2) = 6.99 -> C
ROUND_HALF_EVEN cho 8.495, 6.995, 5.495, 3.995: ['8.50', '7.00', '5.50', '4.00']

Tổng chính xác là 6,995 nên điểm học phần là 7,00 và xếp loại B; bản dùng float cho 6,99 và xếp loại C, một sinh viên bị hạ cả điểm chữ lẫn điểm thang 4. Hai số chỉ chênh nhau cỡ một phần triệu tỷ, vậy mà đủ để điểm rơi xuống mức bên dưới. Vì thế các ca kiểm tự động phải đặt đúng ở bốn cận x,495 (8,495; 6,995; 5,495; 3,995) cho mọi cấu hình quy chế. Nhận điểm bằng chuỗi hay Decimal từ cơ sở dữ liệu, không nhận float. Cách làm tương tự dùng cho tiền điện nước ở bài tính tiền điện nước nhà trọ trong phần mềm.

Số chữ số cũng là cấu hình. Quy chế của Trường Đại học Nguyễn Tất Thành làm tròn điểm học phần đến một chữ số thập phân, trong khi Thông tư 56/2026 làm tròn đến hai chữ số. Điểm 8,45 cho hai kết quả:

c8 = [("8.45", "1")]
for name, sc in [("2 chữ số (TT 56/2026)", SCHEME_TT56), ("1 chữ số (quy chế trường)", SCHEME_ONE_DECIMAL)]:
    score = course_score(c8, sc)
    print(f"{name}: {score} -> {letter_and_point(score, sc)[0]}")
Cùng điểm 8.45, hai cách làm tròn của quy chế
2 chữ số (TT 56/2026): 8.45 -> B
1 chữ số (quy chế trường): 8.5 -> A

Cùng điểm 8,45, quy chế làm tròn hai chữ số xếp B (thang 4 là 3), quy chế làm tròn một chữ số đưa thành 8,5 và xếp A (thang 4 là 4). Điểm thang 4 của học phần đó chênh 1, nên điểm trung bình của sinh viên lệch theo số tín chỉ của học phần; vì vậy mỗi khóa tuyển sinh phải gắn đúng cấu hình của quy chế đang áp dụng cho khóa. Khóa tuyển sinh trước và từ năm 2026 trong cùng một trường có thể phải chạy hai cấu hình song song, vì Điều 27 giữ quy chế cũ cho khóa cũ.

Điểm trung bình học kỳ, tích lũy và xếp loại học lực

Điều 13 khoản 1 điểm c định nghĩa ba loại điểm trung bình: của học kỳ, của năm học và chung tích lũy từ đầu khóa. Cả ba tính theo điểm chính thức của học phần với trọng số là số tín chỉ. Điều 13 khoản 5 làm tròn điểm trung bình đến hàng phần trăm rồi xếp loại thang 4 từ Xuất sắc (3,60 đến 4,0) đến Kém (dưới 1,00). Cơ sở đào tạo theo niên chế và dùng thang 10 thì tính điểm trung bình ngay trên thang 10 (khoản 4).

Ba hàm sau tính điểm trung bình, số tín chỉ tích lũy và xếp loại. Số tín chỉ tích lũy tính cả học phần P đạt và học phần được miễn R (điểm b khoản 1), còn học phần ngoài chương trình bị bỏ (khoản 3):

# Một học phần: {"code", "credits", "attempts": [điểm học phần mỗi lần học], "kind", "special"}
#   kind    = "graded" (tính vào điểm TB), "pass_only" (chỉ cần đạt, P), "outside" (ngoài chương trình)
#   special = None, "I", "X" hoặc "R": các điểm chữ không tính vào điểm TB (Điều 12 k4 điểm đ, Điều 13 k3)
def pick_attempt(attempts, policy):
    """Quy tắc chọn điểm chính thức khi học lại do từng trường quy định (Điều 12 khoản 6 điểm g)."""
    return {"latest": attempts[-1], "first": attempts[0], "highest": max(attempts)}[policy]

def counted(course):
    return course["kind"] == "graded" and course.get("special") is None and course["attempts"]

def gpa(courses, scheme, policy="latest"):
    """Điểm trung bình thang 4, làm tròn 2 chữ số, trọng số là số tín chỉ. None nếu chưa có học phần nào được tính."""
    points = credits = D(0)
    for c in filter(counted, courses):
        _, point = letter_and_point(pick_attempt(c["attempts"], policy), scheme)
        points += point * D(c["credits"])
        credits += D(c["credits"])
    return None if credits == 0 else (points / credits).quantize(D("0.01"), rounding=ROUND_HALF_UP)

def credits_earned(courses, scheme, policy="latest"):
    """Số tín chỉ tích lũy: học phần đạt, kể cả P và R (Điều 13 khoản 1 điểm b); học phần ngoài chương trình thì bỏ."""
    total = D(0)
    for c in courses:
        if c["kind"] == "outside":
            continue
        if c.get("special") == "R":
            total += D(c["credits"])
        elif c.get("special") is None and c["attempts"]:
            score = pick_attempt(c["attempts"], policy)
            ok = score >= D("5.00") if c["kind"] == "pass_only" else letter_and_point(score, scheme)[0] != "F"
            total += D(c["credits"]) if ok else 0
    return total

def rank(gpa4):
    return next(name for low, name in RANKS_4 if gpa4 >= low)

Học kỳ mẫu có tám dòng: ba học phần đạt, một học phần rớt rồi học lại, một học phần chỉ cần đạt (P), một học phần hoãn thi (I), một học phần được miễn (R) và một học phần ngoài chương trình. Ba tín chỉ hoãn thi và hai tín chỉ ngoài chương trình không vào điểm trung bình:

sem = [
    {"code": "MAT101", "credits": "3", "attempts": [D("8.51")], "kind": "graded"},
    {"code": "INF201", "credits": "4", "attempts": [D("7.20")], "kind": "graded"},
    {"code": "ENG102", "credits": "2", "attempts": [D("5.50")], "kind": "graded"},
    {"code": "PHY110", "credits": "3", "attempts": [D("3.90"), D("6.00")], "kind": "graded"},   # rớt rồi học lại
    {"code": "PED100", "credits": "1", "attempts": [D("6.00")], "kind": "pass_only"},         # chỉ cần đạt (P)
    {"code": "CHE105", "credits": "3", "attempts": [], "kind": "graded", "special": "I"},     # hoãn thi
    {"code": "ENG101", "credits": "3", "attempts": [], "kind": "graded", "special": "R"},     # miễn, công nhận tín chỉ
    {"code": "CLB001", "credits": "2", "attempts": [D("9.00")], "kind": "outside"},           # ngoài chương trình
]
print("GPA:", gpa(sem, SCHEME_TT56), "| tín chỉ tích lũy:", credits_earned(sem, SCHEME_TT56), "| xếp loại:", rank(gpa(sem, SCHEME_TT56)))
check = (4 * 3 + 3 * 4 + 2 * 2 + 2 * 3) / D(3 + 4 + 2 + 3)
print("kiểm tay (12+12+4+6)/12 =", check)
print("cùng học kỳ, chọn điểm lần đầu:", gpa(sem, SCHEME_TT56, "first"))
Học kỳ mẫu
GPA: 2.83 | tín chỉ tích lũy: 16 | xếp loại: Khá
kiểm tay (12+12+4+6)/12 = 2.833333333333333333333333333
cùng học kỳ, chọn điểm lần đầu: 2.33

Kiểm tay: (4 x 3 + 3 x 4 + 2 x 2 + 2 x 3) chia 12 tín chỉ bằng 2,8333, làm tròn thành 2,83, xếp loại Khá vì nằm trong khoảng 2,50 đến 3,19. Kết quả khớp phép tính tay. Tín chỉ tích lũy 16 gồm 12 tín chỉ của bốn học phần có điểm đạt, 1 tín chỉ của học phần P và 3 tín chỉ được miễn. Học phần PHY110 có hai lần học là 3,90 rồi 6,00, và chính sách lấy lần cuối cho nó 6,00 là C. Nếu trường lấy điểm lần đầu, 3,90 là F và điểm trung bình học kỳ này giảm xuống 2,33.

Hai ca kiểm tiếp theo là điểm trung bình có phần dư và xếp loại tại các biên:

c9 = [{"code": "a", "credits": "3", "attempts": [D("9")], "kind": "graded"},
      {"code": "b", "credits": "3", "attempts": [D("7.5")], "kind": "graded"},
      {"code": "c", "credits": "3", "attempts": [D("8")], "kind": "graded"},
      {"code": "d", "credits": "2", "attempts": [D("6")], "kind": "graded"}]
print("chưa làm tròn:", D(4 * 3 + 3 * 3 + 3 * 3 + 2 * 2) / D(11), "-> gpa():", gpa(c9, SCHEME_TT56))
g = D("3.595")
print("điểm trung bình 3.595 -> HALF_UP:", rank(g.quantize(D("0.01"), rounding=ROUND_HALF_UP)), "| ROUND_DOWN:", rank(g.quantize(D("0.01"), rounding=ROUND_DOWN)))
for g in ["3.60", "3.59", "3.20", "2.50", "2.00", "1.00", "0.99"]:
    print(g, rank(D(g)))
Điểm trung bình có phần dư: A 3 tín chỉ, B 3 tín chỉ, B 3 tín chỉ, C 2 tín chỉ
chưa làm tròn: 3.090909090909090909090909091 -> gpa(): 3.09
điểm trung bình 3.595 -> HALF_UP: Xuất sắc | ROUND_DOWN: Giỏi
Xếp loại tại các biên
3.60 Xuất sắc
3.59 Giỏi
3.20 Giỏi
2.50 Khá
2.00 Trung bình
1.00 Yếu
0.99 Kém

Điểm trung bình 3,595 qua ROUND_HALF_UP thành 3,60 và xếp Xuất sắc, qua ROUND_DOWN thành 3,59 và xếp Giỏi, nên điểm trung bình cần cùng một cấu hình làm tròn với điểm học phần. Ở các biên xếp loại, 3,60 là Xuất sắc còn 3,59 là Giỏi, 2,00 là Trung bình còn 1,00 là Yếu.

Học lại, cải thiện điểm và học phần không tính vào điểm trung bình

Điều 12 khoản 5 cho hai trường hợp học lại: học phần không đạt thì phải đăng ký học lại, học phần đã đạt thì được đăng ký học lại để cải thiện điểm theo quy định của trường. Khoản 6 điểm g giao cho trường quy định việc cho phép học lại để cải thiện và quy tắc tính điểm chính thức khi điểm lần sau thấp hơn. Thông tư không nói điểm chính thức là điểm lần cuối, lần cao nhất hay lần đầu, nên hàm pick_attempt nhận quy tắc làm tham số. Quy tắc này do từng trường quyết định.

Quy chế của Trường Đại học Nguyễn Tất Thành (Điều 16 khoản 4) cho thấy một trường có thể dùng hai quy tắc cùng lúc: điểm trung bình học kỳ để xét học bổng và khen thưởng chỉ tính điểm lần thi thứ nhất, còn điểm trung bình học kỳ và tích lũy để xét thôi học, xếp hạng học lực và tốt nghiệp tính theo điểm cao nhất trong các lần thi. Phần mềm vì thế gọi cùng hàm gpa với policy khác nhau theo mục đích dùng. Nếu hệ thống chỉ in một điểm trung bình duy nhất, bảng điểm và thông báo học bổng của cùng sinh viên sẽ lệch nhau. Hai ca kiểm cho một học phần 3 tín chỉ:

for label, attempts in [("rớt 3.90 rồi đạt 6.00", [D("3.90"), D("6.00")]),
                        ("cải thiện: 7.20 rồi 6.10", [D("7.20"), D("6.10")])]:
    row = []
    for policy in ["latest", "first", "highest"]:
        c = [{"code": "X", "credits": "3", "attempts": attempts, "kind": "graded"}]
        row.append(f"{policy}={gpa(c, SCHEME_TT56, policy)}")
    print(label, "->", ", ".join(row))
Học lại: ba cách chọn điểm chính thức
rớt 3.90 rồi đạt 6.00 -> latest=2.00, first=0.00, highest=2.00
cải thiện: 7.20 rồi 6.10 -> latest=2.00, first=3.00, highest=3.00

Ca rớt 3,90 rồi đạt 6,00: lấy điểm lần đầu thì điểm trung bình là 0,00, lấy lần cuối hoặc cao nhất thì 2,00. Ca cải thiện 7,20 rồi 6,10: lấy lần cuối cho 2,00, lấy lần đầu hoặc cao nhất cho 3,00, nghĩa là học lại để cải thiện mà điểm thấp hơn thì mất 1 điểm nếu trường lấy lần cuối. Ghi quy tắc của trường thành một tham số cấu hình và hiển thị nó trên bảng điểm để sinh viên biết điểm nào đang được tính.

Mỗi loại học phần trong bảng dưới có hai câu hỏi riêng: có vào điểm trung bình không, và có cộng vào tín chỉ tích lũy không. Hai câu trả lời không luôn trùng nhau. Học phần P và học phần F cho thấy điều đó:

Học phần Vào điểm trung bình Vào tín chỉ tích lũy Căn cứ
Điểm A đến D Có Có Điều 12 khoản 4 điểm a
Điểm F Có, tính là 0 Không Điều 12 khoản 4 điểm c
P (chỉ cần đạt, từ 5,00) Không Có Điều 12 khoản 4 điểm b
R (miễn học, công nhận tín chỉ) Không Có Điều 12 khoản 4 điểm đ, Điều 13 khoản 1 điểm b
I, X (chưa hoàn thiện) Không Chưa Điều 12 khoản 4 điểm đ
Học phần ngoài chương trình đào tạo Không Không Điều 13 khoản 3

Với I và X, cột tín chỉ tích lũy ghi “Chưa” vì thông tư chỉ nói hai điểm này chưa hoàn thiện; theo cách MONA hiểu, khi có điểm chính thức thì học phần vào các tính toán như học phần đã có điểm. Cách hệ thống đưa I hoặc X về điểm chính thức (thời hạn, người xác nhận) do quy chế của trường quy định, và MONA không có căn cứ để viết thay.

Hỏi đáp

Điểm 8,45 thang 10 thành điểm chữ gì?

Theo Thông tư 56/2026, điểm học phần 8,45 nằm trong khoảng 7,00 đến 8,49 nên là B, thang 4 là 3. Quy chế làm tròn một chữ số thập phân sẽ đưa 8,45 thành 8,5 và xếp A, như ca kiểm ở mục làm tròn; trường nào dùng cách đó phải ghi trong quy chế của trường.

Có cần thêm điểm chữ B+, C+, D+ không?

Thông tư 56/2026 chỉ nêu A, B, C, D, F. Điều 13 khoản 2 cho phép trường quy định điểm chữ nhiều mức hơn và quy đổi sang điểm số từ 0 đến 4, vì vậy các mức đó là dữ liệu của trường. MONA không đưa bảng B+ nào vào bài vì không có văn bản quốc gia để dẫn, và mỗi dòng thêm vào cần phòng đào tạo của trường xác nhận bằng văn bản.

Học phần P có tính vào điểm trung bình không?

Không. Điều 12 khoản 4 điểm b định nghĩa P là loại đạt không phân mức, dùng cho học phần chỉ yêu cầu đạt (từ 5,00 trở lên) và không tính vào điểm trung bình học tập. Tín chỉ của học phần P đạt vẫn cộng vào số tín chỉ tích lũy. Trong mã, P nằm ở trường kind bằng “pass_only”, và hàm credits_earned so điểm với ngưỡng 5,00 cho loại này.

Điểm F có làm giảm điểm trung bình không?

Có, với học phần được tính vào điểm trung bình. Điều 12 khoản 4 điểm c xếp F cho học phần dưới 4,00 và Điều 13 khoản 2 quy đổi F thành 0, do đó tín chỉ của học phần đó vào mẫu số của điểm trung bình. Khi sinh viên học lại, điểm nào được tính là quy tắc của trường như phần trên. Với quy tắc lấy điểm lần đầu, học phần rớt rồi đạt vẫn giữ nguyên điểm 0 trong học kỳ đó, như ca kiểm ở mục trên.

Hệ thống đang chạy theo Thông tư 08/2021 có phải đổi ngay không?

Theo Điều 27, thông tư mới áp dụng cho khóa tuyển sinh năm 2026, còn khóa có thông báo tuyển sinh trước ngày hiệu lực theo quy chế hiệu lực lúc thông báo tuyển sinh. Trường rà soát và ban hành quy chế nội bộ trước ngày 31/12/2026. Bảng điểm chữ và kiểu làm tròn của khóa cũ phải lấy từ quy chế nội bộ đang áp dụng cho khóa đó, vì MONA chưa đọc được bản gốc Thông tư 08/2021. Phần mềm nên giữ cả hai cấu hình và gắn theo khóa; quyết định áp dụng quy chế nào cho khóa cụ thể thuộc về phòng đào tạo của trường. Trong dữ liệu, mỗi khóa mang một mã quy chế và hàm tính nhận cấu hình theo mã đó.

MONA Software viết phần mềm quản lý đào tạo tín chỉ cho đại học và cao đẳng. Trang phần mềm quản lý đào tạo tín chỉ giới thiệu MONA UniMaster, trang MONA LMS (hệ thống quản lý học tập, viết tắt LMS) nêu gói UniMaster cho đại học, cao đẳng đào tạo tín chỉ, và trang MONA UniMaster là giới thiệu sản phẩm. Các hàm trong bài chỉ minh họa cách tính, còn tính năng của sản phẩm nằm ở nội dung các trang trên. Trường cần hệ thống tính điểm theo quy chế riêng gọi hotline 1900 636 648 để MONA tư vấn; phần giải thích chung về hệ thống quản lý học tập có ở bài LMS là gì.

Đội MONA gặp khách hàng để khảo sát quy trình trước khi làm phần mềm

Kiến thức phần mềm

Gửi MONA quy trình đang chạy để nhận hướng làm phần mềm

Đội MONA Software khảo sát nghiệp vụ, thiết kế cơ sở dữ liệu, lập trình, bàn giao và đi cùng qua giai đoạn vận hành thử.