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