diff --git a/.dockerignore b/.dockerignore
index e69de29..8d01a77 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -0,0 +1,5 @@
+venv
+__pycache__
+*.pyc
+*.pyo
+*.pyd
diff --git a/.env.example b/.env.example
index e69de29..d68d0f7 100644
--- a/.env.example
+++ b/.env.example
@@ -0,0 +1,8 @@
+# PostgreSQL database setup
+POSTGRES_DB=database_name
+POSTGRES_USER=user
+POSTGRES_PASSWORD=password
+POSTGRES_HOST=database_host
+POSTGRES_PORT=port_number
+
+DATABASE_URL=postgresql+psycopg2://user:password@db:port_number/database_name
\ No newline at end of file
diff --git a/README.md b/README.md
index 7b5a835..bc30092 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,64 @@
-# 🎨 Genius
\ No newline at end of file
+# 🎨 Genius
+
+###
+
+
+
+O projeto **Genius** é um sistema que prevê a próxima cor e sequência de cores em padrões similares ao clássico jogo **Genius**!
+
+Utilizando redes neurais e aprendizado incremental em tempo real, o sistema aprende continuamente a partir de sequências de cores geradas dinamicamente, proporcionando uma experiência única de predição baseada em cores.
+
+
+
+## Tecnologias
+
+Este projeto utiliza as seguintes tecnologias:
+
+- **Python** como linguagem principal;
+- **SQLAlchemy ORM** para integração com o banco de dados **PostgreSQL**;
+- **Flask** para construção de uma aplicação web responsiva;
+- **Socket.IO** para comunicação em tempo real entre o servidor e o cliente;
+- **TensorFlow** para criação e treinamento de uma rede neural do tipo **LSTM (Long Short-Term Memory)**,
+- **Docker** como uma ferramenta de containerização;
+
+
+
+## Arquitetura do Sistema
+
+A rede neural LSTM é configurada para realizar **aprendizado incremental**, processando novas entradas de dados continuamente. A cada nova cor recebida, o modelo é atualizado com o histórico e re-treinado, garantindo que a predição de padrões e sequência de cores se torne mais precisa à medida que o sistema evolui.
+
+O banco de dados registra as cores em suas respectivas componentes RGB, assim como o `timestamp` de cada entrada, facilitando a análise e o processamento dos dados em tempo real.
+
+
+
+## Configuração do Projeto
+
+### Requisitos para rodar a aplicação
+
+- Python (versão 3.11 ou superior)
+- Docker e Docker Compose;
+
+ ### Instalação
+
+1. Clonando o repositório:
+
+```bash
+$ git clone git@github.com:rafittu/python-genius.git
+$ cd python-genius
+```
+
+2. Crie um arquivo `.env` na raiz do projeto e preencha as informações de acordo com o arquivo `.env.example` disponível.
+
+3. Inicie o ambiente de desenvolvimento:
+
+```bash
+$ docker-compose up --build
+```
+
+
+
+##
+
+
+ Rafael Ribeiro 🚀 +
diff --git a/docker-compose.yml b/docker-compose.yml index 15811d6..366366f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,10 +1,28 @@ -version: '3.8' - services: app: - build: . - env_file: .env + build: + context: . + dockerfile: Dockerfile + command: python src/main.py volumes: - - ./src:/app/src + - .:/app ports: - "8000:8000" + env_file: + - .env + depends_on: + - db + + db: + image: postgres:15.3 + environment: + POSTGRES_DB: ${POSTGRES_DB} + POSTGRES_USER: ${POSTGRES_USER} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} + volumes: + - pgdata:/var/lib/postgresql/data + ports: + - "5432:5432" + +volumes: + pgdata: \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index f8e7061..8fdca55 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,7 @@ python-dotenv==1.0.0 +flask-socketio==5.4.1 +eventlet==0.37.0 +Flask==2.2.5 +Flask-SQLAlchemy==2.5.1 +SQLAlchemy==1.4.22 +psycopg2-binary==2.9.10 diff --git a/src/api/__init__.py b/src/api/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/api/color_api.py b/src/api/color_api.py new file mode 100644 index 0000000..42bf6d1 --- /dev/null +++ b/src/api/color_api.py @@ -0,0 +1,59 @@ +import re +import logging +from flask_socketio import SocketIO +from flask import Blueprint +from database.models.color import Color +from database.database import db + +color_api_bp = Blueprint('color_api', __name__) +socketio = SocketIO(cors_allowed_origins="*") +logger = logging.getLogger(__name__) + +COLOR_MAP = { + "rgb(0, 0, 255)": "blue", + "rgb(0, 255, 255)": "blue-green", + "rgb(0, 255, 0)": "green", + "rgb(128, 255, 0)": "yellow-green", + "rgb(255, 255, 0)": "yellow", + "rgb(255, 192, 0)": "yellow-orange", + "rgb(255, 128, 0)": "orange", + "rgb(255, 64, 0)": "red-orange", + "rgb(255, 0, 0)": "red" +} + + +def init_sockets(app): + socketio.init_app(app) + + +def parse_rgb(color_str): + match = re.match(r'rgb\((\d+),\s*(\d+),\s*(\d+)\)', color_str) + if match: + return int(match.group(1)), int(match.group(2)), int(match.group(3)) + raise ValueError("Invalid color format") + + +def get_color_name(color_str): + return COLOR_MAP.get(color_str, "unknown") + + +@socketio.on('send_color') +def handle_receive_color(data): + color_str = data.get('color') + timestamp = data.get('timestamp') + + try: + red, green, blue = parse_rgb(color_str) + color_name = get_color_name(color_str) + + new_color = Color( + color_name=color_name, + red=red, + green=green, + blue=blue, + timestamp=timestamp + ) + db.session.add(new_color) + db.session.commit() + except ValueError as e: + logger.error(f"Error processing color: {e}") diff --git a/src/database/__init__.py b/src/database/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/database/database.py b/src/database/database.py new file mode 100644 index 0000000..19dcec5 --- /dev/null +++ b/src/database/database.py @@ -0,0 +1,10 @@ +from flask_sqlalchemy import SQLAlchemy +from flask import Flask +import os + +db = SQLAlchemy() + +def init_app(app: Flask): + app.config['SQLALCHEMY_DATABASE_URI'] = os.getenv("DATABASE_URL") + app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False + db.init_app(app) diff --git a/src/database/models/__init__.py b/src/database/models/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/database/models/color.py b/src/database/models/color.py new file mode 100644 index 0000000..47cad50 --- /dev/null +++ b/src/database/models/color.py @@ -0,0 +1,11 @@ +from sqlalchemy import Column, Integer, String, DateTime, func +from database.database import db + +class Color(db.Model): + __tablename__ = 'colors' + id = Column(Integer, primary_key=True, index=True) + color_name = Column(String(50), nullable=False) + red = Column(Integer, nullable=False) + green = Column(Integer, nullable=False) + blue = Column(Integer, nullable=False) + timestamp = Column(DateTime(timezone=True), server_default=func.now()) diff --git a/src/main.py b/src/main.py index a92213b..886ed58 100644 --- a/src/main.py +++ b/src/main.py @@ -1,6 +1,29 @@ +from dotenv import load_dotenv +from flask import Flask +from api.color_api import color_api_bp, init_sockets, socketio +from database.database import init_app, db + +load_dotenv() + + +def create_app(): + app = Flask(__name__) + init_app(app) + app.register_blueprint(color_api_bp) + init_sockets(app) + + with app.app_context(): + db.create_all() + + return app + + def main(): print("🎨 Genius!") + app = create_app() + socketio.run(app, host='0.0.0.0', port=8000, debug=True) + if __name__ == "__main__": main()