Để hoàn thành chuyên đề báo cáo thực tập này trước hết em xin gửi lời cảm ơn chân thành nhất đến quý thầy, cô giáo trong khoa Công Nghệ Thông Tin Đại Học Công Nghệ Thông Tin Và Truyền Thông Thái Nguyên đã luôn tận tình chỉ bảo, truyền đạt cho em những kiến thức quý báu trong suốt thời gian học ở trường. Đặc biệt, em xin gửi đến thầy Nguyễn Văn Việt người đã tận tình hướng dẫn, giúp đỡ em hoàn thành chuyên đề báo cáo đồ án tốt nghiệp này lời cảm ơn sâu sắc nhất.
Trang 1TRƯỜNG ĐẠI HỌC CÔNG NGHỆ THÔNG TINVÀ TRUYỀN THÔNG THÁI NGUYÊN
KHOA CÔNG NGHỆ THÔNG TIN
- -BÁO CÁO ĐỒ ÁN TỐT NGHIỆP
Đề tài: Xây dựng ứng dụng ôn thi lý thuyết lái xe B2bằng Flutter
Giáo viên hướng dẫn: Th.S Nguyễn Văn ViệtSinh viên thực hiện: Luân Quang Huy
Lớp: KTPM K16A
Thái Nguyên, ngày… tháng 01 năm 2022
Trang 22.3.1 Biểu đồ use case tổng quát 26
2.3.2 Danh sách các tác nhân và mô tả 28
2.3.3 Danh sách Usecase và mô tả 28
2.3.2 Biểu đồ trình tự 30
2.3.3 Biểu đồ hoạt động 41
2.3.4 Thiết kế cơ sở dữ liệu 52
CHƯƠNG III: Xây dựng và cài đặt chương trình 54
3.1 Áp dụng kiến thức đã tìm hiểu xây dựng app moblie ôn thi GPLX B1 54
Trang 4LỜI CẢM ƠN
Để hoàn thành chuyên đề báo cáo thực tập này trước hết em xin gửi lời cảm ơn chân thành nhất đến quý thầy, cô giáo trong khoa Công Nghệ Thông Tin - Đại Học Công Nghệ Thông Tin Và Truyền Thông Thái Nguyên đã luôn tận tình chỉ bảo, truyền đạt cho em những kiến thức quý báu trong suốt thời gian học ở trường.
Đặc biệt, em xin gửi đến thầy Nguyễn Văn Việt người đã tận tình hướng dẫn, giúp đỡ em hoàn thành chuyên đề báo cáo đồ án tốt nghiệp này lời cảm ơn sâu sắc nhất.
Đồng thời nhà trường đã tạo cho em có cơ hội được thực tập nơi mà em yêu thích, cho em bước ra đời sống thực tế để áp dụng những kiến thức mà các thầy cô giáo đã giảng dạy Qua công việc thực tập này em nhận ra nhiều điều mới mẻ và bổ ích trong việc lập trình để giúp ích cho công việc sau này của bản thân.
Vì kiến thức bản thân còn hạn chế, trong quá trình thực tập, hoàn thiện chuyên đề này em không tránh khỏi những sai sót, kính mong nhận được những ý kiến đóng góp từ quý thầy/cô.
Xin chân thành cảm ơn!
Thái Nguyên, Ngày 22 Tháng 01 Năm 2022 Sinh viên
Luân Quang Huy
Trang 5CHƯƠNG I: Cơ sở lý thuyết1.1 Tìm hiểu về dart
1.1.1 Dart là gì
Dart là ngôn ngữ lập trình đa mục đích ban đầu được phát triển bởi Google và sau đó được Ecma (ECMA-408) phê chuẩn làm tiêu chuẩn Nó được sử dụng để xây dựng các ứng dụng web, server, máy tính để bàn và thiết bị di động Dart là một ngôn ngữ hướng đối tượng, được xác định theo lớp, với cơ chế garbage-collected, sử dụng cú pháp kiểu C để dịch mã tùy ý sang JavaScript Nó hỗ trợ interface, mixin, abstract, generic, static typing và sound type (2 cái cuối có thể hiểu là type-safe) Dart là ngôn ngữ mã nguồn mở và miễn phí, được phát triển trên GitHub Hiện nay Dart đã release phiên bản 2.2
1.1.2 Tại sao lại chọn dart, những ưu điểm của dart
Các nhà phát triển tại Google và các nơi khác sử dụng Dart để tạo các ứng dụng chất lượng cao, quan trọng cho iOS, Android và web Với các tính năng nhắm đến sự phát triển phía khách hàng, Dart rất phù hợp cho cả ứng dụng di động và web Dart giúp bạn tạo ra những trải nghiệm đẹp, chất lượng cao trên tất cả các màn hình, với:
Một ngôn ngữ được tối ưu hóa cho client Framework mạnh mẽ
Công cụ linh hoạt Những ưu điểm của dart
Năng suất Cú pháp Dart rõ ràng và súc tích, công cụ của nó đơn giản nhưng mạnh
mẽ Type-safe giúp bạn xác định sớm các lỗi tinh tế Dart có các thư viện cốt lõi và một hệ sinh thái gồm hàng ngàn package.
Nhanh Dart cung cấp tối ưu hóa việc biên dịch trước thời hạn để có được dự đoán
hiệu suất cao và khởi động nhanh trên các thiết bị di động và web.
Di động Dart biên dịch thành mã ARM và x86, để các ứng dụng di động của Dart
Trang 6có thể chạy tự nhiên trên iOS, Android và hơn thế nữa Đối với các ứng dụng web, chuyển mã từ Dart sang JavaScript.
Dễ gần Dart quen thuộc với nhiều nhà phát triển hiện có, nhờ vào cú pháp và định
hướng đối tượng không gây ngạc nhiên của nó Nếu bạn đã biết C ++, C # hoặc Java, bạn có thể làm việc hiệu quả với Dart chỉ sau vài ngày.
Reactive Dart rất phù hợp với lập trình Reactive, với sự hỗ trợ để quản lý các đối
tượng tồn tại trong thời gian ngắn, chẳng hạn như các widget UI, thông qua phân bổ đối tượng nhanh và GC Dart hỗ trợ lập trình không đồng bộ thông qua các tính năng ngôn ngữ và API sử dụng các đối tượng Future và Stream.
1.1.3 Học dart cơ bản
Biến và kiểu dữ liệu
Biến (Variable) là tên đại diện cho nơi lữu trự dữ liệu còn Kiểu dữ liệu (Data types) đơn giản là loại và kích thước của dữ liệu liện kết với biến và hàm.
Dart sử dụng từ khoá var để khai báo biến var name = 'Dart';
Từ khoá final và const được sử dụng để khai báo hằng số (constants) Như ví dụ
Trang 7dữ liệu cho biến
Numbers − Được sử dụng cho số – Integer và Double.
Strings − Được sử dụng cho chuỗi kí tự Giá trị của String được đặt trong dâu nháy đơn hoặc nháy kép.
Booleans − Được sử dụng cho giá trị Boolean đúng và sai Lists and Maps − Được sử dụng cho nhóm đối tượng Điều kiện, vòng lặp
Một khối điều khiển (decision making block) đánh giá một điều kiện trước khi hướng dẫn thực thi Dart hỗ trợ các khối lênh If, If else và switch.
Vòng lặp được sử dụng để lặp lại một khối lệnh cho đến khi một điều kiện cụ thể được đáp ứng Dart hỗ trợ các vòng lặp for in, while và do while
Ví dụ đoạn code hiển thị các số từ 1 đến 10
Trang 8Lập trình hướng đối tượng
Dart là một ngôn ngữ lập trình hướng đối tượng (object-oriented language) Nó hỗ trợ một số tính năng của lập trình hướng đối tượng như class, interface,
Mỗi một class (lớp) định nghĩa cho một loại đối tượng Một class bao gồm những nội dung sau đây:
- Các thuộc tính (Fields) - Các hàm Getter và setter - Hàm khởi tạo (Constructor) - Phương thức (Function) Toán tử trong dart
Cũng giống như các ngôn ngữ khác, nhưng dart có một vài điểm khác biệt trong các toán tử điều kiện.
var a = 4; var b = 10;
var d = (a > b) ? a : b; // kết quả d=10
Trang 91.2 Tìm hiểu về flutter.
1.2.1 Tổng quan về flutter
1.2.1.1 Flutter là gì
Flutter là mobile UI framework của Google để tạo ra các giao diện chất lượng cao trên iOS và Android trong khoảng thời gian ngắn Flutter hoạt động với những code sẵn có được sử dụng bởi các lập trình viên, các tổ chức.
Flutter hoàn toàn miễn phí và cũng là mã nguồn mở 1.2.1.2 Tại sao lại là flutter
Nếu bạn đang tìm kiếm các phương pháp thay thế để phát triển ứng dụng Android, bạn nên cân nhắc thử Flutter của Google, một framework dựa trên ngôn ngữ lập trình Dart.
Các ứng dụng được xây dựng với Flutter hầu như không thể phân biệt với những ứng dụng được xây dựng bằng cách sử dụng Android SDK, cả về giao diện và hiệu suất Hơn nữa, với những tinh chỉnh nhỏ, chúng có thể chạy trên thiết bị iOS.
Chạy ở 60 fps, giao diện người dùng được tạo ra với Flutter thực thi tốt hơn nhiều so với những ứng dụng được tạo ra với các framework phát triển đa nền tảng khác chẳng hạn như React Native và Ionic Một số lí do khiến bạn có thể hứng thú với Flutter:
1 Flutter sử dụng Dart, một ngôn ngữ nhanh, hướng đối tượng với nhiều tính năng hữu ích như mixin, generic, isolate, và static type.
2 Flutter có các thành phần UI của riêng nó, cùng với một cơ chế để kết xuất chúng trên nền tảng Android và iOS Hầu hết các thành phần giao diện người dùng, đều sẵn dùng, phù hợp với các nguyên tắc của Material Design.
3 Các ứng dụng Flutter có thể được phát triển bằng cách sử dụng IntelliJ IDEA, một IDE rất giống với Android Studio.
Trang 101.2.1.3 Đặc điểm nổi bật
1 Fast Development: Tíng năng Hot Reload hoạt động trong milliseconds để hiện thị giao diện tới bạn Sử dụng tập hợp các widget có thể customizable để xây dựng giao diện trong vài phút Ngoài ra Hot Reload còn giúp bạn thêm các tính năng, fix bug tiết kiệm thời gian hơn mà không cần phải thông qua máy ảo, máy android hoặc iOS
2 Expressive and Flexible UI: Có rất nhiều các thành phần để xây dựng giao diện của Flutter vô cùng đẹp mắt theo phong cách Material Design và Cupertino, hỗ trợ nhiều các APIs chuyển động, smooth scrolling
3 Native Performance: Các widget của fluter kết hợp các sự khác biệt của các nền tảng ví dụ như scrolling, navigation, icons, font để cung cấp một hiệu năng tốt nhất tới iOS và Android.
1.2.1.4 Cài đặt
Bạn có thể cài đặt bằng cách clone Flutter repository từ Github về: git clone https://github.com/flutter/flutter.git
Tiếp theo bạn nên sử dụng công cụ chuẩn đoán của Flutter để kiểm tra các thành phần như Dart SDK, font Material Design:
cd flutter/bin /flutter doctor
Giao diện công cụ chuẩn đoán Flutter Doctor:
Trang 11Để xây dựng ứng dụng Android, bạn phải trỏ Flutter tới thư mục của Android Studio /flutter config android-studio-dir ~/android-studio
Cấu hình với IntelliJ hoặc Android Studio, chọn Configure->Plugins tại màn hình khởi động
Trang 12Sau đó cài đặt plugin Dart
Trang 13Tương tự với plugin Flutter
Trang 14Sau khi cài Dart và Flutter bạn nên khởi động lại IDE
Bây giờ, bạn phải trỏ plugin Flutter đến thư mục mà bạn đã cài đặt Flutter Để làmnhư vậy, hãy chọn Configure > Settings trong màn hình chào mừng và trong hộp thoạibật lên, điều hướng đến Languages & Frameworks > Flutter Trong trường Flutter SDK
path, gõ đường dẫn tuyệt đối của thư mục.
Sau khi cài Dart và Flutter bạn nên khởi động lại IDE
Bây giờ, bạn phải trỏ plugin Flutter đến thư mục mà bạn đã cài đặt Flutter Để làmnhư vậy, hãy chọn Configure > Settings trong màn hình chào mừng và trong hộp thoạibật lên, điều hướng đến Languages & Frameworks > Flutter Trong trường Flutter SDK
Trang 15path, gõ đường dẫn tuyệt đối của thư mục.
1.2.3 Lập trình mobile app với flutter
1.2.3.1 Tìm hiểu về widget, layout Layout trong Flutter
Layout trong Flutter bao gồm một hệ thống phân cấp các widget với các widget bên ngoài thường xử lý sự liên kết và cấu trúc trong khi các yếu tố bên trong thường là các yếu tố hiển thị trên chính trang đó, như các button và image, v.v
new Center(
child: new Column(
Trang 16Widget basic trong flutter
-Trong flutter, mọi thứ đều là widget.
Văn bản có thể được căn chỉnh bằng cách sử dụng thuộc tính textAlign Thuộc tính kiểu cho phép tùy chỉnh văn bản bao gồm phông chữ, cỡ chữ, trọng lượng phông chữ, màu sắc, khoảng cách chữ và nhiều thứ khác.
Trang 17Một widget Button cho phép người dùng thực hiện một số hành động khi nhấn Flutter không có tiện ích trực tiếp "Button", mà thay vào đó nó có các loại nút như
Column là một widget sắp xếp tất cả các widget con của nó trong một ngăn xếp dọc Nó có thể khoảng trống các widget theo thuộc tính mainAxisAlocation và crossAxisAlocation Ở đây, trục chính main axis của đường trục chính là một trục dọc và trục chính của trục là một trục ngang.
mainAxisAlignment: MainAxisAlignment.center,
Trang 18Một widget Trung tâm chỉ đơn giản là tập trung vào child bên trong nó Tất cả các ví dụ trước bao gồm các hàng và cột nằm trong một widget Center Nếu không nằm trong Center, nó sẽ dịch chuyển sang trái.
Không giống như trong phát triển Android thông thường nơi mọi chế độ xem có thuộc tính padding riêng, padding là một widget bao bọc các widget khác để cung cấp cho chúng phần padding theo tất cả hoặc các hướng được chỉ định Điều này cung cấp cho
Trang 19widget văn bản một phần đệm 8.0 theo mọi hướng Scafflod
Widget Scaffold là một khung để thêm các yếu tố thiết kế widget phổ biến như AppBars, Drawers, Floating Action Buttons, Bottom Navigation, etc.
new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
Một Stack được sử dụng để chồng lấp các widget, giống như một nút trên gradient nền Stack là một widget rất quan trọng và chúng ta sẽ đi sâu vào chi tiết hơn trong một bài viết trong tương lai.
Đây là những widgets cơ bản cần có để tạo ra một ứng dụng hoạt động tốt trong Flutter Flutter cũng cho phép bạn tạo các widget của riêng mình nếu bạn cần thêm bất kỳ chức năng nào khác hoặc nếu bạn muốn sử dụng lại một số mẫu widget lặp lại.
Trang 20Widget advance
Custom paint: CustomPaint cho phép ta truy cập vào low-level - graphics khi Flutter vẽ một widget Nó cũng giống như việc custom view trên Android hay IOS tuy nhiên sẽ đơn giản và trực quan hơn khi kết hợp với HotReload của Flutter.
Một vài thuộc tính quan trọng của CustomPaint:
child: Theo mặc định, canvas sẽ lấy kích thước của child, nếu nó được xác định painter : 1 painter được vẽ trước khi child được vẽ.
foregroundPainter: 1 painter được vẽ sau khi child được vẽ (đè lên trên child).
Trang 21size: Nếu child không được khai báo, thì kích thước của canvas phải được chỉ định Khai báo class ShapePainter
class ShapePainter extends CustomPainter { @override
void paint(Canvas canvas, Size size) { // TODO: implement paint
}
@override
bool shouldRepaint(CustomPainter oldDelegate) { // TODO: implement shouldRepaint
return null; }
Animation with Tranform
Trong Flutter, Animation là một lớp trừu tượng, chỉ có biết giá trị hiện tại và trạng thái của nó (isCompleted và isDismissed ) Một trong những loại animation được sử dụng phổ biến là Animation <double>.
Một đối tượng Animation trong Flutter là tạo ra tuần tự các số được xen vào giữa hai giá trị trong một khoảng thời gian nhất định Đầu ra của một đối tượng Animation có thể là tuyến tính, đường cong, hàm theo các bước hoặc bất kỳ ánh xạ nào khác mà bạn có thể nghĩ ra Tùy thuộc vào cách đối tượng Animation được điều khiển, nó có thể chạy theo chiều ngược hoặc thậm chí chuyển hướng ở giữa.
Animations cũng có thể tích hợp vào trong các đối tượng khác ngoài kiểu double,
Trang 22chúng ta còn có thể sử dụng với Animation<Color> hoặc Animation<Size> Một đối tượng Animation cũng có trạng thái của nó Trạng thái đó được biểu hiện qua gía
Khởi tạo hay định nghĩa một curvedAnimation như sau: final CurvedAnimation curve =
CurvedAnimation(parent: controller, curve: Curves.easeIn); AnimationController
AnimationController là một đối tượng Animation đặc biệt tạo ra một giá trị mới bất cứ khi nào phần cứng sẵn sàng cho một khung mới Mặc định, AnimationContoder tạo tuyến tính các số từ 0,0 đến 1,0 trong một khoảng thời gian nhất định Ví dụ sẽ tạo ra một AnimationController
final AnimationController controller = AnimationController( duration: const Duration(milliseconds: 2000), vsync: this); AnimationController hỗ trợ phương thức để điều khiển animation Điều khiển animation forward hoặc reverse, hoặc stop
Đặt animation thành một value cụ thể.
Định nghĩa các giá trị upperBound and lowerBound trong một animation Tạo ra một fling animation với hiệu ứng sử dụng một mô phỏng vật lý Tween
Mặc định, đối tượng AnimationController có giá trị nằm trong khoảng từ 0,0 đến
Trang 231,0 Nếu bạn cần thay đổi khoảng giá trị khác hoặc một loại dữ liệu khác, bạn có thể sử dụng Tween
Tween là một đối tượng không có trạng thái, chỉ có lưu giá trị begin và end Công việc duy nhất của Tween là xác định ánh xạ từ phạm vi đầu vào sang phạm vi đầu ra Phạm vi đầu vào thường là 0,0 đến 1,0.
final Tween doubleTween = Tween<double>(begin: -200.0, end: 0.0); 1.2.3.2 Design UI với flutter
Khi xây dựng ứng dụng Flutter, chúng ta thường sử dụng Widgets để dựng giao diện Khi đó có 2 loại để dựng là statteful và stateless.
Stateless Widget
Stateless widget không có state Nó không chấp nhận sự thay đổi bên trong nó Còn đối với sự thay đổi từ bên ngoài (widget cha) thì nó sẽ thụ động thay đổi theo.
Có nghĩa là StatelessWidget chỉ đơn thuần nhận dữ liệu và hiển thị 1 cách thụ động Việc tương tác với nó không sinh ra bất kỳ một event nào để chính bản thân phải render lại Nếu phải render lại thì là do tác động từ bên ngoài vào.
Vậy nên, nó không có liên quan gì đến State cả Bản thân nó cũng không có hàm createState mà thay vào đó là hàm build(BuildContext)
Trang 241 Statefull Widget
Statefull Wiget là widget có chứa các state( thuộc tính thay đổi) Khi hàm build cập nhật, các state sẽ cập nhật theo thông qua hàm setState().
1.3 Tìm hiểu về sqlite
SQLite là một thư viện phần mềm mà triển khai một SQL Database Engine, không cần máy chủ, không cần cấu hình, khép kín và nhỏ gọn Nó là một cơ sở dữ liệu, không cần cấu hình, có nghĩa là giống như các cơ sở dữ liệu khác mà bạn không cần phải cấu hình nó trong hệ thống của mình.API (Application Programming Interface) là giao diện lập trình ứng dụng giúp tạo ra các phương thức kết nối với các thư viện và ứng dụng khác nhau.
Trang 25CHƯƠNG II: Khảo sát thực trạng và phân tích thiết kế hệ thống2.1 Khảo sát thực trạng
Cùng với sự phát triển của thị trường điện thoại di động là sự phát triển mạnh mẽ c ủa xu hướng lập trình phần mềm ứng dụng cho các thiết bị di dộng Phần mềm ứng dụng cho điện thoại di động hiện nay rất da dạng và phổ biến: Android, IOS, J2MF, … Trong vài năm gần đây, nhu cầu sử dụng app mobile lại càng tăng cao, những ứng dụng càng ngày cần đảm bảo được việc phát triển giao diện người dùng được ưu tiên lên ahfng đầu cùng với việc phải thúc đẩy các dự án càng nhanh nhưng đi đôi với chất lượng Chính vì vậy React Navite hay Flutter bùng lên như một hiện tượng mới cho lập trình mobile Chúng ta không còn phải dùng riêng Object C, Swift, hay Java, Kotlin cho từng nền tảng riêng Flutter có thể đảm bảo được độ chính xác của các ứng dụng đi đôi với việc hiệu quả trên mặt giao diện người dùng.
Nhận thấy cơ hội phát triển ứng dụng trên, đặt kèm với vấn đề giải quyết thực tế Một ứng dụng cho phép người dùng có thể ôn thi GPLX tại bất kỳ đâu đều có thể sử dụng Các ứng dụng ôn thi GPLX hiện tại, đa phần là lấy từ các bộ đề đã cũ, hay chính việc trải nghiệm người dùng chưa được tốt, các tính năng chưa được nhiều và hiệu quả Đây là một cơ hội để giải quyết vấn đề này.
2.2 Khảo sát bài toán
Hiện nay, nhu cầu ôn tập và đăng ký thi bằng lái của người dân tăng cao dẫn đến các trung tâm luyện thi và tổ chức thi cấp giấy phép lái xe trở nên quá tải.
Ngoài ra, người dân cũng không thể lúc nào cũng có thời gian đến các trung tâm luyện thi hoặc người dân nào cũng có máy tính, laptop để sử dụng các phần mềm ôn thi.
Chính vì những nhu cầu đó, việc phát triển một ứng dụng dùng cho các thiết bị di động thông minh như smartphone hay tablet giúp người dùng có thể tranh thủ những thời gian rảnh để ôn thi mà không mất nhiều thời gian và có thể sử dụng ở bất cứ đâu mà không bị ảnh hưởng quá nhiều đến những yếu tố bên ngoài.
Trang 26Trên thực tế, để thi giấy phép lái xe người điều khiển phương tiện cần trải qua 2 phần thi: phần thi lý thuyết và phần thi thực hành lái xe.
Phần thi lý thuyết: đề thi lý thuyết gồm 30 câu hỏi, thời gian làm bài là 20 phút, tài liệu học gồm có 2 phần:
- Những khái niệm, quy tắc giao thông đường bộ - Văn háo, đạo đức người lái xe
- Kỹ thuật lái xe ô tô
- Cấu tạo và sửa chữa xe ô tô - Hệ thống biển báo hiệu đường bộ
Xây dụng ứng dụng di động giúp người dùng luyện thi lý thuyết lái xe và thi thử trước khi đăng ký thi trên thực tế Các câu hỏi được lấy trong bộ 600 câu hỏi lý thuyết lái xe do bộ ban hành bao gồm các câu lý thuyết, các câu về biển báo.
2.3 Phân tích thiết kế hệ thống
2.3.1 Biểu đồ use case tổng quát
Trang 272.3.1.1 Phân rã use case cho chức năng học
2.3.1.2 Phân rã use case cho chức năng ôn
Trang 282.3.2 Danh sách các tác nhân và mô tả.
chú Người dùng Là người có nhu cầu học và ôn thi lái xe B2
Admin Là người quản trị của hệ thống
2.3.3 Danh sách Usecase và mô tả.
ID Tên Use
case Mô tả ngắn gọn Use case Chức năng
Ghi chú UC001 Đăng ký Thêm mới một tài khoản
vào cơ sở dữ liệu
Dùng cho người dùng đăng ký tài khoản mới UC002 Đăng nhập Đăng nhập một tài khoản
Trang 29thống sách bài viết và sửa bài viết UC008 Xoá bài viết Xoá một bài viết trên hệ
thống
Admin sử dụng xem danh sách bài viết và xoá bài viết UC009 Bình luận Thêm một địa điểm vào hệ
thống
Admin sử dụng xem danh sách địa điểm và thêm địa điểm
UC010 Học Người dùng học câu hỏi thi
Người dùng sẽ được xem các câu hỏi và xem đáp án đúng
UC011 Ôn Người dùng ôn câu hỏi thi
Người dùng sẽ được xem các câu hỏi và chọn đáp án, sau khi trả lời kết thúc sẽ có bảng kết quả xuất hiện
Trang 302.3.2 Biểu đồ trình tự
2.3.2.1 Biểu đồ trình tự cho chức năng học
Trang 312.3.2.2 Biểu đồ trình tự cho chức năng ôn
Trang 322.3.2.3 Biểu đồ trình tự cho chức năng đăng ký
Trang 332.3.2.4 Biểu đồ trình tự cho chức năng đăng nhập
Trang 342.3.2.5 Biểu đồ trình tự cho chức năng thêm người dùng