mirror of
https://github.com/Llloooggg/TextSouls.git
synced 2026-03-06 04:26:23 +03:00
backend: полная реструктуризация
This commit is contained in:
@@ -1,14 +1,14 @@
|
|||||||
import json
|
import json
|
||||||
|
|
||||||
from flask import Flask
|
from flask import Flask
|
||||||
|
from flask_sqlalchemy import SQLAlchemy
|
||||||
from flask_migrate import Migrate
|
from flask_migrate import Migrate
|
||||||
from flask_admin import Admin
|
from flask_admin import Admin
|
||||||
|
|
||||||
from textsouls.models import db
|
|
||||||
|
|
||||||
app = Flask(
|
app = Flask(
|
||||||
"__name__",
|
"__name__",
|
||||||
)
|
)
|
||||||
|
db = SQLAlchemy()
|
||||||
|
|
||||||
migrate = Migrate(app, db, compare_type=True)
|
migrate = Migrate(app, db, compare_type=True)
|
||||||
admin = Admin(name="TextSouls")
|
admin = Admin(name="TextSouls")
|
||||||
@@ -25,10 +25,14 @@ app.config.update(db_settings)
|
|||||||
admin.init_app(app)
|
admin.init_app(app)
|
||||||
db.init_app(app)
|
db.init_app(app)
|
||||||
|
|
||||||
from .admin import ts_admin as ts_admin_blueprint
|
from textsouls.actions.api import bp
|
||||||
|
|
||||||
app.register_blueprint(ts_admin_blueprint)
|
app.register_blueprint(bp)
|
||||||
|
|
||||||
from .main import main as main_blueprint
|
from textsouls.characters.api import bp
|
||||||
|
|
||||||
app.register_blueprint(main_blueprint)
|
app.register_blueprint(bp)
|
||||||
|
|
||||||
|
from textsouls.users.api import bp
|
||||||
|
|
||||||
|
app.register_blueprint(bp)
|
||||||
|
|||||||
0
backend/textsouls/actions/__init__.py
Normal file
0
backend/textsouls/actions/__init__.py
Normal file
19
backend/textsouls/actions/api.py
Normal file
19
backend/textsouls/actions/api.py
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
from flask import Blueprint
|
||||||
|
|
||||||
|
from textsouls import db
|
||||||
|
from textsouls import admin
|
||||||
|
|
||||||
|
from textsouls.common.api import register_api
|
||||||
|
from textsouls.common.api import CommonAdminView
|
||||||
|
|
||||||
|
from textsouls.actions.models import DuelParticipant
|
||||||
|
from textsouls.actions.models import Duel
|
||||||
|
|
||||||
|
|
||||||
|
bp = Blueprint("actions", __name__)
|
||||||
|
|
||||||
|
register_api(bp, DuelParticipant, "duels_participant")
|
||||||
|
register_api(bp, Duel, "duels")
|
||||||
|
|
||||||
|
admin.add_view(CommonAdminView(DuelParticipant, db.session))
|
||||||
|
admin.add_view(CommonAdminView(Duel, db.session))
|
||||||
108
backend/textsouls/actions/models.py
Normal file
108
backend/textsouls/actions/models.py
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
import datetime
|
||||||
|
from random import randint
|
||||||
|
|
||||||
|
from sqlalchemy.orm import backref
|
||||||
|
from sqlalchemy_serializer import SerializerMixin
|
||||||
|
|
||||||
|
from textsouls import db
|
||||||
|
|
||||||
|
from textsouls.characters.models import Character
|
||||||
|
|
||||||
|
|
||||||
|
class DuelParticipant(db.Model, SerializerMixin):
|
||||||
|
|
||||||
|
__tablename__ = "duels_participants"
|
||||||
|
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
participant_id = db.Column(
|
||||||
|
db.Integer,
|
||||||
|
db.ForeignKey("characters.id", ondelete="CASCADE"),
|
||||||
|
)
|
||||||
|
turn_order = db.Column(db.Integer, nullable=False)
|
||||||
|
duel_id = db.Column(
|
||||||
|
db.Integer,
|
||||||
|
db.ForeignKey("duels.id", ondelete="CASCADE"),
|
||||||
|
)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"{self.duel_id}: {self.participant_id}"
|
||||||
|
|
||||||
|
|
||||||
|
class Duel(db.Model, SerializerMixin):
|
||||||
|
|
||||||
|
__tablename__ = "duels"
|
||||||
|
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
created_on = db.Column(
|
||||||
|
db.DateTime, nullable=False, default=datetime.datetime.now()
|
||||||
|
)
|
||||||
|
participants = db.relationship(
|
||||||
|
"DuelParticipant",
|
||||||
|
backref=backref("duel", order_by="DuelParticipant.turn_order.asc()"),
|
||||||
|
lazy="dynamic",
|
||||||
|
)
|
||||||
|
|
||||||
|
def attack(self, attacked_character, defensive_character):
|
||||||
|
defensive_character_endurance = (
|
||||||
|
defensive_character.endurance_base
|
||||||
|
- attacked_character.battle_stats["attack_power"]
|
||||||
|
)
|
||||||
|
|
||||||
|
return defensive_character_endurance
|
||||||
|
|
||||||
|
def defence(self, defensive_character):
|
||||||
|
procced = False
|
||||||
|
if (
|
||||||
|
randint(
|
||||||
|
int(10 * defensive_character.battle_stats["defence_chance"]),
|
||||||
|
50,
|
||||||
|
)
|
||||||
|
== 50
|
||||||
|
):
|
||||||
|
procced is True
|
||||||
|
|
||||||
|
return procced
|
||||||
|
|
||||||
|
def dodge(self, defensive_character):
|
||||||
|
procced = False
|
||||||
|
if (
|
||||||
|
randint(
|
||||||
|
int(10 * defensive_character.battle_stats["dodge_chance"]), 50
|
||||||
|
)
|
||||||
|
== 50
|
||||||
|
):
|
||||||
|
procced is True
|
||||||
|
|
||||||
|
return procced
|
||||||
|
|
||||||
|
def duel_one_to_one(self):
|
||||||
|
|
||||||
|
character_first = Character.query.get(
|
||||||
|
self.participants[0].participant_id
|
||||||
|
)
|
||||||
|
character_second = Character.query.get(
|
||||||
|
self.participants[1].participant_id
|
||||||
|
)
|
||||||
|
|
||||||
|
while (
|
||||||
|
character_first.endurance_base > 0
|
||||||
|
and character_second.endurance_base > 0
|
||||||
|
):
|
||||||
|
if not self.defence(character_second) or not self.dodge(
|
||||||
|
character_second
|
||||||
|
):
|
||||||
|
character_second.endurance_base = self.attack(
|
||||||
|
character_first, character_second
|
||||||
|
)
|
||||||
|
if not self.defence(character_first) or not self.dodge(
|
||||||
|
character_first
|
||||||
|
):
|
||||||
|
character_first.endurance_base = self.attack(
|
||||||
|
character_second, character_first
|
||||||
|
)
|
||||||
|
if character_first.endurance_base > 0:
|
||||||
|
return character_first.name
|
||||||
|
elif character_second.endurance_base > 0:
|
||||||
|
return character_second.name
|
||||||
|
else:
|
||||||
|
return "Ничья"
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
from flask import Blueprint
|
|
||||||
from flask_admin.contrib.sqla import ModelView
|
|
||||||
|
|
||||||
from . import admin
|
|
||||||
from textsouls.models import db
|
|
||||||
|
|
||||||
from textsouls.models import User
|
|
||||||
|
|
||||||
from textsouls.models import CharacterRace
|
|
||||||
from textsouls.models import CharacterClass
|
|
||||||
from textsouls.models import CharacterState
|
|
||||||
from textsouls.models import Character
|
|
||||||
|
|
||||||
from textsouls.models import DuelParticipant
|
|
||||||
from textsouls.models import Duel
|
|
||||||
|
|
||||||
ts_admin = Blueprint("ts_admin", __name__)
|
|
||||||
|
|
||||||
|
|
||||||
class AdminView(ModelView):
|
|
||||||
def __init__(self, model, *args, **kwargs):
|
|
||||||
self.column_list = [c.key for c in model.__table__.columns]
|
|
||||||
self.form_columns = self.column_list
|
|
||||||
super(AdminView, self).__init__(model, *args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class CommonView(ModelView):
|
|
||||||
def __init__(self, model, *args, **kwargs):
|
|
||||||
self.column_list = [c.key for c in model.__table__.columns]
|
|
||||||
super(CommonView, self).__init__(model, *args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
admin.add_view(AdminView(User, db.session))
|
|
||||||
|
|
||||||
admin.add_view(CommonView(CharacterRace, db.session))
|
|
||||||
admin.add_view(CommonView(CharacterClass, db.session))
|
|
||||||
admin.add_view(CommonView(CharacterState, db.session))
|
|
||||||
admin.add_view(CommonView(Character, db.session))
|
|
||||||
|
|
||||||
admin.add_view(CommonView(DuelParticipant, db.session))
|
|
||||||
admin.add_view(CommonView(Duel, db.session))
|
|
||||||
0
backend/textsouls/characters/__init__.py
Normal file
0
backend/textsouls/characters/__init__.py
Normal file
25
backend/textsouls/characters/api.py
Normal file
25
backend/textsouls/characters/api.py
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
from flask import Blueprint
|
||||||
|
|
||||||
|
from textsouls import db
|
||||||
|
from textsouls import admin
|
||||||
|
|
||||||
|
from textsouls.common.api import register_api
|
||||||
|
from textsouls.common.api import CommonAdminView
|
||||||
|
|
||||||
|
from textsouls.characters.models import CharacterRace
|
||||||
|
from textsouls.characters.models import CharacterClass
|
||||||
|
from textsouls.characters.models import CharacterState
|
||||||
|
from textsouls.characters.models import Character
|
||||||
|
|
||||||
|
|
||||||
|
bp = Blueprint("characters", __name__)
|
||||||
|
|
||||||
|
register_api(bp, CharacterRace, "character_races")
|
||||||
|
register_api(bp, CharacterClass, "character_classes")
|
||||||
|
register_api(bp, CharacterState, "character_states")
|
||||||
|
register_api(bp, Character, "characters", "owner")
|
||||||
|
|
||||||
|
admin.add_view(CommonAdminView(CharacterRace, db.session))
|
||||||
|
admin.add_view(CommonAdminView(CharacterClass, db.session))
|
||||||
|
admin.add_view(CommonAdminView(CharacterState, db.session))
|
||||||
|
admin.add_view(CommonAdminView(Character, db.session))
|
||||||
@@ -1,34 +1,8 @@
|
|||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
from random import randint
|
|
||||||
|
|
||||||
from flask_sqlalchemy import SQLAlchemy
|
|
||||||
from sqlalchemy.orm import backref
|
|
||||||
from sqlalchemy_serializer import SerializerMixin
|
from sqlalchemy_serializer import SerializerMixin
|
||||||
|
|
||||||
|
from textsouls import db
|
||||||
db = SQLAlchemy()
|
|
||||||
|
|
||||||
|
|
||||||
class User(db.Model, SerializerMixin):
|
|
||||||
|
|
||||||
__tablename__ = "users"
|
|
||||||
|
|
||||||
serialize_rules = ("-character",)
|
|
||||||
|
|
||||||
id = db.Column(db.BigInteger, primary_key=True, autoincrement=False)
|
|
||||||
chat_id = db.Column(db.BigInteger, nullable=False, unique=True)
|
|
||||||
first_name = db.Column(db.String(255), nullable=True)
|
|
||||||
last_name = db.Column(db.String(255), nullable=True)
|
|
||||||
username = db.Column(db.String(255), nullable=False)
|
|
||||||
registered_on = db.Column(
|
|
||||||
db.DateTime, nullable=False, default=datetime.datetime.now()
|
|
||||||
)
|
|
||||||
is_admin = db.Column(db.Boolean, nullable=False, default=False)
|
|
||||||
characters = db.relationship("Character", backref="user", lazy="dynamic")
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return f"{self.id}: {self.username}"
|
|
||||||
|
|
||||||
|
|
||||||
class CharacterRace(db.Model, SerializerMixin):
|
class CharacterRace(db.Model, SerializerMixin):
|
||||||
@@ -174,102 +148,3 @@ class Character(db.Model, SerializerMixin):
|
|||||||
"defence_chance": defence_chance,
|
"defence_chance": defence_chance,
|
||||||
"dodge_chance": dodge_chance,
|
"dodge_chance": dodge_chance,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class DuelParticipant(db.Model, SerializerMixin):
|
|
||||||
|
|
||||||
__tablename__ = "duels_participants"
|
|
||||||
|
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
|
||||||
participant_id = db.Column(
|
|
||||||
db.Integer,
|
|
||||||
db.ForeignKey("characters.id", ondelete="CASCADE"),
|
|
||||||
)
|
|
||||||
turn_order = db.Column(db.Integer, nullable=False)
|
|
||||||
duel_id = db.Column(
|
|
||||||
db.Integer,
|
|
||||||
db.ForeignKey("duels.id", ondelete="CASCADE"),
|
|
||||||
)
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return f"{self.duel_id}: {self.participant_id}"
|
|
||||||
|
|
||||||
|
|
||||||
class Duel(db.Model, SerializerMixin):
|
|
||||||
|
|
||||||
__tablename__ = "duels"
|
|
||||||
|
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
|
||||||
created_on = db.Column(
|
|
||||||
db.DateTime, nullable=False, default=datetime.datetime.now()
|
|
||||||
)
|
|
||||||
participants = db.relationship(
|
|
||||||
"DuelParticipant",
|
|
||||||
backref=backref("duel", order_by="DuelParticipant.turn_order.asc()"),
|
|
||||||
lazy="dynamic",
|
|
||||||
)
|
|
||||||
|
|
||||||
def attack(self, attacked_character, defensive_character):
|
|
||||||
defensive_character_endurance = (
|
|
||||||
defensive_character.endurance_base
|
|
||||||
- attacked_character.battle_stats["attack_power"]
|
|
||||||
)
|
|
||||||
|
|
||||||
return defensive_character_endurance
|
|
||||||
|
|
||||||
def defence(self, defensive_character):
|
|
||||||
procced = False
|
|
||||||
if (
|
|
||||||
randint(
|
|
||||||
int(10 * defensive_character.battle_stats["defence_chance"]),
|
|
||||||
50,
|
|
||||||
)
|
|
||||||
== 50
|
|
||||||
):
|
|
||||||
procced is True
|
|
||||||
|
|
||||||
return procced
|
|
||||||
|
|
||||||
def dodge(self, defensive_character):
|
|
||||||
procced = False
|
|
||||||
if (
|
|
||||||
randint(
|
|
||||||
int(10 * defensive_character.battle_stats["dodge_chance"]), 50
|
|
||||||
)
|
|
||||||
== 50
|
|
||||||
):
|
|
||||||
procced is True
|
|
||||||
|
|
||||||
return procced
|
|
||||||
|
|
||||||
def duel_one_to_one(self):
|
|
||||||
|
|
||||||
character_first = Character.query.get(
|
|
||||||
self.participants[0].participant_id
|
|
||||||
)
|
|
||||||
character_second = Character.query.get(
|
|
||||||
self.participants[1].participant_id
|
|
||||||
)
|
|
||||||
|
|
||||||
while (
|
|
||||||
character_first.endurance_base > 0
|
|
||||||
and character_second.endurance_base > 0
|
|
||||||
):
|
|
||||||
if not self.defence(character_second) or not self.dodge(
|
|
||||||
character_second
|
|
||||||
):
|
|
||||||
character_second.endurance_base = self.attack(
|
|
||||||
character_first, character_second
|
|
||||||
)
|
|
||||||
if not self.defence(character_first) or not self.dodge(
|
|
||||||
character_first
|
|
||||||
):
|
|
||||||
character_first.endurance_base = self.attack(
|
|
||||||
character_second, character_first
|
|
||||||
)
|
|
||||||
if character_first.endurance_base > 0:
|
|
||||||
return character_first.name
|
|
||||||
elif character_second.endurance_base > 0:
|
|
||||||
return character_second.name
|
|
||||||
else:
|
|
||||||
return "Ничья"
|
|
||||||
0
backend/textsouls/common/__init__.py
Normal file
0
backend/textsouls/common/__init__.py
Normal file
@@ -1,8 +1,16 @@
|
|||||||
from .. import db
|
|
||||||
|
|
||||||
from flask import request
|
from flask import request
|
||||||
from flask.views import MethodView
|
from flask.views import MethodView
|
||||||
|
|
||||||
|
from flask_admin.contrib.sqla import ModelView
|
||||||
|
|
||||||
|
from textsouls import db
|
||||||
|
|
||||||
|
|
||||||
|
class CommonAdminView(ModelView):
|
||||||
|
def __init__(self, model, *args, **kwargs):
|
||||||
|
self.column_list = [c.key for c in model.__table__.columns]
|
||||||
|
super(CommonAdminView, self).__init__(model, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class ItemAPI(MethodView):
|
class ItemAPI(MethodView):
|
||||||
init_every_request = False
|
init_every_request = False
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
from flask import Blueprint
|
|
||||||
|
|
||||||
from textsouls.common.views import register_api
|
|
||||||
from textsouls.models import User
|
|
||||||
|
|
||||||
from textsouls.models import CharacterRace
|
|
||||||
from textsouls.models import CharacterClass
|
|
||||||
from textsouls.models import CharacterState
|
|
||||||
from textsouls.models import Character
|
|
||||||
|
|
||||||
from textsouls.models import DuelParticipant
|
|
||||||
from textsouls.models import Duel
|
|
||||||
|
|
||||||
main = Blueprint("main", __name__)
|
|
||||||
|
|
||||||
register_api(main, User, "users")
|
|
||||||
|
|
||||||
register_api(main, CharacterRace, "character_races")
|
|
||||||
register_api(main, CharacterClass, "character_classes")
|
|
||||||
register_api(main, CharacterState, "character_states")
|
|
||||||
register_api(main, Character, "characters", "owner")
|
|
||||||
|
|
||||||
|
|
||||||
register_api(main, DuelParticipant, "duels_participant")
|
|
||||||
register_api(main, Duel, "duels")
|
|
||||||
0
backend/textsouls/users/__init__.py
Normal file
0
backend/textsouls/users/__init__.py
Normal file
24
backend/textsouls/users/api.py
Normal file
24
backend/textsouls/users/api.py
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
from flask import Blueprint
|
||||||
|
|
||||||
|
from flask_admin.contrib.sqla import ModelView
|
||||||
|
|
||||||
|
from textsouls import db
|
||||||
|
from textsouls import admin
|
||||||
|
|
||||||
|
from textsouls.common.api import register_api
|
||||||
|
|
||||||
|
from textsouls.users.models import User
|
||||||
|
|
||||||
|
|
||||||
|
class UserAdminView(ModelView):
|
||||||
|
def __init__(self, model, *args, **kwargs):
|
||||||
|
self.column_list = [c.key for c in model.__table__.columns]
|
||||||
|
self.form_columns = self.column_list
|
||||||
|
super(UserAdminView, self).__init__(model, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
bp = Blueprint("users", __name__)
|
||||||
|
|
||||||
|
register_api(bp, User, "users")
|
||||||
|
|
||||||
|
admin.add_view(UserAdminView(User, db.session))
|
||||||
26
backend/textsouls/users/models.py
Normal file
26
backend/textsouls/users/models.py
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import datetime
|
||||||
|
|
||||||
|
from sqlalchemy_serializer import SerializerMixin
|
||||||
|
|
||||||
|
from textsouls import db
|
||||||
|
|
||||||
|
|
||||||
|
class User(db.Model, SerializerMixin):
|
||||||
|
|
||||||
|
__tablename__ = "users"
|
||||||
|
|
||||||
|
serialize_rules = ("-character",)
|
||||||
|
|
||||||
|
id = db.Column(db.BigInteger, primary_key=True, autoincrement=False)
|
||||||
|
chat_id = db.Column(db.BigInteger, nullable=False, unique=True)
|
||||||
|
first_name = db.Column(db.String(255), nullable=True)
|
||||||
|
last_name = db.Column(db.String(255), nullable=True)
|
||||||
|
username = db.Column(db.String(255), nullable=False)
|
||||||
|
registered_on = db.Column(
|
||||||
|
db.DateTime, nullable=False, default=datetime.datetime.now()
|
||||||
|
)
|
||||||
|
is_admin = db.Column(db.Boolean, nullable=False, default=False)
|
||||||
|
characters = db.relationship("Character", backref="user", lazy="dynamic")
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"{self.id}: {self.username}"
|
||||||
Reference in New Issue
Block a user