"""
US Gambling Regulations Explorer - Streamlit Web Interface with AI Chat
Comprehensive regulatory information for 35+ US states
"""
import streamlit as st
import json
from pathlib import Path
from typing import Dict, List, Any
import pandas as pd
def clean_text(text):
"""Clean up JSON-like formatting from text"""
if not isinstance(text, str):
return str(text)
# Remove dictionary syntax
text = text.replace("{'", "").replace("'}", "")
text = text.replace('{"', '').replace('"}', '')
# Remove brackets and quotes from list representations
text = text.strip("[](){}")
text = text.replace("['", "").replace("']", "")
text = text.replace('["', '').replace('"]', '')
# Clean up separators
text = text.replace("', '", ", ")
text = text.replace('", "', ", ")
text = text.replace("': '", ": ")
text = text.replace('": "', ": ")
# Remove extra quotes
text = text.strip("'\"")
return text
def format_key(key):
"""Format keys to be human-readable"""
# Replace underscores with spaces and title case
formatted = key.replace('_', ' ').replace('-', ' ')
# Title case each word
formatted = ' '.join(word.capitalize() for word in formatted.split())
return formatted
# Page configuration
st.set_page_config(
page_title="US Gambling Regulations Explorer",
page_icon="🇺🇸",
layout="wide",
initial_sidebar_state="expanded"
)
# Constants
DATA_DIR = Path("data/states/completed")
# Helper functions
@st.cache_data
def load_states_index() -> Dict[str, Any]:
"""Load the states index file"""
filepath = DATA_DIR / "us-states-index.json"
if not filepath.exists():
return {"states": []}
with open(filepath, 'r', encoding='utf-8') as f:
return json.load(f)
@st.cache_data
def load_state_data(state_id: str) -> Dict[str, Any]:
"""Load data for a specific state"""
filepath = DATA_DIR / f"{state_id}.json"
if not filepath.exists():
return {}
with open(filepath, 'r', encoding='utf-8') as f:
return json.load(f)
def search_in_data(data: Dict, query: str) -> List[Dict]:
"""Recursively search for query in data structure"""
results = []
query_lower = query.lower()
def search_recursive(obj: Any, path: str = ""):
if isinstance(obj, dict):
for key, value in obj.items():
new_path = f"{path}.{key}" if path else key
if query_lower in key.lower():
results.append({
"path": new_path,
"key": key,
"type": "key_match"
})
if isinstance(value, str) and query_lower in value.lower():
preview = value[:200] + "..." if len(value) > 200 else value
results.append({
"path": new_path,
"key": key,
"value_preview": preview,
"type": "value_match"
})
search_recursive(value, new_path)
elif isinstance(obj, list):
for i, item in enumerate(obj):
search_recursive(item, f"{path}[{i}]")
search_recursive(data)
return results
# Import chat functionality
try:
from chat_interface_us import chat_with_claude_us
CHAT_AVAILABLE = True
except ImportError:
CHAT_AVAILABLE = False
# Main App
def main():
# Header
st.title("🇺🇸 US Gambling Regulations Explorer")
st.markdown("**Comprehensive regulatory information for 35+ US states**")
st.markdown("---")
# Load states
index = load_states_index()
states = index.get("states", [])
# Sidebar
with st.sidebar:
st.header("📍 State Selection")
# State selector
state_names = [s["name"] for s in states]
selected_state_name = st.selectbox(
"Choose a state:",
state_names,
index=state_names.index("New York") if "New York" in state_names else 0
)
# Get selected state data
selected_state = next(s for s in states if s["name"] == selected_state_name)
st.markdown("---")
st.header("📚 Navigation")
pages = ["💬 Chat with Regulations", "💰 Compare States",
"📊 State Overview", "ℹ️ About"]
if not CHAT_AVAILABLE:
pages = pages[1:]
page = st.radio("Choose a section:", pages)
st.markdown("---")
st.markdown("### 📊 Coverage")
st.success(f"**{len(states)} States Complete**")
st.markdown("---")
st.markdown("### 🔗 Resources")
st.markdown("[GitHub Repository](https://github.com/Angeltooth/us-gambling-regulations-mcp)")
# Page content
if page == "💬 Chat with Regulations":
show_chat_page(selected_state)
elif page == "💰 Compare States":
show_compare_page(states)
elif page == "📊 State Overview":
show_overview_page(selected_state)
else:
show_about_page(states)
def show_chat_page(selected_state: Dict):
"""AI Chat interface"""
st.header(f"💬 Chat About {selected_state['name']} Gambling Regulations")
st.markdown("Ask me anything about gambling regulations in this state!")
# Check for API key
try:
api_key = st.secrets["ANTHROPIC_API_KEY"]
except:
st.error("⚠️ API key not configured. Please add ANTHROPIC_API_KEY to Streamlit secrets.")
return
# Initialize chat history
if "messages" not in st.session_state:
st.session_state.messages = []
if "current_state" not in st.session_state:
st.session_state.current_state = selected_state["id"]
# Reset chat if state changed
if st.session_state.current_state != selected_state["id"]:
st.session_state.messages = []
st.session_state.current_state = selected_state["id"]
# Display chat history
for message in st.session_state.messages:
with st.chat_message(message["role"]):
st.markdown(message["content"])
# Chat input
if prompt := st.chat_input(f"Ask about {selected_state['name']} regulations..."):
# Display user message
with st.chat_message("user"):
st.markdown(prompt)
# Get AI response
with st.chat_message("assistant"):
with st.spinner("Thinking..."):
try:
response, updated_messages = chat_with_claude_us(
api_key,
st.session_state.messages.copy(),
prompt,
selected_state["id"]
)
st.markdown(response)
st.session_state.messages = updated_messages
except Exception as e:
st.error(f"Error: {str(e)}")
# Clear chat button
if st.session_state.messages:
if st.button("🗑️ Clear Chat"):
st.session_state.messages = []
st.rerun()
# Example questions
with st.expander("💡 Example Questions"):
st.markdown(f"""
- What are the licensing requirements in {selected_state['name']}?
- What are the tax rates for online gambling?
- Are there mobile betting requirements?
- What are the key compliance requirements?
- Tell me about the regulatory authority
""")
def show_compare_page(states: List[Dict]):
"""State comparison tool"""
st.header("💰 Compare State Regulations")
st.markdown("Compare gambling regulations across multiple states")
# Select states to compare
col1, col2, col3 = st.columns(3)
with col1:
state_names = [s["name"] for s in states]
state1 = st.selectbox("First State:", state_names, index=state_names.index("New York") if "New York" in state_names else 0)
with col2:
state2 = st.selectbox("Second State:", state_names, index=state_names.index("New Jersey") if "New Jersey" in state_names else 1)
with col3:
category = st.selectbox(
"Compare:",
["All Categories", "Licensing", "Taxes & Fees", "Game Types", "Compliance", "Regulatory Authority"]
)
if st.button("Compare States", type="primary"):
# Load data for both states
state1_id = next(s["id"] for s in states if s["name"] == state1)
state2_id = next(s["id"] for s in states if s["name"] == state2)
data1 = load_state_data(state1_id)
data2 = load_state_data(state2_id)
st.markdown("---")
if category == "All Categories":
# Show comprehensive comparison
show_full_comparison(state1, state2, data1, data2)
else:
# Show category-specific comparison
show_category_comparison(state1, state2, data1, data2, category)
def show_full_comparison(state1: str, state2: str, data1: Dict, data2: Dict):
"""Display full side-by-side comparison"""
col1, col2 = st.columns(2)
with col1:
st.subheader(f"📍 {state1}")
try:
display_state_sections(data1)
except Exception as e:
st.error(f"Error displaying {state1} data")
with st.expander("Show raw data"):
st.write(data1)
with col2:
st.subheader(f"📍 {state2}")
try:
display_state_sections(data2)
except Exception as e:
st.error(f"Error displaying {state2} data")
with st.expander("Show raw data"):
st.write(data2)
def show_category_comparison(state1: str, state2: str, data1: Dict, data2: Dict, category: str):
"""Display side-by-side comparison with ALL sections aligned"""
st.subheader(f"Comparing: {category}")
st.markdown("---")
# Extract sections for both states
if category == "Licensing":
sections1 = extract_licensing_sections(data1)
sections2 = extract_licensing_sections(data2)
elif category == "Taxes & Fees":
sections1 = extract_tax_sections(data1)
sections2 = extract_tax_sections(data2)
elif category == "Game Types":
sections1 = extract_game_sections(data1)
sections2 = extract_game_sections(data2)
elif category == "Compliance":
sections1 = extract_compliance_sections(data1)
sections2 = extract_compliance_sections(data2)
elif category == "Regulatory Authority":
sections1 = extract_regulatory_sections(data1)
sections2 = extract_regulatory_sections(data2)
else:
sections1 = {}
sections2 = {}
# Get all unique section keys from BOTH states
all_keys = sorted(set(sections1.keys()) | set(sections2.keys()))
if not all_keys:
st.info("No comparison data available for this category")
return
# Create two main columns for the entire comparison
main_col1, main_col2 = st.columns(2)
with main_col1:
st.markdown(f"## 📍 {state1}")
st.markdown("---")
with main_col2:
st.markdown(f"## 📍 {state2}")
st.markdown("---")
# Now display each section in perfect sync
for key in all_keys:
section_title = format_key(key)
# Create columns for this section
col1, col2 = st.columns(2)
with col1:
st.markdown(f"### {section_title}")
if key in sections1:
for item in sections1[key]:
if item.startswith('**') or item.startswith('•'):
st.markdown(item)
else:
st.markdown(f"- {item}")
else:
st.info("Not specified")
st.markdown("")
with col2:
st.markdown(f"### {section_title}")
if key in sections2:
for item in sections2[key]:
if item.startswith('**') or item.startswith('•'):
st.markdown(item)
else:
st.markdown(f"- {item}")
else:
st.info("Not specified")
st.markdown("")
def extract_compliance_sections(data: Dict) -> Dict[str, List[str]]:
"""Extract compliance sections into a dictionary - simplified"""
sections = {}
comp_keys = ["compliance", "requirements", "regulations", "compliance_requirements",
"kyc", "aml", "responsible_gaming", "internal_controls",
"background_investigations", "regulatory_structure", "audit_requirements",
"anti_money_laundering", "reporting_requirements"]
for key in comp_keys:
if key in data:
value = data[key]
items = []
if isinstance(value, dict):
# For dictionaries, show each key-value pair clearly
for k, v in value.items():
sub_key = format_key(k)
if isinstance(v, list):
# If value is a list, show each item
for item in v:
clean_item = clean_text(str(item))
if clean_item:
items.append(f"• {clean_item}")
elif isinstance(v, dict):
# If value is another dict, show it indented
items.append(f"**{sub_key}:**")
for sub_k, sub_v in v.items():
clean_sub = clean_text(str(sub_v))
items.append(f" - {format_key(sub_k)}: {clean_sub}")
else:
# Simple value
clean_v = clean_text(str(v))
if len(clean_v) > 100:
# Break long text into multiple lines
words = clean_v.split(', ')
for word in words:
if word.strip():
items.append(f"• {word.strip()}")
else:
items.append(f"**{sub_key}:** {clean_v}")
elif isinstance(value, list):
# For lists, show each item
for item in value:
clean_item = clean_text(str(item))
if clean_item:
items.append(f"• {clean_item}")
else:
# For simple strings, split if very long
clean_val = clean_text(str(value))
if len(clean_val) > 150:
# Split long strings by commas
parts = clean_val.split(', ')
for part in parts:
if part.strip():
items.append(f"• {part.strip()}")
else:
items.append(clean_val)
if items:
sections[key] = items
return sections
def extract_licensing_sections(data: Dict) -> Dict[str, List[str]]:
"""Extract licensing sections into a dictionary"""
sections = {}
license_keys = ["license_types", "licensing", "license", "licenses", "application_process"]
for key in license_keys:
if key in data:
value = data[key]
items = []
if isinstance(value, dict):
for k, v in value.items():
if isinstance(v, list):
for item in v:
items.append(f"{format_key(k)}: {clean_text(str(item))}")
elif isinstance(v, dict):
for sub_k, sub_v in v.items():
items.append(f"{format_key(k)} - {format_key(sub_k)}: {clean_text(str(sub_v))}")
else:
items.append(f"{format_key(k)}: {clean_text(str(v))}")
elif isinstance(value, list):
items = [clean_text(str(item)) for item in value]
else:
items = [clean_text(str(value))]
sections[key] = items
return sections
def extract_tax_sections(data: Dict) -> Dict[str, List[str]]:
"""Extract tax sections"""
sections = {}
tax_keys = ["tax_rate", "taxes", "tax", "fees", "taxation", "revenue", "license_fees"]
for key in tax_keys:
if key in data:
value = data[key]
items = []
if isinstance(value, dict):
for k, v in value.items():
items.append(f"{format_key(k)}: {clean_text(str(v))}")
elif isinstance(value, list):
items = [clean_text(str(item)) for item in value]
else:
items = [clean_text(str(value))]
sections[key] = items
return sections
def extract_game_sections(data: Dict) -> Dict[str, List[str]]:
"""Extract game type sections"""
sections = {}
game_keys = ["sports_betting", "online_casino", "poker", "lottery",
"casino_gaming", "gaming_types", "permitted_games"]
for key in game_keys:
if key in data:
value = data[key]
if isinstance(value, bool):
sections[key] = ["✅ Allowed" if value else "❌ Not Allowed"]
elif isinstance(value, dict):
items = [f"{format_key(k)}: {clean_text(str(v))}" for k, v in value.items()]
sections[key] = items
else:
sections[key] = [clean_text(str(value))]
return sections
def extract_regulatory_sections(data: Dict) -> Dict[str, List[str]]:
"""Extract regulatory authority sections"""
sections = {}
reg_keys = ["regulatory_authority", "regulator", "commission", "authority"]
for key in reg_keys:
if key in data:
value = data[key]
items = []
if isinstance(value, dict):
for k, v in value.items():
items.append(f"{format_key(k)}: {clean_text(str(v))}")
else:
items = [clean_text(str(value))]
sections[key] = items
return sections
def show_licensing_info(data: Dict):
"""Display licensing information in a clean format"""
license_keys = ["license_types", "licensing", "license", "licenses", "application_process"]
found = False
for key in license_keys:
if key in data:
found = True
value = data[key]
display_key = format_key(key)
st.markdown(f"**{display_key}:**")
st.markdown("")
if isinstance(value, dict):
for k, v in value.items():
sub_key = format_key(k)
st.markdown(f"**{sub_key}:**")
if isinstance(v, list):
for item in v:
clean_item = clean_text(str(item))
st.markdown(f" - {clean_item}")
elif isinstance(v, dict):
for sub_k, sub_v in v.items():
formatted_sub_k = format_key(sub_k)
clean_sub_v = clean_text(str(sub_v))
st.markdown(f" - **{formatted_sub_k}:** {clean_sub_v}")
else:
clean_v = clean_text(str(v))
st.markdown(f" {clean_v}")
st.markdown("")
elif isinstance(value, list):
for item in value:
clean_item = clean_text(str(item))
st.markdown(f"- {clean_item}")
else:
clean_value = clean_text(str(value))
st.write(clean_value)
st.markdown("---")
if not found:
st.info("No licensing information available")
def show_tax_info(data: Dict):
"""Display tax and fee information"""
tax_keys = ["tax_rate", "taxes", "tax", "fees", "taxation", "revenue", "license_fees"]
found = False
for key in tax_keys:
if key in data:
found = True
st.markdown(f"**{key.replace('_', ' ').title()}:**")
value = data[key]
if isinstance(value, dict):
for k, v in value.items():
st.markdown(f"- **{k.replace('_', ' ').title()}:** {v}")
elif isinstance(value, list):
for item in value:
st.markdown(f"- {item}")
else:
st.markdown(f"{value}")
st.markdown("")
if not found:
st.info("No tax information available")
def show_game_types(data: Dict):
"""Display game types and offerings"""
game_keys = ["sports_betting", "online_casino", "poker", "lottery",
"casino_gaming", "gaming_types", "permitted_games",
"online_gaming", "retail_sports_betting", "mobile_sports_betting",
"daily_fantasy_sports", "horse_racing"]
found = False
for key in game_keys:
if key in data:
found = True
value = data[key]
# Determine status icon
if isinstance(value, bool):
icon = "✅" if value else "❌"
st.markdown(f"{icon} **{key.replace('_', ' ').title()}**")
elif isinstance(value, str):
if value.lower() in ["yes", "allowed", "legal", "permitted", "available"]:
icon = "✅"
elif value.lower() in ["no", "not allowed", "illegal", "prohibited", "not available"]:
icon = "❌"
else:
icon = "ℹ️"
st.markdown(f"{icon} **{key.replace('_', ' ').title()}:** {value}")
elif isinstance(value, dict):
st.markdown(f"**{key.replace('_', ' ').title()}:**")
for k, v in value.items():
st.markdown(f" - {k}: {v}")
else:
st.markdown(f"**{key.replace('_', ' ').title()}:** {value}")
if not found:
st.info("No game type information available")
def show_compliance_info(data: Dict):
"""Display compliance information in a clean, readable format"""
comp_keys = ["compliance", "requirements", "regulations", "compliance_requirements",
"kyc", "aml", "responsible_gaming", "internal_controls", "background_investigations",
"regulatory_structure"]
found = False
for key in comp_keys:
if key in data:
found = True
value = data[key]
display_key = format_key(key)
st.markdown(f"**{display_key}:**")
st.markdown("")
if isinstance(value, dict):
for k, v in value.items():
sub_key = format_key(k)
st.markdown(f"**{sub_key}:**")
if isinstance(v, list):
for item in v:
clean_item = clean_text(str(item))
st.markdown(f" - {clean_item}")
elif isinstance(v, dict):
for sub_k, sub_v in v.items():
formatted_sub_k = format_key(sub_k)
clean_sub_v = clean_text(str(sub_v))
st.markdown(f" - **{formatted_sub_k}:** {clean_sub_v}")
else:
clean_value = clean_text(str(v))
st.markdown(f" {clean_value}")
st.markdown("")
elif isinstance(value, list):
for item in value:
clean_item = clean_text(str(item))
st.markdown(f"- {clean_item}")
else:
clean_value = clean_text(str(value))
st.write(clean_value)
st.markdown("---")
if not found:
st.info("No compliance information available")
def show_regulatory_info(data: Dict):
"""Display regulatory authority information"""
reg_keys = ["regulatory_authority", "regulator", "commission", "authority", "oversight"]
found = False
for key in reg_keys:
if key in data:
found = True
value = data[key]
if isinstance(value, dict):
for k, v in value.items():
st.markdown(f"**{k.replace('_', ' ').title()}:** {v}")
else:
st.markdown(f"**{key.replace('_', ' ').title()}:** {value}")
st.markdown("")
if not found:
st.info("No regulatory authority information available")
def extract_value(data: Dict, key: str) -> Any:
"""Extract value from nested dict by key"""
if key in data:
return data[key]
# Search nested
for k, v in data.items():
if isinstance(v, dict):
result = extract_value(v, key)
if result:
return result
return None
def format_value(value: Any) -> str:
"""Format value for display"""
if value is None:
return "Not specified"
if isinstance(value, bool):
return "✅ Yes" if value else "❌ No"
if isinstance(value, (list, dict)):
return json.dumps(value, indent=2)
return str(value)
def display_state_sections(data: Dict):
"""Display state data in organized, readable sections"""
def format_section_content(content, indent=0):
"""Recursively format content in a readable way"""
indent_str = " " * indent
if isinstance(content, dict):
for key, value in content.items():
key_formatted = key.replace('_', ' ').replace('-', ' ').title()
if isinstance(value, dict):
st.markdown(f"{indent_str}**{key_formatted}:**")
format_section_content(value, indent + 1)
elif isinstance(value, list):
st.markdown(f"{indent_str}**{key_formatted}:**")
for item in value:
if isinstance(item, str):
st.markdown(f"{indent_str}- {item}")
else:
format_section_content(item, indent + 1)
else:
st.markdown(f"{indent_str}**{key_formatted}:** {value}")
elif isinstance(content, list):
for item in content:
if isinstance(item, str):
st.markdown(f"{indent_str}- {item}")
else:
format_section_content(item, indent)
else:
st.markdown(f"{indent_str}{content}")
try:
# Section 1: Licensing
license_keys = ["license_types", "licensing", "license", "licenses"]
license_data = next((data.get(k) for k in license_keys if k in data), None)
if license_data:
with st.expander("📋 Licensing Requirements", expanded=True):
format_section_content(license_data)
except Exception as e:
pass
try:
# Section 2: Taxes
tax_keys = ["tax_rate", "taxes", "tax", "fees", "taxation", "revenue"]
tax_data = {k: data.get(k) for k in tax_keys if k in data}
if tax_data:
with st.expander("💰 Taxes & Fees", expanded=True):
format_section_content(tax_data)
except Exception as e:
pass
try:
# Section 3: Game Types
game_keys = ["sports_betting", "online_casino", "poker", "lottery",
"casino_gaming", "gaming_types", "permitted_games", "online_gaming",
"retail_sports_betting", "mobile_sports_betting"]
game_data = {k: data.get(k) for k in game_keys if k in data}
if game_data:
with st.expander("🎮 Game Types & Offerings", expanded=True):
format_section_content(game_data)
except Exception as e:
pass
try:
# Section 4: Regulatory Authority
reg_keys = ["regulatory_authority", "regulator", "commission", "authority", "oversight"]
reg_data = next((data.get(k) for k in reg_keys if k in data), None)
if reg_data:
with st.expander("🏛️ Regulatory Authority", expanded=True):
format_section_content(reg_data)
except Exception as e:
pass
try:
# Section 5: Compliance
comp_keys = ["compliance", "requirements", "regulations", "compliance_requirements"]
comp_data = next((data.get(k) for k in comp_keys if k in data), None)
if comp_data:
with st.expander("⚖️ Compliance Requirements", expanded=True):
format_section_content(comp_data)
except Exception as e:
pass
try:
# Section 6: Market Info
market_keys = ["market_size", "operators", "revenue", "statistics", "market_data"]
market_data = {k: data.get(k) for k in market_keys if k in data}
if market_data:
with st.expander("📊 Market Information"):
format_section_content(market_data)
except Exception as e:
pass
try:
# Section 7: Additional Info
with st.expander("📄 Additional Information"):
# Show remaining data
displayed_keys = [
"license_types", "licensing", "license", "licenses",
"tax_rate", "taxes", "tax", "fees", "taxation", "revenue",
"sports_betting", "online_casino", "poker", "lottery",
"casino_gaming", "gaming_types", "permitted_games", "online_gaming",
"retail_sports_betting", "mobile_sports_betting",
"regulatory_authority", "regulator", "commission", "authority", "oversight",
"compliance", "requirements", "regulations", "compliance_requirements",
"market_size", "operators", "revenue", "statistics", "market_data"
]
remaining = {k: v for k, v in data.items() if k not in displayed_keys}
if remaining:
format_section_content(remaining)
else:
st.info("No additional information available")
except Exception as e:
st.warning("Some additional information could not be displayed")
def show_overview_page(selected_state: Dict):
"""State overview page with organized sections"""
st.header(f"📊 {selected_state['name']} Gambling Regulations Overview")
# Load state data
state_data = load_state_data(selected_state["id"])
if not state_data:
st.warning("No data available for this state")
return
# Display organized sections
display_state_sections(state_data)
# Search within state
st.markdown("---")
st.subheader("🔍 Search This State's Regulations")
query = st.text_input("Search for:", placeholder="e.g., license, tax, online casino")
if query:
with st.spinner("Searching..."):
results = search_in_data(state_data, query)
if results:
st.success(f"Found {len(results)} matches")
for i, match in enumerate(results[:10]):
if match['type'] == 'value_match':
st.markdown(f"**Match {i+1}:** `{match['path']}`")
st.info(match['value_preview'])
else:
st.markdown(f"**Key match:** `{match['path']}`")
else:
st.warning("No matches found")
def show_about_page(states: List[Dict]):
"""About page"""
st.header("ℹ️ About This Tool")
st.markdown(f"""
### 🎯 US Gambling Regulations Explorer
Comprehensive regulatory information for gambling across the United States.
**Coverage:**
- ✅ **{len(states)} states and territories**
- ✅ Complete regulatory frameworks
- ✅ Licensing, compliance, tax information
**Features:**
- 🤖 **AI-powered chat** - Ask questions in natural language
- 💰 **State comparison** - Compare regulations side-by-side
- 📊 **State overviews** - Detailed regulatory information
- 🔍 **Search** - Find specific requirements
**States Covered:**
""")
# Display states in columns
cols = st.columns(4)
for i, state in enumerate(states):
with cols[i % 4]:
st.markdown(f"✅ {state['name']}")
st.markdown("""
---
**Data Sources:**
- State gaming commissions and regulatory authorities
- Official legislation and administrative codes
- Licensing requirements and fee schedules
**Last Updated:** October 2025
**Version:** 1.0.0
---
**Built with ❤️ for the gambling compliance community**
""")
if __name__ == "__main__":
main()