diff --git a/learn_sql_model/api/websocket.py b/learn_sql_model/api/websocket.py index 962399c..ddfcb0d 100644 --- a/learn_sql_model/api/websocket.py +++ b/learn_sql_model/api/websocket.py @@ -1,13 +1,13 @@ from fastapi import APIRouter, Depends, WebSocket, WebSocketDisconnect from fastapi.responses import HTMLResponse from rich.console import Console -from sqlmodel import Session +from sqlmodel import Session, select from websockets.exceptions import ConnectionClosed from learn_sql_model.api.websocket_connection_manager import manager from learn_sql_model.config import get_session from learn_sql_model.console import console -from learn_sql_model.models.hero import HeroDelete, HeroUpdate, Heros +from learn_sql_model.models.hero import Hero, HeroDelete, HeroUpdate, Heros web_socket_router = APIRouter() @@ -46,7 +46,9 @@ async def websocket_endpoint_connect( ): Console().log(f"Client #{id} connecting") await manager.connect(websocket, channel) - heros = Heros.list(session=session) + statement = select(Hero) + heros = session.exec(statement).all() + heros = Heros(__root__=heros) await websocket.send_text(heros.json()) try: @@ -83,11 +85,18 @@ async def websocket_endpoint_hero_echo( while True: data = await websocket.receive_text() hero = HeroUpdate.parse_raw(data) - heros = Heros.list(session=session) + statement = select(Hero) + heros = session.exec(statement).all() + heros = Heros(__root__=heros) if heros != last_heros: await manager.broadcast(heros.json(), "heros") last_heros = heros - hero.update(session=session) + db_hero = session.get(Hero, hero.id) + for key, value in hero.dict(exclude_unset=True).items(): + setattr(db_hero, key, value) + session.add(db_hero) + session.commit() + session.refresh(db_hero) console.print(heros) await websocket.send_text(heros.json()) @@ -96,7 +105,9 @@ async def websocket_endpoint_hero_echo( HeroDelete(id=hero.id).delete(session=session) except Exception: ... - heros = Heros.list(session=session) + statement = select(Hero) + heros = session.exec(statement).all() + heros = Heros(__root__=heros) await manager.broadcast(heros.json(), "heros") print("disconnected") except ConnectionClosed: @@ -104,6 +115,8 @@ async def websocket_endpoint_hero_echo( HeroDelete(id=hero.id).delete(session=session) except Exception: ... - heros = Heros.list(session=session) + statement = select(Hero) + heros = session.exec(statement).all() + heros = Heros(__root__=heros) await manager.broadcast(heros.json(), "heros") print("connection closed") diff --git a/learn_sql_model/cli/api.py b/learn_sql_model/cli/api.py index aca3703..2dadd71 100644 --- a/learn_sql_model/cli/api.py +++ b/learn_sql_model/cli/api.py @@ -29,8 +29,6 @@ def run( help="show the log messages", ), ): - import uvicorn - uvicorn.run(**get_config().api_server.dict()) diff --git a/learn_sql_model/game/game.py b/learn_sql_model/game/game.py index aea1c26..5b14a17 100644 --- a/learn_sql_model/game/game.py +++ b/learn_sql_model/game/game.py @@ -5,10 +5,10 @@ from websocket import create_connection from learn_sql_model.config import get_config from learn_sql_model.console import console +from learn_sql_model.game.light import Light from learn_sql_model.game.map import Map from learn_sql_model.game.menu import Menu from learn_sql_model.game.player import Player -from learn_sql_model.game.light import Light from learn_sql_model.optional import _optional_import_ pygame = _optional_import_("pygame", group="game") @@ -37,15 +37,22 @@ class Client: self.light = Light(self) self.font = pygame.font.SysFont("", 50) self.joysticks = {} + self.darkness = pygame.Surface( + (self.screen.get_width(), self.screen.get_height()) + ) atexit.register(self.quit) @property def ws(self): def connect(): - self._ws = create_connection( - f"wss://{config.api_client.url.replace('https://', '')}/wsecho" - ) + if "https" in config.api_client.url: + url = f"wss://{config.api_client.url.replace('https://', '')}/wsecho" + elif "http" in config.api_client.url: + url = f"ws://{config.api_client.url.replace('http://', '')}/wsecho" + else: + url = f"ws://{config.api_client.url}/wsecho" + self._ws = create_connection(url) if not hasattr(self, "_ws"): connect() @@ -80,6 +87,19 @@ class Client: self.screen.fill((0, 0, 0)) self.map.render() self.player.render() + light_level = 0 + self.darkness.fill((light_level, light_level, light_level)) + # self.darkness.blit( + # pygame.transform.smoothscale( + # self.spot, [self.light_power, self.light_power] + # ), + # (self.x - self.light_power / 2, self.y - self.light_power / 2), + # ) + self.screen.blit( + pygame.transform.scale(self.darkness, self.screen.get_size()).convert(), + (0, 0), + special_flags=pygame.BLEND_MULT, + ) self.light.render() # update the screen diff --git a/learn_sql_model/game/light.py b/learn_sql_model/game/light.py index f562361..43ec4d1 100644 --- a/learn_sql_model/game/light.py +++ b/learn_sql_model/game/light.py @@ -6,15 +6,41 @@ pygame = _optional_import_("pygame", group="game") class Light: def __init__(self, game): self.game = game + self.surf = pygame.Surface((1000, 100)) + # pil_image = Image.new("RGBA", (1000, 500)) + # pil_draw = ImageDraw.Draw(pil_image) + # pil_draw.pieslice((-1500, -100, 1000, 600), 340, 20, fill=(255, 250, 205)) + # pil_image = pil_image.filter(ImageFilter.GaussianBlur(radius=5)) + + # mode = pil_image.mode + # size = pil_image.size + # data = pil_image.tobytes() + + # self.image = pygame.image.fromstring(data, size, mode) + + # for r in range(-25, 25): + # _v = v.rotate(r) + # pygame.draw.line( + # self.game.screen, + # (255, 250, 205), + # (0, 50), + # (0 + _v.x, self.game.player.hero.y + _v.y), + # 50, + # ) def render(self): mx, my = pygame.mouse.get_pos() v = pygame.math.Vector2( mx - self.game.player.hero.x, my - self.game.player.hero.y ) - v.scale_to_length(1000) + v.scale_to_length(self.game.player.hero.flashlight_strength) + self.game.player.hero.flashlight_angle = v.angle_to(pygame.math.Vector2(0, 0)) + # self.game.screen.blit( + # pygame.transform.rotate(self.image, pygame.math.Vector2(0, 0).angle_to(v)), + # (self.game.player.hero.x, self.game.player.hero.y - 250), + # ) - for r in range(0, 360): + for r in range(-25, 25): _v = v.rotate(r) pygame.draw.line( self.game.screen, @@ -23,3 +49,29 @@ class Light: (self.game.player.hero.x + _v.x, self.game.player.hero.y + _v.y), 50, ) + # draw a circle + pygame.draw.circle( + self.game.screen, + (255, 250, 205), + (self.game.player.hero.x, self.game.player.hero.y), + self.game.player.hero.lanturn_strength, + ) + + +def render_flashlight(light, strength, angle): + + # self.darkness.blit( + # pygame.transform.smoothscale( + # self.spot, [self.light_power, self.light_power] + # ), + # (self.x - self.light_power / 2, self.y - self.light_power / 2), + # ) + for r in range(-25, 25): + _v = v.rotate(r) + pygame.draw.line( + light, + (255, 250, 205), + (self.game.player.hero.x, self.game.player.hero.y), + (self.game.player.hero.x + _v.x, self.game.player.hero.y + _v.y), + 50, + ) diff --git a/learn_sql_model/game/player.py b/learn_sql_model/game/player.py index f5db3f3..0f2f702 100644 --- a/learn_sql_model/game/player.py +++ b/learn_sql_model/game/player.py @@ -1,5 +1,6 @@ +from learn_sql_model.config import get_config from learn_sql_model.console import console -from learn_sql_model.models.hero import HeroCreate, HeroDelete, HeroUpdate, Heros +from learn_sql_model.models.hero import Hero, HeroCreate, HeroUpdate, Heros from learn_sql_model.optional import _optional_import_ pygame = _optional_import_("pygame", group="game") @@ -12,11 +13,18 @@ HeroFactory = _optional_import_( class Player: def __init__(self, game): - hero = HeroFactory().build(size=25, x=100, y=100) + hero = HeroFactory().build( + size=25, + x=100, + y=100, + flashlight_strength=1000, + lanturn_strength=100, + flashlight_angle=0, + ) self.hero = HeroCreate(**hero.dict()).post() self.game = game - self.others = [] #Heros(heros=[]) + self.others = [] # Heros(heros=[]) self.width = 16 self.height = 16 self.white = (255, 255, 255) @@ -42,13 +50,21 @@ class Player: def rename_hero(self): old_hero = self.hero hero = HeroFactory().build( - size=self.hero.size, x=self.hero.x, y=self.hero.y, id=old_hero.id + size=self.hero.size, + x=self.hero.x, + y=self.hero.y, + id=old_hero.id, + flashlight_strength=self.hero.flashlight_strength, + lanturn_strength=self.hero.lanturn_strength, ) self.hero = HeroCreate(**hero.dict()).post() def quit(self): try: - HeroDelete(id=self.hero.id).delete() + session = get_config().database.session + hero = session.get(Hero, self.hero.id) + session.delete(hero) + session.commit() except RuntimeError: pass @@ -158,6 +174,10 @@ class Player: movement_vector = end_pos - start_pos try: movement_direction = movement_vector.normalize() + except ValueError: + end_pos = pygame.math.Vector2(self.hero.x + 128, self.hero.y + 128) + movement_vector = end_pos - start_pos + movement_direction = movement_vector.normalize() except ZeroDivisionError: end_pos = pygame.math.Vector2(self.hero.x + 128, self.hero.y + 128) movement_vector = end_pos - start_pos @@ -200,7 +220,7 @@ class Player: ) def render(self): - for other in self.others.heros: + for other in self.others.__root__: if other.id != self.hero.id: pygame.draw.circle( self.game.screen, (255, 0, 0), (other.x, other.y), other.size diff --git a/learn_sql_model/models/hero.py b/learn_sql_model/models/hero.py index 67a19c0..04ff72f 100644 --- a/learn_sql_model/models/hero.py +++ b/learn_sql_model/models/hero.py @@ -1,6 +1,7 @@ -from typing import Dict +from typing import Dict, Optional import httpx +import pydantic from pydantic import BaseModel from sqlmodel import Field, SQLModel @@ -13,13 +14,24 @@ class HeroBase(SQLModel, table=False): secret_name: str x: int y: int - # size: int + size: Optional[int] + flashlight_strength: Optional[int] = 1000 + flashlight_angle: Optional[int] = 0 + lanturn_strength: Optional[int] = 100 # age: Optional[int] = None # shoe_size: Optional[int] = None # pet_id: Optional[int] = Field(default=None, foreign_key="pet.id") # pet: Optional[Pet] = Relationship(back_populates="hero") + @pydantic.validator("size", pre=True, always=True) + def validate_size(cls, v): + if v is None: + return 50 + if v <= 0: + raise ValueError("size must be > 0") + return v + class Hero(HeroBase, table=True): id: int = Field(default=None, primary_key=True) diff --git a/migrations/versions/a1cd0a1947be_add_hero_lighting.py b/migrations/versions/a1cd0a1947be_add_hero_lighting.py new file mode 100644 index 0000000..4e48a0c --- /dev/null +++ b/migrations/versions/a1cd0a1947be_add_hero_lighting.py @@ -0,0 +1,36 @@ +"""add hero.lighting + +Revision ID: a1cd0a1947be +Revises: c79214cdc7b3 +Create Date: 2023-06-28 19:43:47.108749 + +""" +from alembic import op +import sqlalchemy as sa +import sqlmodel +from learn_sql_model.er_diagram import generate_er_diagram, generate_er_markdown +from learn_sql_model.config import get_config + + + +# revision identifiers, used by Alembic. +revision = 'a1cd0a1947be' +down_revision = 'c79214cdc7b3' +branch_labels = None +depends_on = None + + +def upgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('hero', sa.Column('flashlight_strength', sa.Integer(), nullable=True)) + op.add_column('hero', sa.Column('lanturn_strength', sa.Integer(), nullable=True)) + # ### end Alembic commands ### + generate_er_diagram(f'migrations/versions/{revision}_er_diagram.png') + generate_er_markdown(f'migrations/versions/{revision}_er_diagram.md', f'migrations/versions/er_diagram_{revision}.png') + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.drop_column('hero', 'lanturn_strength') + op.drop_column('hero', 'flashlight_strength') + # ### end Alembic commands ### diff --git a/migrations/versions/a1cd0a1947be_er_diagram.md b/migrations/versions/a1cd0a1947be_er_diagram.md new file mode 100644 index 0000000..3fc470a --- /dev/null +++ b/migrations/versions/a1cd0a1947be_er_diagram.md @@ -0,0 +1,75 @@ +![ER Diagram](migrations/versions/er_diagram_a1cd0a1947be.png) + +--- + +## Table: learn_sql_model_alembic_version + +### First 5 rows + +| version_num | +|-------------| +| c79214cdc7b3 | + +### Columns + +| Column Name | Type | Foreign Key | Example Value | +|-------------|------|-------------|---------------| +| version_num | VARCHAR(32) | | | | + +### Records Count + +The table learn_sql_model_alembic_version contains 1 records. + +--- + +## Table: hero + +### First 5 rows + +| name | secret_name | id | x | y | size | flashlight_strength | lanturn_strength | +|------|-------------|----|---|---|------|---------------------|------------------| +| deep-insect | unusual-inspection | 1 | 100 | 100 | 25 | None | None | +| flat-foundation | personal-incident | 2 | 100 | 100 | 25 | None | None | +| formal-cap | mental-substance | 3 | 100 | 100 | 25 | None | None | +| political-routine | low-engineer | 4 | 100 | 100 | 25 | None | None | + +### Columns + +| Column Name | Type | Foreign Key | Example Value | +|-------------|------|-------------|---------------| +| name | VARCHAR | | | | +| secret_name | VARCHAR | | | | +| id | INTEGER | | | | +| x | INTEGER | | | | +| y | INTEGER | | | | +| size | INTEGER | | | | +| flashlight_strength | INTEGER | | | | +| lanturn_strength | INTEGER | | | | + +### Records Count + +The table hero contains 4 records. + +--- + +## Table: pet + +### First 5 rows + +| name | birthday | id | +|------|----------|----| + +### Columns + +| Column Name | Type | Foreign Key | Example Value | +|-------------|------|-------------|---------------| +| name | VARCHAR | | | | +| birthday | DATETIME | | | | +| id | INTEGER | | | | + +### Records Count + +The table pet contains 0 records. + +--- + diff --git a/migrations/versions/a1cd0a1947be_er_diagram.png b/migrations/versions/a1cd0a1947be_er_diagram.png new file mode 100644 index 0000000..8e26ac5 Binary files /dev/null and b/migrations/versions/a1cd0a1947be_er_diagram.png differ diff --git a/migrations/versions/c79214cdc7b3_add_hero_size.py b/migrations/versions/c79214cdc7b3_add_hero_size.py new file mode 100644 index 0000000..643480b --- /dev/null +++ b/migrations/versions/c79214cdc7b3_add_hero_size.py @@ -0,0 +1,34 @@ +"""add hero.size + +Revision ID: c79214cdc7b3 +Revises: 3555f61aaa79 +Create Date: 2023-06-28 11:39:02.606001 + +""" +from alembic import op +import sqlalchemy as sa +import sqlmodel +from learn_sql_model.er_diagram import generate_er_diagram, generate_er_markdown +from learn_sql_model.config import get_config + + + +# revision identifiers, used by Alembic. +revision = 'c79214cdc7b3' +down_revision = '3555f61aaa79' +branch_labels = None +depends_on = None + + +def upgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('hero', sa.Column('size', sa.Integer(), nullable=True)) + # ### end Alembic commands ### + generate_er_diagram(f'migrations/versions/{revision}_er_diagram.png') + generate_er_markdown(f'migrations/versions/{revision}_er_diagram.md', f'migrations/versions/er_diagram_{revision}.png') + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.drop_column('hero', 'size') + # ### end Alembic commands ### diff --git a/migrations/versions/c79214cdc7b3_er_diagram.md b/migrations/versions/c79214cdc7b3_er_diagram.md new file mode 100644 index 0000000..9969846 --- /dev/null +++ b/migrations/versions/c79214cdc7b3_er_diagram.md @@ -0,0 +1,74 @@ +![ER Diagram](migrations/versions/er_diagram_c79214cdc7b3.png) + +--- + +## Table: learn_sql_model_alembic_version + +### First 5 rows + +| version_num | +|-------------| +| 3555f61aaa79 | + +### Columns + +| Column Name | Type | Foreign Key | Example Value | +|-------------|------|-------------|---------------| +| version_num | VARCHAR(32) | | | | + +### Records Count + +The table learn_sql_model_alembic_version contains 1 records. + +--- + +## Table: hero + +### First 5 rows + +| name | secret_name | id | x | y | size | +|------|-------------|----|---|---|------| +| tight-gold | successful-health | 1 | 6430 | 6231 | None | +| hard-rope | green-research | 2 | 1395 | 2865 | None | +| sure-priority | pretty-series | 3 | 2770 | 7835 | None | +| huge-library | adult-body | 4 | 656 | 2377 | None | +| specific-courage | suspicious-delivery | 5 | 4193 | 9011 | None | + +### Columns + +| Column Name | Type | Foreign Key | Example Value | +|-------------|------|-------------|---------------| +| name | VARCHAR | | | | +| secret_name | VARCHAR | | | | +| id | INTEGER | | | | +| x | INTEGER | | | | +| y | INTEGER | | | | +| size | INTEGER | | | | + +### Records Count + +The table hero contains 1572 records. + +--- + +## Table: pet + +### First 5 rows + +| name | birthday | id | +|------|----------|----| + +### Columns + +| Column Name | Type | Foreign Key | Example Value | +|-------------|------|-------------|---------------| +| name | VARCHAR | | | | +| birthday | DATETIME | | | | +| id | INTEGER | | | | + +### Records Count + +The table pet contains 0 records. + +--- + diff --git a/migrations/versions/c79214cdc7b3_er_diagram.png b/migrations/versions/c79214cdc7b3_er_diagram.png new file mode 100644 index 0000000..887cf61 Binary files /dev/null and b/migrations/versions/c79214cdc7b3_er_diagram.png differ diff --git a/migrations/versions/d79dd8e699d1_add_hero_flashlight_angle.py b/migrations/versions/d79dd8e699d1_add_hero_flashlight_angle.py new file mode 100644 index 0000000..f59d974 --- /dev/null +++ b/migrations/versions/d79dd8e699d1_add_hero_flashlight_angle.py @@ -0,0 +1,34 @@ +"""add hero.flashlight_angle + +Revision ID: d79dd8e699d1 +Revises: e1af975310a1 +Create Date: 2023-06-28 19:54:19.322431 + +""" +from alembic import op +import sqlalchemy as sa +import sqlmodel +from learn_sql_model.er_diagram import generate_er_diagram, generate_er_markdown +from learn_sql_model.config import get_config + + + +# revision identifiers, used by Alembic. +revision = 'd79dd8e699d1' +down_revision = 'e1af975310a1' +branch_labels = None +depends_on = None + + +def upgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('hero', sa.Column('flashlight_angle', sa.Integer(), nullable=True)) + # ### end Alembic commands ### + generate_er_diagram(f'migrations/versions/{revision}_er_diagram.png') + generate_er_markdown(f'migrations/versions/{revision}_er_diagram.md', f'migrations/versions/er_diagram_{revision}.png') + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.drop_column('hero', 'flashlight_angle') + # ### end Alembic commands ### diff --git a/migrations/versions/d79dd8e699d1_er_diagram.md b/migrations/versions/d79dd8e699d1_er_diagram.md new file mode 100644 index 0000000..da209b0 --- /dev/null +++ b/migrations/versions/d79dd8e699d1_er_diagram.md @@ -0,0 +1,72 @@ +![ER Diagram](migrations/versions/er_diagram_d79dd8e699d1.png) + +--- + +## Table: learn_sql_model_alembic_version + +### First 5 rows + +| version_num | +|-------------| +| e1af975310a1 | + +### Columns + +| Column Name | Type | Foreign Key | Example Value | +|-------------|------|-------------|---------------| +| version_num | VARCHAR(32) | | | | + +### Records Count + +The table learn_sql_model_alembic_version contains 1 records. + +--- + +## Table: hero + +### First 5 rows + +| name | secret_name | id | x | y | size | flashlight_strength | lanturn_strength | flashlight_angle | +|------|-------------|----|---|---|------|---------------------|------------------|------------------| + +### Columns + +| Column Name | Type | Foreign Key | Example Value | +|-------------|------|-------------|---------------| +| name | VARCHAR | | | | +| secret_name | VARCHAR | | | | +| id | INTEGER | | | | +| x | INTEGER | | | | +| y | INTEGER | | | | +| size | INTEGER | | | | +| flashlight_strength | INTEGER | | | | +| lanturn_strength | INTEGER | | | | +| flashlight_angle | INTEGER | | | | + +### Records Count + +The table hero contains 0 records. + +--- + +## Table: pet + +### First 5 rows + +| name | birthday | id | +|------|----------|----| + +### Columns + +| Column Name | Type | Foreign Key | Example Value | +|-------------|------|-------------|---------------| +| name | VARCHAR | | | | +| birthday | DATETIME | | | | +| id | INTEGER | | | | + +### Records Count + +The table pet contains 0 records. + +--- + diff --git a/migrations/versions/d79dd8e699d1_er_diagram.png b/migrations/versions/d79dd8e699d1_er_diagram.png new file mode 100644 index 0000000..f1560e3 Binary files /dev/null and b/migrations/versions/d79dd8e699d1_er_diagram.png differ diff --git a/migrations/versions/e1af975310a1_add_hero_flashlight_angle.py b/migrations/versions/e1af975310a1_add_hero_flashlight_angle.py new file mode 100644 index 0000000..e2df16f --- /dev/null +++ b/migrations/versions/e1af975310a1_add_hero_flashlight_angle.py @@ -0,0 +1,34 @@ +"""add hero.flashlight_angle + +Revision ID: e1af975310a1 +Revises: a1cd0a1947be +Create Date: 2023-06-28 19:53:18.068873 + +""" +from alembic import op +import sqlalchemy as sa +import sqlmodel +from learn_sql_model.er_diagram import generate_er_diagram, generate_er_markdown +from learn_sql_model.config import get_config + + + +# revision identifiers, used by Alembic. +revision = 'e1af975310a1' +down_revision = 'a1cd0a1947be' +branch_labels = None +depends_on = None + + +def upgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + pass + # ### end Alembic commands ### + generate_er_diagram(f'migrations/versions/{revision}_er_diagram.png') + generate_er_markdown(f'migrations/versions/{revision}_er_diagram.md', f'migrations/versions/er_diagram_{revision}.png') + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + pass + # ### end Alembic commands ### diff --git a/migrations/versions/e1af975310a1_er_diagram.md b/migrations/versions/e1af975310a1_er_diagram.md new file mode 100644 index 0000000..a5dd9d2 --- /dev/null +++ b/migrations/versions/e1af975310a1_er_diagram.md @@ -0,0 +1,71 @@ +![ER Diagram](migrations/versions/er_diagram_e1af975310a1.png) + +--- + +## Table: learn_sql_model_alembic_version + +### First 5 rows + +| version_num | +|-------------| +| a1cd0a1947be | + +### Columns + +| Column Name | Type | Foreign Key | Example Value | +|-------------|------|-------------|---------------| +| version_num | VARCHAR(32) | | | | + +### Records Count + +The table learn_sql_model_alembic_version contains 1 records. + +--- + +## Table: hero + +### First 5 rows + +| name | secret_name | id | x | y | size | flashlight_strength | lanturn_strength | +|------|-------------|----|---|---|------|---------------------|------------------| + +### Columns + +| Column Name | Type | Foreign Key | Example Value | +|-------------|------|-------------|---------------| +| name | VARCHAR | | | | +| secret_name | VARCHAR | | | | +| id | INTEGER | | | | +| x | INTEGER | | | | +| y | INTEGER | | | | +| size | INTEGER | | | | +| flashlight_strength | INTEGER | | | | +| lanturn_strength | INTEGER | | | | + +### Records Count + +The table hero contains 0 records. + +--- + +## Table: pet + +### First 5 rows + +| name | birthday | id | +|------|----------|----| + +### Columns + +| Column Name | Type | Foreign Key | Example Value | +|-------------|------|-------------|---------------| +| name | VARCHAR | | | | +| birthday | DATETIME | | | | +| id | INTEGER | | | | + +### Records Count + +The table pet contains 0 records. + +--- + diff --git a/migrations/versions/e1af975310a1_er_diagram.png b/migrations/versions/e1af975310a1_er_diagram.png new file mode 100644 index 0000000..8e26ac5 Binary files /dev/null and b/migrations/versions/e1af975310a1_er_diagram.png differ