You are on page 1of 20

HỆ THỐNG CONTEST MANAGEMENT SYSTEM – CMS

Biên soạn bởi Đỗ Phan Thuận và cộng sự

Bộ môn Khoa học máy tính

Đại học Bách Khoa Hà Nội

Mục lục

1. GIỚI THIỆU CHUNG .............................................................................................................................. 1


2. KIẾN TRÚC HỆ THỐNG ........................................................................................................................ 3
3. CÁC THÀNH PHẦN HỆ THỒNG .......................................................................................................... 4
4. CÀI ĐẶT .................................................................................................................................................. 7
5. CHẠY CMS ............................................................................................................................................. 8
5. CẤU HÌNH CMS CHO BAN TỔ CHỨC .............................................................................................. 12

<Phần cài đặt và vận hành chính là phần 4 và phần 5>

1. GIỚI THIỆU CHUNG


Hệ thống quản lý kì thi (CMS) là một hệ thống chấm bài mã nguồn mở đã được sử dụng trong nhiều kỳ
thi lập trình quốc tế.

Hệ thống này có những tính chất cơ bản sau đây:

Bảo mật: Mặc dù biện pháp bảo mật chính cho một cuộc thi là cô lập thí sinh với hệ thống chấm, nhưng
rõ ràng phải có một mối liên hệ giữa hai cái này, và hệ thống chấm phải giảm thiểu tối đa con đường tấn
công hệ thống.

Ổn định: Kể cả khi một lỗi thì hệ thống cũng không sụp đổ. Tính xuyên suốt của hệ thống phải được bảo
đảm.

Mã nguồn mở: CMS được truy cập dễ dàng, miễn phí và mã nguồn mở.

Mở rộng được: Các kiểu bài mới hoặc các kiểu chấm hiếm gặp có thể được bổ sung thông qua các
plugin.
Tương thích: CMS không can thiệp vào việc tạo đề bài hay tạo test, nó không yêu cầu một số lượng tối
thiểu của máy chấm, hoặc cấu hình mạng đặc biệt.

Dễ sử dụng: CMS cung cấp tài liệu đầy đủ cho các quản trị viên, nhà phát triển và thí sinh; nó không yêu
cầu phải hiểu sâu vào những gì mà nó thực hiện.

Việc thiết kế và phát triển của CMS bắt đầu trong nửa sau năm 2010. Phiên bản alpha bắt đầu lưu hành
trong nửa đầu của năm 2011 và đã được sử dụng trong quá trình lựa chọn của đội tuyển Ý cho IOI 2011.
Sau đó, các phiên bản tinh tế và ổn định hơn đã được sử dụng cho các cuộc thi chính thức: OII 2011
(Olympic tin học Italia) vào tháng Mười 2011, AIIO 2012 (Olympic tin học Australia) và FARIO 2012
(Olympic tin học Pháp-Úc vòng khu vực) trong tháng 2 và tháng 3 năm 2012, IOI 2012, IOI 2013.
2. KIẾN TRÚC HỆ THỐNG
CMS bao gồm nhiều Dịch vụ, các Dịch vụ có thể được cài đặt phân tán trên nhiều server.

LogService: Ghi lại tất cả các thông điệp gửi trong hệ thống, phục vụ mục đích ghi nhật ký cuộc thi.

ResourceService: thu thập tất cả các dữ liệu về dịch vụ chạy trên cùng một server. Khởi động các dịch vụ
khi có yêu cầu

Checker: Chạy thường xuyên, định kỳ kiểm soát toàn bộ các dịch vụ trong hệ thống

EvaluationService: Duy trì hàng đội các bài nộp. Thực hiện biên dịch từng bài nộp và chạy trên các bộ
test. Công việc chấm này có thể gửi cho các worker

Worker: thực hiện công việc chấm trong sandbox.

ScoringService: Thu thập tất cả các lượt chấm, tính điểm, và gửi kết quả này cho bảng xếp hạng

ContestWebServer: Webserver mà các thí sinh đăng nhập vào, gửi bài.

AdminWebServer: Webserver quản trị hệ thống thi.

RnkingWebServer – hiển thị cho bên ngoài xem bảng xếp hạng. Server này nên ở bên ngoài hệ thống
CMS để tránh hệ thống bị quá tải (khi có nhiều người xem).

Có thể cần thêm một số dịch vụ khác để test, import, export các kỳ thi.

Các dịch vụ phải được thiết kế sao cho có thể dừng và tái thực thi mà không làm mất tính nhất quán của
hệ thống. Một vài dịch vụ (ResourceService, ContestWebServer and Worker) có thể thực thi đồng thời
trên nhiều server

Hệ thống CMS cho phép Ban Tổ chức cài đặt thời gian, bộ test trên các hệ thống nhiều máy (Server quản
trị, server tương tác với người thi, server tương tác với bảng điểm, máy chấm…) giúp tổ chức một kỳ thi
có đông thí sinh tham gia.

Việc chấm điểm dựa trên bộ test có thể thực hiện tự động, và kết quả chấm được phản hồi ngay cho thí
sinh (giúp thí sinh có thể căn chỉnh bài làm).
3. CÁC THÀNH PHẦN HỆ THỒNG

Thí Sinh

Resource Service

Load Balancer

Admin Web
Server
Contest Web Server

Worker
Data
Evaluation Service
File

Scoring Service
Checker

Ranking Web Server

INTERNE

CMS được quản lý theo hình thức phân tán (nhiều module), với nhiều dịch vụ tiện ích (service), và có thể
quản lý trên nhiều máy tính. Khi chạy, các dịch vụ tiện ích có thể điều chỉnh cho một cuộc thi lớn.

Những dịch vụ tiện ích của CMS:

Các dịch vụ tiện ích (service), được liệt kê như bảng 1, là các chương trình Python xây dựng dựa trên nền
AsyncLibrary, một thư viện RPC tự tạo sử dụng khung asyncore (Asynchronous socket handler, Sam
Rushing and Python Software Foundation, 1996). Một vài dịch vụ, gọi là các server, còn cung cấp giao
diện dựa trên khung web Tornado (Facebook, Inc., 2009), bởi vậy mà nó có thể cho phép giao tiếp tới các
dịch vụ khác và phục vụ các trang web cho quản trị viên và các thí sinh.
Chúng ta cần các dịch vụ luôn luôn phản hồi, do vậy các lệnh yêu cầu từ xa phải được hoàn thành trong
một thời gian ngắn hoặc sinh ra một luồng (thread) để xử lý yêu cầu. Quá trình này (chạy đa luồng) chỉ
xảy ra trong Worker, nơi mà quá trình biên dịch hay chấm bài không thể được tách ra thành nhiều yêu
cầu. Ngoài ra tất cả dịch vụ còn lại đều chạy đơn luồng (single-threaded). Quá trình tương tác giữa các
dịch vụ được thể hiện ở hình vẽ 1.

Bảng 1. Danh sách các dịch vụ xây dựng nên CMS. Khả năng nhân rộng là "Có" khi mà nhiều đối tượng
(multiple instances) của dịch vụ có thể được thực hiện đồng thời (đa luồng) để tăng sức tải. Hai dịch vụ
cuối cùng (ContestWebServer và AdminWebServer) còn là các server.

Tên dịch vụ Khả năng nhân rộng Nhiệm vụ


LogService Không Nhận, tổng hợp tất cả các sự kiện của hệ thống.
Worker Có Thực hiện biên dịch và chấm bài tất cả các bài nộp trong
một môi trường an toàn (safe environment).
EvaluateService Không Duy trì hàng đợi công việc được gán cho các Worker.
ScoringService Không Biến đổi kết quả chấm bài thành điểm số, và giao tiếp với
bảng điểm (live rankings).
Checker Không Gọi hàm heartbeat (kiểm tra xem dịch vụ còn chạy tốt
hay không) của tất cả các dịch vụ còn lại.
ResourceService Có Thu thập số liệu về tài nguyên đã được sử dụng về máy
đang chạy, và bật tất cả các dịch vụ trên máy.

ContestWebServer Có Phục vụ trang web cho các thí sinh, nhận các bài nộp.

AdminWebServer Không Phục vụ trang web cho quản trị viên, cấu hình và quản lý
cuộc thi.

Tính chất của hệ thống chấm buộc nó phải chạy những code không an toàn. Để ngăn chặn thí sinh gian
lận hay thậm chí là phá hoại máy chấm, tất cả các quá trình chấm bài và thậm chí cả quá trình biên dịch
được yêu cầu bởi thí sinh được chạy trong sandbox. Ở đây ta dùng sandbox của Martin Mares, một phần
của Hệ thống chấm bài.

Kiểu dữ liệu

Trên góc độ của CMS, một thành phần của một cuộc thi được biểu diễn bằng một trong hai kiểu đối
tượng: file (tệp tin) và data (dữ liệu).

Đối với file, ta hiểu mọi thứ giống như khái niệm file thông thường: chỉ có một điểm khác biệt là CMS
không quan tâm như một phần của cấu trúc thư mục. Chúng được dùng để chứa các thứ mà trông giống
như file, như là test, đề bài, bài nộp, chương trình sau khi đã biên dịch, ...

Đối với data, nó là một bộ (collection) các đối tượng (object), thực hiện (implement) một tập hợp các lớp
(class) được định nghĩa trong CMS; chúng được "gắn dính" với các file và kết hợp thành một thông tin
(description) của cuộc thi.
File được định vị bằng checksum của nó, bằng cách sử dụng mã SHA1, (hiện tại nó là SHA1 và có thể dễ
dàng thay đổi nó); nói một cách khác, địa chỉ của chúng không thay đổi. Việc này đơn giản hóa nhiều thứ.
Thứ nhất, không có chuyện truy cập vào cùng một chỗ. Thứ hai, không cần quan tâm về cơ chế đồng bộ.
Thứ ba nó đảm bảo các file là toàn vẹn.

Mỗi data (PostgreSQL Global Development Group, 2012a) có thể lên đến 2GB. Postgre SQL hỗ trợ việc
truy cập bằng luồng (stream), do vậy chúng có thể được copy tới ổ đĩa (local disk) ở trong máy tính để
tránh việc tải chúng vào RAM.

Dữ liệu (data) được lưu trữ trong cơ sở dữ liệu SQL, sử dụng SQL Alchemy (Bayer, 2005) để thực hiện
ORM (Object-Relational Mapping, tức là tực động gắn kết đối tượng Python (objects) tới thông tin
(description) trong một cơ sở dữ liệu SQL. Phần lớn công nghệ SQL ngày nay có thể sử dụng với SQL
Alchemy.

File và data được lưu trong CMS theo hai phương thức, tức là, trên lý thuyết, một phương thức có thể sử
dụng hai database độc lập.

Xử lý sự cố

Cần phải chú ý quan trọng rằng chỉ có database mới có thể làm hỏng toàn bộ hệ thống. Vì vậy quản trị
viên có thể dùng các thủ tục chuẩn (standard procedure) để bảo đám sự hợp lý giữa thời gian hoạt động và
khả năng khôi phục dữ liệu. Ta có thể sử dụng Postgre SQL để xử lí các tình huống như vậy, ví dụ
(PostgreSQL Global Development Group, 2012b). CMS không uỷ quyền sử dụng bất kỳ các giải pháp,
và, trên thực tế, các tác giả CMS không ưu tiên giải pháp nào.

Bằng cách khác, các dịch vụ (service) có thể được bật và tắt độc lập mà không tác động đến hệ thống, tất
nhiên ngoài những thời gian chết của bản thân các dịch vụ. Điều này cho phép các quản trị viên nhanh
chóng thay thế phần cứng hoặc phần mềm bị lỗi với bản sao giống hệt nhau, mà không quan tâm về việc
mất dữ liệu hoặc phải chuyển thông tin giữa cái cũ và các bản sao mới của dịch vụ, miễn là cơ sở dữ liệu
đang làm việc một cách chính xác.

Khi tổ chức một kỳ thi, có 3 giai đoạn chính

Đầu tiên là làm đề, xây dựng bộ test cho đề, cách tính điểm cho mỗi test hoặc bộ test nhỏ. Việc làm test
diễn ra trước khi thi.

Trước khi thi : Cấu hình các hệ thống server sử dụng trong kỳ thi.

Khi thi : Trực để đề phòng những tình huống phát sinh.


4. CÀI ĐẶT
Dưới đây là những gói cần thiết để hoạt động hệ thống CMS:

Trình biên dịch, thông dịch cho các ngôn ngữ được sử dụng trong kì thi.

• PostgreSQL ≥ 8.4
• gettext ≥ 0.18;
• Python ≥ 2.7, < 3.0
• setuptools ≥ 0.6
• Tornado ≥ 2.0
• Psycopg ≥ 2.4
• simplejson ≥ 2.1
• SQLAlchemy ≥ 0.7
• psutil ≥ 0.2
• netifaces ≥ 0.5
• PyCrypto ≥ 2.3
• Ptyz
• iso-codes
• shared-mime-info
• PyYAML ≥ 3.10
• BeautifulSoup ≥ 3.2
• mechanize ≥ 0.2
• coverage ≥ 3.4
• Sphinx
Trên hệ điều hành Ubuntu >12.04, sử dụng lệnh dưới đây để cài đặt đủ các gói nêu trên:

sudo apt-get install build-essential fpc postgresql postgresql-client \


gettext python3.6 python-setuptools python-tornado python-psycopg2 \
python-simplejson python-sqlalchemy python-psutil python-netifaces \
python-crypto python-tz iso-codes shared-mime-info stl-manual \
python-beautifulsoup python-mechanize python-coverage \
phppgadmin python-yaml python-sphinx

Cài đặt CMS

Tải CMS theo đường link: https://github.com/cms-dev/cms/releases/download/v1.4.rc1/v1.4.rc1.tar.gz và


giải nén ra thư mục /cms.

Ví du: wget https://github.com/cms-dev/cms/releases/download/v1.4.rc1/v1.4.rc1.tar.gz

tar -zxvf v1.4.rc1.tar.gz

Bước chuẩn bị:


sudo python3 prerequisites.py install

Nên trả lời mặc định là Y hết trong các câu hỏi phát sinh. Tên nhóm mặc định sẽ là cmsuser

Bước cài: vào thư mục /cms,

sudo pip3 install -r requirements.txt

sudo python3 setup.py install

LƯU Ý: Trong quá trình cài đặt, nếu lỗi thiếu gói nào thì cài thêm: pip install <tên gói tin>

5. CHẠY CMS
Cấu hình CSDL

CSDL được sử dụng là PostgreSQL. Cấu hình bằng cách sử dụng lệnh sau:

sudo su - postgres

createuser --username=postgres --pwprompt cmsuser

createdb --username=postgres --owner=cmsuser cmsdb

psql --username=postgres --dbname=cmsdb --command='ALTER SCHEMA


public OWNER TO cmsuser'

psql --username=postgres --dbname=cmsdb --command='GRANT SELECT ON


pg_largeobject TO cmsuser'

Lưu ý: nếu tên người dùng và CSDL bị trùng hoặc làm lại thì hãy đổi sang tên khác (ví dụ cmsuser1).

Lệnh trên tạo người dùng có tên là cmsuser và CDSL cmsdb thuộc về người dùng này. Người dùng
cmsuser không nhất thiết phải là superuser, không cần có quyền tạo CSDL, role. Password yêu cầu trong
quá trình chạy cần cập nhật lại trong file cms.conf ở bước sau.

Nếu các dịch vụ của CMS được đặt ở các host khác với host mà PostgreSQL hoạt động, cần chỉ ra có
PostgreSQL biết để chấp nhận kết nối từ các host đó bằng cách chỉnh sửa file
/etc/postgresql/9.1/main/postgresql.conf. Ví dụ, thêm vào dòng:
listen_address = ‘127.0.0.1,192.168.0.x`

Ngoài ra cần chỉnh sửa HBA để chấp nhận yêu cầu đăng nhập từ host bên ngoài. Mở file
/etc/postgresql/9.1/main/pg_hba.conf và thêm vào một dòng có dạng:

host cmsdb cmsuser 192.168.0.0/24 md5

Cấu hình CMS

Có hai file cấu hình, một file dùng cho CMS và một file cho dịch vụ Ranking. Vào thư mục cms/config
và /usr/local/etc/cms.conf, copy file cms.conf.sample thành file cms.conf và file
cms.ranking.conf.sample thành file cms.ranking.conf trước khi trình sửa hai file .conf này.

cms.conf: File này giống nhau trên tất cả các server, có hai phần quan trọng là core_services chỉ định ra
số lượng và vị trí các dịch vụ hoạt động, và dòng chỉ ra đường liên kết tới CSDL.

Mở file cms.conf sửa lại tên người dùng lại dòng “database”: (nếu khác cmsuser và mật khẩu đã tạo ra ở
trên).

cms.ranking.conf: File này có thể khác nhau giữa những server host ranking. Địa chỉ và thông tin đăng
nhập cho mỗi ranking phải được tìm thấy trong cms.conf.

Cần thay đổi secrect_key khác đi so với mặc định.

Sau khi chỉnh sửa xong 2 file nêu trên, chạy lệnh dưới đây để cập nhật lại CMS:

sudo ./setup.py install

Cài thêm nếu lỗi:

sudo apt install python-pip

pip install future

và chạy lệnh sau đề hoàn tất config database

cmsInitDB

Chạy CMS

Tạo account admin để vào tạo contest đầu tiên:


cmsAddAdmin -p <your_password, ex:12345678> <your_user, ex:admin>

cmsLogService 0

(nếu gặp lỗi ImportError: cannot import name DispatcherMiddleware thì pip install
werkzeug==0.16.0)

cmsAdminWebServer

Tiếp theo vào localhost:8889, đăng nhập vào account admin và tạo contest đầu tiên. Tiếp theo tạo user và
add vào contest trên giao diện. Địa chỉ nộp bài tại localhost:8888

Từ lần sau, để khởi động CMS chạy các lệnh dưới đây:

sudo cmsResourceService –a

Nếu có lỗi thì có thể chỉ cần dùng tạm lệnh cmsRankingWebServer

Lệnh khởi tạo ranking (địa chỉ: localhost:8890)

sudo cmsRankingWebServer

Để xoá ranking cũ

sudo cmsRankingWebServer –- drop

Lưu ý:

- file cấu hình trên các máy chạy CMS phải giống nhau.
- nếu không fix được lỗi thì nên download phiên bản cms khác trên server về cài lại
Khi chạy lệnh thứ 2 sẽ được yêu cầu chỉ ra số thứ tự của kì thi muốn sử dụng. Để tạo kì thi xem phần Tạo
kì thi.

Khuyến nghị

Hệ điều hành được khuyến nghị là Ubuntu >12.04 LTS 32 bit.

Log

Có các log như sau:

Debug: những thông tin này không quan trọng, với cấu hình mặc định sẽ không được hiển thị.

Info: thông báo về những gì đang diễn ra trong hệ thống, tức là hệ thống đang hoạt động tốt.
Warning: Có điều bất ổn xảy ra nhưng CMS có thể giải quyết được vấn đề này. Các vấn đề này nên được
kiểm tra trước khi phát triển lên mức Error hoặc Unexpeted behaviors, đây cũng có thể là gợi ý để kiểm
tra về việc có một thi sinh đang có ý định gian lận.

Error: Một điều kiện không mong muốn đã xảy ra, những điều này nên được sửa chữa. Hệ thống vẫn sẽ
tiếp tục hoạt động (bỏ qua những lỗi và dữ liệu liên quan tới lỗi đó).

Critical: Một lỗi rất không mong muốn đã xảy ra, hệ thống không tiếp tục hoạt động nữa. Người dùng
cần phải có hành động sửa chữa vì nếu không hệ thống vẫn có thể gặp lại vấn đề tương tự ngay cả khi
khởi động lại.

Warning, Error và Critial log cũng được hiển thị ở trang chính của AdminWebServer.
5. CẤU HÌNH CMS CHO BAN TỔ CHỨC
Cấu hình CMS cho Ban Tổ Chức

Trang web dành cho người quản trị có dạng địa chỉ IP:8889, ví dụ : http://192.168.1.100:8889/

Cấu hình Cuộc Thi

Trang web quản trị cuộc thi ban đầu có dạng :

Để thêm một cuộc thi mới, ấn chuột vào nút dấu cộng (+) trong bảng bên trái, cửa sổ mới sẽ hiện ra như
sau:

Địa chỉ : http://192.168.1.100:8889/contest/add

Trong bảng cấu hình bên tay trái, ban tổ chức có thể cấu hình nhiều thông số. Chú ý:
Các thông số này sẽ là giá trị ngầm định cho mọi bài toán (task). Nếu task nào yêu cầu khác, có thể cấu
hình riêng cho từng task. Giá trị thông số cấu hình riêng sẽ được áp dụng cho riêng task đó.

Các thông số không được cấu hình (không có giá trị) sẽ nhận giá trị ngầm định của hệ thống. Bảng ý
nghĩa của các thông số được liệt kê như sau :

Tên Ý Nghĩa Cấu hình

Name tên của cuộc thi VD: VOI R2 DAY1

tên hiển thị trên bảng VD: DAY1


Description
rank

thời gian bắt đầu cuộc


Start (in UTC)
thi (theo UTC)

thời gian kết thúc cuộc


End (in UTC)
thi (theo UTC)

Timezone (like múi giờ


"Europe/Rome",
"America/New_York",
...)

Maximum length of the


contest for a user (in
seconds)

Maximum number of số lần submit tối đa của


submissions for each một thí sinh
user (for the whole
contest)

Maximum number of số lần test tối đa của


user_tests for each user một thí sinh
(for the whole contest)

Minimum interval khoảng cách tối thiểu


between two giữa 2 lần submit của
submissions of each một thí sinh
user (for the whole
contest, in seconds)

The number of decimal số chữ số thập phân của


places the scores will be điểm
rounded to

Sau khi cấu hình thành công, trang Web của cuộc thi sẽ có dạng : http://192.168.1.100:8889/contest/2.

Bảng bên trái có ghi tên cuộc thi.

Tuy nhiên, sau này ta vẫn có thể chỉnh lại các tham số chung của cuộc thi bằng cách quay lại trang web
này (hoặc ấn vào Link general bên bảng trái; thực hiện cấu hình lại, và ấn nút Update (bên dưới).

Sau khi mở và cấu hình Cuộc Thi, chúng ta có thể cấu hình cho Thí Sinh và Bài Toán.

Cấu hình Cho Thí Sinh

Để thực hiện cấu hình cho thí sinh, nhấn chuột vào đường dẫn Users bên bảng trái

http://192.168.1.100:8889/userlist/2
Để cấu hình cho từng người sử dụng, nhấn chuột vào đường dẫn Add a new user

http://192.168.1.100:8889/add_user/2

Trang web sẽ có dạng :

Chúng ta có thể cấu hình cho mỗi thí sinh trên trang web này.
First name Tên

Last name Họ

Username Tên đăng nhập

Password Mật khẩu

Email

Ip của thí sinh, để trống hoặc 0.0.0.0 nếu không cố


IP
định

Timezone (like "Europe/Rome", múi giờ


"America/New_York", ...)

First login time during contest

Extra time (in seconds)

Hidden?

Primary statements (JSON-encoded dict whose


keys are task names and whose values are lists of
language codes)

Sau khi cấu hình xong, ta ấn nút Submit Query để hoàn thành. Trang web sẽ hiện ra như sau:

http://192.168.1.100:8889/user/1
Ta có thể quay lại trang web này sau để chỉnh sửa cho từng thí sinh.

Sau khi cấu hình cho Thí sinh, ta có thể cấu hình cho các bài toán.

Cấu hình Các bài toán.

Cuộc thi có nhiều Bài toán, chúng ta phải cấu hình cho từng bài toán cùng bộ test tương ứng.

Để cấu hình cho một Bài toán, chúng ta ấn vào đường dẫn Tasks ở bảng bên trái, trang web sẽ hiện ra như
sau

http://192.168.1.100:8889/tasklist/2
Để tạo mới một bài toán, chúng ta ấn vào nút Add a new task, sẽ được màn hình sau đây :

http://192.168.1.100:8889/add_task/2

Có rất nhiều cấu hình cho các bài toán:

Name: tên hiển thị, VD: POST


Title: tiêu đề

Time limit : giới hạn thời gian, theo giây

Memory limit: giới hạn bộ nhớ

Primary statements (JSON-encoded list of language codes)

Task type settings:

Task type: Batch (bài thí sinh sẽ chấm lần lượt với 1 bộ input output)

Compilation: Submissions are self-sufficient (không cần grader để compile)

I/O (blank for stdin/stdout):

Input file: tên file input, để trống nếu chọn stdin

Output file: tên file output, để trống nếu chọn stdout

Sau khi cấu hình xong, nhấn chuột vào Submit, ta có hình sau:

http://192.168.1.100:8889/task/1

Chúng ta có thể nhấn chuột vào đường dẫn Add a test case
Position: vị trí của bộ test, đánh số từ 0

Input: đường dẫn đến input

Output: đường dẫn đến output

Public: có đánh dấu, công khai bộ test

Sau khi chọn xong, ấn nút Upload để hoàn thành.

Link tài liệu tham khảo gốc: https://cms.readthedocs.io/en/v1.4/Installation.html

You might also like