Spaces:
Sleeping
Sleeping
| # contacts_data.py | |
| """ | |
| Contact database with 500 fake contacts covering all departments and divisions. | |
| Each contact has Arabic and English names for better search support. | |
| """ | |
| from typing import List, Dict | |
| from division_hierarchy import DIVISION_TO_DEPARTMENT | |
| import random | |
| # Common Arabic first names (male and female) | |
| ARABIC_FIRST_NAMES_MALE = [ | |
| "محمد", "أحمد", "عبدالله", "عمر", "خالد", "سعد", "فيصل", "سلطان", "ناصر", "طلال", | |
| "عبدالعزيز", "فهد", "تركي", "سلمان", "بندر", "مشعل", "ماجد", "يوسف", "حسن", "علي", | |
| "وليد", "زياد", "رامي", "كريم", "عادل", "راشد", "مازن", "طارق", "إبراهим", "عيسى", | |
| "نواف", "سامي", "بدر", "عاصم", "وسام", "هاني", "ثامر", "صالح", "ياسر", "جاسم", | |
| "هشام", "فواز", "معاذ", "عثمان", "أسامة", "باسل", "عمار", "نبيل", "توفيق", "جمال" | |
| ] | |
| ARABIC_FIRST_NAMES_FEMALE = [ | |
| "فاطمة", "نورة", "سارة", "منى", "هند", "ريم", "لينا", "دانة", "شهد", "جود", | |
| "رهف", "غلا", "عبير", "أمل", "ندى", "رنا", "لمى", "ديمة", "بشرى", "سمية", | |
| "هيفاء", "ليلى", "زينب", "خلود", "شروق", "أريج", "جميلة", "رباب", "سلمى", "وفاء", | |
| "عائشة", "خديجة", "مريم", "رقية", "زهراء", "نجود", "حصة", "عزة", "صفية", "ملاك", | |
| "روان", "تالا", "جنى", "لين", "ريتاج", "أسماء", "سديم", "لمار", "بيان", "شيماء" | |
| ] | |
| # Common Arabic last names | |
| ARABIC_LAST_NAMES = [ | |
| "العتيبي", "الدوسري", "القحطاني", "الشهري", "الغامدي", "الزهراني", "العنزي", "الحربي", | |
| "المطيري", "العسيري", "السبيعي", "الشمري", "الجهني", "العمري", "البقمي", "الفهد", | |
| "السديري", "الثبيتي", "الصقري", "الأحمد", "الخالد", "السليمان", "العبدالله", "الفهيد", | |
| "الشايع", "الرشيد", "العجمي", "المالك", "الفريح", "الحمود", "الناصر", "الشريف", | |
| "البلوي", "اليامي", "الوادعي", "الفيفي", "الشهراني", "البكري", "العسكر", "الراشد", | |
| "الفايز", "الخليف", "المنيع", "العبيد", "السحيم", "الغنام", "السلمان", "الهاجري", | |
| "النهدي", "الرويلي", "المري", "السواط", "الربيعان", "الدغيثر", "الفضلي", "القرني", | |
| "الثنيان", "العريفي", "الهويدي", "الجريسي", "البدراني", "المهيدب", "السالم", "الحارثي", | |
| "العطوي", "الصخري", "الرحيلي", "السعيد", "الحافظ", "الوهيبي", "البراك", "الضويان" | |
| ] | |
| # Job titles in English and Arabic by category | |
| JOB_TITLES = { | |
| "executive": [ | |
| ("Chief Executive Officer", "المدير التنفيذي"), | |
| ("Executive Director", "المدير التنفيذي"), | |
| ("Vice President", "نائب الرئيس"), | |
| ("Senior Vice President", "نائب الرئيس الأول"), | |
| ], | |
| "management": [ | |
| ("Director", "مدير"), | |
| ("Senior Manager", "مدير أول"), | |
| ("Manager", "مدير"), | |
| ("Assistant Manager", "مساعد مدير"), | |
| ("Team Leader", "قائد فريق"), | |
| ("Supervisor", "مشرف"), | |
| ], | |
| "specialist": [ | |
| ("Senior Specialist", "أخصائي أول"), | |
| ("Specialist", "أخصائي"), | |
| ("Senior Analyst", "محلل أول"), | |
| ("Analyst", "محلل"), | |
| ("Senior Consultant", "مستشار أول"), | |
| ("Consultant", "مستشار"), | |
| ("Senior Officer", "موظف أول"), | |
| ("Officer", "موظف"), | |
| ], | |
| "technical": [ | |
| ("Senior Engineer", "مهندس أول"), | |
| ("Engineer", "مهندس"), | |
| ("Technical Lead", "قائد تقني"), | |
| ("Developer", "مطور"), | |
| ("Architect", "مهندس معماري"), | |
| ], | |
| "support": [ | |
| ("Coordinator", "منسق"), | |
| ("Administrator", "إداري"), | |
| ("Assistant", "مساعد"), | |
| ("Associate", "معاون"), | |
| ] | |
| } | |
| # Phone extensions (4-digit) | |
| def generate_extension() -> str: | |
| """Generate a 4-digit phone extension""" | |
| return str(random.randint(1000, 9999)) | |
| # Email generation | |
| def generate_email(first_name_en: str, last_name_en: str) -> str: | |
| """Generate an email address""" | |
| # Remove spaces and special characters | |
| first = first_name_en.lower().replace(" ", "").replace("-", "") | |
| last = last_name_en.lower().replace(" ", "").replace("-", "") | |
| return f"{first}.{last}@sidf.gov.sa" | |
| def transliterate_arabic_name(arabic_name: str) -> str: | |
| """ | |
| Simple transliteration of Arabic names to English. | |
| This is a basic mapping for common names. | |
| """ | |
| transliteration_map = { | |
| # Male names | |
| "محمد": "Mohammed", "أحمد": "Ahmed", "عبدالله": "Abdullah", "عمر": "Omar", "خالد": "Khalid", | |
| "سعد": "Saad", "فيصل": "Faisal", "سلطان": "Sultan", "ناصر": "Nasser", "طلال": "Talal", | |
| "عبدالعزيز": "Abdulaziz", "فهد": "Fahad", "تركي": "Turki", "سلمان": "Salman", "بندر": "Bandar", | |
| "مشعل": "Mishaal", "ماجد": "Majed", "يوسف": "Yousef", "حسن": "Hassan", "علي": "Ali", | |
| "وليد": "Waleed", "زياد": "Ziyad", "رامي": "Rami", "كريم": "Kareem", "عادل": "Adel", | |
| "راشد": "Rashed", "مازن": "Mazen", "طارق": "Tariq", "إبراهim": "Ibrahim", "عيسى": "Issa", | |
| "نواف": "Nawaf", "سامي": "Sami", "بدر": "Badr", "عاصم": "Asim", "وسام": "Wissam", | |
| "هاني": "Hani", "ثامر": "Thamer", "صالح": "Saleh", "ياسر": "Yasser", "جاسم": "Jasim", | |
| "هشام": "Hisham", "فواز": "Fawaz", "معاذ": "Muath", "عثمان": "Othman", "أسامة": "Osama", | |
| "باسل": "Basel", "عمار": "Ammar", "نبيل": "Nabil", "توفيق": "Tawfiq", "جمال": "Jamal", | |
| # Female names | |
| "فاطمة": "Fatima", "نورة": "Noura", "سارة": "Sarah", "منى": "Mona", "هند": "Hind", | |
| "ريم": "Reem", "لينا": "Lina", "دانة": "Dana", "شهد": "Shahad", "جود": "Joud", | |
| "رهف": "Rahaf", "غلا": "Ghala", "عبير": "Abeer", "أمل": "Amal", "ندى": "Nada", | |
| "رنا": "Rana", "لمى": "Lama", "ديمة": "Dima", "بشرى": "Bushra", "سمية": "Somaya", | |
| "هيفاء": "Haifa", "ليلى": "Layla", "زينب": "Zainab", "خلود": "Kholoud", "شروق": "Shorouq", | |
| "أريج": "Areej", "جميلة": "Jamila", "رباب": "Rabab", "سلمى": "Salma", "وفاء": "Wafa", | |
| "عائشة": "Aisha", "خديجة": "Khadija", "مريم": "Maryam", "رقية": "Ruqaya", "زهراء": "Zahra", | |
| "نجود": "Nujoud", "حصة": "Hessa", "عزة": "Azza", "صفية": "Safiya", "ملاك": "Malak", | |
| "روان": "Rawan", "تالا": "Tala", "جنى": "Jana", "لين": "Leen", "ريتاج": "Ritaj", | |
| "أسماء": "Asma", "سديم": "Sadeem", "لمار": "Lamar", "بيان": "Bayan", "شيماء": "Shaima", | |
| # Last names | |
| "العتيبي": "Al-Otaibi", "الدوسري": "Al-Dosari", "القحطاني": "Al-Qahtani", "الشهري": "Al-Shahri", | |
| "الغامدي": "Al-Ghamdi", "الزهراني": "Al-Zahrani", "العنزي": "Al-Anazi", "الحربي": "Al-Harbi", | |
| "المطيري": "Al-Mutairi", "العسيري": "Al-Asiri", "السبيعي": "Al-Subaie", "الشمري": "Al-Shammari", | |
| "الجهني": "Al-Juhani", "العمري": "Al-Omari", "البقمي": "Al-Buqami", "الفهد": "Al-Fahad", | |
| "السديري": "Al-Sudairi", "الثبيتي": "Al-Thubaiti", "الصقري": "Al-Saqri", "الأحمد": "Al-Ahmad", | |
| "الخالد": "Al-Khalid", "السليمان": "Al-Sulaiman", "العبدالله": "Al-Abdullah", "الفهيد": "Al-Fahaid", | |
| "الشايع": "Al-Shaya", "الرشيد": "Al-Rasheed", "العجمي": "Al-Ajmi", "المالك": "Al-Malek", | |
| "الفريح": "Al-Fraihi", "الحمود": "Al-Hamoud", "الناصر": "Al-Nasser", "الشريف": "Al-Shareef", | |
| "البلوي": "Al-Balawi", "اليامي": "Al-Yami", "الوادعي": "Al-Wadei", "الفيفي": "Al-Faifi", | |
| "الشهراني": "Al-Shahrani", "البكري": "Al-Bakri", "العسكر": "Al-Askar", "الراشد": "Al-Rashed", | |
| "الفايز": "Al-Fayez", "الخليف": "Al-Khleif", "المنيع": "Al-Manie", "العبيد": "Al-Obaid", | |
| "السحيم": "Al-Suhaim", "الغنام": "Al-Ghannam", "السلمان": "Al-Salman", "الهاجري": "Al-Hajri", | |
| "النهدي": "Al-Nahdi", "الرويلي": "Al-Ruwaili", "المري": "Al-Marri", "السواط": "Al-Sawat", | |
| "الربيعان": "Al-Rabian", "الدغيثر": "Al-Dughither", "الفضلي": "Al-Fadhli", "القرني": "Al-Qarni", | |
| "الثنيان": "Al-Thuniyan", "العريفي": "Al-Arifi", "الهويدي": "Al-Huwaidi", "الجريسي": "Al-Juraysi", | |
| "البدراني": "Al-Badrani", "المهيدب": "Al-Muhaidib", "السالم": "Al-Salem", "الحارثي": "Al-Harthi", | |
| "العطوي": "Al-Atawi", "الصخري": "Al-Sakhri", "الرحيلي": "Al-Rahili", "السعيد": "Al-Saeed", | |
| "الحافظ": "Al-Hafiz", "الوهيبي": "Al-Wahaibi", "البراك": "Al-Barrak", "الضويان": "Al-Dhuwayan", | |
| } | |
| return transliteration_map.get(arabic_name, arabic_name) | |
| def generate_contacts() -> List[Dict]: | |
| """ | |
| Generate 500 fake contacts distributed across all divisions. | |
| Returns a list of contact dictionaries. | |
| """ | |
| contacts = [] | |
| contact_id = 1000 # Starting ID | |
| # Get all divisions | |
| divisions = list(DIVISION_TO_DEPARTMENT.keys()) | |
| # Calculate contacts per division (aim for ~7-8 per division) | |
| contacts_per_division = 500 // len(divisions) | |
| extra_contacts = 500 % len(divisions) | |
| for div_index, division in enumerate(divisions): | |
| department_name, department_id = DIVISION_TO_DEPARTMENT[division] | |
| # Number of contacts for this division | |
| num_contacts = contacts_per_division | |
| if div_index < extra_contacts: | |
| num_contacts += 1 | |
| # Determine seniority distribution (more junior staff than senior) | |
| # 10% executive, 20% management, 50% specialist, 15% technical, 5% support | |
| seniority_distribution = [] | |
| seniority_distribution.extend(["executive"] * max(1, int(num_contacts * 0.10))) | |
| seniority_distribution.extend(["management"] * max(1, int(num_contacts * 0.20))) | |
| seniority_distribution.extend(["specialist"] * max(1, int(num_contacts * 0.50))) | |
| seniority_distribution.extend(["technical"] * max(1, int(num_contacts * 0.15))) | |
| seniority_distribution.extend(["support"] * max(1, int(num_contacts * 0.05))) | |
| # Ensure we have exactly num_contacts | |
| while len(seniority_distribution) < num_contacts: | |
| seniority_distribution.append("specialist") | |
| seniority_distribution = seniority_distribution[:num_contacts] | |
| random.shuffle(seniority_distribution) | |
| for i in range(num_contacts): | |
| # Mix male and female names (60% male, 40% female) | |
| is_male = random.random() < 0.6 | |
| if is_male: | |
| first_name_ar = random.choice(ARABIC_FIRST_NAMES_MALE) | |
| else: | |
| first_name_ar = random.choice(ARABIC_FIRST_NAMES_FEMALE) | |
| last_name_ar = random.choice(ARABIC_LAST_NAMES) | |
| # Transliterate to English | |
| first_name_en = transliterate_arabic_name(first_name_ar) | |
| last_name_en = transliterate_arabic_name(last_name_ar) | |
| # Full names | |
| full_name_ar = f"{first_name_ar} {last_name_ar}" | |
| full_name_en = f"{first_name_en} {last_name_en}" | |
| # Get job title based on seniority | |
| seniority = seniority_distribution[i] | |
| title_en, title_ar = random.choice(JOB_TITLES[seniority]) | |
| # Generate contact info | |
| extension = generate_extension() | |
| email = generate_email(first_name_en, last_name_en) | |
| contact = { | |
| "id": contact_id, | |
| "first_name_ar": first_name_ar, | |
| "last_name_ar": last_name_ar, | |
| "full_name_ar": full_name_ar, | |
| "first_name_en": first_name_en, | |
| "last_name_en": last_name_en, | |
| "full_name_en": full_name_en, | |
| "title_en": title_en, | |
| "title_ar": title_ar, | |
| "division": division, | |
| "department": department_name, | |
| "department_id": department_id, | |
| "email": email, | |
| "extension": extension, | |
| "phone": f"+966-11-218-{extension}", | |
| } | |
| contacts.append(contact) | |
| contact_id += 1 | |
| return contacts | |
| # Generate contacts on module load | |
| CONTACTS_DATABASE = generate_contacts() | |
| # Create indexes for fast lookup | |
| CONTACTS_BY_NAME_AR = {contact["full_name_ar"]: contact for contact in CONTACTS_DATABASE} | |
| CONTACTS_BY_NAME_EN = {contact["full_name_en"]: contact for contact in CONTACTS_DATABASE} | |
| CONTACTS_BY_DIVISION = {} | |
| for contact in CONTACTS_DATABASE: | |
| division = contact["division"] | |
| if division not in CONTACTS_BY_DIVISION: | |
| CONTACTS_BY_DIVISION[division] = [] | |
| CONTACTS_BY_DIVISION[division].append(contact) | |
| def get_all_contacts() -> List[Dict]: | |
| """Get all contacts""" | |
| return CONTACTS_DATABASE | |
| def get_contacts_by_division(division: str) -> List[Dict]: | |
| """Get contacts for a specific division""" | |
| return CONTACTS_BY_DIVISION.get(division, []) | |
| def get_contact_by_name(name: str) -> Dict: | |
| """Get contact by exact name (Arabic or English)""" | |
| # Try Arabic first | |
| contact = CONTACTS_BY_NAME_AR.get(name) | |
| if contact: | |
| return contact | |
| # Try English | |
| contact = CONTACTS_BY_NAME_EN.get(name) | |
| if contact: | |
| return contact | |
| return None | |
| if __name__ == "__main__": | |
| # Test the contact generation | |
| contacts = get_all_contacts() | |
| print(f"Generated {len(contacts)} contacts") | |
| print(f"\nSample contacts:") | |
| for i, contact in enumerate(contacts[:5]): | |
| print(f"{i+1}. {contact['full_name_en']} ({contact['full_name_ar']})") | |
| print(f" {contact['title_en']} - {contact['division']}") | |
| print(f" {contact['email']} | Ext: {contact['extension']}") | |
| print() | |
| # Show distribution by department | |
| from collections import Counter | |
| dept_counts = Counter(contact["department"] for contact in contacts) | |
| print("\nContacts by Department:") | |
| for dept, count in sorted(dept_counts.items(), key=lambda x: -x[1]): | |
| print(f" {dept}: {count}") | |