Gacha écrit en python-Practice 3 ・ Ajout de fonctions gacha step-up-

Contenu

La dernière fois, j'ai créé un step-up gacha. Cette fois, nous allons ajouter un traitement de contrôle au gacha step-up et le modifier pour qu'il puisse être utilisé de manière plus pratique.

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

Gacha écrit en python-Pratique 2 / Bases du step-up gacha-

Réparation de step-up gacha

Lors de cette rénovation, le traitement de contrôle suivant sera ajouté au gacha step-up.

--Répéter

répétition

Dernière fois Le step-up gacha que j'ai créé a été conçu pour se terminer lorsqu'il est passé à l'étape finale. Dans le jeu réel, il existe un gacha qui vous permet de dessiner la dernière étape à plusieurs reprises après la dernière étape. Pour y parvenir, nous devons ajouter un contrôle pour la «répétition». Cette fois, réfléchissons à la manière de créer les trois types de gacha intensifs suivants.

--step_up_N: Step-up de base (terminé à la dernière étape) --step_up_S1: Répéter step-up (revenir à l'étape 1 après la dernière étape) --step_up_S2: répétition finale progressive (répétez la dernière étape pour toujours)

Ajout du paramètre de type gacha (répété)

Pour définir des ** étapes répétées ** pour les paramètres de dessin gacha (gacha_lottery) Créez une table appelée Gacha Type Setting (gacha_type).

gacha_type

id kind rotation_step_no
step_up_N step_up 0
step_up_S1 step_up 1
step_up_S2 step_up 4

L'élément rotation_step_no indique les étapes vers lesquelles effectuer la transition après la dernière étape. Dans le cas de «0», il est défini comme se terminant à l'étape finale.

Réparation du réglage de tirage gacha

Remplacez l'élément gacha_type dans le paramètre de dessin gacha (gacha_lottery) par l'ID de paramètre de type gacha (gacha_type_id)` défini ci-dessus.

gacha_lottery

id gacha_type_id step_no item_type times rarity omake_times omake_rarity cost
step_up_N_1 step_up_N 1 0 1 0 0 0 10
step_up_N_2 step_up_N 2 0 2 0 1 3 30
step_up_N_3 step_up_N 3 0 3 0 2 3 50
step_up_N_4 step_up_N 4 0 4 0 1 4 50
step_up_S1_1 step_up_S1 1 0 1 0 0 0 10
step_up_S1_2 step_up_S1 2 0 2 0 1 3 30
step_up_S1_3 step_up_S1 3 0 1 0 2 3 30
step_up_S1_4 step_up_S1 4 0 4 0 1 4 50
step_up_S2_1 step_up_S2 1 0 1 0 0 0 10
step_up_S2_2 step_up_S2 2 0 2 0 1 3 30
step_up_S2_3 step_up_S2 3 0 4 0 1 5 50
step_up_S2_4 step_up_S2 4 0 4 0 1 3 50

Réparation du réglage de la période gacha

De même, remplacez l'élément gacha_type dans le paramètre de période gacha (gacha) par l'ID de paramètre de type gacha (gacha_type_id)` afin que l'association entre le paramètre de méthode de dessin gacha (gacha_lottery) et le paramètre de type gacha (gacha_type) soit liée. Je vais.

gacha

id start_time end_time gacha_group gacha_type_id
10 2020-05-01 00:00:00 2020-05-31 23:59:59 A step_up_N
11 2020-06-01 00:00:00 2020-06-30 23:59:59 C step_up_N
12 2020-05-01 00:00:00 2020-07-31 23:59:59 A step_up_S1
13 2020-05-01 00:00:00 2020-05-31 23:59:59 A step_up_S2
14 2020-06-01 00:00:00 2020-06-30 23:59:59 C step_up_S2
gacha_step_p1.png

réinitialiser

Ajout (réinitialisation) du paramètre de type gacha

Selon l'opération, vous souhaiterez peut-être revenir à l'état initial à un certain moment. Par conséquent, ajoutez la définition de réinitialisation au paramètre de type gacha (gacha_type).

En fonction de la définition de réinitialisation ajoutée cette fois, elle sera configurée pour être automatiquement réinitialisée en fonction de la période.

reset_type Il y a deux * reset_type * à définir.

--daily: retour à l'état initial (étape 1) lors du premier accès tous les jours

Un mois n'est pas pratique, mais il est prêt à comprendre la différence

gacha_type

id kind rotation_step_no reset_type
step_up_N step_up 0 daily
step_up_S1 step_up 1 monthly
step_up_S2 step_up 4

Cette fois, définissez gacha_type en fonction du paramètre de période gacha (gacha). ** step_up_S2 ** n'a pas de paramètre de réinitialisation car reset_type est vide.

gacha_step_p0.png

la mise en oeuvre

Les spécifications de mise en œuvre sont résumées ci-dessous.

Répéter (lors de l'exécution à l'étape finale)

réinitialiser

Informations sur Gacha DB

Si vous souhaitez modifier la structure / les données ou réinitialiser l'historique, veuillez réexécuter ce processus.

gacha_db.py


# -*- 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},
        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},
        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 = {
        10: {"start_time": "2020-05-01 00:00:00", "end_time": "2020-05-31 23:59:59", "gacha_group": "A",
            "gacha_type_id": "step_up_N"},
        11: {"start_time": "2020-06-01 00:00:00", "end_time": "2020-06-30 23:59:59", "gacha_group": "C",
             "gacha_type_id": "step_up_N"},
        12: {"start_time": "2020-05-01 00:00:00", "end_time": "2020-07-31 23:59:59", "gacha_group": "A",
             "gacha_type_id": "step_up_S1"},
        13: {"start_time": "2020-05-01 00:00:00", "end_time": "2020-05-31 23:59:59", "gacha_group": "A",
             "gacha_type_id": "step_up_S2"},
        14: {"start_time": "2020-06-01 00:00:00", "end_time": "2020-06-30 23:59:59", "gacha_group": "C",
             "gacha_type_id": "step_up_S2"},
    }

    return convert_values(items)

def get_gacha_type():
    items = {
        "step_up_N":  {"rotation_step_no": 0, "kind": "step_up", "reset_type": "daily"},
        "step_up_S1": {"rotation_step_no": 1, "kind": "step_up", "reset_type": "monthly"},
        "step_up_S2": {"rotation_step_no": 4, "kind": "step_up", "reset_type": None},
    }

    return convert_values(items)


def get_gacha_lottery():
    items = {
        "normal_1":  {"gacha_type_id": "normal", "step_no": 0, "item_type": 0, "times": 1, "rarity": 0, "omake_times": 0, "omake_rarity": 0, "cost":10},
        "normal_11":  {"gacha_type_id": "normal", "step_no": 0, "item_type": 0, "times": 10, "rarity": 0, "omake_times": 1, "omake_rarity": 3, "cost":100},
        "fighter":  {"gacha_type_id": "fighter", "step_no": 0, "item_type": 0, "times": 2, "rarity": 0, "omake_times": 0, "omake_rarity": 0, "cost":30},
        "omake_2":  {"gacha_type_id": "omake_2", "step_no": 0, "item_type": 0, "times": 9, "rarity": 2, "omake_times": 2, "omake_rarity": 3, "cost":150},
        "omake_fighter":  {"gacha_type_id": "omake_fighter", "step_no": 0, "item_type": 2, "times": 5, "rarity": 0, "omake_times": 1, "omake_rarity": 3, "cost":100},
        "step_up_N_1": {"gacha_type_id": "step_up_N", "step_no": 1, "item_type": 0, "times": 1, "rarity": 0, "omake_times": 0,
                     "omake_rarity": 0, "cost": 10},
        "step_up_N_2": {"gacha_type_id": "step_up_N", "step_no": 2, "item_type": 0, "times": 2, "rarity": 0, "omake_times": 1,
                      "omake_rarity": 3, "cost": 30},
        "step_up_N_3": {"gacha_type_id": "step_up_N", "step_no": 3, "item_type": 0, "times": 3, "rarity": 0, "omake_times": 2,
                      "omake_rarity": 3, "cost": 50},
        "step_up_N_4": {"gacha_type_id": "step_up_N", "step_no": 4, "item_type": 0, "times": 4, "rarity": 0, "omake_times": 1,
                      "omake_rarity": 4, "cost": 50},
        "step_up_S1_1": {"gacha_type_id": "step_up_S1", "step_no": 1, "item_type": 0, "times": 1, "rarity": 0,
                        "omake_times": 0, "omake_rarity": 0, "cost": 10},
        "step_up_S1_2": {"gacha_type_id": "step_up_S1", "step_no": 2, "item_type": 0, "times": 2, "rarity": 0,
                        "omake_times": 1, "omake_rarity": 3, "cost": 30},
        "step_up_S1_3": {"gacha_type_id": "step_up_S1", "step_no": 3, "item_type": 0, "times": 1, "rarity": 0,
                        "omake_times": 2, "omake_rarity": 3, "cost": 30},
        "step_up_S1_4": {"gacha_type_id": "step_up_S1", "step_no": 4, "item_type": 0, "times": 3, "rarity": 0,
                        "omake_times": 2, "omake_rarity": 4, "cost": 50},
        "step_up_S2_1": {"gacha_type_id": "step_up_S2", "step_no": 1, "item_type": 0, "times": 1, "rarity": 0,
                        "omake_times": 0, "omake_rarity": 0, "cost": 10},
        "step_up_S2_2": {"gacha_type_id": "step_up_S2", "step_no": 2, "item_type": 0, "times": 2, "rarity": 0,
                        "omake_times": 1, "omake_rarity": 3, "cost": 30},
        "step_up_S2_3": {"gacha_type_id": "step_up_S2", "step_no": 3, "item_type": 0, "times": 4, "rarity": 0,
                        "omake_times": 1, "omake_rarity": 5, "cost": 50},
        "step_up_S2_4": {"gacha_type_id": "step_up_S2", "step_no": 4, "item_type": 0, "times": 4, "rarity": 0,
                        "omake_times": 1, "omake_rarity": 3, "cost": 50},
    }

    return convert_values(items)

def get_users():
    items = {
        "u001": {"nick_name": "taro"},
        "u002": {"nick_name": "hana"},
    }

    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()

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

    #Remise à neuf
    cursor.execute(
        """CREATE TABLE gacha 
          (id INTEGER PRIMARY KEY AUTOINCREMENT
          ,start_time DATETIME
          ,end_time DATETIME
          ,gacha_group VARCHAR(32)
          ,gacha_type_id VARCHAR(32)
          )
        """
    )

    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
          )
        """
    )

    #ajouter à
    cursor.execute("DROP TABLE IF EXISTS gacha_type")
    cursor.execute(
        """CREATE TABLE gacha_type 
          (id VARCHAR(32) PRIMARY KEY
          ,kind VARCHAR(32)
          ,rotation_step_no INTEGER
          ,reset_type VARCHAR(32)
          )
        """
    )

    #Remise à neuf
    cursor.execute("DROP TABLE IF EXISTS gacha_lottery")
    cursor.execute(
        """CREATE TABLE gacha_lottery 
          (id VARCHAR(32) PRIMARY KEY
          ,gacha_type_id VARCHAR(32)
          ,step_no INTEGER
          ,item_type INTEGER
          ,times INTEGER
          ,rarity INTEGER
          ,omake_times INTEGER
          ,omake_rarity INTEGER
          ,cost INTEGER
          )
        """
    )

    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
          )
        """
    )

    cursor.execute("DROP TABLE IF EXISTS users")
    cursor.execute(
        """CREATE TABLE users 
          (id VARCHAR(16) PRIMARY KEY
          ,nick_name VARCHAR(64)
          )
        """
    )

    #Remise à neuf
    cursor.execute("DROP TABLE IF EXISTS gacha_user_step")
    cursor.execute(
        """CREATE TABLE gacha_user_step 
          (user_id VARCHAR(16) 
          ,gacha_id INTEGER
          ,gacha_type_id VARCHAR(32)
          ,step_no INTEGER DEFAULT 2
          ,updated_time DATETIME          
          ,PRIMARY KEY(user_id,gacha_id,gacha_type_id)
          )
        """
    )


    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_type()
    sql = "insert into {0}({1}) values({2})".format('gacha_type', ','.join(keys), ','.join(['?'] * len(keys)))
    cursor.executemany(sql,values)
    select_sql = "SELECT * FROM gacha_type ORDER BY id"
    result = cursor.execute(select_sql)
    print("===gach_type===")
    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)

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

    con.commit()
    con.close()

if __name__ == '__main__':
    main()

Traitement Gacha

gacha.py


import random
import sqlite3
from datetime import datetime
from typing import Dict, List, Tuple, Optional

def convert_row2dict(row) -> Dict:
    if row is None:
        return {}
    return {key: row[key] for key in row.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, user_id:str) -> 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_id"])
        gacha_user = get_gacha_user_step(cursor, user_id, gacha_id, info["gacha_type_id"])

        set_list = []
        for lottery_info in lottery_info_list:
            if lottery_info["step_no"] > 0:
                now_step_no = 1
                if len(gacha_user) > 0:
                    now_step_no = gacha_user["step_no"] + 1
                if now_step_no == lottery_info["step_no"]:
                    set_list.append(lottery_info)
            else:
                set_list.append(lottery_info)
        gacha_list[gacha_id]["gacha_lottery_list"] = set_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_type(cursor, gacha_type_id: str) -> Dict:
    select_sql = "SELECT * FROM gacha_type WHERE id = ? ORDER BY id"
    cursor.execute(select_sql, (gacha_type_id,))
    return convert_row2dict(cursor.fetchone())

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,))
    return convert_row2dict(cursor.fetchone())


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

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

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,))
    return {
        row["id"]: convert_row2dict(row)
        for row in rows
    }

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

def get_gacha_info(cursor, gacha_id: int, gacha_lottery_id: str, now_time: int, user_id: str) -> Tuple[Optional[Dict], Optional[Dict]]:
    gacha = get_gacha(cursor, gacha_id, now_time)
    gacha_lottery = get_gacha_lottery(cursor, gacha_lottery_id)

    if len(gacha) == 0:
        print("===Gacha qui ne peut pas être exécuté_id:%s===" % (gacha_id))
        return None, None

    if len(gacha_lottery) == 0:
        print("===Gacha qui n'existe pas_lottery_id:%s===" % (gacha_lottery_id))
        return None, None

    if gacha["gacha_type_id"] != gacha_lottery["gacha_type_id"]:
        print("===gacha_type_id est différent:%s,%s===" % (gacha["gacha_type_id"],gacha_lottery["gacha_type_id"]))
        return None, None

    # step_contrôle de gacha
    if gacha_lottery["step_no"] > 0:
        # user_Réinitialiser l'étape
        reset_gacha_user_step(cursor, user_id, gacha_id, gacha["gacha_type_id"], now_time)

        max_step_no = get_max_step_no(cursor, gacha["gacha_type_id"])
        gacha_user = get_gacha_user_step(cursor, user_id, gacha_id, gacha["gacha_type_id"])
        step_no = 1
        if len(gacha_user) > 0:
            step_no = gacha_user["step_no"]
        if max_step_no < step_no:
            print("===Jusqu'à l'étape maximale a été exécutée (étape maximale):%s, l'étape que vous allez effectuer:%s)===" %(max_step_no,gacha_lottery["step_no"]))
            return None, None

        if gacha_lottery["step_no"] != step_no:
            print("===Différent des étapes pouvant être effectuées (étape en cours:%s, l'étape que vous allez effectuer:%s)===" %(step_no, gacha_lottery["step_no"]))
            return None, None

    return gacha, gacha_lottery


def get_gacha_user_step(cursor, user_id: str, gacha_id: int, gacha_type_id: str) -> Dict:
    select_sql = "SELECT * FROM gacha_user_step WHERE user_id = ? AND gacha_id = ? AND gacha_type_id = ?"
    cursor.execute(select_sql, (user_id,gacha_id,gacha_type_id))
    row = cursor.fetchone()

    return convert_row2dict(row)

def get_max_step_no(cursor, gacha_type_id: str) -> Dict:
    select_sql = "SELECT MAX(step_no) AS max_step_no FROM gacha_lottery WHERE gacha_type_id = ?"
    cursor.execute(select_sql, (gacha_type_id,))
    row = cursor.fetchone()

    row_dict = convert_row2dict(row)
    return row_dict["max_step_no"]

def insert_gacha_user_step(cursor, step_no: int, user_id: str, gacha_id: int, gacha_type_id: str, update_time: int) -> None:
    dt = datetime.fromtimestamp(update_time)
    keys = ("user_id", "gacha_id", "gacha_type_id", "updated_time", "step_no")
    sql = "insert into {0}({1}) values({2})".format('gacha_user_step', ','.join(keys), ','.join(['?'] * len(keys)))
    cursor.execute(sql, (user_id, gacha_id, gacha_type_id, dt, step_no))

def update_gacha_user_step(cursor, step_no: int, user_id: str, gacha_id: int, gacha_type_id: str, update_time: int) -> None:
    dt = datetime.fromtimestamp(update_time)
    sql = "UPDATE gacha_user_step SET step_no = ?, updated_time = ? WHERE user_id = ? AND gacha_id = ? AND gacha_type_id = ?"
    cursor.execute(sql, (step_no, dt, user_id, gacha_id, gacha_type_id))

def next_gacha_user_step(cursor, user_id: str, gacha_id: int, gacha_type_id: str, update_time: int) -> None:
    row = get_gacha_user_step(cursor, user_id, gacha_id, gacha_type_id)
    if len(row) == 0:
        insert_gacha_user_step(
            cursor,
            rotation_gacha_user_step(cursor, gacha_type_id, 1),
            user_id, gacha_id, gacha_type_id, update_time
        )
    else:
        update_gacha_user_step(
            cursor,
            rotation_gacha_user_step(cursor, gacha_type_id, row["step_no"]),
            user_id, gacha_id, gacha_type_id, update_time
        )

#Numéro de l'étape suivante avec le jugement de répétition ajouté
def rotation_gacha_user_step(cursor, gacha_type_id: str, step_no: int) -> int:
    if step_no == get_max_step_no(cursor, gacha_type_id):
        row = get_gacha_type(cursor, gacha_type_id)
        if row["rotation_step_no"] > 0:
            print("check:{0},{1},{2}".format(gacha_type_id, step_no,row["rotation_step_no"]))
            return row["rotation_step_no"]
        else:
            print("check:{0},{1},{2}".format(gacha_type_id, step_no,step_no + 1))
            return step_no + 1
    else:
        print("check:{0},{1},{2}".format(gacha_type_id, step_no, step_no + 1))
        return step_no + 1

#Processus de réinitialisation
def reset_gacha_user_step(cursor, user_id: str, gacha_id: int, gacha_type_id: str, now_time: int) -> None:
    user_step = get_gacha_user_step(cursor, user_id, gacha_id, gacha_type_id)
    if len(user_step) == 0:
        return

    dt = datetime.fromtimestamp(now_time)
    gacha_type = get_gacha_type(cursor, gacha_type_id)
    if gacha_type["reset_type"] == "daily":
        if dt.day != datetime.strptime(user_step["updated_time"], '%Y-%m-%d %H:%M:%S').day:
            update_gacha_user_step(cursor,1,user_id, gacha_id, gacha_type_id, now_time)
    elif gacha_type["reset_type"] == "monthly":
        if dt.month != datetime.strptime(user_step["updated_time"], '%Y-%m-%d %H:%M:%S').month:
            update_gacha_user_step(cursor,1,user_id, gacha_id, gacha_type_id, now_time)

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

    #Extraire la liste des cibles de loterie
    def get_lots(gacha_group: str, lottery_info: dict) -> Tuple[Dict,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, user_id)
        if gacha_info is None or gacha_lottery_info is None:
            return []

        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"]))

        #Dans le cas du step-up gacha, mettre à jour le nombre d'exécutions
        if len(ids) > 0 and gacha_lottery_info["step_no"] > 0:
            next_gacha_user_step(cursor, user_id, exec_gacha_id, gacha_info["gacha_type_id"], now_time)

        return ids

    return exec

def test_step(cursor, user_id, now_time, gacha_id, gacha_type_id, step_no_list):
    print("[TEST:{0}]".format(gacha_type_id))

    #Gacha exécutable_lottery
    available_list = get_available_gacha_info_list(cursor,now_time,user_id)
    for available_gacha_id,available in available_list.items():
        print(available_gacha_id,available)

    func_gacha = set_gacha(cursor, now_time, user_id)
    items = get_items_all(cursor)
    gacha_items = get_gacha_items_all(cursor)

    #Step-up gacha
    for step_no in step_no_list:
        gacha_lottery_id = "{0}_{1}".format(gacha_type_id,str(step_no))
        ids = func_gacha(gacha_id,gacha_lottery_id)
        if len(ids) > 0:
            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"]))

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

    #En fait, l'ID utilisateur sera obtenu à partir des informations d'authentification.
    user_id = "u001"

    #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())

    # step_up_Test N
    test_step(cursor, user_id, now_time, 10, "step_up_N", [1,2,3,4,1,])

    print("\n [Confirmation qu'il peut être réinitialisé et exécuté en avançant la date]")
    now_time = int(datetime.strptime("2020-05-02 00:00:00", '%Y-%m-%d %H:%M:%S').timestamp())
    test_step(cursor, user_id, now_time, 10, "step_up_N", [1,2,3,4,])

    # step_up_Test S1
    print("\n [Confirmer pour revenir à l'étape 1]")
    test_step(cursor, user_id, now_time, 12, "step_up_S1", [1,2,3,4,1,2,])
    print("\n [Confirmation que la date sera avancée et réinitialisée: le mois précédent s'est terminé jusqu'à l'étape 2]")
    now_time = int(datetime.strptime("2020-06-01 00:00:00", '%Y-%m-%d %H:%M:%S').timestamp())
    test_step(cursor, user_id, now_time, 12, "step_up_S1", [1,2,3,4,])

    # step_up_Test S2
    print("\n [Confirmez qu'il peut être exécuté à plusieurs reprises à l'étape 4]")
    test_step(cursor, user_id, now_time, 14, "step_up_S2", [1,2,3,4,4,])

    con.commit()
    con.close()

if __name__ == '__main__':
    main()

Résultat d'exécution

[TEST:step_up_N]
10 {'id': 10, 'start_time': '2020-05-01 00:00:00', 'end_time': '2020-05-31 23:59:59', 'gacha_group': 'A', 'gacha_type_id': 'step_up_N', 'gacha_lottery_list': []}
12 {'id': 12, 'start_time': '2020-05-01 00:00:00', 'end_time': '2020-07-31 23:59:59', 'gacha_group': 'A', 'gacha_type_id': 'step_up_S1', 'gacha_lottery_list': [{'id': 'step_up_S1_2', 'gacha_type_id': 'step_up_S1', 'step_no': 2, 'item_type': 0, 'times': 1, 'rarity': 0, 'omake_times': 1, 'omake_rarity': 3, 'cost': 20}]}
13 {'id': 13, 'start_time': '2020-05-01 00:00:00', 'end_time': '2020-05-31 23:59:59', 'gacha_group': 'A', 'gacha_type_id': 'step_up_S2', 'gacha_lottery_list': [{'id': 'step_up_S2_1', 'gacha_type_id': 'step_up_S2', 'step_no': 1, 'item_type': 0, 'times': 1, 'rarity': 0, 'omake_times': 0, 'omake_rarity': 0, 'cost': 10}]}
==step_up_N_1==:gacha_group:A
check:step_up_N,1,2
ID:9, R, R_sorcier
==step_up_N_2==:gacha_group:A
check:step_up_N,2,3
ID:10, R, R_Prêtre
ID:9, R, R_sorcier
ID:4, SSR, SSR_Prêtre
==step_up_N_3==:gacha_group:A
check:step_up_N,3,4
ID:9, R, R_sorcier
ID:10, R, R_Prêtre
ID:9, R, R_sorcier
ID:7, SR, SR_Prêtre
ID:5, SR, SR_guerrier
==step_up_N_4==:gacha_group:A
check:step_up_N,4,5
ID:9, R, R_sorcier
ID:9, R, R_sorcier
ID:10, R, R_Prêtre
ID:5, SR, SR_guerrier
ID:1, UR, UR_Courageux
===Terminé jusqu'à l'étape maximale (étape maximale):4, l'étape que vous allez effectuer:1)===

[Confirmation qu'il sera réinitialisé et exécutable en avançant la date]
[TEST:step_up_N]
10 {'id': 10, 'start_time': '2020-05-01 00:00:00', 'end_time': '2020-05-31 23:59:59', 'gacha_group': 'A', 'gacha_type_id': 'step_up_N', 'gacha_lottery_list': []}
12 {'id': 12, 'start_time': '2020-05-01 00:00:00', 'end_time': '2020-07-31 23:59:59', 'gacha_group': 'A', 'gacha_type_id': 'step_up_S1', 'gacha_lottery_list': [{'id': 'step_up_S1_2', 'gacha_type_id': 'step_up_S1', 'step_no': 2, 'item_type': 0, 'times': 1, 'rarity': 0, 'omake_times': 1, 'omake_rarity': 3, 'cost': 20}]}
13 {'id': 13, 'start_time': '2020-05-01 00:00:00', 'end_time': '2020-05-31 23:59:59', 'gacha_group': 'A', 'gacha_type_id': 'step_up_S2', 'gacha_lottery_list': [{'id': 'step_up_S2_1', 'gacha_type_id': 'step_up_S2', 'step_no': 1, 'item_type': 0, 'times': 1, 'rarity': 0, 'omake_times': 0, 'omake_rarity': 0, 'cost': 10}]}
==step_up_N_1==:gacha_group:A
check:step_up_N,1,2
ID:7, SR, SR_Prêtre
==step_up_N_2==:gacha_group:A
check:step_up_N,2,3
ID:10, R, R_Prêtre
ID:5, SR, SR_guerrier
ID:6, SR, SR_sorcier
==step_up_N_3==:gacha_group:A
check:step_up_N,3,4
ID:10, R, R_Prêtre
ID:8, R, R_guerrier
ID:5, SR, SR_guerrier
ID:4, SSR, SSR_Prêtre
ID:7, SR, SR_Prêtre
==step_up_N_4==:gacha_group:A
check:step_up_N,4,5
ID:9, R, R_sorcier
ID:8, R, R_guerrier
ID:7, SR, SR_Prêtre
ID:5, SR, SR_guerrier
ID:3, SSR, SSR_sorcier

[Confirmez pour revenir à l'étape 1]
[TEST:step_up_S1]
10 {'id': 10, 'start_time': '2020-05-01 00:00:00', 'end_time': '2020-05-31 23:59:59', 'gacha_group': 'A', 'gacha_type_id': 'step_up_N', 'gacha_lottery_list': []}
12 {'id': 12, 'start_time': '2020-05-01 00:00:00', 'end_time': '2020-07-31 23:59:59', 'gacha_group': 'A', 'gacha_type_id': 'step_up_S1', 'gacha_lottery_list': [{'id': 'step_up_S1_2', 'gacha_type_id': 'step_up_S1', 'step_no': 2, 'item_type': 0, 'times': 1, 'rarity': 0, 'omake_times': 1, 'omake_rarity': 3, 'cost': 20}]}
13 {'id': 13, 'start_time': '2020-05-01 00:00:00', 'end_time': '2020-05-31 23:59:59', 'gacha_group': 'A', 'gacha_type_id': 'step_up_S2', 'gacha_lottery_list': [{'id': 'step_up_S2_1', 'gacha_type_id': 'step_up_S2', 'step_no': 1, 'item_type': 0, 'times': 1, 'rarity': 0, 'omake_times': 0, 'omake_rarity': 0, 'cost': 10}]}
==step_up_S1_1==:gacha_group:A
check:step_up_S1,1,2
ID:10, R, R_Prêtre
==step_up_S1_2==:gacha_group:A
check:step_up_S1,2,3
ID:5, SR, SR_guerrier
ID:7, SR, SR_Prêtre
==step_up_S1_3==:gacha_group:A
check:step_up_S1,3,4
ID:7, SR, SR_Prêtre
ID:7, SR, SR_Prêtre
ID:7, SR, SR_Prêtre
==step_up_S1_4==:gacha_group:A
check:step_up_S1,4,1
ID:2, SSR, SSR_guerrier
ID:10, R, R_Prêtre
ID:7, SR, SR_Prêtre
ID:3, SSR, SSR_sorcier
ID:1, UR, UR_Courageux
==step_up_S1_1==:gacha_group:A
check:step_up_S1,1,2
ID:9, R, R_sorcier
==step_up_S1_2==:gacha_group:A
check:step_up_S1,2,3
ID:10, R, R_Prêtre
ID:6, SR, SR_sorcier

[Confirmation que la date sera avancée et réinitialisée: le mois précédent a été terminé jusqu'à l'étape 2]
[TEST:step_up_S1]
11 {'id': 11, 'start_time': '2020-06-01 00:00:00', 'end_time': '2020-06-30 23:59:59', 'gacha_group': 'C', 'gacha_type_id': 'step_up_N', 'gacha_lottery_list': [{'id': 'step_up_N_1', 'gacha_type_id': 'step_up_N', 'step_no': 1, 'item_type': 0, 'times': 1, 'rarity': 0, 'omake_times': 0, 'omake_rarity': 0, 'cost': 10}]}
12 {'id': 12, 'start_time': '2020-05-01 00:00:00', 'end_time': '2020-07-31 23:59:59', 'gacha_group': 'A', 'gacha_type_id': 'step_up_S1', 'gacha_lottery_list': [{'id': 'step_up_S1_4', 'gacha_type_id': 'step_up_S1', 'step_no': 4, 'item_type': 0, 'times': 3, 'rarity': 0, 'omake_times': 2, 'omake_rarity': 4, 'cost': 50}]}
14 {'id': 14, 'start_time': '2020-06-01 00:00:00', 'end_time': '2020-06-30 23:59:59', 'gacha_group': 'C', 'gacha_type_id': 'step_up_S2', 'gacha_lottery_list': []}
==step_up_S1_1==:gacha_group:A
check:step_up_S1,1,2
ID:10, R, R_Prêtre
==step_up_S1_2==:gacha_group:A
check:step_up_S1,2,3
ID:5, SR, SR_guerrier
ID:4, SSR, SSR_Prêtre
==step_up_S1_3==:gacha_group:A
check:step_up_S1,3,4
ID:8, R, R_guerrier
ID:5, SR, SR_guerrier
ID:6, SR, SR_sorcier
==step_up_S1_4==:gacha_group:A
check:step_up_S1,4,1
ID:6, SR, SR_sorcier
ID:5, SR, SR_guerrier
ID:7, SR, SR_Prêtre
ID:2, SSR, SSR_guerrier
ID:3, SSR, SSR_sorcier

[Confirmez qu'il peut être exécuté à plusieurs reprises à l'étape 4]
[TEST:step_up_S2]
11 {'id': 11, 'start_time': '2020-06-01 00:00:00', 'end_time': '2020-06-30 23:59:59', 'gacha_group': 'C', 'gacha_type_id': 'step_up_N', 'gacha_lottery_list': [{'id': 'step_up_N_1', 'gacha_type_id': 'step_up_N', 'step_no': 1, 'item_type': 0, 'times': 1, 'rarity': 0, 'omake_times': 0, 'omake_rarity': 0, 'cost': 10}]}
12 {'id': 12, 'start_time': '2020-05-01 00:00:00', 'end_time': '2020-07-31 23:59:59', 'gacha_group': 'A', 'gacha_type_id': 'step_up_S1', 'gacha_lottery_list': [{'id': 'step_up_S1_2', 'gacha_type_id': 'step_up_S1', 'step_no': 2, 'item_type': 0, 'times': 1, 'rarity': 0, 'omake_times': 1, 'omake_rarity': 3, 'cost': 20}]}
14 {'id': 14, 'start_time': '2020-06-01 00:00:00', 'end_time': '2020-06-30 23:59:59', 'gacha_group': 'C', 'gacha_type_id': 'step_up_S2', 'gacha_lottery_list': []}
===Différent des étapes pouvant être effectuées (étape en cours:4, l'étape que vous allez effectuer:1)===
===Différent des étapes pouvant être effectuées (étape en cours:4, l'étape que vous allez effectuer:2)===
===Différent des étapes pouvant être effectuées (étape en cours:4, l'étape que vous allez effectuer:3)===
==step_up_S2_4==:gacha_group:C
check:step_up_S2,4,4
ID:24, R, R_guerrier
ID:25, R, R_sorcier
ID:23, SR, SR_Prêtre
ID:25, R, R_sorcier
ID:23, SR, SR_Prêtre
==step_up_S2_4==:gacha_group:C
check:step_up_S2,4,4
ID:26, R, R_Prêtre
ID:25, R, R_sorcier
ID:15, UR, UR_guerrier
ID:22, SR, SR_sorcier
ID:20, SSR, SSR_Prêtre

Considération

step_up_N (pas de répétition, réinitialisation quotidienne)

Puisqu'il n'y a pas de réglage de répétition, vous pouvez confirmer qu'il est terminé après la quatrième exécution. Et lorsque la date change, vous pouvez voir qu'il est possible d'exécuter à nouveau à partir de l'étape 1.

step_up_S1 (répété, réinitialisé tous les mois)

Puisqu'il y a un réglage de répétition, vous pouvez revenir à l'étape 1 après avoir exécuté la quatrième fois et confirmer qu'il peut être exécuté. Ensuite, lorsque le mois change, vous serez renvoyé à l'étape 1 et vous pouvez voir que c'est faisable à partir de là.

step_up_S2 (avec répétition, pas de réinitialisation)

Puisqu'il existe un réglage de répétition, vous pouvez confirmer que l'étape 4 peut être exécutée à plusieurs reprises après la quatrième exécution.

Avantages des spécifications

Ajout du traitement de contrôle «Répéter» et «Réinitialiser» à la logique Dernière fois. C'est un peu plus difficile, mais il n'a pas été tellement rénové. (* Il a fallu plus de temps pour assembler le code de test ... *)

Avec l'ajout de cette fonction, il est possible de contrôler la progression de gacha par «réglage maître». Il est possible de créer divers modèles de gacha en combinant les paramètres du maître. En fonctionnement, il est nécessaire de répéter l'hypothèse et la vérification d'une approche efficace des utilisateurs. Un fonctionnement efficace peut être réalisé en réglant le maître de sorte que le planificateur puisse le faire.

Recommended Posts

Gacha écrit en python-Practice 3 ・ Ajout de fonctions gacha step-up-
Gacha écrit en python-Practice 2 ・ Bases du step-up gacha-
Gacha écrit en python-Practice 1-
Gacha écrit en python - Ajout d'une fonction de réglage de période -
Gacha écrit en Python-Data design-
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-
Utilisation des fonctions récursives utilisées chez les pros de la compétition
Résumé des fonctions d'évaluation utilisées dans l'apprentissage automatique