Create an automatic grade management app for Tenhou private room with LINE bot and Python Part ③

Introduction

This time, I added __Rating function __ to the Tenhou automatic grade management app created in the following post.

-Create an automatic grade management app for Tenhou private room with LINE bot and Python (1) -Create an automatic grade management app for Tenhou private room with LINE bot and Python (2)

Rating formula

Rating adopts the following Tenhou format. In Tenhou, the Rating is also a complete ranking system based on the complete ranking system of grades. In our private room, we adopted the rule that the weight of the ranking point is relatively high, so we adopted the Tenhou style Rating.

-Tenhou Official Manual

(Partial excerpt below)

--The ranking points (10-30) are corrected by the average of the same table players. --Initial value = R1500 --The higher the average R of the table, the greater the increase. (Rate fluctuation) = (Number of games corrected) x (Competition result + Correction value) x (Scaling coefficient) Match number correction (less than 400 matches): 1-Number of matches x 0.002 Match number correction (400 games or more): 0.2 Match result (3 dan battle): 1st place +30 2nd place 0 3rd place-30 Correction value: (Table average R-your own R) / 40 Scaling factor (dan battle): 1.0

If your private room has a rule that emphasizes raw scores over ranking scores, it may be more correlated with grades if you emphasize other Rating formulas. The following site calculates the Rating of M Leaguer using three types of formulas, so please refer to it.

-I calculated the rate ranking of M Leaguer with 3 patterns of Tenhou, MaruJan, and MJ!

Implementation

Preamble

import re
import matplotlib.pyplot as plt

Rating / R initialization

The rating data is initialized by the initial data (Player name: player, initial R: init_rating, initial number of villas: init_games) in ʻinitial_file.txt`. Basically R = 1500, games = 0.

calc_rating.py



def initialize_rating(initial_file):
    
    with open(initial_file) as f:
        init_ratings = f.readlines() 

    rating = {}
    games  = {}
    rating_history = {}
    
    for l in init_ratings:
        player      = l.split()[0]
        init_rating = l.split()[1] 
        init_games  = l.split()[2]
        rating[player] = float(init_rating) 
        games[player]  = int(init_games)
        rating_history[player] = [float(init_rating)]
        print(games)
    
    return rating,games,rating_history

initial_file.txt


Mr. A 1500 0
Mr. B 1500 0
Mr. C 1500 0
Mr. D 1500 0

Calculation of R

def calc_rating(initial_rating,initial_games,initial_rating_history,logfile,tip=False):
    with open(logfile) as f:
        lines = f.readlines() #Read everything up to the end of the file line by line(Newline character is also included)

    rating = initial_rating
    games  = initial_games
    rating_history = initial_rating_history

    for line in lines[1:]:
        # print(games)

        if len(line) > 10: #Skip strange lines
         
            roomid  = line.split("|")[0]
            time    = line.split("|")[1]
            rools   = line.split("|")[2]
            players = line.split("|")[3]
            
       #Without congratulations
            if tip == False:
                l = re.split('[ ()]', players)
                player1 = l[1]
                player2 = l[4]
                player3 = l[7]
                
            #If there is a celebration
            if tip == True:
                l = re.split('[ (,)]', players)
                player1 = l[1]
                player2 = l[5]
                player3 = l[9]

            rate_average = (rating[player1]+rating[player2]+rating[player3])/3.0
            rate_average = round(rate_average,3)
            if rate_average < 1500.0:
                rate_average = 1500.0

            #Match number correction
            if games[player1] < 400:
                games_correction1 = 1.0 - games[player1]*0.002
            if games[player1] >= 400:
                games_correction1 = 0.2
            if games[player2] < 400:
                games_correction2 = 1.0 - games[player2]*0.002
            if games[player2] >= 400:
                games_correction2 = 0.2
            if games[player3] < 400:
                games_correction3 = 1.0 - games[player3]*0.002
            if games[player3] >= 400:
                games_correction3 = 0.2

            #Average R correction
            averageR_correction1 = (rate_average - rating[player1])/40.0
            averageR_correction2 = (rate_average - rating[player2])/40.0
            averageR_correction3 = (rate_average - rating[player3])/40.0

            #Rating fluctuation
            rate_delta1 = round(games_correction1 * ( 30.0  + averageR_correction1 ) * 1.0, 3) # 1st
            rate_delta2 = round(games_correction2 * ( 0.0   + averageR_correction2 ) * 1.0, 3) # 2nd
            rate_delta3 = round(games_correction3 * ( -30.0 + averageR_correction3 ) * 1.0, 3) # 3rd
            print(rate_delta1,rate_delta2,rate_delta3)

            # Rating
            rating[player1] += rate_delta1
            rating[player2] += rate_delta2
            rating[player3] += rate_delta3

            # Rating History
            rating_history[player1].append(rating[player1]) 
            rating_history[player2].append(rating[player2]) 
            rating_history[player3].append(rating[player3])             

            # Games
            games[player1] += 1
            games[player2] += 1
            games[player3] += 1

    return rating,games,rating_history

Graphing R fluctuations

def rating_plot(rating_history):

    plt.clf()
    names = {"Mr. A":"a","Mr. B":"b","Mr. C":"c","Mr. D":"d"}
    for player in rating_history.keys():
        x = [i for i in range(len(rating_history[player]))]
        y = rating_history[player]
        plt.plot(x,y,linewidth=0.5,alpha=0.5)
        plt.scatter(x[-1],y[-1],label=names[player])
        plt.text(x[-1],y[-1]+5,int(y[-1]))

    plt.legend()
    plt.savefig("rating.png ")

Run (test in local environment)

if __name__ == "__main__":
    r,g,h = initialize_rating("rating.txt")
    r,g,h = calc_rating(r,g,h,"logvol1.txt",tip=False)
    r,g,h = calc_rating(r,g,h,"logvol2.txt",tip=True)
    r,g,h = calc_rating(r,g,h,"logvol3.txt",tip=True)

    rating_plot(h)

Output result

Implementation on LINE bot

tenhoulinebot.py



(Omission)
    import download4
    import rating.calc_rating as cr
(Omission)
    elif postbackdata == "request_rating":
        download4.download("/logvol1.txt","rating/logvol1.txt")
        download4.download("/logvol2.txt","rating/logvol2.txt")
        download4.download("/logvol3.txt","rating/logvol3.txt")
        
        initial_rating,initial_games,initial_rating_history = cr.initialize_rating("rating/rating.txt")
        r,g,h = cr.calc_rating(initial_rating,initial_games,initial_rating_history,"rating/logvol1.txt",tip=False)
        r,g,h = cr.calc_rating(r,g,h,"rating/logvol2.txt",tip=True)
        r,g,h = cr.calc_rating(r,g,h,"rating/logvol3.txt",tip=True)
        cr.rating_plot(h)

        bucket.upload_file("rating.png ", "rating.png ")
        s3_image_url = s3_client.generate_presigned_url(
            ClientMethod = 'get_object',
            Params       = {'Bucket': aws_s3_bucket, 'Key': "rating.png "},
            ExpiresIn    = 600,
            HttpMethod   = 'GET'
        )

        line_bot_api.reply_message(
            event.reply_token,
            ImageSendMessage(
                original_content_url = s3_image_url,
                preview_image_url    = s3_image_url,
            )
        )
        download4.upload("rating.png ","/rating.png ")  


P.S.

Mahjong this season is in very good shape. One person wins. I would like to win the championship as it is. I would like to try Tenhou's score analysis, but the mjlog format (xml) is difficult. .. .. Please let me know. .. ..

Recommended Posts

Create an automatic grade management app for Tenhou private room with LINE bot and Python Part 1
Create an automatic grade management app for Tenhou private room with LINE bot and Python Part 2
Create an automatic grade management app for Tenhou private room with LINE bot and Python Part ③
Create a LINE BOT with Minette for Python
LINE BOT (Messaging API) development with API Gateway and Lambda (Python) [Part 2]
Create an English word app with python
Create an app that guesses students with python
Let's make an app that can search similar images with Python and Flask Part2
[LINE Messaging API] Create parrot return BOT with Python
Create a machine learning app with ABEJA Platform + LINE Bot
Create an LCD (16x2) game with Raspberry Pi and Python
Create a Twitter BOT with the GoogleAppEngine SDK for Python
Create a striped illusion with gamma correction for Python3 and openCV3
[LINE Messaging API] Create a BOT that connects with someone with Python
FX automatic trading system made with python and genetic algorithm Part 1
Create an Excel file with Python3
An app for smart people and smart people
Explanation of creating an application for displaying images and drawing with Python
FM modulation and demodulation with Python Part 3
Quickly create an excel file with Python #python
Create and decrypt Caesar cipher with python
[Python] [LINE Bot] Create a parrot return LINE Bot
FM modulation and demodulation with Python Part 2
[Python] Quickly create an API with Flask
[LINE WORKS version Trello Bot] How to create a private talk room including a talk bot