// //]]>
Đang tải...

Thứ Hai, 20 tháng 2, 2017

Cách viết code hệ thống ranking member trong group (Analytics for group)


Hôm nay, mình sẽ hướng dẫn các bạn cách viết code hệ thống ranking member cho group cả thuật toán lẫn viết code. Ở post này, mình sẽ viết bằng ngôn ngữ Autoit, còn thím nào muốn chuyển qua php hay gì đó thì chỉ cần thay đổi vài chỗ và hàm tương ứng là xong rồi :V

I. Ý tưởng Thật ra, ý tưởng này mình thấy đã lâu, cụ thể là mấy tháng trước anh Huỳnh Phúc Huy bên group "Lập trình Autoit" đã ra mắt chức năng này, hay mới gần đây là anh Mạnh Tuấn (với điều này đã lôi kéo được khá nhiều lượt tương tác cho group "J2TeaM Community") . Mình thấy khá hay, nên muốn bắt tay vào làm thử.

II. Chuẩn bịUDF
+ Json (tác giả : Ward và Zserge)

Token
+ Các bạn có thể lấy token của HTC Sense (Cái này thưởng thấy ở trong mấy hệ thống auto like, yên tâm, sẽ không sao, nếu bạn không sài mấy hệ thống đó, token của bạn sẽ vẫn được an toàn) - tham khảo tại đây
+ Hoặc bạn có thể tự tạo app - đây là phương pháp an toàn - tham khảo tại đây
Và một số kiến thức về lập trình (trong bài, mình có sử dụng đệ quy, để dễ tích hợp hơn với hệ thống ranking này) - bạn có thể tham khảo trên mạng

III. Cơ chế Tạm giống của anh Mạnh Tuấn
+ Người Post bài : +3 điểm . + 1 điểm đối với 1 lượt like bài. +1 điểm cho 1 lượt cmt. +1 điểm cho 1 lượt share
+ Người không đăng bài : +1 điểm có reactions bài, +1 điểm cho 1 lượt cmt,...

IV. Thuật toán
Thuật toán của mình thì chắc chả có gì đăt biệt, nhưng đây chỉ là ý tưởng riêng của mình (có thể sẽ chậm hơn nhìu so với mấy bậc tiền bối kia :3 )
Mình nghĩ là: thực hiện lọc trùng id trong lúc chạy hơn là lọc trùng sau khi có id (nhưng chắc sẽ chậm hơn cách của anh Mạnh Tuấn :3 )


+ Đầu tiên, ta khai báo mảng 2 chiều (Đây là mảng chưa thông số điểm của từng thành viên hoạt động)

|Cột thứ 1|Cột thứ 2|Cột thứ 3|
|Id User |Điểm |Tên User|



+ Chạy Json để thu về Id post của từng bài để đưa vào khâu xử lý (như id user post bài, id user reactions stt + số lượng reactions , id user cmt, id user share + số lượng share. Tất cả, mình để chia thành từng function nhỏ, cho đỡ rối trong khi code và trả giá trị ra là mảng). Đồng thời lấy giá trị Updated_time để thống kê theo ngày giờ (làm biến Limit Time, ví dụ : Thống kê trong 30 ngày, 1 tuần hay 1 ngày chẳng hạn,...)

+ Sau khi có được mảng user reaction, cmt, share, ta sẽ thực hiện cộng điểm cho từng user reaction, cmt, share ấy dựa trên id

* Chạy vòng lập For -> Số lượng mảng()
* Kiểm tra trùng

Nếu không có thì add id đó vào danh sách ranking với point là 1 (like) hay 2 (share) tùy vào số điểm chẳng hạn

Nếu có thì cộng dồn điểm đó vào vị trí trùng tìm được

+ Tiếp theo, ta lấy ID của người post và tiến hành add vào danh sách (giống như cách kiểm tra trùng trên)
+ Trong lúc chạy, nếu Updated_time vẫn lớn hơn Limit Time (Limit time là thời gian thống kê trước đó, như đã nói trên) thì cứ chạy, ngược lại thì thoát khỏi quá trình chạy Json
+ Chắc chắn Api facebook sẽ tự động phân thành trang với dạng Json là : ["paging"]["next"], lúc này, bạn thực hiện đệ quy :

* Nếu Updated_time vẫn lớn hơn Limit Time thì ta lấy link next phía trên và tiến hành gọi lại hàm, để tiếp tục cộng dồn vào hệ thống ranking ( hàm có dạng _ham(ByRef $link, ....)

+ Cuối cùng, ta tiến hành sắp xếp giảm dần theo giá trị điểm trong mảng 2 chiều

=> Vậy là ta đã có được một hệ thống ranking hoàn chỉnh về số điểm của từng thành viên rồi nhé ^_^ ! Nếu bạn nào giỏi thì có thể ra thuật toán ngon hơn của mình, và share cho mọi người nha, hoặc cmt bên dưới bài viết, để mình cập nhập thêm cho Bài viết này.

V. Viết code Đầu tiên, ta tạo biến $LimitTime

$LimitTime = _DateDiff('s', "1970/01/01 00:00:00", _NowCalc()) ; Lấy time hiện tại (convert to seconds)
$ngay = 86400 ; tổng giây một ngày
$tuan = 604800 ; tổng giây một tuần
$thang = 2592000 ; tổng giây một tháng
$LimitTime = $LimitTime-$ngay ; Vd : thống kê trong một ngày

Hàm _FormatTime() do mình viết dựa trên time mà Api facebook cung cấp (dùng để chuyển đối chuỗi time thành tổng giây)

Func _FormatTime($string)
 $string = StringReplace($string, "T", " ")
 $string = StringReplace($string, "+0000", "")
 $string = StringReplace($string, "-", "/")
 $time = _DateDiff('s', "1970/01/01 00:00:00", $string)
 Return $time
EndFunc

Hàm đệ quy để tiến hành chạy Ranking

Func _GetPost2($access_token,ByRef $link, $LimitTime)
 $JsonObj = Json_Decode(_INetGetSource($link))
 If @error then Return SetError(1,0,0)
 $i = 0
 $point = 0
 While 1
  $point = 0
  $updated_time = Json_Get($JsonObj, '["data"][' & $i & ']["updated_time"]')
  If @error then ExitLoop
  If _FOrmatTime($updated_time)<$LimitTime Then ExitLoop
  $actor_id = Json_Get($JsonObj, '["data"][' & $i & ']["from"]["id"]')
  If @error then ExitLoop
  $point += 3
  $post_id = Json_Get($JsonObj, '["data"][' & $i & ']["id"]')
  If @error then ExitLoop
  ConsoleWrite($post_id&@CRLF)
  $sharecount = _GetShare($post_id, $access_token)
  If $sharecount <> False then $point += $sharecount
  $linkReactions = "https://graph.facebook.com/v2.8/"&$post_id&"/reactions?limit=25&access_token="&$access_token
  Global $Array[0]
  _GetReactions($linkReactions)

  If Not IsArray($Array) Then
   _ArrayAdd($Array2d, $actor_id&"|1") ; Nếu không có ai like, sẽ tự động tăng điểm +1 cho người đăng bài
  Else
   $point += Ubound($Array) ; Tăng điểm cho người đăng bài dựa trên số lượng like
  EndIf  ;

Lọc Trùng Sau khi thêm Reactions
  For $j = 0 To (UBound($Array)-1)
   $tam = _ArrayFindAll($Array2d, $Array[$j], Default, Default, Default, Default, 0) ; Lọc Trùng của ID Người like trong Danh Sách Ranking
   If UBound($tam)>=1 Then
    $Array2d[$tam[0]][1] += 1 ; Nếu trùng thì cộng dồn điểm cho user id (+1)
   Else
    _ArrayAdd($Array2d, $Array[$j]&"|1") ; Nếu không có trùng thì tạo user id mới cho Array
   EndIf
  Next

  $linkCMT = "https://graph.facebook.com/v2.8/"&$post_id&"?fields=comments&access_token="&$access_token
  Global $ArrayCMT[0]
  _GetCMT($linkCMT)

  If Not IsArray($ArrayCMT) Then
   _ArrayAdd($Array2d, $actor_id&"|1") ;Nếu không có ai cmt, sẽ tự động tăng điểm +1 cho người đăng bài
  Else
   $point += Ubound($ArrayCMT);Tăng điểm cho người đăng bài dựa trên số lượng cmt
  EndIf

  For $j = 0 To (UBound($ArrayCMT)-1)
   $tam = _ArrayFindAll($Array2d, $ArrayCMT[$j], Default, Default, Default, Default, 0);Lọc Trùng của ID Người CMT trong Danh Sách Ranking
   If UBound($tam)>=1 Then
    $Array2d[$tam[0]][1] += 1; Nếu trùng thì cộng dồn điểm cho user id (+1)
   Else
    _ArrayAdd($Array2d, $ArrayCMT[$j]&"|1");Nếu không có trùng thì tạo user id mới cho Array
   EndIf
  Next  ;


Lọc Trùng để thêm vào danh sách Ranking đối với người đăng bài
  $tam = _ArrayFindAll($Array2d, $actor_id, Default, Default, Default, Default, 0) ; Kiểm tra xem id người đăng bài có trong danh sách Ranking hay không?
  If UBound($tam)=1 Then
   $Array2d[$tam[0]][1] += $point ;  Nếu trùng thì cộng dồn điểm
  Else
   _ArrayAdd($Array2d, $actor_id&"|"&$point) ;Nếu không trùng thì tạo user id
  EndIf
  $updated_time = Json_Get($JsonObj, '["data"][' & $i & ']["updated_time"]') ; Lấy Update time để kiểm tra Limit Time
  $i += 1
 WEnd
 If _FOrmatTime($updated_time)<$LimitTime Then
  Return 1
 Else
  $updated_time = Json_Get($JsonObj, '["data"][' & $i-1 & ']["updated_time"]')
  If @error then Return SetError(1,0,0)
  If $updated_time<=$LimitTime Then
   Return 1
  Else
   $link = Json_Get($JsonObj, '["paging"]["next"]') ; Lấy link kế tiếp của api để get tiếp
   If $link<>"" then
    _GetPost2($access_token, $link, $LimitTime) ; Gọi đệ quy để cộng dồn
   Else
    Return 1
   EndIf
  EndIf
 EndIf
EndFunc


Cách gọi hàm đệ quy ra :
Global $Array2d[0][3]
$access_token="Token của bạn"
$id_group = "id group";Vd : 364997627165697
$link = "https://graph.facebook.com/v2.8/"&$id_group&"/feed?fields=from,updated_time&access_token="&$access_token
_GetPost2($access_token, $link, $LimitTime)

Sau khi gọi hàm đó xong, ta tiến hành get tên cho từng id với lệnh sau :
_ArraySort($Array2d,1,0,0,1); Sắp xếp điểm point theo thứ tự giảm dần
FOr $i=0 to UBound($Array2d, 1)-1
 $Array2d[$i][2] = _GetName($Array2d[$i][0], $access_token); Lấy tên của id
 ConsoleWrite($Array2d[$i][2]&@CRLF); Write tên ra
Next

Trong đó có hàm _GetName()
Func _GetName($id, $access_token)
 $link = "https://graph.facebook.com/v2.8/"&$id&"?access_token=" & $access_token
 $JsonObj = Json_Decode(_INetGetSource($link))
 $name = Json_Get($JsonObj, '["name"]')
 Return $name
EndFunc


Lấy user reactions từ ID Post
Func _GetReactions(ByRef $link)
 If $link="" then Return SetError(1,0,0)
 $JsonObj = Json_Decode(_INetGetSource($link))
 $i = 0
 While 1
  $id = Json_Get($JsonObj, '["data"][' & $i & ']["id"]')      
  If @error then ExitLoop
  _ArrayAdd($Array, $id)
  $i += 1
 Wend
 $next = Json_Get($JsonObj, '["paging"]["next"]')
 If @error Then Return $Array
 If $next<>"" and not @error Then
  _GetReactions($next); Gọi đệ quy
 EndIf
 Return $Array
EndFunc

Lấy comment từ ID Post
Func _GetCMT(ByRef $link)
 If $link="" then Return SetError(1,0,0)
 $JsonObj = Json_Decode(_INetGetSource($link))
 $i = 0
 While 1
  $id = Json_Get($JsonObj, '["comments"]["data"][' & $i & ']["from"]["id"]')      
  If @error then ExitLoop
  _ArrayAdd($ArrayCMT, $id)
  $i += 1
 Wend
 $next = Json_Get($JsonObj, '["paging"]["next"]')
 If @error Then Return $ArrayCMT
 If $next<>"" and not @error Then
  _GetCMT($next); Gọi đệ quy
 EndIf
 Return $ArrayCMT
EndFunc

Lấy số lựợng share từ ID Post
Func _GetShare($id, $access_token)
 If StringInStr($id, "_")=0 or $id="" or $access_token="" then Return SetError(1,0,False)
 $link = "https://graph.facebook.com/v2.8/"&$id&"?fields=shares&access_token=" & $access_token
 $JsonObj = Json_Decode(_INetGetSource($link))
 $count = Json_Get($JsonObj, '["shares"]["count"]')
 ConsoleWrite($count&@CRLF)
 Return $count
EndFunc

Link DownLoad Full UDF (AutoIT) : https://github.com/nguyenphucbao68/Ranking-Members-In-Group

VI. Kết quả Test code trong vòng 1 tuần đối với group J2Team
Thời gian chạy code : 18 phút 1 giây (hao nhất ở phần GetName, tốn 16 phút, nếu bạn nào có ý tưởng thì cứ cmt bên dưới nha, mình sẽ bổ sung vào bài của mình nếu thấy hợp lí >.< )

Thu được 1332 id user và số điểm tương ứng ! Thánh Lâm Oscar rank cao vl =.=


VII. Đôi lời Các bạn có thể copy, có thể phát triển code và share, nhưng mình mong các bạn ghi rõ nguồn người viết ^^, nếu bạn sử dụng lõi cũ và thuật toán như code mình.

Nguồn (Tác giả): https://www.facebook.com/trojannguyen.dev

Bài viết xem nhiều

Liên kết từ khóa

Đăng ký theo dõi qua Email

Đăng ký bằng email của bạn để nhận được tin mới nhất từ chúng tôi.

Liên hệ với chúng tôi

Gửi tin nhắn cho chúng tôi.

MysTown Beta Version II | Copyright 2015 - 2016 | Rip Code by MyS | Trở về đầu trang