diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index f1ffeaf..0000000 Binary files a/.DS_Store and /dev/null differ diff --git a/set_crafter/CONTRIBUTING.md b/set_crafter/CONTRIBUTING.md new file mode 100755 index 0000000..d24d23d --- /dev/null +++ b/set_crafter/CONTRIBUTING.md @@ -0,0 +1,57 @@ +# Contributing to SetCrafter AI + +We love your input! We want to make contributing to this project as easy and transparent as possible, whether it's: + +- Reporting a bug +- Discussing the current state of the code +- Submitting a fix +- Proposing new features +- Becoming a maintainer + +## We Develop with Github + +We use github to host code, to track issues and feature requests, as well as accept pull requests. + +## We Use [Github Flow](https://guides.github.com/introduction/flow/index.html), So All Code Changes Happen Through Pull Requests + +Pull requests are the best way to propose changes to the codebase. We actively welcome your pull requests: + +1. Fork the repo and create your branch from `main`. +2. If you've added code that should be tested, add tests. +3. If you've changed APIs, update the documentation. +4. Ensure the test suite passes. +5. Make sure your code lints. +6. Issue that pull request! + +## Any contributions you make will be under the MIT Software License + +In short, when you submit code changes, your submissions are understood to be under the same [MIT License](https://choosealicense.com/licenses/mit/) that covers the project. Feel free to contact the maintainers if that's a concern. + +## Report bugs using Github's [issues](https://github.com/briandk/transcriptase-atom/issues) + +We use GitHub issues to track public bugs. Report a bug by [opening a new issue](https://github.com/briandk/transcriptase-atom/issues); it's that easy! + +## Write bug reports with detail, background, and sample code + +**Great Bug Reports** tend to have: + +- A quick summary and/or background +- Steps to reproduce + - Be specific! + - Give sample code if you can. +- What you expected would happen +- What actually happens +- Notes (possibly including why you think this might be happening, or stuff you tried that didn't work) + +## Use a Consistent Coding Style + +* 2 spaces for indentation rather than tabs +* You can try running `npm run lint` for style unification + +## License + +By contributing, you agree that your contributions will be licensed under its MIT License. + +## References + +This document was adapted from the open-source contribution guidelines for [Facebook's Draft](https://github.com/facebook/draft-js) \ No newline at end of file diff --git a/LICENSE b/set_crafter/LICENSE.md old mode 100644 new mode 100755 similarity index 96% rename from LICENSE rename to set_crafter/LICENSE.md index a76d3a1..2f60545 --- a/LICENSE +++ b/set_crafter/LICENSE.md @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2023 Myuzeo Labs +Copyright (c) 2022 SetCrafter AI Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +SOFTWARE. \ No newline at end of file diff --git a/README.md b/set_crafter/README.md old mode 100644 new mode 100755 similarity index 89% rename from README.md rename to set_crafter/README.md index 370dc96..d28197d --- a/README.md +++ b/set_crafter/README.md @@ -1,4 +1,4 @@ -# SetCraifter +# SetCraifter ## Introduction @@ -27,9 +27,10 @@ SetCrafter AI is a tentative project designed to revolutionize the way DJs organ ### Usage Run the main script to start categorizing and curating your DJ library: + ## Contribution -We welcome contributions to SetCrafter AI. Please read the [CONTRIBUTING.md](CONTRIBUTING.md) file for guidelines on how to contribute. +We welcome contributions to SetCrafter AI. Please read the CONTRIBUTING.md file for guidelines on how to contribute. ## Alternative Solutions @@ -38,19 +39,18 @@ We welcome contributions to SetCrafter AI. Please read the [CONTRIBUTING.md](CON ## License -SetCrafter AI is licensed under the MIT License. See the [LICENSE.md](LICENSE.md) file for details. +SetCrafter AI is licensed under the MIT License. See the LICENSE.md file for details. ## Contact -For any inquiries or feedback, please reach out to [username@email.com](mailto:username@email.com). +For any inquiries or feedback, please reach out to username@email.com. ## Acknowledgments Special thanks to the music community for inspiring this innovative approach to DJ library organization. - - ======= + # Set Crafter Tool Set Crafter is a tool designed to assist DJs in crafting their music sets with the help of AI-driven recommendations and data analysis. @@ -65,19 +65,23 @@ Set Crafter is a tool designed to assist DJs in crafting their music sets with t ## Modules ### Data Preprocessing Module + - `DJLibraryDataExtractor`: Extracts data from a DJ's music library - `DataPreprocessor`: Processes the data for AI model consumption - `SpotifyDataDownloader`: Downloads track data from Spotify ### AI Models Module + - `TrackCategorizer`: Categorizes tracks based on their features - `SetCurator`: Curates music sets based on the categorized tracks - `ModelTrainingDataBuilder`: Prepares datasets for training AI models ### Main Application Module + - `SetCrafterApp`: Coordinates modules and provides the user interface ## Libraries + - spotipy - pandas - scikit-learn @@ -85,16 +89,20 @@ Set Crafter is a tool designed to assist DJs in crafting their music sets with t - streamlit ## Backend Development + - Endpoints for Spotify authentication and track downloading ## Frontend Development + - Implemented using Streamlit for a user-friendly interface ## Security and Error Handling + - OAuth 2.0 implementation for secure Spotify authentication - Robust error handling and logging mechanisms ## Testing and Deployment + - Comprehensive testing of backend and frontend components - Deployment strategies for the Flask and Streamlit applications @@ -104,5 +112,4 @@ Instructions on how to set up and run Set Crafter will be provided here. ## License -This project is licensed under the MIT License - see the LICENSE file for details. - +This project is licensed under the MIT License - see the LICENSE file for details. \ No newline at end of file diff --git a/set_crafter/ai_models/model_training_data_builder.py b/set_crafter/ai_models/model_training_data_builder.py new file mode 100755 index 0000000..2bdd073 --- /dev/null +++ b/set_crafter/ai_models/model_training_data_builder.py @@ -0,0 +1,18 @@ +```python +import pandas as pd +from sklearn.model_selection import train_test_split + +class ModelTrainingDataBuilder: + def __init__(self, track_data): + self.track_data = track_data + + def build_training_data(self): + # Split the data into features and target + X = self.track_data.drop('category', axis=1) + y = self.track_data['category'] + + # Split the data into training and testing sets + X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) + + return X_train, X_test, y_train, y_test +``` \ No newline at end of file diff --git a/set_crafter/ai_models/set_curator.py b/set_crafter/ai_models/set_curator.py new file mode 100755 index 0000000..26ce721 --- /dev/null +++ b/set_crafter/ai_models/set_curator.py @@ -0,0 +1,35 @@ +```python +from sklearn.neighbors import NearestNeighbors +import pandas as pd + +class SetCurator: + def __init__(self, track_data): + self.track_data = track_data + self.curated_set = None + + def curate_set(self): + # Use nearest neighbors to curate a set based on track features + model = NearestNeighbors(n_neighbors=7) + model.fit(self.track_data) + + # Generate a set starting with a random track + start_track = self.track_data.sample(1) + set_indices = model.kneighbors(start_track, return_distance=False) + + # Create a curated set dataframe + self.curated_set = self.track_data.iloc[set_indices[0]] + + return self.curated_set + + def save_curated_set(self, filename): + # Save the curated set to a CSV file + self.curated_set.to_csv(filename, index=False) + + def load_curated_set(self, filename): + # Load a curated set from a CSV file + self.curated_set = pd.read_csv(filename) + + def get_curated_set(self): + # Return the curated set + return self.curated_set +``` \ No newline at end of file diff --git a/set_crafter/ai_models/track_categorizer.py b/set_crafter/ai_models/track_categorizer.py new file mode 100755 index 0000000..a49c128 --- /dev/null +++ b/set_crafter/ai_models/track_categorizer.py @@ -0,0 +1,30 @@ +```python +from sklearn.neighbors import KNeighborsClassifier +import pandas as pd + +class TrackCategorizer: + def __init__(self): + self.model = KNeighborsClassifier() + + def build_training_data(self, track_data): + # Extract features and labels from track_data + features = track_data.drop('category', axis=1) + labels = track_data['category'] + return features, labels + + def train_model(self, features, labels): + self.model.fit(features, labels) + + def categorize_track(self, track): + # Predict the category of a single track + category = self.model.predict([track]) + return category[0] + +if __name__ == "__main__": + track_data = pd.read_csv('track_data.csv') + categorizer = TrackCategorizer() + features, labels = categorizer.build_training_data(track_data) + categorizer.train_model(features, labels) + test_track = [0.6, 0.7, 120] # Example track data + print(categorizer.categorize_track(test_track)) +``` \ No newline at end of file diff --git a/set_crafter/app/set_crafter_app.py b/set_crafter/app/set_crafter_app.py new file mode 100755 index 0000000..0554d39 --- /dev/null +++ b/set_crafter/app/set_crafter_app.py @@ -0,0 +1,45 @@ +```python +import os +from set_crafter.data_preprocessing.dj_library_data_extractor import DJLibraryDataExtractor +from set_crafter.data_preprocessing.data_preprocessor import DataPreprocessor +from set_crafter.data_preprocessing.spotify_data_downloader import SpotifyDataDownloader +from set_crafter.ai_models.track_categorizer import TrackCategorizer +from set_crafter.ai_models.set_curator import SetCurator +from set_crafter.ai_models.model_training_data_builder import ModelTrainingDataBuilder + +class SetCrafterApp: + def __init__(self): + self.spotify_credentials = os.getenv('SPOTIFY_CREDENTIALS') + self.data_extractor = DJLibraryDataExtractor() + self.data_preprocessor = DataPreprocessor() + self.data_downloader = SpotifyDataDownloader(self.spotify_credentials) + self.track_categorizer = TrackCategorizer() + self.set_curator = SetCurator() + self.training_data_builder = ModelTrainingDataBuilder() + + def run(self): + # Extract data from DJ's library + track_data = self.data_extractor.extract_data() + + # Download additional track data from Spotify + track_data = self.data_downloader.download_data(track_data) + + # Preprocess the data for AI model consumption + track_data = self.data_preprocessor.preprocess_data(track_data) + + # Build training data for AI models + training_data = self.training_data_builder.build_training_data(track_data) + + # Categorize tracks based on their features + categorized_tracks = self.track_categorizer.categorize_track(training_data) + + # Curate music sets based on the categorized tracks + curated_sets = self.set_curator.curate_set(categorized_tracks) + + return curated_sets + +if __name__ == "__main__": + app = SetCrafterApp() + curated_sets = app.run() + print(curated_sets) +``` \ No newline at end of file diff --git a/set_crafter/backend/spotify_auth.py b/set_crafter/backend/spotify_auth.py new file mode 100755 index 0000000..72cf9dc --- /dev/null +++ b/set_crafter/backend/spotify_auth.py @@ -0,0 +1,53 @@ +```python +import spotipy +from spotipy.oauth2 import SpotifyOAuth +from flask import Flask, request, redirect, session +import os +from ..config import spotify_credentials + +app = Flask(__name__) + +# Set the secret key to some random bytes. Keep this really secret! +app.secret_key = os.urandom(16) + +@app.route('/') +def index(): + auth_url = create_spotify_oauth().get_authorize_url() + return redirect(auth_url) + +@app.route('/callback') +def callback(): + code = request.args.get('code') + token_info = create_spotify_oauth().get_access_token(code) + session["token_info"] = token_info + return redirect("AuthenticationSuccess") + +def create_spotify_oauth(): + return SpotifyOAuth( + client_id=spotify_credentials["client_id"], + client_secret=spotify_credentials["client_secret"], + redirect_uri=spotify_credentials["redirect_uri"], + scope="user-library-read" + ) + +def get_token(session): + token_valid = False + token_info = session.get("token_info", {}) + + # Checking if the session already has a token. + if not (session.get('token_info', False)): + token_valid = False + else: + now = int(time.time()) + is_token_expired = session['token_info']['expires_at'] - now < 60 + + # If the token is expired, refresh it + if (is_token_expired): + sp_oauth = create_spotify_oauth() + token_info = sp_oauth.refresh_access_token(session['token_info']['refresh_token']) + token_valid = True + return token_info, token_valid + +if __name__ == "__main__": + app.run(debug=True, port=spotify_credentials["port"]) +``` \ No newline at end of file diff --git a/set_crafter/backend/track_downloader.py b/set_crafter/backend/track_downloader.py new file mode 100755 index 0000000..6c648ba --- /dev/null +++ b/set_crafter/backend/track_downloader.py @@ -0,0 +1,16 @@ +```python +import spotipy +from spotipy.oauth2 import SpotifyOAuth +from ..config import spotify_credentials + +class SpotifyDataDownloader: + def __init__(self): + self.sp = spotipy.Spotify(auth_manager=SpotifyOAuth(client_id=spotify_credentials['client_id'], + client_secret=spotify_credentials['client_secret'], + redirect_uri=spotify_credentials['redirect_uri'], + scope=spotify_credentials['scope'])) + + def download_data(self, track_id): + track_data = self.sp.track(track_id) + return track_data +``` \ No newline at end of file diff --git a/set_crafter/config.py b/set_crafter/config.py new file mode 100755 index 0000000..09dc33f --- /dev/null +++ b/set_crafter/config.py @@ -0,0 +1,11 @@ +```python +# Configuration file for SetCrafter + +# Spotify API credentials +spotify_credentials = { + "client_id": "", + "client_secret": "", + "redirect_uri": "", + "username": "" +} +``` \ No newline at end of file diff --git a/set_crafter/data_preprocessing/data_preprocessor.py b/set_crafter/data_preprocessing/data_preprocessor.py new file mode 100755 index 0000000..556ca08 --- /dev/null +++ b/set_crafter/data_preprocessing/data_preprocessor.py @@ -0,0 +1,21 @@ +```python +import pandas as pd +from sklearn.preprocessing import StandardScaler + +class DataPreprocessor: + def __init__(self): + self.scaler = StandardScaler() + + def preprocess_data(self, track_data): + # Drop unnecessary columns + track_data = track_data.drop(['track_id', 'track_name', 'artist'], axis=1) + + # Fill missing values with mean + track_data = track_data.fillna(track_data.mean()) + + # Standardize numerical features + numerical_features = ['acousticness', 'danceability', 'energy', 'instrumentalness', 'liveness', 'loudness', 'speechiness', 'tempo', 'valence'] + track_data[numerical_features] = self.scaler.fit_transform(track_data[numerical_features]) + + return track_data +``` \ No newline at end of file diff --git a/set_crafter/data_preprocessing/dj_library_data_extractor.py b/set_crafter/data_preprocessing/dj_library_data_extractor.py new file mode 100755 index 0000000..2bfdc6e --- /dev/null +++ b/set_crafter/data_preprocessing/dj_library_data_extractor.py @@ -0,0 +1,15 @@ +```python +import pandas as pd + +class DJLibraryDataExtractor: + def __init__(self, library_path): + self.library_path = library_path + + def extract_data(self): + try: + track_data = pd.read_csv(self.library_path) + return track_data + except Exception as e: + print(f"Error occurred while extracting data: {e}") + return None +``` \ No newline at end of file diff --git a/set_crafter/data_preprocessing/spotify_data_downloader.py b/set_crafter/data_preprocessing/spotify_data_downloader.py new file mode 100755 index 0000000..72df0d1 --- /dev/null +++ b/set_crafter/data_preprocessing/spotify_data_downloader.py @@ -0,0 +1,14 @@ +```python +import spotipy +from spotipy.oauth2 import SpotifyClientCredentials +from config import spotify_credentials + +class SpotifyDataDownloader: + def __init__(self): + self.client_credentials_manager = SpotifyClientCredentials(client_id=spotify_credentials['client_id'], client_secret=spotify_credentials['client_secret']) + self.sp = spotipy.Spotify(client_credentials_manager=self.client_credentials_manager) + + def download_data(self, track_id): + track_data = self.sp.track(track_id) + return track_data +``` \ No newline at end of file diff --git a/set_crafter/deployment/flask_deployment.py b/set_crafter/deployment/flask_deployment.py new file mode 100755 index 0000000..f8d6853 --- /dev/null +++ b/set_crafter/deployment/flask_deployment.py @@ -0,0 +1,21 @@ +```python +from flask import Flask +from set_crafter.backend.spotify_auth import SpotifyAuth +from set_crafter.backend.track_downloader import TrackDownloader + +app = Flask(__name__) + +spotify_auth = SpotifyAuth() +track_downloader = TrackDownloader() + +@app.route('/spotify-auth', methods=['GET']) +def authenticate_spotify(): + return spotify_auth.authenticate() + +@app.route('/download-track', methods=['POST']) +def download_track(): + return track_downloader.download() + +if __name__ == '__main__': + app.run(host='0.0.0.0', port=5000) +``` \ No newline at end of file diff --git a/set_crafter/deployment/streamlit_deployment.py b/set_crafter/deployment/streamlit_deployment.py new file mode 100755 index 0000000..2ad0e98 --- /dev/null +++ b/set_crafter/deployment/streamlit_deployment.py @@ -0,0 +1,23 @@ +```python +import streamlit as st +from set_crafter.app.set_crafter_app import SetCrafterApp + +def run_streamlit_app(): + st.title('SetCrafter AI') + st.write('Welcome to SetCrafter AI, a tool designed to assist DJs in crafting their music sets with the help of AI-driven recommendations and data analysis.') + + spotify_credentials = st.text_input('Enter your Spotify credentials:') + if spotify_credentials: + app = SetCrafterApp(spotify_credentials) + st.write('Spotify credentials set successfully.') + + if st.button('Start Categorizing and Curating'): + try: + app.run() + st.write('Categorization and curation completed successfully.') + except Exception as e: + st.write(f'An error occurred: {str(e)}') + +if __name__ == "__main__": + run_streamlit_app() +``` \ No newline at end of file diff --git a/set_crafter/error_handling/error_logger.py b/set_crafter/error_handling/error_logger.py new file mode 100755 index 0000000..cdcc6a0 --- /dev/null +++ b/set_crafter/error_handling/error_logger.py @@ -0,0 +1,16 @@ +```python +import logging + +class ErrorLogger: + def __init__(self, log_file='set_crafter.log'): + self.logger = logging.getLogger('SetCrafter') + self.logger.setLevel(logging.ERROR) + handler = logging.FileHandler(log_file) + handler.setLevel(logging.ERROR) + formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') + handler.setFormatter(formatter) + self.logger.addHandler(handler) + + def log_error(self, error_message): + self.logger.error(error_message) +``` \ No newline at end of file diff --git a/set_crafter/frontend/streamlit_app.py b/set_crafter/frontend/streamlit_app.py new file mode 100755 index 0000000..7e8281b --- /dev/null +++ b/set_crafter/frontend/streamlit_app.py @@ -0,0 +1,31 @@ +```python +import streamlit as st +from set_crafter.app.set_crafter_app import SetCrafterApp + +def main(): + st.title("SetCrafter AI") + st.write("Welcome to SetCrafter AI, a tool designed to assist DJs in crafting their music sets with the help of AI-driven recommendations and data analysis.") + + spotify_auth_button = st.button("Authenticate with Spotify") + if spotify_auth_button: + SetCrafterApp.authenticate_spotify() + + track_download_button = st.button("Download Track Data") + if track_download_button: + SetCrafterApp.download_data() + + data_preprocess_button = st.button("Preprocess Data") + if data_preprocess_button: + SetCrafterApp.preprocess_data() + + track_categorize_button = st.button("Categorize Tracks") + if track_categorize_button: + SetCrafterApp.categorize_track() + + set_curate_button = st.button("Curate Set") + if set_curate_button: + SetCrafterApp.curate_set() + +if __name__ == "__main__": + main() +``` \ No newline at end of file diff --git a/set_crafter/main.py b/set_crafter/main.py new file mode 100755 index 0000000..43fd8f5 --- /dev/null +++ b/set_crafter/main.py @@ -0,0 +1,29 @@ +```python +import os +from set_crafter.config import spotify_credentials +from set_crafter.data_preprocessing.dj_library_data_extractor import DJLibraryDataExtractor +from set_crafter.data_preprocessing.data_preprocessor import DataPreprocessor +from set_crafter.data_preprocessing.spotify_data_downloader import SpotifyDataDownloader +from set_crafter.ai_models.track_categorizer import TrackCategorizer +from set_crafter.ai_models.set_curator import SetCurator +from set_crafter.ai_models.model_training_data_builder import ModelTrainingDataBuilder +from set_crafter.app.set_crafter_app import SetCrafterApp + +def main(): + # Initialize modules + data_extractor = DJLibraryDataExtractor() + data_preprocessor = DataPreprocessor() + data_downloader = SpotifyDataDownloader(spotify_credentials) + track_categorizer = TrackCategorizer() + set_curator = SetCurator() + training_data_builder = ModelTrainingDataBuilder() + + # Initialize main application + set_crafter_app = SetCrafterApp(data_extractor, data_preprocessor, data_downloader, track_categorizer, set_curator, training_data_builder) + + # Run the application + set_crafter_app.run() + +if __name__ == "__main__": + main() +``` \ No newline at end of file diff --git a/set_crafter/security/oauth.py b/set_crafter/security/oauth.py new file mode 100755 index 0000000..c48fa7c --- /dev/null +++ b/set_crafter/security/oauth.py @@ -0,0 +1,17 @@ +```python +import spotipy +from spotipy.oauth2 import SpotifyOAuth +from set_crafter.config import spotify_credentials + +def authenticate_spotify(): + """Authenticate with Spotify using OAuth 2.0.""" + scope = "user-library-read" + + sp = spotipy.Spotify(auth_manager=SpotifyOAuth( + client_id=spotify_credentials['client_id'], + client_secret=spotify_credentials['client_secret'], + redirect_uri=spotify_credentials['redirect_uri'], + scope=scope)) + + return sp +``` \ No newline at end of file diff --git a/set_crafter/testing/backend_tests.py b/set_crafter/testing/backend_tests.py new file mode 100755 index 0000000..9b5ea26 --- /dev/null +++ b/set_crafter/testing/backend_tests.py @@ -0,0 +1,24 @@ +```python +import unittest +from set_crafter.backend.spotify_auth import SpotifyAuth +from set_crafter.backend.track_downloader import TrackDownloader + +class TestBackend(unittest.TestCase): + + def setUp(self): + self.spotify_auth = SpotifyAuth() + self.track_downloader = TrackDownloader() + + def test_spotify_auth(self): + response = self.spotify_auth.authenticate() + self.assertEqual(response.status_code, 200) + + def test_track_downloader(self): + track_id = '6rqhFgbbKwnb9MLmUQDhG6' # example track id + track_data = self.track_downloader.download(track_id) + self.assertIsNotNone(track_data) + self.assertEqual(track_data['id'], track_id) + +if __name__ == '__main__': + unittest.main() +``` \ No newline at end of file diff --git a/set_crafter/testing/frontend_tests.py b/set_crafter/testing/frontend_tests.py new file mode 100755 index 0000000..a54e2ca --- /dev/null +++ b/set_crafter/testing/frontend_tests.py @@ -0,0 +1,40 @@ +```python +import unittest +from unittest.mock import patch +from set_crafter.frontend.streamlit_app import SetCrafterApp + +class TestFrontend(unittest.TestCase): + + @patch('streamlit.button') + def test_spotify_auth_button(self, mock_button): + mock_button.return_value = True + app = SetCrafterApp() + self.assertTrue(app.spotify_auth_button()) + + @patch('streamlit.button') + def test_track_download_button(self, mock_button): + mock_button.return_value = True + app = SetCrafterApp() + self.assertTrue(app.track_download_button()) + + @patch('streamlit.button') + def test_data_preprocess_button(self, mock_button): + mock_button.return_value = True + app = SetCrafterApp() + self.assertTrue(app.data_preprocess_button()) + + @patch('streamlit.button') + def test_track_categorize_button(self, mock_button): + mock_button.return_value = True + app = SetCrafterApp() + self.assertTrue(app.track_categorize_button()) + + @patch('streamlit.button') + def test_set_curate_button(self, mock_button): + mock_button.return_value = True + app = SetCrafterApp() + self.assertTrue(app.set_curate_button()) + +if __name__ == '__main__': + unittest.main() +``` \ No newline at end of file diff --git a/shared_dependencies.md b/shared_dependencies.md new file mode 100755 index 0000000..4a65612 --- /dev/null +++ b/shared_dependencies.md @@ -0,0 +1,38 @@ +Shared Dependencies: + +1. **Variables:** + - `spotify_credentials`: Spotify API credentials used in `config.py`, `spotify_auth.py`, and `spotify_data_downloader.py`. + - `track_data`: Data extracted from DJ's library, used in `dj_library_data_extractor.py`, `data_preprocessor.py`, `track_categorizer.py`, and `set_curator.py`. + +2. **Data Schemas:** + - `TrackSchema`: Schema for track data, used in `dj_library_data_extractor.py`, `data_preprocessor.py`, `track_categorizer.py`, and `set_curator.py`. + - `SetSchema`: Schema for curated sets, used in `set_curator.py` and `set_crafter_app.py`. + +3. **Function Names:** + - `extract_data()`: Function in `dj_library_data_extractor.py`, used in `set_crafter_app.py`. + - `preprocess_data()`: Function in `data_preprocessor.py`, used in `set_crafter_app.py`. + - `download_data()`: Function in `spotify_data_downloader.py`, used in `set_crafter_app.py`. + - `categorize_track()`: Function in `track_categorizer.py`, used in `set_crafter_app.py`. + - `curate_set()`: Function in `set_curator.py`, used in `set_crafter_app.py`. + - `build_training_data()`: Function in `model_training_data_builder.py`, used in `track_categorizer.py` and `set_curator.py`. + +4. **Message Names:** + - `AuthenticationSuccess`: Message sent from `spotify_auth.py` to `set_crafter_app.py` upon successful Spotify authentication. + - `DataDownloaded`: Message sent from `spotify_data_downloader.py` to `set_crafter_app.py` upon successful data download. + - `DataPreprocessed`: Message sent from `data_preprocessor.py` to `set_crafter_app.py` upon successful data preprocessing. + - `TrackCategorized`: Message sent from `track_categorizer.py` to `set_crafter_app.py` upon successful track categorization. + - `SetCurated`: Message sent from `set_curator.py` to `set_crafter_app.py` upon successful set curation. + +5. **DOM Element IDs:** + - `spotify-auth-button`: Button for Spotify authentication in `streamlit_app.py`. + - `track-download-button`: Button for track downloading in `streamlit_app.py`. + - `data-preprocess-button`: Button for data preprocessing in `streamlit_app.py`. + - `track-categorize-button`: Button for track categorization in `streamlit_app.py`. + - `set-curate-button`: Button for set curation in `streamlit_app.py`. + +6. **Libraries:** + - `spotipy`: Used in `spotify_auth.py` and `spotify_data_downloader.py`. + - `pandas`: Used in `dj_library_data_extractor.py`, `data_preprocessor.py`, `track_categorizer.py`, and `set_curator.py`. + - `scikit-learn`: Used in `track_categorizer.py` and `set_curator.py`. + - `flask`: Used in `spotify_auth.py` and `flask_deployment.py`. + - `streamlit`: Used in `streamlit_app.py` and `streamlit_deployment.py`. \ No newline at end of file diff --git a/src/.DS_Store b/src/.DS_Store deleted file mode 100644 index 41c1628..0000000 Binary files a/src/.DS_Store and /dev/null differ diff --git a/src/data_preprocessor.py b/src/data_preprocessor.py deleted file mode 100644 index a8787e2..0000000 --- a/src/data_preprocessor.py +++ /dev/null @@ -1,7 +0,0 @@ -import pandas as pd - - -class DataPreprocessor: - def process_data(self, raw_data): - # TODO: Implement the method to process the data for AI model consumption - pass diff --git a/src/dj_library_data_extractor.py b/src/dj_library_data_extractor.py deleted file mode 100644 index 938fc2e..0000000 --- a/src/dj_library_data_extractor.py +++ /dev/null @@ -1,7 +0,0 @@ -import os - - -class DJLibraryDataExtractor: - def extract_data(self, library_path): - # TODO: Implement the method to extract data from a DJ's music library - pass diff --git a/src/model_training_data_builder.py b/src/model_training_data_builder.py deleted file mode 100644 index 5f20a31..0000000 --- a/src/model_training_data_builder.py +++ /dev/null @@ -1,4 +0,0 @@ -class ModelTrainingDataBuilder: - def build_training_dataset(self, preprocessed_data): - # TODO: Implement the method to prepare datasets for training AI models - pass diff --git a/src/set_crafter_app.py b/src/set_crafter_app.py deleted file mode 100644 index ef2a873..0000000 --- a/src/set_crafter_app.py +++ /dev/null @@ -1,7 +0,0 @@ -import streamlit as st - - -class SetCrafterApp: - def run(self): - # TODO: Implement the method to coordinate modules and provide the user interface - pass diff --git a/src/set_curator.py b/src/set_curator.py deleted file mode 100644 index 3b0a2d3..0000000 --- a/src/set_curator.py +++ /dev/null @@ -1,4 +0,0 @@ -class SetCurator: - def curate_set(self, categorized_tracks): - # TODO: Implement the method to curate music sets based on the categorized tracks - pass diff --git a/src/setcrafter_ui.py b/src/setcrafter_ui.py deleted file mode 100644 index 27de9da..0000000 --- a/src/setcrafter_ui.py +++ /dev/null @@ -1,39 +0,0 @@ -import streamlit as st -from dj_library_data_extractor import DJLibraryDataExtractor -from data_preprocessor import DataPreprocessor -from spotify_data_downloader import SpotifyDataDownloader -from track_categorizer import TrackCategorizer -from set_curator import SetCurator - - -def main(): - st.title('SetCrafter AI') - - st.header('Welcome to SetCrafter AI') - st.write('This tool assists DJs in organizing and curating their music libraries with the help of AI.') - - if st.button('Start Categorizing'): - st.write('Categorization process will start.') - # Instantiate the necessary classes - extractor = DJLibraryDataExtractor() - preprocessor = DataPreprocessor() - downloader = SpotifyDataDownloader() - categorizer = TrackCategorizer() - - # Example steps for the categorization process - library_path = st.text_input('Enter your music library path:') - if library_path: - raw_data = extractor.extract_data(library_path) - preprocessed_data = preprocessor.process_data(raw_data) - track_ids = [track['id'] for track in preprocessed_data] - track_data = downloader.download_track_data(track_ids) - categorized_tracks = categorizer.categorize_tracks(track_data) - st.write('Categorization complete!') - - if st.button('Curate Set'): - st.write('Set curation process will start.') - curator = SetCurator() - # TODO: Implement set curation process - -if __name__ == '__main__': - main() diff --git a/src/spotify_data_downloader.py b/src/spotify_data_downloader.py deleted file mode 100644 index b893815..0000000 --- a/src/spotify_data_downloader.py +++ /dev/null @@ -1,8 +0,0 @@ -import spotipy -from spotipy.oauth2 import SpotifyClientCredentials - - -class SpotifyDataDownloader: - def download_track_data(self, track_ids): - # TODO: Implement the method to download track data from Spotify - pass diff --git a/src/spotify_integration.py b/src/spotify_integration.py deleted file mode 100644 index 9973d52..0000000 --- a/src/spotify_integration.py +++ /dev/null @@ -1,12 +0,0 @@ -import spotipy -from spotipy.oauth2 import SpotifyClientCredentials - - -class SpotifyIntegration: - def __init__(self, client_id, client_secret): - client_credentials_manager = SpotifyClientCredentials(client_id=client_id, client_secret=client_secret) - self.sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager) - - def get_track_features(self, track_id): - # TODO: Implement the method to get track features from Spotify - pass diff --git a/src/track_categorizer.py b/src/track_categorizer.py deleted file mode 100644 index 18607f3..0000000 --- a/src/track_categorizer.py +++ /dev/null @@ -1,7 +0,0 @@ -from sklearn.neighbors import KNeighborsClassifier - - -class TrackCategorizer: - def categorize_tracks(self, features): - # TODO: Implement the method to categorize tracks based on their features - pass diff --git a/venv/.DS_Store b/venv/.DS_Store deleted file mode 100644 index d154117..0000000 Binary files a/venv/.DS_Store and /dev/null differ