commit
6fb4b2a278
24 changed files with 563 additions and 0 deletions
0
__init__.py
Normal file
0
__init__.py
Normal file
22
app.py
22
app.py
|
@ -1,10 +1,18 @@
|
|||
import os
|
||||
|
||||
from flask import Flask
|
||||
|
||||
# ! SQLAlchemy > Marshmallow - these must be imported in this order
|
||||
from flask_sqlalchemy import SQLAlchemy
|
||||
from flask_marshmallow import Marshmallow
|
||||
|
||||
from flask_migrate import Migrate
|
||||
|
||||
from flask_bcrypt import Bcrypt
|
||||
from flask_cors import CORS
|
||||
|
||||
app = Flask(__name__)
|
||||
CORS(app)
|
||||
|
||||
# base directory
|
||||
basedir = os.path.abspath(os.path.dirname(__file__))
|
||||
|
@ -16,12 +24,26 @@ DATABASE = 'postgresql://localhost/browser-go'
|
|||
app.config['SQLALCHEMY_DATABASE_URI'] = DATABASE
|
||||
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
|
||||
|
||||
#init bcrypt
|
||||
bcrypt = Bcrypt(app)
|
||||
|
||||
# init database
|
||||
db = SQLAlchemy(app)
|
||||
|
||||
# init marshmallow
|
||||
ma = Marshmallow(app)
|
||||
|
||||
# init all db models
|
||||
from .models.User import User
|
||||
from .models.GameRoom import GameRoom
|
||||
from .models.TimeSettings import TimeSettings
|
||||
from .models.Game import Game
|
||||
from .models.Move import Move
|
||||
from .models.Message import Message
|
||||
|
||||
migrate = Migrate(app, db)
|
||||
|
||||
|
||||
# dev server
|
||||
DEBUG = True
|
||||
PORT = 8000
|
||||
|
|
0
games/__init__.py
Normal file
0
games/__init__.py
Normal file
7
games/game.py
Normal file
7
games/game.py
Normal file
|
@ -0,0 +1,7 @@
|
|||
from flask import Blueprint
|
||||
|
||||
game = Blueprint('games', __name__)
|
||||
|
||||
@game.route('/<int:game_id>')
|
||||
def func():
|
||||
pass
|
0
home/__init__.py
Normal file
0
home/__init__.py
Normal file
7
home/home.py
Normal file
7
home/home.py
Normal file
|
@ -0,0 +1,7 @@
|
|||
from flask import Blueprint
|
||||
|
||||
home = Blueprint('home', __name__)
|
||||
|
||||
@home.route('/home')
|
||||
def func():
|
||||
pass
|
1
migrations/README
Normal file
1
migrations/README
Normal file
|
@ -0,0 +1 @@
|
|||
Generic single-database configuration.
|
45
migrations/alembic.ini
Normal file
45
migrations/alembic.ini
Normal file
|
@ -0,0 +1,45 @@
|
|||
# A generic, single database configuration.
|
||||
|
||||
[alembic]
|
||||
# template used to generate migration files
|
||||
# file_template = %%(rev)s_%%(slug)s
|
||||
|
||||
# set to 'true' to run the environment during
|
||||
# the 'revision' command, regardless of autogenerate
|
||||
# revision_environment = false
|
||||
|
||||
|
||||
# Logging configuration
|
||||
[loggers]
|
||||
keys = root,sqlalchemy,alembic
|
||||
|
||||
[handlers]
|
||||
keys = console
|
||||
|
||||
[formatters]
|
||||
keys = generic
|
||||
|
||||
[logger_root]
|
||||
level = WARN
|
||||
handlers = console
|
||||
qualname =
|
||||
|
||||
[logger_sqlalchemy]
|
||||
level = WARN
|
||||
handlers =
|
||||
qualname = sqlalchemy.engine
|
||||
|
||||
[logger_alembic]
|
||||
level = INFO
|
||||
handlers =
|
||||
qualname = alembic
|
||||
|
||||
[handler_console]
|
||||
class = StreamHandler
|
||||
args = (sys.stderr,)
|
||||
level = NOTSET
|
||||
formatter = generic
|
||||
|
||||
[formatter_generic]
|
||||
format = %(levelname)-5.5s [%(name)s] %(message)s
|
||||
datefmt = %H:%M:%S
|
96
migrations/env.py
Normal file
96
migrations/env.py
Normal file
|
@ -0,0 +1,96 @@
|
|||
from __future__ import with_statement
|
||||
|
||||
import logging
|
||||
from logging.config import fileConfig
|
||||
|
||||
from sqlalchemy import engine_from_config
|
||||
from sqlalchemy import pool
|
||||
|
||||
from alembic import context
|
||||
|
||||
# this is the Alembic Config object, which provides
|
||||
# access to the values within the .ini file in use.
|
||||
config = context.config
|
||||
|
||||
# Interpret the config file for Python logging.
|
||||
# This line sets up loggers basically.
|
||||
fileConfig(config.config_file_name)
|
||||
logger = logging.getLogger('alembic.env')
|
||||
|
||||
# add your model's MetaData object here
|
||||
# for 'autogenerate' support
|
||||
# from myapp import mymodel
|
||||
# target_metadata = mymodel.Base.metadata
|
||||
from flask import current_app
|
||||
config.set_main_option(
|
||||
'sqlalchemy.url', current_app.config.get(
|
||||
'SQLALCHEMY_DATABASE_URI').replace('%', '%%'))
|
||||
target_metadata = current_app.extensions['migrate'].db.metadata
|
||||
|
||||
# other values from the config, defined by the needs of env.py,
|
||||
# can be acquired:
|
||||
# my_important_option = config.get_main_option("my_important_option")
|
||||
# ... etc.
|
||||
|
||||
|
||||
def run_migrations_offline():
|
||||
"""Run migrations in 'offline' mode.
|
||||
|
||||
This configures the context with just a URL
|
||||
and not an Engine, though an Engine is acceptable
|
||||
here as well. By skipping the Engine creation
|
||||
we don't even need a DBAPI to be available.
|
||||
|
||||
Calls to context.execute() here emit the given string to the
|
||||
script output.
|
||||
|
||||
"""
|
||||
url = config.get_main_option("sqlalchemy.url")
|
||||
context.configure(
|
||||
url=url, target_metadata=target_metadata, literal_binds=True
|
||||
)
|
||||
|
||||
with context.begin_transaction():
|
||||
context.run_migrations()
|
||||
|
||||
|
||||
def run_migrations_online():
|
||||
"""Run migrations in 'online' mode.
|
||||
|
||||
In this scenario we need to create an Engine
|
||||
and associate a connection with the context.
|
||||
|
||||
"""
|
||||
|
||||
# this callback is used to prevent an auto-migration from being generated
|
||||
# when there are no changes to the schema
|
||||
# reference: http://alembic.zzzcomputing.com/en/latest/cookbook.html
|
||||
def process_revision_directives(context, revision, directives):
|
||||
if getattr(config.cmd_opts, 'autogenerate', False):
|
||||
script = directives[0]
|
||||
if script.upgrade_ops.is_empty():
|
||||
directives[:] = []
|
||||
logger.info('No changes in schema detected.')
|
||||
|
||||
connectable = engine_from_config(
|
||||
config.get_section(config.config_ini_section),
|
||||
prefix='sqlalchemy.',
|
||||
poolclass=pool.NullPool,
|
||||
)
|
||||
|
||||
with connectable.connect() as connection:
|
||||
context.configure(
|
||||
connection=connection,
|
||||
target_metadata=target_metadata,
|
||||
process_revision_directives=process_revision_directives,
|
||||
**current_app.extensions['migrate'].configure_args
|
||||
)
|
||||
|
||||
with context.begin_transaction():
|
||||
context.run_migrations()
|
||||
|
||||
|
||||
if context.is_offline_mode():
|
||||
run_migrations_offline()
|
||||
else:
|
||||
run_migrations_online()
|
24
migrations/script.py.mako
Normal file
24
migrations/script.py.mako
Normal file
|
@ -0,0 +1,24 @@
|
|||
"""${message}
|
||||
|
||||
Revision ID: ${up_revision}
|
||||
Revises: ${down_revision | comma,n}
|
||||
Create Date: ${create_date}
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
${imports if imports else ""}
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = ${repr(up_revision)}
|
||||
down_revision = ${repr(down_revision)}
|
||||
branch_labels = ${repr(branch_labels)}
|
||||
depends_on = ${repr(depends_on)}
|
||||
|
||||
|
||||
def upgrade():
|
||||
${upgrades if upgrades else "pass"}
|
||||
|
||||
|
||||
def downgrade():
|
||||
${downgrades if downgrades else "pass"}
|
28
migrations/versions/16c70b11242e_.py
Normal file
28
migrations/versions/16c70b11242e_.py
Normal file
|
@ -0,0 +1,28 @@
|
|||
"""empty message
|
||||
|
||||
Revision ID: 16c70b11242e
|
||||
Revises: 9519d28f13f0
|
||||
Create Date: 2019-10-02 14:50:27.180692
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '16c70b11242e'
|
||||
down_revision = '9519d28f13f0'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.add_column('moves', sa.Column('is_main', sa.Boolean(), nullable=False))
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.drop_column('moves', 'is_main')
|
||||
# ### end Alembic commands ###
|
109
migrations/versions/9519d28f13f0_.py
Normal file
109
migrations/versions/9519d28f13f0_.py
Normal file
|
@ -0,0 +1,109 @@
|
|||
"""empty message
|
||||
|
||||
Revision ID: 9519d28f13f0
|
||||
Revises:
|
||||
Create Date: 2019-10-02 13:54:17.877590
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '9519d28f13f0'
|
||||
down_revision = None
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.create_table('game_rooms',
|
||||
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
|
||||
sa.Column('name', sa.String(length=40), nullable=False),
|
||||
sa.Column('description', sa.String(length=200), nullable=False),
|
||||
sa.Column('private', sa.Boolean(), nullable=False),
|
||||
sa.Column('language', sa.Enum(name='languages'), nullable=False),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
)
|
||||
op.create_table('time_settings',
|
||||
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
|
||||
sa.Column('main_time', sa.Enum('BYOYOMI', 'ABSOLUTE', 'HOURGLASS', 'NONE', name='timetypes'), nullable=False),
|
||||
sa.Column('time_period', sa.Integer(), nullable=True),
|
||||
sa.Column('period_length', sa.Integer(), nullable=True),
|
||||
sa.Column('overtime', sa.Enum('BYOYOMI', 'ABSOLUTE', 'HOURGLASS', 'NONE', name='timetypes'), nullable=False),
|
||||
sa.Column('overtime_period', sa.Integer(), nullable=True),
|
||||
sa.Column('overtime_length', sa.Integer(), nullable=True),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
)
|
||||
op.create_table('users',
|
||||
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
|
||||
sa.Column('email', sa.String(length=255), nullable=False),
|
||||
sa.Column('password', sa.DateTime(), nullable=False),
|
||||
sa.Column('registered_on', sa.DateTime(), nullable=False),
|
||||
sa.Column('admin', sa.Boolean(), nullable=False),
|
||||
sa.Column('rank', sa.Enum('D7', 'D6', 'D5', 'D4', 'D3', 'D2', 'D1', 'K1', 'K2', 'K3', 'K4', 'K5', 'K6', 'K7', 'K8', 'K9', 'K10', 'K11', 'K12', 'K13', 'K14', 'K15', 'K16', 'K17', 'K18', 'K19', 'K20', 'K21', 'K22', 'K23', 'K24', 'K25', 'K26', 'K27', 'K28', 'K29', 'K30', name='ranks'), nullable=True),
|
||||
sa.Column('elo', sa.Integer(), nullable=True),
|
||||
sa.Column('rank_certainty', sa.Boolean(), nullable=False),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('email')
|
||||
)
|
||||
op.create_table('games',
|
||||
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
|
||||
sa.Column('date', sa.DateTime(), nullable=True),
|
||||
sa.Column('komi', sa.Numeric(precision=2, scale=1), nullable=False),
|
||||
sa.Column('handicap', sa.Integer(), nullable=False),
|
||||
sa.Column('board_size', sa.Integer(), nullable=False),
|
||||
sa.Column('win_type', sa.Enum('DRAW', 'RESIGN', 'SCORE', 'TIME', 'VOID', name='wintype'), nullable=True),
|
||||
sa.Column('winner', sa.Enum('BLACK', 'WHITE', 'VOID', name='players'), nullable=True),
|
||||
sa.Column('score', sa.Numeric(precision=2, scale=1), nullable=True),
|
||||
sa.Column('white_captures', sa.Integer(), nullable=True),
|
||||
sa.Column('black_captures', sa.Integer(), nullable=True),
|
||||
sa.Column('application', sa.String(length=40), nullable=True),
|
||||
sa.Column('application_version', sa.String(length=20), nullable=True),
|
||||
sa.Column('event', sa.String(length=40), nullable=True),
|
||||
sa.Column('name', sa.String(length=40), nullable=True),
|
||||
sa.Column('description', sa.String(length=200), nullable=True),
|
||||
sa.Column('round', sa.Integer(), nullable=True),
|
||||
sa.Column('game_room', sa.Integer(), nullable=True),
|
||||
sa.Column('time_settings', sa.Integer(), nullable=True),
|
||||
sa.Column('player_black', sa.Integer(), nullable=True),
|
||||
sa.Column('player_white', sa.Integer(), nullable=True),
|
||||
sa.ForeignKeyConstraint(['game_room'], ['game_rooms.id'], ),
|
||||
sa.ForeignKeyConstraint(['player_black'], ['users.id'], ),
|
||||
sa.ForeignKeyConstraint(['player_white'], ['users.id'], ),
|
||||
sa.ForeignKeyConstraint(['time_settings'], ['time_settings.id'], ),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
)
|
||||
op.create_table('moves',
|
||||
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
|
||||
sa.Column('player', sa.Enum('BLACK', 'WHITE', name='players'), nullable=True),
|
||||
sa.Column('x_point', sa.Integer(), nullable=True),
|
||||
sa.Column('y_point', sa.Integer(), nullable=True),
|
||||
sa.Column('move_number', sa.Integer(), nullable=True),
|
||||
sa.Column('game', sa.Integer(), nullable=False),
|
||||
sa.Column('preceding_move', sa.Integer(), nullable=True),
|
||||
sa.ForeignKeyConstraint(['game'], ['games.id'], ),
|
||||
sa.ForeignKeyConstraint(['preceding_move'], ['moves.id'], ),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
)
|
||||
op.create_table('messages',
|
||||
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
|
||||
sa.Column('date', sa.DateTime(), nullable=False),
|
||||
sa.Column('content', sa.String(length=200), nullable=False),
|
||||
sa.Column('move', sa.Integer(), nullable=False),
|
||||
sa.ForeignKeyConstraint(['move'], ['moves.id'], ),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
)
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.drop_table('messages')
|
||||
op.drop_table('moves')
|
||||
op.drop_table('games')
|
||||
op.drop_table('users')
|
||||
op.drop_table('time_settings')
|
||||
op.drop_table('game_rooms')
|
||||
# ### end Alembic commands ###
|
44
models/Game.py
Normal file
44
models/Game.py
Normal file
|
@ -0,0 +1,44 @@
|
|||
from ..app import db, ma
|
||||
import enum
|
||||
|
||||
class Players(enum.Enum):
|
||||
BLACK = "The player taking black stones"
|
||||
WHITE = "The player taking white stones"
|
||||
VOID = "The game was a draw or voided"
|
||||
|
||||
class WinType(enum.Enum):
|
||||
DRAW = "The game is a draw"
|
||||
RESIGN = "The game ended in resignation"
|
||||
SCORE = "The game ended by counting points"
|
||||
TIME = "The game ended in loss by time out"
|
||||
VOID = "The game was suspended"
|
||||
|
||||
class Game(db.Model):
|
||||
__tablename__ = "games"
|
||||
__table_args__ = {'extend_existing': True}
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
|
||||
date = db.Column(db.DateTime())
|
||||
komi = db.Column(db.Numeric(2,1), nullable=False)
|
||||
handicap = db.Column(db.Integer, nullable=False)
|
||||
board_size = db.Column(db.Integer, nullable=False)
|
||||
win_type = db.Column(db.Enum(WinType))
|
||||
winner = db.Column(db.Enum(Players))
|
||||
score = db.Column(db.Numeric(2,1))
|
||||
white_captures = db.Column(db.Integer)
|
||||
black_captures = db.Column(db.Integer)
|
||||
application = db.Column(db.String(40))
|
||||
application_version = db.Column(db.String(20))
|
||||
event = db.Column(db.String(40))
|
||||
name = db.Column(db.String(40))
|
||||
description = db.Column(db.String(200))
|
||||
round = db.Column(db.Integer)
|
||||
|
||||
# foreign keys
|
||||
game_room = db.Column(db.Integer, db.ForeignKey("game_rooms.id"))
|
||||
time_settings = db.Column(db.Integer, db.ForeignKey("time_settings.id"))
|
||||
player_black = db.Column(db.Integer, db.ForeignKey("users.id"))
|
||||
player_white = db.Column(db.Integer, db.ForeignKey("users.id"))
|
||||
|
||||
def __init__(self):
|
||||
pass
|
18
models/GameRoom.py
Normal file
18
models/GameRoom.py
Normal file
|
@ -0,0 +1,18 @@
|
|||
from ..app import db, ma
|
||||
import enum
|
||||
|
||||
class Languages(enum.Enum):
|
||||
EN: "English"
|
||||
|
||||
class GameRoom(db.Model):
|
||||
__tablename__ = "game_rooms"
|
||||
__table_args__ = {'extend_existing': True}
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
|
||||
name = db.Column(db.String(40), nullable=False)
|
||||
description = db.Column(db.String(200), nullable=False)
|
||||
private = db.Column(db.Boolean(), nullable=False, default=False)
|
||||
language = db.Column(db.Enum(Languages), nullable=False)
|
||||
|
||||
def __init__(self):
|
||||
pass
|
20
models/Message.py
Normal file
20
models/Message.py
Normal file
|
@ -0,0 +1,20 @@
|
|||
from ..app import db, ma
|
||||
import enum
|
||||
|
||||
class Players(enum.Enum):
|
||||
BLACK = "The player taking black stones"
|
||||
WHITE = "The player taking white stones"
|
||||
|
||||
class Message(db.Model):
|
||||
__tablename__ = "messages"
|
||||
__table_args__ = {'extend_existing': True}
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
|
||||
date = db.Column(db.DateTime(), nullable=False)
|
||||
content = db.Column(db.String(200), nullable=False)
|
||||
|
||||
# foreign key
|
||||
move = db.Column(db.Integer, db.ForeignKey("moves.id"), nullable=False)
|
||||
|
||||
def __init__(self):
|
||||
pass
|
25
models/Move.py
Normal file
25
models/Move.py
Normal file
|
@ -0,0 +1,25 @@
|
|||
from ..app import db, ma
|
||||
import enum
|
||||
|
||||
class Players(enum.Enum):
|
||||
BLACK = "The player taking black stones"
|
||||
WHITE = "The player taking white stones"
|
||||
|
||||
class Move(db.Model):
|
||||
__tablename__ = "moves"
|
||||
__table_args__ = {'extend_existing': True}
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
|
||||
player = db.Column(db.Enum(Players))
|
||||
x_point = db.Column(db.Integer)
|
||||
y_point = db.Column(db.Integer)
|
||||
move_number = db.Column(db.Integer)
|
||||
is_pass = db.Column(db.Boolean, nullable=False, default=False)
|
||||
is_main = db.Column(db.Boolean, nullable=False, default=True)
|
||||
|
||||
# foreign keys
|
||||
game = db.Column(db.Integer, db.ForeignKey("games.id"), nullable=False)
|
||||
preceding_move = db.Column(db.Integer, db.ForeignKey("moves.id"))
|
||||
|
||||
def __init__(self):
|
||||
pass
|
23
models/TimeSettings.py
Normal file
23
models/TimeSettings.py
Normal file
|
@ -0,0 +1,23 @@
|
|||
from ..app import db, ma
|
||||
import enum
|
||||
|
||||
class TimeTypes(enum.Enum):
|
||||
BYOYOMI = "Counting by time period"
|
||||
ABSOLUTE = "One period to use time"
|
||||
HOURGLASS = "Absolute time for both players"
|
||||
NONE = "Untimed"
|
||||
|
||||
class TimeSettings(db.Model):
|
||||
__table_args__ = {'extend_existing': True}
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
|
||||
main_time = db.Column(db.Enum(TimeTypes), nullable=False)
|
||||
time_period = db.Column(db.Integer) # number of periods
|
||||
period_length = db.Column(db.Integer) # seconds
|
||||
overtime = db.Column(db.Enum(TimeTypes), nullable=False)
|
||||
overtime_period = db.Column(db.Integer) # number of overtime periods
|
||||
overtime_length = db.Column(db.Integer) # seconds
|
||||
|
||||
|
||||
def __init__(self):
|
||||
pass
|
58
models/User.py
Normal file
58
models/User.py
Normal file
|
@ -0,0 +1,58 @@
|
|||
from ..app import db, ma, bcrypt
|
||||
import enum
|
||||
|
||||
class Ranks(enum.Enum): # with minimal Elo rating
|
||||
D7 = "Seven Dan" # Elo 2700+
|
||||
D6 = "Six Dan"
|
||||
D5 = "Five Dan" # Elo 2500
|
||||
D4 = "Four Dan"
|
||||
D3 = "Three Dan"
|
||||
D2 = "Two Dan"
|
||||
D1 = "One Dan"
|
||||
K1 = "One Kyu" # Elo 2000
|
||||
K2 = "Two Kyu"
|
||||
K3 = "Three Kyu"
|
||||
K4 = "Four Kyu"
|
||||
K5 = "Five Kyu"
|
||||
K6 = "Six Kyu" # Elo 1500
|
||||
K7 = "Seven Kyu"
|
||||
K8 = "Eight Kyu"
|
||||
K9 = "Nine Kyu"
|
||||
K10 = "Ten Kyu"
|
||||
K11 = "Eleven Kyu" # ELo 1000
|
||||
K12 = "Twelve Kyu"
|
||||
K13 = "Thirteen Kyu"
|
||||
K14 = "Fourteen Kyu"
|
||||
K15 = "Fifteen Kyu"
|
||||
K16 = "Sixteen Kyu" # Elo 500
|
||||
K17 = "Seventeen Kyu"
|
||||
K18 = "Eighteen Kyu"
|
||||
K19 = "Nineteen Kyu"
|
||||
K20 = "Twenty Kyu"
|
||||
K21 = "Twenty-One Kyu" # Elo 0
|
||||
K22 = "Twenty-Two Kyu"
|
||||
K23 = "Twenty-Three Kyu"
|
||||
K24 = "Twenty-Four Kyu"
|
||||
K25 = "Twenty-Five Kyu"
|
||||
K26 = "Twenty-Six Kyu" # Elo -500
|
||||
K27 = "Twenty-Seven Kyu"
|
||||
K28 = "Twenty-Eight Kyu"
|
||||
K29 = "Twenty-Nine Kyu"
|
||||
K30 = "Thirty Kyu" # Elo -900
|
||||
|
||||
class User(db.Model):
|
||||
__tablename__ = "users"
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
|
||||
email = db.Column(db.String(255), unique=True, nullable=False)
|
||||
password = db.Column(db.DateTime, nullable=False)
|
||||
registered_on = db.Column(db.DateTime, nullable=False)
|
||||
admin = db.Column(db.Boolean, nullable=False, default=False)
|
||||
rank = db.Column(db.Enum(Ranks))
|
||||
elo = db.Column(db.Integer)
|
||||
rank_certainty = db.Column(db.Boolean, nullable=False, default=False)
|
||||
|
||||
def __init__(self):
|
||||
self.password = bcrypt.generate_password_hash(
|
||||
password, app.config.get('BCRYPT_LOG_ROUNDS')
|
||||
).decode()
|
0
models/__init__.py
Normal file
0
models/__init__.py
Normal file
|
@ -1,13 +1,31 @@
|
|||
alembic==1.2.1
|
||||
astroid==2.3.1
|
||||
bcrypt==3.1.7
|
||||
cffi==1.12.3
|
||||
Click==7.0
|
||||
Flask==1.1.1
|
||||
Flask-Bcrypt==0.7.1
|
||||
Flask-Cors==3.0.8
|
||||
flask-marshmallow==0.10.1
|
||||
Flask-Migrate==2.5.2
|
||||
Flask-SQLAlchemy==2.4.1
|
||||
isort==4.3.21
|
||||
itsdangerous==1.1.0
|
||||
Jinja2==2.10.1
|
||||
lazy-object-proxy==1.4.2
|
||||
Mako==1.1.0
|
||||
MarkupSafe==1.1.1
|
||||
marshmallow==3.2.0
|
||||
marshmallow-sqlalchemy==0.19.0
|
||||
mccabe==0.6.1
|
||||
numpy==1.17.2
|
||||
psycopg2==2.8.3
|
||||
pycparser==2.19
|
||||
pylint==2.4.2
|
||||
python-dateutil==2.8.0
|
||||
python-editor==1.0.4
|
||||
six==1.12.0
|
||||
SQLAlchemy==1.3.8
|
||||
typed-ast==1.4.0
|
||||
Werkzeug==0.16.0
|
||||
wrapt==1.11.2
|
||||
|
|
0
rooms/__init__.py
Normal file
0
rooms/__init__.py
Normal file
7
rooms/room.py
Normal file
7
rooms/room.py
Normal file
|
@ -0,0 +1,7 @@
|
|||
from flask import Blueprint
|
||||
|
||||
room = Blueprint('rooms', __name__)
|
||||
|
||||
@room.route('/<int:room_id>')
|
||||
def func():
|
||||
pass
|
0
users/__init__.py
Normal file
0
users/__init__.py
Normal file
11
users/user.py
Normal file
11
users/user.py
Normal file
|
@ -0,0 +1,11 @@
|
|||
from flask import Blueprint
|
||||
|
||||
user = Blueprint('users', __name__)
|
||||
|
||||
@user.route('/<int:user_id>')
|
||||
def func():
|
||||
pass
|
||||
|
||||
@user.route('/<str:user_username>')
|
||||
def func():
|
||||
pass
|
Loading…
Reference in a new issue