Cách tính điểm rating TAC

Điểm rating ước tính trình độ chơi của thành viên (và của một cặp đấu cố định) dựa trên kết quả các ván đấu đã ghi nhận. Trang này sẽ giải thích khái quát một cách dễ hiểu trước, sau đó là chi tiết dành cho các nhà phát triển.

Dễ hiểu

Điểm rating TAC là gì?

Điểm rating là một con số thể hiện trình độ chơi TAC của một người — tương tự như hệ số Elo trong cờ vua, nhưng sử dụng phương pháp hiện đại hơn. Điểm số này được tính toán duy nhất từ các ván đấu được ghi nhận trong app. Không ai tự ý cộng điểm thủ công.

Có hai loại điểm rating: một rating cá nhân cho mỗi thành viên và một rating đồng đội cho một cặp người chơi cố định (hai thành viên cùng chơi với nhau).

Khi nào điểm rating được tạo?

Điểm rating chỉ được tính khi có ít nhất một thành viên tham gia ở cả hai bên. Khách (người chơi không có tài khoản thành viên) không được tính. Vì vậy, nếu một thành viên chỉ chơi cùng hoặc đối đầu với khách, sẽ không có sự so sánh và do đó không có điểm rating. Để tính điểm rating đội, hai thành viên không kèm khách phải cùng chơi trên một bên.

Điểm rating thay đổi như thế nào?

Sau mỗi ván đấu tính điểm, điểm rating sẽ được điều chỉnh. Khi thắng đối thủ mạnh hơn, điểm rating tăng đáng kể; khi thua đối thủ yếu hơn, điểm sẽ giảm mạnh hơn. Khi thắng đối thủ yếu hơn nhiều, điểm rating hầu như không thay đổi vì kết quả này đã được dự đoán trước.

Mỗi điểm rating đều có một mức độ không chắc chắn: Lúc đầu, hệ thống chưa biết nhiều về bạn, nên điểm rating có thể biến động mạnh. Bạn càng chơi nhiều, kết quả đánh giá sẽ càng chính xác và ổn định hơn.

Điểm rating tạm thời

Khi một thành viên có ít hơn 10 ván đấu được tính điểm, điểm rating sẽ được coi là tạm thời — mức điểm này chưa đủ căn cứ để so sánh một cách công bằng.

Các bảng xếp hạng

Điểm rating được tính riêng cho từng hạng mục để việc so sánh được công bằng:

  • Toàn cầu — trên tất cả các câu lạc bộ.
  • Câu lạc bộ — chỉ bao gồm các trận đấu trong một câu lạc bộ.
  • Sự kiện — chỉ gồm các ván đấu của một buổi chơi/giải đấu cụ thể.
  • Mùa giải — chỉ bao gồm các trận đấu trong thời gian một mùa giải của một câu lạc bộ.

Không hoạt động

Nếu bạn không chơi trong một thời gian dài, đánh giá về trình độ của bạn sẽ trở nên kém chắc chắn hơn theo thời gian. Bản thân điểm rating (trình độ ước tính) vẫn giữ nguyên — chỉ có độ tin cậy giảm đi cho đến khi bạn chơi trở lại.

Một số ván đấu có thể được loại khỏi việc tính điểm rating (ví dụ: ván đấu thử). Khách không có tài khoản thành viên sẽ không có điểm rating riêng.

Mô tả kỹ thuật (cho nhà phát triển)

Mô hình và giá trị khởi đầu

Điểm rating dựa trên OpenSkill (phương pháp Weng-Lin Bayes với mô hình Plackett-Luce). Bản triển khai tham chiếu chạy trên Java với thư viện com.pocketcombats:openskill; bản thân phương pháp này không phụ thuộc vào ngôn ngữ lập trình và được mô tả chi tiết bên dưới.

Mỗi điểm rating là một phân phối chuẩn với giá trị trung bình μ (sức mạnh ước tính) và độ lệch chuẩn σ (độ không chắc chắn). Giá trị khởi đầu cho một đối tượng mới:

μ₀ = 25.0     σ₀ = 25 / 3 ≈ 8.3333
Giá trị điểm rating khởi tạo (RatingEngine.DEFAULT_MU / DEFAULT_SIGMA)

Giá trị so sánh được hiển thị là số thứ tự bảo thủ — mức sức mạnh trừ đi một khoản dự phòng an toàn cho độ không chắc chắn:

ordinal = μ − Z · σ     (Z = 3)
Điểm số thận trọng. Một đối tượng mới bắt đầu với 25 − 3 · 8.3333 = 0.

Các thông số ván đấu sử dụng giá trị mặc định của thư viện (Weng-Lin) mà không có thay đổi: β = σ₀ / 2 ≈ 4.167 (độ phân tán giữa thực lực và phong độ) và τ = σ₀ / 100 ≈ 0.083 (số hạng động cộng thêm, giúp tăng nhẹ σ trước mỗi lần cập nhật để điểm rating luôn linh hoạt).

Tính điểm ván đấu

Một ván đấu gồm hai bên (Đội A và Đội B). Mỗi bên được tổng hợp từ điểm rating cá nhân của các người chơi thành một điểm rating của đội (tổng các μ hoặc tổng các σ², DefaultTeamRatingAggregator). Từ kết quả này, các thứ hạng sẽ được xác định:

  • Bên thắng: hạng 1, bên thua: hạng 2.
  • Hòa: cả hai bên hạng 1.

Với những thứ hạng này, mô hình Plackett-Luce cập nhật cho mỗi đối tượng tham gia: chỉ số sức mạnh μ được điều chỉnh theo hướng của kết quả thực tế, và độ không chắc chắn σ giảm dần sau mỗi ván đấu. Mức độ điều chỉnh phụ thuộc vào sự chênh lệch giữa kết quả dự kiến và thực tế, cũng như độ không chắc chắn hiện tại.

Xác suất thắng của bên A trước bên B (dùng để dự đoán/ghép cặp) được tính từ các giá trị tổng hợp của đội thông qua hàm phân phối chuẩn tích lũy Φ:

P(A > B) = Φ( (μ_A − μ_B) / √(σ_A² + σ_B² + β²) )
RatingEngine.predictWin — hàm phân phối tích lũy Gauss.

Hai phép chiếu: cá nhân và cặp

Mỗi ván đấu được tính điểm theo hai hình chiếu độc lập:

  • Cá nhân — Đối tượng là ID thành viên. Yêu cầu ít nhất một thành viên thực sự ở cả hai bên.
  • Cặp (đội) — đối tượng là một cặp thành viên không theo thứ tự. Một bên đầy đủ (2 thành viên thực sự) tạo thành một cặp; một bên có khách không tạo thành một cặp.

Phân chia đội từ dữ liệu ghi nhận: result_player.teamA hoặc B; đội thắng nằm trong result.winner_team (nếu để trống, ván đấu được tính là hòa). Những người chơi không có ID thành viên (khách) sẽ bị loại bỏ khi tính điểm rating. Nếu một bên chỉ bao gồm khách, bên đó sẽ không được tính điểm rating, nhưng đóng vai trò là đối thủ tiêu chuẩn (đối tượng với giá trị khởi tạo) để bên còn lại vẫn có thể được tính điểm đầy đủ. Các ván đấu có exclude_from_rating sẽ bị bỏ qua hoàn toàn.

Phân đoạn và lặp lại theo trình tự thời gian

Một partition là một bộ (scope, scopeRefId). Có bốn phạm vi: GLOBAL (không có ref), CLUB (clubId), EVENT (eventId), SEASON (seasonId). Mỗi partition được tính toán độc lập — một ván đấu được tính vào nhiều partition cùng lúc.

Điểm rating phụ thuộc vào thứ tự và có sự liên kết (kết quả của một ván đấu phụ thuộc vào điểm rating trước đó). Vì vậy, chúng không được "tính toán lại" theo kiểu lũy tiến, mà được hình thành thông qua việc lặp lại theo trình tự thời gian của các ván đấu trong phân vùng. Lịch sử snapshot cho mỗi ván đấu (μ/σ trước và sau mỗi ván đấu) là nguồn sự thật; các bảng vật lý hóa member_rating / team_rating chỉ lưu giữ trạng thái hiện tại để truy xuất đọc nhanh.

  • Tính toán lại toàn bộ: tất cả các ván đấu của phân vùng sẽ được tính toán lại từ các giá trị khởi đầu.
  • Phát lại một phần từ một thời điểm: trạng thái được tải từ snapshot cuối cùng trước thời điểm thay đổi (seeding) và được chạy lại từ đó — các snapshot kể từ thời điểm đó sẽ bị xóa trước.

Giá trị vật chất cho mỗi đối tượng

Sau khi lặp lại, bản ghi hiện tại của mỗi đối tượng sẽ được viết lại:

TrườngÝ nghĩa
mu, sigmaGiá trị sau ván đấu cuối cùng
ordinalmu − 3 · sigma (thận trọng)
ordinalPreviousThứ hạng trước ván đấu cuối cùng (cho mũi tên xu hướng)
peakOrdinal / peakAtthứ hạng cao nhất từng đạt được và thời điểm
gamesCountSố ván đấu tính điểm trong phân vùng
provisionalđúng, miễn là gamesCount < 10
lastGameAtThời điểm ván đấu tính điểm gần nhất
Tất cả các giá trị μ/σ/thứ tự được lưu đều được làm tròn đến 4 chữ số thập phân (HALF_UP).

Giảm điểm do không hoạt động

Một tác vụ hằng ngày (Mặc định: 04:00) làm tăng độ không chắc chắn của các điểm rating không hoạt động. Đối với mỗi điểm rating có ván đấu cuối cùng cách đây hơn 30 ngày, áp dụng:

σ ← min(σ + 0.05, 8.3333)
ordinal ← μ − 3 · σ
Mỗi lần chạy job. μ không đổi; không ghi lịch sử snapshot (decay không phải là một sự kiện ván đấu).
  • Mỗi ván, σ tăng thêm 0.05, giới hạn tại σ_max = 8.3333 (= giá trị bắt đầu σ₀).
  • Chỉ những điểm rating dưới mức giới hạn trên mới được điều chỉnh (một lệnh cập nhật hàng loạt).
  • Phạm vi EVENT không áp dụng decay (một giải đấu là một khoảng thời gian cố định).

Xử lý (bất đồng bộ, nhất quán cuối cùng)

Việc tính toán không bao giờ diễn ra đồng bộ với việc lưu kết quả, mà theo cơ chế eventual: Một thay đổi kết quả sẽ đánh dấu các phân vùng bị ảnh hưởng là "dirty" sau khi commit (AFTER_COMMIT) (được đưa vào hàng đợi tính toán lại). Một worker duy nhất sẽ xử lý hàng đợi một cách tuần tự và tính toán lại mỗi phân vùng bị ảnh hưởng kể từ thời điểm thay đổi. Nhờ đó, các điểm rating liên kết luôn nhất quán mà không làm gián đoạn quá trình lưu.

Việc thay đổi kết quả luôn ảnh hưởng đến: GLOBAL, câu lạc bộ của ván đấu, sự kiện (cả cũ và mới nếu bị dời lịch) cũng như mọi mùa giải có thời gian bao gồm thời điểm diễn ra ván đấu.