CoolFace
Apppublic

Dev9893/encoder

sourceHugging Facemitupdated 1y agoView on Hugging Face
0likes
app.py1679 linesDownload Raw Back to root
1import streamlit as st2import json3import os4import numpy as np5from sklearn.metrics.pairwise import cosine_similarity6import re7from datetime import datetime, date, timedelta8import pandas as pd9from PIL import Image10import plotly.express as px11import plotly.graph_objects as go12import random13 14# Configuration15st.set_page_config(16    page_title="HackMate - CYHI Quick Teams",17    page_icon="โšก",18    layout="wide",19    initial_sidebar_state="expanded"20)21 22# Custom CSS for better styling23st.markdown("""24<style>25    .main-header {26        background: linear-gradient(90deg, #667eea 0%, #764ba2 100%);27        padding: 2rem 1rem;28        border-radius: 10px;29        color: white;30        text-align: center;31        margin-bottom: 2rem;32    }33    .profile-card {34        background: #1a1a2e;35        padding: 1.5rem;36        border-radius: 15px;37        box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);38        border-left: 5px solid #667eea;39        margin: 1rem 0;40        color: white;41    }42    .team-card {43        background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);44        padding: 1.5rem;45        border-radius: 15px;46        color: white;47        margin: 1rem 0;48        position: relative;49        overflow: hidden;50    }51    .team-card::before {52        content: '';53        position: absolute;54        top: -50%;55        left: -50%;56        width: 200%;57        height: 200%;58        background: radial-gradient(circle, rgba(255,255,255,0.1) 0%, transparent 70%);59        animation: pulse 3s ease-in-out infinite;60    }61    @keyframes pulse {62        0%, 100% { transform: scale(1); opacity: 0.5; }63        50% { transform: scale(1.1); opacity: 0.8; }64    }65    .quick-match-card {66        background: linear-gradient(45deg, #ff6b6b, #feca57);67        padding: 1rem;68        border-radius: 10px;69        color: white;70        text-align: center;71        margin: 0.5rem 0;72    }73    .skill-badge {74        display: inline-block;75        background: #667eea;76        color: white;77        padding: 0.3rem 0.8rem;78        border-radius: 20px;79        margin: 0.2rem;80        font-size: 0.8rem;81    }82    .urgent-badge {83        background: #ff4757 !important;84        animation: blink 1s infinite;85    }86    @keyframes blink {87        0%, 50% { opacity: 1; }88        51%, 100% { opacity: 0.5; }89    }90    .metric-card {91        background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);92        padding: 1rem;93        border-radius: 10px;94        color: white;95        text-align: center;96    }97    .score-badge {98        display: inline-block;99        padding: 0.5rem 1rem;100        border-radius: 20px;101        color: white;102        font-weight: bold;103        margin: 0.2rem;104        font-size: 0.9rem;105    }106    .score-excellent { background: #2ecc71; }107    .score-good { background: #f39c12; }108    .score-average { background: #e67e22; }109    .score-poor { background: #e74c3c; }110    .single-score-card {111        background: #2c2c54;112        border: 2px solid #667eea;113        border-radius: 15px;114        padding: 1rem;115        margin: 0.5rem 0;116        color: white;117        text-align: center;118    }119    .stButton > button {120        background: linear-gradient(90deg, #667eea 0%, #764ba2 100%);121        color: white;122        border-radius: 25px;123        border: none;124        padding: 0.5rem 2rem;125        font-weight: bold;126        transition: all 0.3s;127    }128    .stButton > button:hover {129        transform: translateY(-2px);130        box-shadow: 0 4px 8px rgba(0,0,0,0.2);131    }132    /* Remove white backgrounds globally */133    .stApp {134        background-color: #0f0f1a;135    }136    .main .block-container {137        background-color: transparent;138    }139    div[data-testid="stVerticalBlock"] > div {140        background-color: transparent;141    }142    .element-container {143        background-color: transparent;144    }145    .pending-request {146        background: linear-gradient(45deg, #ff9a3c, #ff6b6b) !important;147        border-left: 5px solid #ff9a3c;148    }149    .accepted-request {150        background: linear-gradient(45deg, #2ecc71, #27ae60) !important;151        border-left: 5px solid #2ecc71;152    }153    .rejected-request {154        background: linear-gradient(45deg, #e74c3c, #c0392b) !important;155        border-left: 5px solid #e74c3c;156    }157</style>158""", unsafe_allow_html=True)159 160# File paths161CATEGORIES_FILE = 'categories.json'162USERS_FILE = 'users.json'163TEAMS_FILE = 'teams.json'164QUICK_TEAMS_FILE = 'quick_teams.json'165HACKATHONS_FILE = 'hackathons.json'166TEAM_REQUESTS_FILE = 'team_requests.json'167UPLOAD_DIR = 'src'168 169# Create upload directory if it doesn't exist170if not os.path.exists(UPLOAD_DIR):171    os.makedirs(UPLOAD_DIR)172 173# Initialize session state174if 'show_instant_match' not in st.session_state:175    st.session_state['show_instant_match'] = False176if 'show_create_team' not in st.session_state:177    st.session_state['show_create_team'] = False178if 'selected_team' not in st.session_state:179    st.session_state['selected_team'] = None180 181def load_json(file_path):182    """Load JSON data from file with error handling"""183    try:184        if os.path.exists(file_path):185            with open(file_path, 'r', encoding='utf-8') as f:186                return json.load(f)187        else:188            return {}189    except Exception as e:190        st.error(f"Error loading {file_path}: {str(e)}")191        return {}192 193def save_json(file_path, data):194    """Save JSON data to file with error handling"""195    try:196        with open(file_path, 'w', encoding='utf-8') as f:197            json.dump(data, f, indent=4, ensure_ascii=False)198    except Exception as e:199        st.error(f"Error saving {file_path}: {str(e)}")200 201def add_user_profile(profile):202    """Add user profile to the database"""203    users = load_json(USERS_FILE)204    users[profile['name']] = profile205    save_json(USERS_FILE, users)206 207def get_all_users():208    """Get all user profiles"""209    users = load_json(USERS_FILE)210    return list(users.values())211 212def save_team(team_data):213    """Save team data"""214    teams = load_json(TEAMS_FILE)215    team_id = f"team_{len(teams) + 1}_{datetime.now().strftime('%Y%m%d%H%M%S')}"216    teams[team_id] = team_data217    save_json(TEAMS_FILE, teams)218    return team_id219 220def get_all_teams():221    """Get all teams"""222    teams = load_json(TEAMS_FILE)223    return list(teams.values())224 225def save_quick_team(quick_team_data):226    """Save quick team data"""227    quick_teams = load_json(QUICK_TEAMS_FILE)228    team_id = f"quick_{len(quick_teams) + 1}_{datetime.now().strftime('%Y%m%d%H%M%S')}"229    quick_teams[team_id] = quick_team_data230    save_json(QUICK_TEAMS_FILE, quick_teams)231    return team_id232 233def get_quick_teams():234    """Get all quick teams"""235    quick_teams = load_json(QUICK_TEAMS_FILE)236    return list(quick_teams.values())237 238def get_team_requests():239    """Get all team requests"""240    return load_json(TEAM_REQUESTS_FILE)241 242def save_team_request(request_data):243    """Save a team request"""244    requests = get_team_requests()245    request_id = f"request_{len(requests) + 1}_{datetime.now().strftime('%Y%m%d%H%M%S')}"246    requests[request_id] = request_data247    save_json(TEAM_REQUESTS_FILE, requests)248    return request_id249 250def update_team_request(request_id, updates):251    """Update a team request"""252    requests = get_team_requests()253    if request_id in requests:254        requests[request_id].update(updates)255        save_json(TEAM_REQUESTS_FILE, requests)256        return True257    return False258 259def get_user_team_requests(username):260    """Get all team requests for a specific user"""261    requests = get_team_requests()262    user_requests = []263    264    for req_id, req_data in requests.items():265        if req_data.get('to_user') == username or req_data.get('from_user') == username:266            user_requests.append((req_id, req_data))267    268    return user_requests269 270def get_team_by_id(team_id):271    """Get a specific team by ID"""272    teams = load_json(TEAMS_FILE)273    return teams.get(team_id)274 275def update_team(team_id, updates):276    """Update a team"""277    teams = load_json(TEAMS_FILE)278    if team_id in teams:279        teams[team_id].update(updates)280        save_json(TEAMS_FILE, teams)281        return True282    return False283 284# ML Skillset Enhancer Functions285def vectorize_profiles(profiles, all_skills):286    """Convert profiles to vector representation based on skills"""287    matrix = []288    for p in profiles:289        skills_lower = [s.lower() for s in p.get('skills', [])]290        row = [1 if skill in skills_lower else 0 for skill in all_skills]291        matrix.append(row)292    return np.array(matrix)293 294def find_best_matches(user_profile, profiles, top_k=5):295    """Find best matches using cosine similarity"""296    all_skills = set()297    for p in profiles:298        all_skills.update([s.lower() for s in p.get('skills', [])])299    all_skills.update([s.lower() for s in user_profile.get('skills', [])])300    all_skills = sorted(list(all_skills))301 302    if not all_skills:303        return []304 305    try:306        matrix = vectorize_profiles(profiles, all_skills)307        user_vec = np.array([[1 if s in [sk.lower() for sk in user_profile.get('skills', [])] else 0 for s in all_skills]])308 309        if matrix.size > 0 and user_vec.size > 0:310            sims = cosine_similarity(user_vec, matrix)[0]311            idx_sim = sorted([(i, s) for i, s in enumerate(sims) if s < 0.999], key=lambda x: x[1], reverse=True)[:top_k]312 313            user_avail = set(user_profile.get('availability', []))314            matches = []315            for idx, sim in idx_sim:316                if idx < len(profiles):317                    candidate = profiles[idx]318                    cand_avail = set(candidate.get('availability', []))319                    # Check overlapping availability320                    if user_avail and cand_avail and user_avail.isdisjoint(cand_avail):321                        continue322                    matches.append((candidate, sim))323            return matches324    except Exception as e:325        st.error(f"Error in finding matches: {str(e)}")326        return []327    328    return []329 330def analyze_fit(cat_sel, dom_sel, selected_skills, categories):331    """Analyze skill fit for a specific domain"""332    if not categories or cat_sel not in categories or dom_sel not in categories[cat_sel]['domains']:333        return None334 335    domain_skills = set(s.lower() for s in categories[cat_sel]['domains'][dom_sel])336    user_skills = set(s.lower() for s in selected_skills)337 338    matched = user_skills.intersection(domain_skills)339    missing = domain_skills.difference(user_skills)340 341    max_score = max(len(domain_skills), 10)342    score = min(100, (len(matched) / max_score) * 100) if max_score > 0 else 0343 344    if score >= 80:345        rec = "Excellent fit! Strong skills for this role."346    elif score >= 60:347        rec = f"Good fit; consider improving missing skills: {', '.join(list(missing)[:3])}"348    elif score >= 40:349        rec = f"Moderate fit; focus on acquiring key skills: {', '.join(list(missing)[:3])}"350    else:351        rec = f"Low fit; strongly recommend gaining these skills: {', '.join(list(missing)[:3])}"352 353    return {354        "score": score,355        "matched": matched,356        "missing": missing,357        "recommendation": rec,358    }359 360def calculate_domain_scores(user_profile, categories):361    """Calculate domain match scores for a user"""362    user_skills = set(skill.lower() for skill in user_profile.get('skills', []))363    domain_scores = {}364    365    for cat, cat_info in categories.items():366        for domain, skills in cat_info.get("domains", {}).items():367            domain_skills = set(skill.lower() for skill in skills)368            if domain_skills:369                matched = user_skills.intersection(domain_skills)370                score = (len(matched) / len(domain_skills)) * 100371                domain_scores[domain] = {372                    'score': score,373                    'matched': matched,374                    'missing': domain_skills - user_skills,375                    'category': cat376                }377    378    return domain_scores379 380def get_score_class(score):381    """Get CSS class for score badge"""382    if score >= 80:383        return "score-excellent"384    elif score >= 60:385        return "score-good"386    elif score >= 40:387        return "score-average"388    else:389        return "score-poor"390 391def get_score_label(score):392    """Get label for score"""393    if score >= 80:394        return "Excellent"395    elif score >= 60:396        return "Good"397    elif score >= 40:398        return "Average"399    else:400        return "Needs Work"401 402def display_profile_card_with_scores(user, categories, show_scores=True, role=None):403    """Display a profile card with single domain score"""404    with st.container():405        role_emoji = {"Team Lead": "๐Ÿ‘‘", "Tech Lead": "๐Ÿš€", "Designer": "๐ŸŽจ", "Backend Dev": "โš™", 406                     "Frontend Dev": "๐Ÿ’ป", "Data Specialist": "๐Ÿ“Š", "Business Analyst": "๐Ÿ“ˆ"}.get(role, "๐Ÿ‘ค")407        408        col1, col2 = st.columns([3, 1])409        410        with col1:411            st.markdown(f"""412            <div class="profile-card">413                <h3>{role_emoji} {user['name']} {f"({role})" if role else ""}</h3>414                <p><strong>๐Ÿ“ Bio:</strong> {user.get('bio', 'Ready to hack!')[:100]}...</p>415                <p><strong>๐ŸŽฏ Domain:</strong> {', '.join(user.get('domain', ['General']))}</p>416                <p><strong>๐Ÿ“ˆ Experience:</strong> {user.get('experience_level', 'Intermediate')}</p>417                <p><strong>โฐ Availability:</strong> {', '.join(user.get('availability', ['Flexible']))}</p>418            </div>419            """, unsafe_allow_html=True)420            421            # Skills as badges422            if user.get('skills'):423                skills_html = ""424                for skill in user['skills'][:8]:  # Limit to 8 skills for display425                    skills_html += f'<span class="skill-badge">{skill}</span>'426                if len(user['skills']) > 8:427                    skills_html += f'<span class="skill-badge">+{len(user["skills"]) - 8} more</span>'428                st.markdown(skills_html, unsafe_allow_html=True)429        430        with col2:431            if show_scores and categories:432                domain_scores = calculate_domain_scores(user, categories)433                434                if domain_scores:435                    # Get the highest scoring domain only436                    best_domain, best_data = max(domain_scores.items(), key=lambda x: x[1]['score'])437                    score = best_data['score']438                    score_class = get_score_class(score)439                    score_label = get_score_label(score)440                    441                    st.markdown(f"""442                    <div class="single-score-card">443                        <h4>๐ŸŽฏ Best Match</h4>444                        <strong>{best_domain}</strong><br>445                        <span class="score-badge {score_class}">{score:.0f}% - {score_label}</span>446                    </div>447                    """, unsafe_allow_html=True)448 449def create_instant_team_match(user_profile, hackathon_context=None):450    """Create instant team matches based on complementary skills and hackathon needs"""451    users = get_all_users()452    453    if len(users) < 2:454        return None455    456    user_skills = set(s.lower() for s in user_profile.get('skills', []))457    matches = []458    459    for candidate in users:460        if candidate['name'] == user_profile['name']:461            continue462            463        candidate_skills = set(s.lower() for s in candidate.get('skills', []))464        465        # Calculate complementary score (different skills are better for teams)466        complement_score = len(user_skills.symmetric_difference(candidate_skills))467        overlap_penalty = len(user_skills.intersection(candidate_skills)) * 0.5468        469        # Availability match470        user_avail = set(user_profile.get('availability', []))471        cand_avail = set(candidate.get('availability', []))472        avail_score = len(user_avail.intersection(cand_avail)) if user_avail and cand_avail else 0.5473        474        # Experience diversity bonus475        exp_levels = {"Beginner": 1, "Intermediate": 2, "Advanced": 3, "Expert": 4}476        user_exp = exp_levels.get(user_profile.get('experience_level', 'Intermediate'), 2)477        cand_exp = exp_levels.get(candidate.get('experience_level', 'Intermediate'), 2)478        exp_diversity = abs(user_exp - cand_exp) * 0.3  # Reward diversity479        480        total_score = complement_score + avail_score * 2 + exp_diversity - overlap_penalty481        482        if total_score > 0:483            matches.append((candidate, total_score))484    485    matches.sort(key=lambda x: x[1], reverse=True)486    return matches[:3]  # Return top 3 matches487 488def generate_team_roles(team_members, hackathon_theme=None):489    """Generate optimal role assignments for team members"""490    roles = {491        'Team Lead': {'skills': ['leadership', 'project management', 'communication'], 'assigned': None},492        'Tech Lead': {'skills': ['programming', 'software development', 'architecture'], 'assigned': None},493        'Designer': {'skills': ['ui/ux', 'design', 'figma', 'adobe', 'graphics'], 'assigned': None},494        'Backend Dev': {'skills': ['python', 'java', 'node.js', 'database', 'api'], 'assigned': None},495        'Frontend Dev': {'skills': ['react', 'javascript', 'html', 'css', 'vue'], 'assigned': None},496        'Data Specialist': {'skills': ['data science', 'machine learning', 'analytics', 'sql'], 'assigned': None},497        'Business Analyst': {'skills': ['business', 'strategy', 'marketing', 'finance'], 'assigned': None}498    }499    500    # Score each member for each role501    for role, role_info in roles.items():502        best_score = 0503        best_member = None504        505        for member in team_members:506            member_skills = [s.lower() for s in member.get('skills', [])]507            score = sum(1 for skill in role_info['skills'] if any(skill in ms for ms in member_skills))508            509            # Bonus for experience level510            exp_bonus = {'Expert': 3, 'Advanced': 2, 'Intermediate': 1, 'Beginner': 0.5}511            score += exp_bonus.get(member.get('experience_level', 'Intermediate'), 1)512            513            if score > best_score:514                best_score = score515                best_member = member516        517        if best_member:518            roles[role]['assigned'] = best_member['name']519            roles[role]['score'] = best_score520    521    return roles522 523def calculate_team_compatibility(members):524    """Calculate overall team compatibility score"""525    if len(members) < 2:526        return 0527    528    # Skill diversity score529    all_skills = set()530    for member in members:531        all_skills.update(s.lower() for s in member.get('skills', []))532    533    total_skills = sum(len(member.get('skills', [])) for member in members)534    skill_diversity = len(all_skills) / (total_skills + 1) if total_skills > 0 else 0535    536    # Experience level balance537    exp_levels = [member.get('experience_level', 'Intermediate') for member in members]538    exp_variety = len(set(exp_levels)) / len(exp_levels) if exp_levels else 0539    540    # Availability overlap541    avail_sets = [set(member.get('availability', [])) for member in members if member.get('availability')]542    if avail_sets:543        common_avail = set.intersection(*avail_sets) if len(avail_sets) > 1 else avail_sets[0]544        avail_score = len(common_avail) / 5  # Assuming max 5 availability options545    else:546        avail_score = 0.5547    548    # Domain diversity549    domains = set()550    for member in members:551        domains.update(member.get('domain', []))552    domain_diversity = len(domains) / len(members) if members else 0553    554    total_score = (skill_diversity * 0.4 + exp_variety * 0.2 + avail_score * 0.2 + domain_diversity * 0.2) * 100555    return min(100, total_score)556 557def show_browse_users_with_ml():558    """Enhanced user browsing with ML-powered domain scoring - FIXED VERSION"""559    st.markdown("## ๐Ÿ‘ฅ Browse Hackers with Smart Matching")560    561    users = get_all_users()562    categories = load_json(CATEGORIES_FILE)563    564    if not users:565        st.info("No users registered yet. Be the first!")566        return567    568    # Enhanced filters with ML features569    col1, col2, col3, col4 = st.columns(4)570    571    with col1:572        available_now = st.checkbox("โšก Available Now", help="Show only users available for immediate team formation")573    574    with col2:575        experience_filter = st.selectbox("๐Ÿ“ˆ Min Experience", ["Any", "Beginner", "Intermediate", "Advanced", "Expert"])576    577    with col3:578        all_domains = set()579        for user in users:580            all_domains.update(user.get('domain', []))581        domain_filter = st.selectbox("๐ŸŽฏ Domain Filter", ["Any"] + sorted(list(all_domains)))582    583    with col4:584        min_domain_score = st.slider("๐ŸŽฏ Min Domain Score", 0, 100, 0, help="Minimum domain match score")585    586    # Domain-based matching587    search_domain = ""588    if categories:589        st.markdown("### ๐Ÿค– Domain-Based Smart Search")590        col1, col2 = st.columns(2)591        592        with col1:593            search_category = st.selectbox("Search by Category", [""] + list(categories.keys()))594        595        with col2:596            if search_category:597                domain_options = list(categories[search_category].get("domains", {}).keys())598                search_domain = st.selectbox("Search by Domain", [""] + domain_options)599    600    # Apply filters601    filtered_users = users.copy()602    603    if available_now:604        filtered_users = [u for u in filtered_users if 'Flexible' in u.get('availability', []) or 'Right Now' in u.get('availability', [])]605    606    if experience_filter != "Any":607        filtered_users = [u for u in filtered_users if u.get('experience_level') == experience_filter]608    609    if domain_filter != "Any":610        filtered_users = [u for u in filtered_users if domain_filter in u.get('domain', [])]611    612    # Filter by domain score if ML search is active613    if categories and search_domain and min_domain_score > 0:614        scored_users = []615        for user in filtered_users:616            domain_scores = calculate_domain_scores(user, categories)617            if search_domain in domain_scores and domain_scores[search_domain]['score'] >= min_domain_score:618                scored_users.append((user, domain_scores[search_domain]['score']))619        620        # Sort by domain score621        scored_users.sort(key=lambda x: x[1], reverse=True)622        filtered_users = [user for user, score in scored_users]623    624    # Display results625    st.markdown(f"### ๐Ÿ‘ฅ {len(filtered_users)} Hackers Found")626    627    if search_domain and categories:628        st.info(f"๐ŸŽฏ Showing users ranked by {search_domain} domain expertise")629    630    for i, user in enumerate(filtered_users):631        col1, col2 = st.columns([4, 1])632        633        with col1:634            # Show domain score for searched domain only if searching635            if search_domain and categories:636                domain_scores = calculate_domain_scores(user, categories)637                if search_domain in domain_scores:638                    score = domain_scores[search_domain]['score']639                    score_class = get_score_class(score)640                    score_label = get_score_label(score)641                    st.markdown(f"""642                    <div style="margin-bottom: 1rem;">643                        <strong>๐ŸŽฏ {search_domain} Match:</strong>644                        <span class="score-badge {score_class}">{score:.0f}% - {score_label}</span>645                    </div>646                    """, unsafe_allow_html=True)647            648            display_profile_card_with_scores(user, categories, show_scores=True)649        650        with col2:651            st.markdown("<br><br>", unsafe_allow_html=True)652            if st.button(f"โšก Quick Team", key=f"qt_{user['name']}_{i}", help="Form instant team with this user"):653                # Simulate quick team formation654                matches = create_instant_team_match(user)655                if matches:656                    st.success(f"โœ… Team formed with {user['name']}!")657                    # Store the team formation658                    team_data = {659                        'name': f"QuickTeam_{datetime.now().strftime('%H%M%S')}",660                        'members': [user] + [match[0] for match in matches[:2]],661                        'formation_time': datetime.now().strftime('%H:%M:%S'),662                        'compatibility': calculate_team_compatibility([user] + [match[0] for match in matches[:2]]),663                        'type': 'instant_match'664                    }665                    save_quick_team(team_data)666                else:667                    st.warning("No immediate matches found")668            669            if st.button(f"๐Ÿ’ฌ Contact", key=f"contact_{user['name']}_{i}"):670                st.info(f"Contact request sent to {user['name']}")671            672            if st.button(f"๐Ÿ“Š View All Scores", key=f"scores_{user['name']}_{i}", help="View detailed domain scores"):673                with st.expander(f"{user['name']}'s All Domain Scores", expanded=True):674                    if categories:675                        domain_scores = calculate_domain_scores(user, categories)676                        677                        if domain_scores:678                            # Show top 5 domains only679                            sorted_domains = sorted(domain_scores.items(), key=lambda x: x[1]['score'], reverse=True)[:5]680                            681                            for domain, data in sorted_domains:682                                score = data['score']683                                score_class = get_score_class(score)684                                score_label = get_score_label(score)685                                686                                st.markdown(f"""687                                <div style="background: #2c2c54; padding: 0.8rem; border-radius: 10px; margin: 0.3rem 0; color: white;">688                                    <strong>{domain}</strong> ({data['category']})<br>689                                    <span class="score-badge {score_class}">{score:.0f}% - {score_label}</span>690                                    <br><small>{len(data['matched'])} matched skills, {len(data['missing'])} missing</small>691                                </div>692                                """, unsafe_allow_html=True)693 694def show_group_management():695    """Manage groups and categories"""696    st.markdown("## ๐Ÿข Group & Category Management")697    698    categories = load_json(CATEGORIES_FILE)699    if not categories:700        categories = {}701    702    tab1, tab2 = st.tabs(["๐Ÿ“‹ View Groups", "โž• Add New Group"])703    704    with tab1:705        st.markdown("### Existing Groups & Categories")706        707        if not categories:708            st.info("No groups created yet. Add some groups to get started!")709        else:710            for category, cat_info in categories.items():711                with st.expander(f"๐Ÿ“ {category}"):712                    if "domains" in cat_info:713                        for domain, skills in cat_info["domains"].items():714                            st.markdown(f"**{domain}**")715                            st.write(f"Skills: {', '.join(skills)}")716                            if st.button(f"Delete {domain}", key=f"del_{category}_{domain}"):717                                if category in categories and domain in categories[category]["domains"]:718                                    del categories[category]["domains"][domain]719                                    if not categories[category]["domains"]:720                                        del categories[category]721                                    save_json(CATEGORIES_FILE, categories)722                                    st.success(f"Deleted {domain} from {category}")723                                    st.rerun()724    725    with tab2:726        st.markdown("### Add New Group or Category")727        728        with st.form("group_form"):729            new_cat = st.text_input("New Group Type (Category)", max_chars=50)730            new_dom = st.text_input("New Domain/Subgroup", max_chars=50)731            new_sk = st.text_area("Skills (comma separated)")732            subm = st.form_submit_button("Add Group")733            734            if subm:735                if not (new_cat and new_dom):736                    st.warning("Category and domain are required.")737                else:738                    new_cat = new_cat.strip()739                    new_dom = new_dom.strip()740                    sk_list = [s.strip() for s in new_sk.split(",") if s.strip()]741                    742                    if new_cat not in categories:743                        categories[new_cat] = {"domains": {}}744                    745                    if new_dom in categories[new_cat]["domains"]:746                        st.warning(f"Domain '{new_dom}' already exists in '{new_cat}'.")747                    else:748                        categories[new_cat]["domains"][new_dom] = sk_list749                        save_json(CATEGORIES_FILE, categories)750                        st.success(f"Added '{new_dom}' under '{new_cat}'.")751 752def show_create_team_form():753    """Form to create a new team"""754    st.markdown("## ๐Ÿš€ Create a New Team")755    756    users = get_all_users()757    if not users:758        st.warning("No users available to form a team. Create profiles first!")759        return760    761    with st.form("create_team_form"):762        team_name = st.text_input("Team Name", placeholder="Awesome Hackers Team")763        team_description = st.text_area("Team Description", placeholder="What's your team's mission?")764        765        col1, col2 = st.columns(2)766        with col1:767            target_size = st.slider("Target Team Size", 2, 8, 4)768            focus_area = st.selectbox("Primary Focus Area", 769                                    ["Web Development", "Mobile App", "AI/ML", "Data Science", 770                                     "IoT", "Blockchain", "Game Development", "Open Choice"])771        with col2:772            project_type = st.selectbox("Project Type", 773                                      ["New Idea", "Existing Project", "Open Source Contribution", "Research"])774            hackathon_name = st.text_input("Hackathon Name (if applicable)", placeholder="e.g., Hack the North")775        776        # Team members selection777        st.markdown("### ๐Ÿ‘ฅ Select Team Members")778        available_members = [user for user in users]779        selected_members = st.multiselect("Choose team members", 780                                         [user['name'] for user in available_members],781                                         help="Select other hackers to join your team")782        783        # Privacy settings784        st.markdown("### ๐Ÿ”’ Team Privacy")785        col1, col2 = st.columns(2)786        with col1:787            team_privacy = st.selectbox("Team Visibility", 788                                      ["Public - Anyone can join", 789                                       "Private - Approval required", 790                                       "Invite only"])791        with col2:792            application_required = st.checkbox("Require application", value=True)793        794        submitted = st.form_submit_button("๐Ÿš€ Create Team", use_container_width=True)795        796        if submitted:797            if not team_name:798                st.error("Team name is required!")799                return800            801            if not selected_members:802                st.error("Please select at least one team member!")803                return804            805            # Get full user objects for selected members806            team_members = []807            for member_name in selected_members:808                member = next((u for u in users if u['name'] == member_name), None)809                if member:810                    team_members.append(member)811            812            # Create team data813            team_data = {814                'name': team_name,815                'description': team_description,816                'members': team_members,817                'target_size': target_size,818                'focus_area': focus_area,819                'project_type': project_type,820                'hackathon_name': hackathon_name,821                'privacy': team_privacy,822                'application_required': application_required,823                'created_date': datetime.now().strftime("%Y-%m-%d %H:%M:%S"),824                'status': 'active',825                'compatibility': calculate_team_compatibility(team_members)826            }827            828            # Save team829            team_id = save_team(team_data)830            st.success(f"โœ… Team '{team_name}' created successfully!")831            832            # Send join requests to selected members if private team833            if team_privacy != "Public - Anyone can join":834                for member in team_members:835                    request_data = {836                        'team_id': team_id,837                        'team_name': team_name,838                        'from_user': "System",  # Or the creator's name if available839                        'to_user': member['name'],840                        'status': 'pending',841                        'message': f"You've been invited to join {team_name}",842                        'timestamp': datetime.now().strftime("%Y-%m-%d %H:%M:%S")843                    }844                    save_team_request(request_data)845                846                st.info("๐Ÿ“จ Join requests sent to selected members!")847            848            st.session_state['show_create_team'] = False849 850def show_team_requests(username):851    """Show team requests for a user"""852    st.markdown("## ๐Ÿ“จ Team Requests")853    854    user_requests = get_user_team_requests(username)855    if not user_requests:856        st.info("You don't have any team requests yet.")857        return858    859    pending_requests = [(req_id, req) for req_id, req in user_requests if req.get('status') == 'pending']860    accepted_requests = [(req_id, req) for req_id, req in user_requests if req.get('status') == 'accepted']861    rejected_requests = [(req_id, req) for req_id, req in user_requests if req.get('status') == 'rejected']862    863    if pending_requests:864        st.markdown("### โณ Pending Requests")865        for req_id, request in pending_requests:866            status_class = "pending-request"867            st.markdown(f"""868            <div class="profile-card {status_class}">869                <h3>๐Ÿ‘ฅ {request.get('team_name', 'Unknown Team')}</h3>870                <p><strong>From:</strong> {request.get('from_user', 'Unknown')}</p>871                <p><strong>Message:</strong> {request.get('message', 'No message')}</p>872                <p><strong>Date:</strong> {request.get('timestamp', 'Unknown')}</p>873            </div>874            """, unsafe_allow_html=True)875            876            col1, col2 = st.columns(2)877            with col1:878                if st.button(f"โœ… Accept", key=f"accept_{req_id}"):879                    update_team_request(req_id, {'status': 'accepted'})880                    st.success("Request accepted!")881                    st.rerun()882            with col2:883                if st.button(f"โŒ Reject", key=f"reject_{req_id}"):884                    update_team_request(req_id, {'status': 'rejected'})885                    st.info("Request rejected.")886                    st.rerun()887    888    if accepted_requests:889        st.markdown("### โœ… Accepted Requests")890        for req_id, request in accepted_requests:891            status_class = "accepted-request"892            st.markdown(f"""893            <div class="profile-card {status_class}">894                <h3>๐Ÿ‘ฅ {request.get('team_name', 'Unknown Team')}</h3>895                <p><strong>From:</strong> {request.get('from_user', 'Unknown')}</p>896                <p><strong>Status:</strong> Accepted</p>897                <p><strong>Date:</strong> {request.get('timestamp', 'Unknown')}</p>898            </div>899            """, unsafe_allow_html=True)900    901    if rejected_requests:902        st.markdown("### โŒ Rejected Requests")903        for req_id, request in rejected_requests:904            status_class = "rejected-request"905            st.markdown(f"""906            <div class="profile-card {status_class}">907                <h3>๐Ÿ‘ฅ {request.get('team_name', 'Unknown Team')}</h3>908                <p><strong>From:</strong> {request.get('from_user', 'Unknown')}</p>909                <p><strong>Status:</strong> Rejected</p>910                <p><strong>Date:</strong> {request.get('timestamp', 'Unknown')}</p>911            </div>912            """, unsafe_allow_html=True)913 914def main():915    # Header with CYHI branding916    st.markdown("""917    <div class="main-header">918        <h1>โšก HackMate - CYHI Quick Teams</h1>919        <p>Capture Your Hackathon Idea & Find Your Perfect Team in Minutes!</p>920    </div>921    """, unsafe_allow_html=True)922 923    # Load or create sample data924    categories = load_json(CATEGORIES_FILE)925    if not categories:926        categories = create_sample_categories()927 928    # Navigation929    st.sidebar.markdown("## โšก Quick Actions")930    931    if st.sidebar.button("๐Ÿš€ INSTANT TEAM MATCH", help="Get matched with a team in under 60 seconds!"):932        st.session_state['show_instant_match'] = True933    934    st.sidebar.markdown("---")935    st.sidebar.markdown("## ๐Ÿงญ Navigation")936    937    page = st.sidebar.radio("Choose your action:", 938                           ["๐Ÿ  Home", "โšก Quick Teams", "๐Ÿ‘ค Create Profile", "๐Ÿ” Find/Create Teams", 939                            "๐Ÿ“Š Team Analytics", "๐Ÿ‘ฅ Smart Browse", "๐Ÿข Group Management", "๐Ÿ“จ My Requests"])940 941    if page == "๐Ÿ  Home":942        show_home_page()943    elif page == "โšก Quick Teams":944        show_quick_teams_page()945    elif page == "๐Ÿ‘ค Create Profile":946        show_create_profile_page(categories)947    elif page == "๐Ÿ” Find Teams":948        show_find_teams_page()949    elif page == "๐Ÿ“Š Team Analytics":950        show_team_analytics_page()951    elif page == "๐Ÿ‘ฅ Smart Browse":952        show_browse_users_with_ml()953    elif page == "๐Ÿข Group Management":954        show_group_management()955    elif page == "๐Ÿ“จ My Requests":956        # Get current user (for demo, using first user)957        users = get_all_users()958        if users:959            show_team_requests(users[0]['name'])960        else:961            st.info("No users found. Create a profile first!")962    963    # Handle instant team matching964    if st.session_state.get('show_instant_match', False):965        show_instant_team_match()966 967def show_home_page():968    """Enhanced home page with quick team stats"""969    col1, col2, col3, col4 = st.columns(4)970    971    users = get_all_users()972    teams = get_all_teams()973    quick_teams = get_quick_teams()974    975    with col1:976        st.markdown(f"""977        <div class="metric-card">978            <h2>๐Ÿ‘ฅ</h2>979            <h3>{len(users)}</h3>980            <p>Active Hackers</p>981        </div>982        """, unsafe_allow_html=True)983    984    with col2:985        st.markdown(f"""986        <div class="metric-card">987            <h2>โšก</h2>988            <h3>{len(quick_teams)}</h3>989            <p>Quick Teams Formed</p>990        </div>991        """, unsafe_allow_html=True)992    993    with col3:994        avg_team_time = "< 2 min"995        st.markdown(f"""996        <div class="metric-card">997            <h2>โฑ</h2>998            <h3>{avg_team_time}</h3>999            <p>Avg Team Formation</p>1000        </div>1001        """, unsafe_allow_html=True)1002    1003    with col4:1004        success_rate = 711005        st.markdown(f"""1006        <div class="metric-card">1007            <h2>๐ŸŽฏ</h2>1008            <h3>{success_rate}%</h3>1009            <p>Match Success Rate</p>1010        </div>1011        """, unsafe_allow_html=True)1012    1013    st.markdown("---")1014    1015    # Quick team formation CTA1016    st.markdown("""1017    ## ๐Ÿš€ Ready to Form a Team in Under 2 Minutes?1018    1019    *CYHI Quick Teams* uses advanced matching algorithms to instantly connect you with compatible teammates based on:1020    - ๐ŸŽฏ Complementary skills (not just similar ones!)1021    - โฐ Real-time availability1022    - ๐ŸŽจ Role optimization1023    - ๐Ÿง  Experience level balance1024    """)1025    1026    col1, col2, col3 = st.columns([1, 2, 1])1027    with col2:1028        if st.button("โšก START QUICK TEAM FORMATION", key="main_quick_team"):1029            st.session_state['page'] = 'quick_teams'1030            st.rerun()1031    1032    # Recent quick teams1033    if quick_teams:1034        st.markdown("## ๐Ÿ”ฅ Recently Formed Quick Teams")1035        for team in quick_teams[-3:]:1036            display_quick_team_card(team)1037 1038def display_quick_team_card(team_data):1039    """Display quick team formation card"""1040    compatibility = calculate_team_compatibility(team_data.get('members', []))1041    urgency_class = "urgent-badge" if team_data.get('urgency', 'normal') == 'high' else ""1042    1043    st.markdown(f"""1044    <div class="team-card">1045        <h3>โšก {team_data.get('name', 'Quick Team')}</h3>1046        <p><strong>๐ŸŽฏ Goal:</strong> {team_data.get('goal', 'Build something amazing!')}</p>1047        <p><strong>๐Ÿ‘ฅ Size:</strong> {len(team_data.get('members', []))} / {team_data.get('target_size', 4)} members</p>1048        <p><strong>๐Ÿ”ฅ Compatibility:</strong> {compatibility:.0f}%</p>1049        <p><strong>โฑ Formation Time:</strong> {team_data.get('formation_time', 'Just now')}</p>1050    </div>1051    """, unsafe_allow_html=True)1052 1053def show_quick_teams_page():1054    """Enhanced quick team formation page"""1055    st.markdown("## โšก CYHI Quick Teams - Form Teams in Minutes!")1056    1057    # Quick stats at top1058    col1, col2, col3 = st.columns(3)1059    with col1:1060        st.markdown("""1061        <div class="quick-match-card">1062            <h3>โฑ Average Time</h3>1063            <h2>90 seconds</h2>1064        </div>1065        """, unsafe_allow_html=True)1066    1067    with col2:1068        st.markdown("""1069        <div class="quick-match-card">1070            <h3>๐ŸŽฏ Match Accuracy</h3>1071            <h2>68%</h2>1072        </div>1073        """, unsafe_allow_html=True)1074    1075    with col3:1076        st.markdown("""1077        <div class="quick-match-card">1078            <h3>๐Ÿ‘ฅ Teams Formed</h3>1079            <h2>{}</h2>1080        </div>1081        """.format(len(get_quick_teams())), unsafe_allow_html=True)1082    1083    # Quick team formation form1084    st.markdown("### ๐Ÿš€ Form Your Team Now")1085    1086    users = get_all_users()1087    if len(users) < 2:1088        st.warning("Need at least 2 registered users for team matching. Create profiles first!")1089        return1090    1091    with st.form("instant_match_form"):1092        col1, col2 = st.columns(2)1093        1094        with col1:1095            user_name = st.selectbox("๐Ÿ‘ค Your Name", [user['name'] for user in users])1096            team_size = st.slider("๐Ÿ‘ฅ Desired Team Size", 2, 6, 3)1097            urgency = st.selectbox("๐Ÿ”ฅ Urgency Level", ["normal", "high", "critical"])1098        1099        with col2:1100            focus_area = st.selectbox("๐ŸŽฏ Project Focus", 1101                                    ["Web Development", "Mobile App", "AI/ML", "Data Science", 1102                                     "IoT", "Blockchain", "Game Development", "Open Choice"])1103            time_commitment = st.selectbox("โฐ Time Commitment", 1104                                         ["2-4 hours", "Half day", "Full day", "Weekend", "Week+"])1105        1106        project_idea = st.text_area("๐Ÿ’ก Quick Project Idea (Optional)", 1107                                   placeholder="Briefly describe what you want to build...")1108        1109        match_button = st.form_submit_button("โšก FIND MY TEAM NOW!", use_container_width=True)1110        1111        if match_button:1112            user_profile = next((u for u in users if u['name'] == user_name), None)1113            if user_profile:1114                with st.spinner("๐Ÿ” Finding your perfect teammates..."):1115                    import time1116                    time.sleep(2)1117                    1118                    matches = create_instant_team_match(user_profile)1119                    1120                    if matches:1121                        st.success("๐ŸŽ‰ Team formed successfully!")1122                        1123                        team_members = [user_profile] + [match[0] for match in matches[:team_size-1]]1124                        roles = generate_team_roles(team_members, focus_area)1125                        compatibility = calculate_team_compatibility(team_members)1126                        1127                        quick_team_data = {1128                            'name': f"QuickTeam_{datetime.now().strftime('%H%M%S')}",1129                            'members': team_members,1130                            'goal': project_idea or f"Build amazing {focus_area} solution",1131                            'focus_area': focus_area,1132                            'urgency': urgency,1133                            'target_size': team_size,1134                            'formation_time': datetime.now().strftime('%H:%M:%S'),1135                            'compatibility': compatibility,1136                            'roles': roles,1137                            'time_commitment': time_commitment1138                        }1139                        1140                        team_id = save_quick_team(quick_team_data)1141                        1142                        st.markdown(f"""1143                        ### ๐Ÿ† Your Team: QuickTeam_{datetime.now().strftime('%H%M%S')}1144                        *๐Ÿ”ฅ Compatibility Score: {compatibility:.0f}%*1145                        """)1146                        1147                        categories = load_json(CATEGORIES_FILE)1148                        for i, member in enumerate(team_members):1149                            role = None1150                            for role_name, role_info in roles.items():1151                                if role_info.get('assigned') == member['name']:1152                                    role = role_name1153                                    break1154                            display_profile_card_with_scores(member, categories, show_scores=True, role=role)1155                        1156                        # Next steps1157                        st.markdown("### ๐Ÿš€ Next Steps:")1158                        col1, col2, col3 = st.columns(3)1159                        1160                        with col1:1161                            if st.button("๐Ÿ’ฌ Start Team Chat"):1162                                st.info("Team chat initiated!")1163                        1164                        with col2:1165                            if st.button("๐Ÿ“‹ Create Project Board"):1166                                st.info("Project board created!")1167                        1168                        with col3:1169                            if st.button("๐Ÿ“… Schedule Kickoff"):1170                                st.info("Kickoff meeting scheduled!")1171                    1172                    else:1173                        st.warning("No compatible teammates found right now. Try adjusting your preferences!")1174 1175def show_create_profile_page(categories):1176    """Enhanced profile creation with team formation focus"""1177    st.markdown("## ๐Ÿ‘ค Create Your Hacker Profile")1178    st.markdown("Build your profile to get instant team matches!")1179    1180    with st.form("profile_form", clear_on_submit=True):1181        col1, col2 = st.columns(2)1182        1183        with col1:1184            name = st.text_input("๐Ÿ’ฌ Full Name *", placeholder="Your name")1185            1186            all_domains = []1187            for cat in categories.values():1188                all_domains.extend(cat.get("domains", {}).keys())1189            1190            primary_domain = st.selectbox("๐ŸŽฏ Primary Domain *", [""] + all_domains)1191            secondary_domain = st.selectbox("๐ŸŽฏ Secondary Domain", ["None"] + all_domains)1192            1193            experience_level = st.selectbox("๐Ÿ“ˆ Experience Level *", 1194                                          ["Beginner", "Intermediate", "Advanced", "Expert"])1195            1196            availability = st.multiselect("โฐ Availability *", 1197                                        ["Right Now", "Weekends", "Evenings", "Flexible", 1198                                         "Full-time", "Part-time", "Remote Only"])1199        1200        with col2:

Showing the first 1,200 of 1679 lines. Download the file for the rest.