Gacha écrit en python-Practice 1-

Contenu

Jusqu'à présent, je n'ai considéré que le traitement gacha, mais dans le jeu réel

--Affichez l'écran pour exécuter gacha --L'utilisateur sélectionne et exécute gacha

Considérez la conception et la modification des données susmentionnées qui peuvent gérer le traitement. De plus, à partir de ce moment, DB sera utilisé pour stocker les données liées à gacha.

** Les sources suivantes ont été modifiées et mises en œuvre **

Gacha écrit en python-Ajout de la fonction de réglage de période-

Collecter des informations de paramétrage redondantes

Informations sur Gacha

id start_time end_time gacha_group gacha_lottery_id
1 2020-05-01 00:00:00 2020-05-31 23:59:59 A normal_1
2 2020-05-01 00:00:00 2020-05-31 23:59:59 A normal_11
6 2020-06-01 00:00:00 2020-06-30 23:59:59 C normal_1
7 2020-06-01 00:00:00 2020-06-30 23:59:59 C normal_11

Éléments d'information gacha

Le rôle de ** Gacha Information ** est de définir un «groupe d'éléments gacha cibles» pendant la «période de mise en œuvre» et de le lier au «comment dessiner un gacha». La seule différence entre les ID ** 1 ** et ** 2 ** (ou ** 6 ** et ** 7 **) est que le "comment dessiner le gacha" est un coup (une fois) ou 11 consécutifs. est. La configuration d'informations redondantes augmente le temps et les efforts et entraîne des erreurs de configuration pendant le fonctionnement. Si possible, je voudrais éviter de définir les mêmes informations plus d'une fois, je vais donc modifier la structure des données.

Changement de la structure des données d'information gacha

À partir des informations ** gacha **, ajoutez l'élément gacha_type au lieu de gacha_lottery_id. Ajoutez gacha_type à ** gacha_lottery ** pour lier les informations gacha et les informations de définition de méthode gacha.

gacha

id start_time end_time gacha_group gacha_type
1 2020-05-01 00:00:00 2020-05-31 23:59:59 A normal
6 2020-06-01 00:00:00 2020-06-30 23:59:59 C normal

gacha_lottery

id gacha_type item_type times rarity omake_times omake_rarity cost
normal_1 normal 0 1 0 0 0 10
normal_11 normal 0 10 0 1 3 100

Imaginez ce qui suit affiché sur l'écran gacha du jeu.

gacha_2.png

la mise en oeuvre

Étant donné que diverses informations seront acquises à partir de la base de données à partir de cette implémentation, créez d'abord une table et définissez les données.

Informations de la base de données Gacha (exécutées en cas de changement de structure ou de données)

gacha_db


# -*- coding: utf-8 -*-
import sqlite3
import random

def get_items():
    items = {
        5101: {"rarity": 5, "item_name": "UR_Courageux", "item_type": 1, "hp": 1200},
        4201: {"rarity": 4, "item_name": "SSR_guerrier", "item_type": 2, "hp": 1000},
        4301: {"rarity": 4, "item_name": "SSR_sorcier", "item_type": 3, "hp": 800},
        4401: {"rarity": 4, "item_name": "SSR_Prêtre", "item_type": 4, "hp": 800},
        3201: {"rarity": 3, "item_name": "SR_guerrier", "item_type": 2, "hp": 600},
        3301: {"rarity": 3, "item_name": "SR_sorcier", "item_type": 3, "hp": 500},
        3401: {"rarity": 3, "item_name": "SR_Prêtre", "item_type": 4, "hp": 500},
        2201: {"rarity": 2, "item_name": "R_guerrier", "item_type": 2, "hp": 400},
        2301: {"rarity": 2, "item_name": "R_sorcier", "item_type": 3, "hp": 300},
        2401: {"rarity": 2, "item_name": "R_Prêtre", "item_type": 4, "hp": 300},
        3199: {"rarity": 3, "item_name": "SR_Courageux", "item_type": 1, "hp": 600},
        #Ajouté ci-dessous
        4101: {"rarity": 4, "item_name": "SSR_Courageux", "item_type": 1, "hp": 1000},
        5201: {"rarity": 5, "item_name": "UR_guerrier", "item_type": 2, "hp": 1300},
        5301: {"rarity": 5, "item_name": "UR_sorcier", "item_type": 3, "hp": 1000},
    }

    return convert_values(items)

def get_gacha_items():
    items = {
        1:  {"gacha_group": "A", "weight": 3, "item_id": 5101},
        2:  {"gacha_group": "A", "weight": 9, "item_id": 4201},
        3:  {"gacha_group": "A", "weight": 9, "item_id": 4301},
        4:  {"gacha_group": "A", "weight": 9, "item_id": 4401},
        5:  {"gacha_group": "A", "weight": 20, "item_id": 3201},
        6:  {"gacha_group": "A", "weight": 20, "item_id": 3301},
        7:  {"gacha_group": "A", "weight": 20, "item_id": 3401},
        8:  {"gacha_group": "A", "weight": 40, "item_id": 2201},
        9:  {"gacha_group": "A", "weight": 40, "item_id": 2301},
        10: {"gacha_group": "A", "weight": 40, "item_id": 2401},
        11: {"gacha_group": "B", "weight": 15, "item_id": 4201},
        12: {"gacha_group": "B", "weight": 30, "item_id": 3201},
        13: {"gacha_group": "B", "weight": 55, "item_id": 2201},
        #Ajouté ci-dessous
        14: {"gacha_group": "C", "weight": 1, "item_id": 5101},
        15: {"gacha_group": "C", "weight": 1, "item_id": 5201},
        16: {"gacha_group": "C", "weight": 1, "item_id": 5301},
        17: {"gacha_group": "C", "weight": 9, "item_id": 4101},
        18: {"gacha_group": "C", "weight": 6, "item_id": 4201},
        19: {"gacha_group": "C", "weight": 6, "item_id": 4301},
        20: {"gacha_group": "C", "weight": 6, "item_id": 4401},
        21: {"gacha_group": "C", "weight": 20, "item_id": 3201},
        22: {"gacha_group": "C", "weight": 20, "item_id": 3301},
        23: {"gacha_group": "C", "weight": 20, "item_id": 3401},
        24: {"gacha_group": "C", "weight": 40, "item_id": 2201},
        25: {"gacha_group": "C", "weight": 40, "item_id": 2301},
        26: {"gacha_group": "C", "weight": 40, "item_id": 2401},
    }

    return convert_values(items)

def get_gacha():
    items = {
        1: {"start_time": "2020-05-01 00:00:00", "end_time": "2020-05-31 23:59:59", "gacha_group": "A",
            "gacha_type": "normal"},
        3: {"start_time": "2020-05-25 00:00:00", "end_time": "2020-05-31 23:59:59", "gacha_group": "B",
            "gacha_type": "fighter"},
        4: {"start_time": "2020-06-01 00:00:00", "end_time": "2020-06-04 23:59:59", "gacha_group": "C",
            "gacha_type": "omake_2"},
        5: {"start_time": "2020-05-20 00:00:00", "end_time": "2020-05-31 23:59:59", "gacha_group": "A",
            "gacha_type": "omake_fighter"},
        6: {"start_time": "2020-06-01 00:00:00", "end_time": "2020-06-30 23:59:59", "gacha_group": "C",
            "gacha_type": "normal"},
    }

    return convert_values(items)

def get_gacha_lottery():
    items = {
        "normal_1":  {"gacha_type": "normal", "item_type": 0, "times": 1, "rarity": 0, "omake_times": 0, "omake_rarity": 0, "cost":10},
        "normal_11":  {"gacha_type": "normal", "item_type": 0, "times": 10, "rarity": 0, "omake_times": 1, "omake_rarity": 3, "cost":100},
        "fighter":  {"gacha_type": "fighter", "item_type": 0, "times": 2, "rarity": 0, "omake_times": 0, "omake_rarity": 0, "cost":30},
        "omake_2":  {"gacha_type": "omake_2", "item_type": 0, "times": 9, "rarity": 2, "omake_times": 2, "omake_rarity": 3, "cost":150},
        "omake_fighter":  {"gacha_type": "omake_fighter", "item_type": 2, "times": 5, "rarity": 0, "omake_times": 1, "omake_rarity": 3, "cost":100}
    }

    return convert_values(items)


def convert_values(items: dict):
    values = []
    keys = []
    for id,info in items.items():
        if len(keys) == 0 :
            keys = list(info.keys())
            keys.insert(0,'id')

        value = list(info.values())
        value.insert(0,id)
        values.append(tuple(value))
    return keys,values

def print_rows(rows, keys: list):
    for row in rows:
        result = []
        for key in keys:
            result.append(str(row[key]))
        print(",".join(result))


def main():
    con = sqlite3.connect("data.db")
    con.row_factory = sqlite3.Row
    cursor = con.cursor()

    # gacha
    cursor.execute("DROP TABLE IF EXISTS gacha")

    #id
    #start_time
    #end_time
    #gacha_group
    #gacha_lottery_id
    cursor.execute(
        """CREATE TABLE gacha 
          (id INTEGER PRIMARY KEY AUTOINCREMENT
          ,start_time DATETIME
          ,end_time DATETIME
          ,gacha_group VARCHAR(32)
          ,gacha_type VARCHAR(32)
          )
        """
    )

    #         1:  {"gacha_group": "A", "weight": 3, "item_id": 5101},

    cursor.execute("DROP TABLE IF EXISTS gacha_items")
    cursor.execute(
        """CREATE TABLE gacha_items 
          (id INTEGER PRIMARY KEY AUTOINCREMENT
          ,gacha_group VARCHAR(32)
          ,weight INTEGER
          ,item_id INTEGER
          )
        """
    )

    #  "normal_1":  {"item_type": 0, "times": 1, "rarity": 0, "omake_times": 0, "omake_rarity": 0, "cost":10},

    cursor.execute("DROP TABLE IF EXISTS gacha_lottery")
    cursor.execute(
        """CREATE TABLE gacha_lottery 
          (id VARCHAR(32) PRIMARY KEY
          ,gacha_type VARCHAR(32)
          ,item_type INTEGER
          ,times INTEGER
          ,rarity INTEGER
          ,omake_times INTEGER
          ,omake_rarity INTEGER
          ,cost INTEGER
          )
        """
    )

    #        5101: {"rarity": 5, "item_name": "UR_Courageux", "item_type": 1, "hp": 1200},
    cursor.execute("DROP TABLE IF EXISTS items")
    cursor.execute(
        """CREATE TABLE items 
          (id INTEGER PRIMARY KEY AUTOINCREMENT
          ,rarity INTEGER
          ,item_name VARCHAR(64)
          ,item_type INTEGER
          ,hp INTEGER
          )
        """
    )

    keys, values = get_items()
    sql = "insert into {0}({1}) values({2})".format('items', ','.join(keys), ','.join(['?'] * len(keys)))
    cursor.executemany(sql,values)
    select_sql = "SELECT * FROM items ORDER BY id"
    result = cursor.execute(select_sql)
    print("===items===")
    print_rows(result, keys)

    keys, values = get_gacha_items()
    sql = "insert into {0}({1}) values({2})".format('gacha_items', ','.join(keys), ','.join(['?'] * len(keys)))
    cursor.executemany(sql,values)
    select_sql = "SELECT * FROM gacha_items ORDER BY id"
    result = cursor.execute(select_sql)
    print("===gacha_items===")
    print_rows(result, keys)


    keys, values = get_gacha()
    sql = "insert into {0}({1}) values({2})".format('gacha', ','.join(keys), ','.join(['?'] * len(keys)))
    cursor.executemany(sql,values)
    select_sql = "SELECT * FROM gacha ORDER BY id"
    result = cursor.execute(select_sql)
    print("===gacha===")
    print_rows(result, keys)

    keys, values = get_gacha_lottery()
    sql = "insert into {0}({1}) values({2})".format('gacha_lottery', ','.join(keys), ','.join(['?'] * len(keys)))
    cursor.executemany(sql,values)
    select_sql = "SELECT * FROM gacha_lottery ORDER BY id"
    result = cursor.execute(select_sql)
    print("===gacha_lottery===")
    print_rows(result, keys)


    con.commit()
    con.close()

if __name__ == '__main__':
    main()

Traitement Gacha

gacha.py


import random
import sqlite3
from datetime import datetime

def convert_row2dict(row) -> dict:
    keys = row.keys()
    return {key: row[key] for key in keys}


def gacha(lots, times: int=1) -> list:
    return random.choices(tuple(lots), weights=lots.values(), k=times)

def get_rarity_name(rarity: int) -> str:
    rarity_names = {5: "UR", 4: "SSR", 3: "SR", 2: "R", 1: "N"}
    return rarity_names[rarity]

#Liste d'informations gacha exécutable
def get_gacha_list(cursor, now_time: int) -> dict:
    select_sql = "SELECT * FROM gacha ORDER BY id"
    rows = cursor.execute(select_sql)
    results = {}
    for row in rows:
        start_time = int(datetime.strptime(row["start_time"], '%Y-%m-%d %H:%M:%S').timestamp())
        end_time = int(datetime.strptime(row["end_time"], '%Y-%m-%d %H:%M:%S').timestamp())
        #Affinez les informations gacha cible dans la plage de la date et de l'heure
        if start_time <= now_time <= end_time:
            results[row["id"]] = convert_row2dict(row)

    return results

#Liste d'informations gacha exécutable (gacha_(Y compris les informations de loterie)
def get_available_gacha_info_list(cursor, now_time: int) -> dict:
    gacha_list = get_gacha_list(cursor, now_time)
    for gacha_id, info in gacha_list.items():
        lottery_info_list = get_gacha_lottery_by_type(cursor, info["gacha_type"])
        gacha_list[gacha_id]["gacha_lottery_list"] = lottery_info_list
    return gacha_list

def get_gacha(cursor, gacha_id: int, now_time: int) -> dict:
    select_sql = "SELECT * FROM gacha WHERE id = ? ORDER BY id"
    cursor.execute(select_sql, (gacha_id,))
    row = cursor.fetchone()
    start_time = int(datetime.strptime(row["start_time"], '%Y-%m-%d %H:%M:%S').timestamp())
    end_time = int(datetime.strptime(row["end_time"], '%Y-%m-%d %H:%M:%S').timestamp())
    #Affinez les informations gacha cible dans la plage de la date et de l'heure
    if start_time <= now_time <= end_time:
        return convert_row2dict(row)

    return {}


def get_gacha_lottery(cursor, gacha_lottery_id: str) -> dict:
    select_sql = "SELECT * FROM gacha_lottery WHERE id = ? ORDER BY id"
    cursor.execute(select_sql, (gacha_lottery_id,))
    row = cursor.fetchone()
    return convert_row2dict(row)


def get_gacha_lottery_by_type(cursor, gacha_type: str) -> list:
    select_sql = "SELECT * FROM gacha_lottery WHERE gacha_type = ? ORDER BY id"
    rows = cursor.execute(select_sql, (gacha_type,))
    results = []
    for row in rows:
        row_dict = convert_row2dict(row)
        results.append(row_dict)
    return results


def get_items_all(cursor) -> dict:
    select_sql = "SELECT * FROM items ORDER BY id"
    rows = cursor.execute(select_sql)
    results = {}
    for row in rows:
        row_dict = convert_row2dict(row)
        results[row["id"]] = row_dict
    return results


def get_gacha_items(cursor, gacha_group: str) -> dict:
    select_sql = "SELECT * FROM gacha_items WHERE gacha_group = ? ORDER BY id"
    rows = cursor.execute(select_sql, (gacha_group,))
    results = {}
    for row in rows:
        row_dict = convert_row2dict(row)
        results[row["id"]] = row_dict
    return results


def get_gacha_items_all(cursor) -> dict:
    select_sql = "SELECT * FROM gacha_items ORDER BY id"
    rows = cursor.execute(select_sql)
    results = {}
    for row in rows:
        row_dict = convert_row2dict(row)
        results[row["id"]] = row_dict
    return results



def get_gacha_info(cursor, gacha_id: int, gacha_lottery_id: str, now_time: int):
    gacha = get_gacha(cursor, gacha_id, now_time)
    gacha_lottery = get_gacha_lottery(cursor, gacha_lottery_id)

    if gacha["gacha_type"] != gacha_lottery["gacha_type"]:
        return None, None

    return gacha, gacha_lottery


def set_gacha(cursor, now_time: int):
    cursor = cursor
    now_time = now_time
    items = get_items_all(cursor)

    #Extraire la liste des cibles de loterie
    def get_lots(gacha_group: str, lottery_info: dict):
        gacha_items = get_gacha_items(cursor, gacha_group)
        dic_gacha_items = {}
        for gacha_item_id, gacha_item in gacha_items.items():
            gacha_item["item_info"] = items[gacha_item["item_id"]]
            dic_gacha_items[gacha_item_id] = gacha_item

        lots = {}
        omake_lots = {}
        for id, info in dic_gacha_items.items():
            if lottery_info["item_type"] and lottery_info["item_type"] != info["item_info"]["item_type"]:
                continue

            if not(lottery_info["rarity"]) or lottery_info["rarity"] <= info["item_info"]["rarity"]:
                lots[id] = info["weight"]

            if lottery_info["omake_times"]:
                if not(lottery_info["omake_rarity"]) or lottery_info["omake_rarity"] <= info["item_info"]["rarity"]:
                    omake_lots[id] = info["weight"]

        return lots, omake_lots

    #Exécution de Gacha
    def exec(exec_gacha_id: int, exec_gacha_lottery_id: str) -> list:
        gacha_info, gacha_lottery_info = get_gacha_info(cursor, exec_gacha_id, exec_gacha_lottery_id, now_time)

        print("==%s==:gacha_group:%s" % (gacha_lottery_info["id"], gacha_info["gacha_group"]))
        lots, omake_lots = get_lots(gacha_info["gacha_group"], gacha_lottery_info)
        ids = gacha(lots, gacha_lottery_info["times"])
        if len(omake_lots) > 0:
            ids.extend(gacha(omake_lots, gacha_lottery_info["omake_times"]))

        return ids

    return exec


def main():
    con = sqlite3.connect("data.db")
    con.row_factory = sqlite3.Row
    cursor = con.cursor()


    #Spécifiez la date et l'heure d'exécution de gacha pour vérifier l'opération
    now_time = int(datetime.strptime("2020-05-01 00:00:00", '%Y-%m-%d %H:%M:%S').timestamp())

    #Initialisation (définir la date et l'heure d'exécution, les éléments, etc.)
    func_gacha = set_gacha(cursor, now_time)

    items = get_items_all(cursor)
    gacha_items = get_gacha_items_all(cursor)
    #Exécuter du gacha à un seul coup
    # gacha_id et gacha_lottery_id passé lors de l'exécution
    ids = func_gacha(1,"normal_1")
    for id in ids:
        item_info = items[gacha_items[id]["item_id"]]
        print("ID:%d, %s, %s" % (id, get_rarity_name(item_info["rarity"]), item_info["item_name"]))

    #Exécuter 11 gachas consécutifs
    # gacha_id et gacha_lottery_id passé lors de l'exécution
    ids = func_gacha(1,"normal_11")
    for id in ids:
        item_info = items[gacha_items[id]["item_id"]]
        print("ID:%d, %s, %s" % (id, get_rarity_name(item_info["rarity"]), item_info["item_name"]))

    #con.commit()
    con.close()


if __name__ == '__main__':
    main()

Résultat d'exécution

==normal_1==:gacha_group:A
ID:8, R, R_guerrier
==normal_11==:gacha_group:A
ID:5, SR, SR_guerrier
ID:8, R, R_guerrier
ID:3, SSR, SSR_sorcier
ID:10, R, R_Prêtre
ID:9, R, R_sorcier
ID:9, R, R_sorcier
ID:8, R, R_guerrier
ID:1, UR, UR_Courageux
ID:10, R, R_Prêtre
ID:10, R, R_Prêtre
ID:7, SR, SR_Prêtre

Supplément

Vous vous demandez peut-être si vous passez ** gacha_id ** et ** gacha_lottery_id ** comme arguments lorsque vous exécutez le gacha. Tout ce dont vous avez besoin pour exécuter un gacha est ** gacha_lottery_id **, et si vous obtenez les gacha_type et ** gacha_id ** associés qui correspondent à la date et à l'heure du traitement, il n'y a pas de problème avec le traitement gacha. Cependant, si le gacha est exécuté au "moment de commutation" de la période d'exécution du gacha, l'utilisateur peut exécuter le gacha de l'élément cible différent de l'élément cible qu'il souhaite dessiner.

Exemple

Afin d'éviter une telle chose, ** gacha_id ** est également passé en argument lors de l'exécution de gacha, et si ce ** gacha_id ** n'est pas couvert par la période d'implémentation, le gacha est terminé et l'utilisateur en est informé. Notifier et afficher à nouveau l'écran gacha. Gacha est un processus qui suppose que la facturation est impliquée, il est donc nécessaire d'empêcher un traitement strictement différent de l'intention de l'utilisateur.

Dans cette source, la gestion des erreurs est un peu omise, veuillez donc considérer et implémenter la gestion des erreurs requise pour l'application.

Recommended Posts

Gacha écrit en python-Practice 1-
Gacha écrit en python-Practice 2 ・ Bases du step-up gacha-
Gacha écrit en Python-Data design-
Gacha écrit en python-Practice 3 ・ Ajout de fonctions gacha step-up-
Gacha écrit en Python -BOX Gacha-
Logique gacha simple écrite en Python
Gacha écrit en python-Rareté confirmée avec bonus-
Gacha écrit en python-Implémentation dans la structure de données de base-
Gacha écrit en python - Ajout d'une fonction de réglage de période -
Cool Lisp écrit en Python: Hy
Programme de diagnostic de compatibilité écrit en python
Code de vérification de la série Fourier écrit en Python
Test de stress avec Locust écrit en Python
Probabilité de transition de la chaîne de Markov écrite en Python