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