| | from flask import Flask, render_template, request, jsonify |
| | from flask_cors import CORS |
| | import csv |
| | import io |
| | import os |
| | from werkzeug.utils import secure_filename |
| |
|
| | app = Flask(__name__) |
| | CORS(app) |
| |
|
| | |
| | UPLOAD_FOLDER = '/tmp/uploads' |
| | ALLOWED_EXTENSIONS = {'csv'} |
| |
|
| | if not os.path.exists(UPLOAD_FOLDER): |
| | os.makedirs(UPLOAD_FOLDER) |
| |
|
| | app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER |
| |
|
| | def allowed_file(filename): |
| | return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS |
| |
|
| | def parse_csv_file(file_content): |
| | """Parse CSV content and extract guest information from name and message columns""" |
| | try: |
| | |
| | if isinstance(file_content, bytes): |
| | file_content = file_content.decode('utf-8') |
| | |
| | |
| | csv_file = io.StringIO(file_content) |
| | |
| | |
| | for delimiter in [',', ';', '\t']: |
| | try: |
| | csv_file.seek(0) |
| | reader = csv.DictReader(csv_file, delimiter=delimiter) |
| | |
| | |
| | headers = reader.fieldnames |
| | if not headers or len(headers) < 2: |
| | continue |
| | |
| | |
| | name_column = headers[0] |
| | message_column = headers[1] |
| | |
| | |
| | guests = [] |
| | for i, row in enumerate(reader): |
| | name = row.get(name_column, '').strip() |
| | title = row.get(message_column, '').strip() |
| | |
| | |
| | if name and title: |
| | guests.append({ |
| | 'id': i, |
| | 'name': name, |
| | 'title': title |
| | }) |
| | |
| | if guests: |
| | return {'success': True, 'guests': guests, 'total': len(guests)} |
| | |
| | except Exception as e: |
| | continue |
| | |
| | return {'success': False, 'error': 'Could not parse CSV file. Please ensure it has at least 2 columns (name and message).'} |
| | |
| | except Exception as e: |
| | return {'success': False, 'error': f'Error parsing CSV: {str(e)}'} |
| |
|
| | @app.route('/') |
| | def index(): |
| | return render_template('index.html') |
| |
|
| | @app.route('/upload-csv', methods=['POST']) |
| | def upload_csv(): |
| | """Handle CSV file upload""" |
| | try: |
| | if 'file' not in request.files: |
| | return jsonify({'success': False, 'error': 'No file uploaded'}) |
| | |
| | file = request.files['file'] |
| | |
| | if file.filename == '': |
| | return jsonify({'success': False, 'error': 'No file selected'}) |
| | |
| | if not allowed_file(file.filename): |
| | return jsonify({'success': False, 'error': 'Please upload a CSV file'}) |
| | |
| | |
| | file_content = file.read() |
| | |
| | |
| | result = parse_csv_file(file_content) |
| | |
| | if result['success']: |
| | return jsonify({ |
| | 'success': True, |
| | 'guests': result['guests'], |
| | 'total': result['total'], |
| | 'message': f'Successfully loaded {result["total"]} guests from CSV (filtered out entries with blank names or descriptions)' |
| | }) |
| | else: |
| | return jsonify(result) |
| | |
| | except Exception as e: |
| | return jsonify({'success': False, 'error': f'Upload error: {str(e)}'}) |
| |
|
| | @app.route('/arrange-tables', methods=['POST']) |
| | def arrange_tables(): |
| | data = request.get_json() |
| | selected_guests = data.get('selected_guests', []) |
| | |
| | if not selected_guests: |
| | return jsonify({'success': False, 'error': 'No guests selected for arrangement'}) |
| | |
| | |
| | tables = arrange_guests_into_tables(selected_guests) |
| | |
| | return jsonify({'success': True, 'tables': tables}) |
| |
|
| | def arrange_guests_into_tables(guests): |
| | """Arrange guests into tables of 10 people each with smart distribution""" |
| | if not guests: |
| | return [] |
| | |
| | |
| | categories = { |
| | 'tech': ['engineer', 'developer', 'programmer', 'software', 'tech', 'it', 'data', 'ai', 'ml', 'technology', 'scientist'], |
| | 'business': ['manager', 'director', 'ceo', 'founder', 'executive', 'business', 'strategy', 'operations', 'consultant', 'product'], |
| | 'creative': ['designer', 'creative', 'marketing', 'content', 'writer', 'artist', 'media', 'communications', 'strategist'], |
| | 'sales': ['sales', 'account', 'client', 'business development', 'partnership', 'account manager'], |
| | 'finance': ['finance', 'accounting', 'investment', 'banking', 'financial', 'analyst', 'cfo'], |
| | 'other': [] |
| | } |
| | |
| | categorized_guests = {cat: [] for cat in categories.keys()} |
| | |
| | |
| | for guest in guests: |
| | title_lower = guest['title'].lower() |
| | categorized = False |
| | |
| | for category, keywords in categories.items(): |
| | if category == 'other': |
| | continue |
| | if any(keyword in title_lower for keyword in keywords): |
| | categorized_guests[category].append(guest) |
| | categorized = True |
| | break |
| | |
| | if not categorized: |
| | categorized_guests['other'].append(guest) |
| | |
| | |
| | total_guests = len(guests) |
| | num_tables = (total_guests + 9) // 10 |
| | |
| | |
| | tables = [[] for _ in range(num_tables)] |
| | |
| | |
| | |
| | major_categories = ['tech', 'business', 'creative', 'sales'] |
| | |
| | for category in major_categories: |
| | guests_in_category = categorized_guests[category] |
| | if guests_in_category: |
| | |
| | for i, guest in enumerate(guests_in_category): |
| | table_index = i % num_tables |
| | if len(tables[table_index]) < 10: |
| | tables[table_index].append(guest) |
| | |
| | |
| | remaining_guests = [] |
| | for category in ['finance', 'other']: |
| | remaining_guests.extend(categorized_guests[category]) |
| | |
| | |
| | for table in tables: |
| | for guest in guests: |
| | if guest not in [g for table_guests in tables for g in table_guests]: |
| | if len(table) < 10: |
| | table.append(guest) |
| | break |
| | |
| | |
| | for guest in guests: |
| | if guest not in [g for table_guests in tables for g in table_guests]: |
| | for table in tables: |
| | if len(table) < 10: |
| | table.append(guest) |
| | break |
| | |
| | return tables |
| |
|
| | if __name__ == '__main__': |
| | app.run(host='0.0.0.0', port=5000) |