Soulcompass / app.py
Rong6693's picture
Update app.py
bef6f3d verified
raw
history blame
24.3 kB
import streamlit as st
import random
from datetime import datetime
# 頁面配置
st.set_page_config(
page_title=“SoulCompass - Find Your Inner North Star”,
page_icon=“🧭”,
layout=“wide”
)
# 語言配置
LANGUAGES = {
“English”: “en”,
“中文”: “zh”,
“Español”: “es”,
“Français”: “fr”
}
# 多語言文本
TEXTS = {
“en”: {
“title”: “SoulCompass”,
“subtitle”: “Find Your Inner North Star”,
“features”: “Tarot Reading | Numerology | Soul Journal | AI Therapist”,
“tarot_tab”: “Tarot Reading”,
“numerology_tab”: “Numerology”,
“journal_tab”: “Soul Journal”,
“ai_tab”: “AI Therapist”,
“question_label”: “Please describe your question in detail”,
“question_placeholder”: “Example: I’m facing difficulties at work and don’t know which path to choose next…”,
“start_reading”: “Start Tarot Reading”,
“quota_text”: “Daily Free Readings”,
“quota_exceeded”: “Daily free quota exceeded! Come back tomorrow”,
“reading_complete”: “Your tarot reading is complete!”,
“mood_score”: “Today’s mood score”,
“energy_level”: “Energy level”,
“save_journal”: “Save Today’s Journal”,
“journal_saved”: “Journal saved! Another precious record added to your growth journey”
},
“zh”: {
“title”: “SoulCompass 心靈羅盤”,
“subtitle”: “找到內心的北極星”,
“features”: “塔羅占卜 | 數字占卜 | 心靈日記 | AI療癒師”,
“tarot_tab”: “塔羅占卜”,
“numerology_tab”: “數字占卜”,
“journal_tab”: “心靈日記”,
“ai_tab”: “AI療癒師”,
“question_label”: “請詳細描述您想要占卜的問題”,
“question_placeholder”: “例如:我最近在工作上遇到困難,不知道該如何選擇下一步…”,
“start_reading”: “開始塔羅占卜”,
“quota_text”: “每日免費占卜次數”,
“quota_exceeded”: “今日免費額度已用完!明天再來”,
“reading_complete”: “您的塔羅占卜已完成!”,
“mood_score”: “今日心情指數”,
“energy_level”: “能量水平”,
“save_journal”: “保存今日日記”,
“journal_saved”: “日記已保存!您的成長軌跡又增加了珍貴的記錄”
}
}
# 塔羅牌數據
TAROT_CARDS = {
“The Fool”: {
“meaning”: “New beginnings, adventure, innocence”,
“description”: “Represents the beginning of a life journey, symbolizing infinite possibilities”
},
“The Magician”: {
“meaning”: “Creativity, skill, willpower”,
“description”: “Has all the tools needed to achieve goals”
},
“The High Priestess”: {
“meaning”: “Intuition, mystery, inner wisdom”,
“description”: “Represents inner wisdom and intuitive guidance”
},
“The Empress”: {
“meaning”: “Fertility, motherhood, creation”,
“description”: “Symbolizes maternal energy and creativity”
},
“The Emperor”: {
“meaning”: “Authority, structure, control”,
“description”: “Represents authority and order”
},
“The Hierophant”: {
“meaning”: “Spiritual guidance, tradition”,
“description”: “Provides spiritual guidance and wisdom”
},
“The Lovers”: {
“meaning”: “Love, relationships, choices”,
“description”: “Symbolizes love and important choices”
},
“The Chariot”: {
“meaning”: “Victory, willpower, control”,
“description”: “Achieving victory through determination”
},
“Strength”: {
“meaning”: “Inner strength, courage”,
“description”: “Symbolizes inner courage and gentle strength”
},
“The Hermit”: {
“meaning”: “Introspection, searching, wisdom”,
“description”: “Represents inner exploration and seeking wisdom”
},
“Wheel of Fortune”: {
“meaning”: “Fate, cycles, change”,
“description”: “Symbolizes life cycles and transformation”
},
“Justice”: {
“meaning”: “Fairness, balance, truth”,
“description”: “Represents fairness and moral choices”
},
“The Hanged Man”: {
“meaning”: “Sacrifice, pause, new perspective”,
“description”: “Gaining new insights through letting go”
},
“Death”: {
“meaning”: “Transformation, endings, rebirth”,
“description”: “Represents endings and new beginnings”
},
“Temperance”: {
“meaning”: “Balance, patience, harmony”,
“description”: “Teaching balance and moderation”
},
“The Devil”: {
“meaning”: “Bondage, temptation, addiction”,
“description”: “Symbolizes inner fears and bondage”
},
“The Tower”: {
“meaning”: “Sudden change, destruction, awakening”,
“description”: “Represents sudden awakening and transformation”
},
“The Star”: {
“meaning”: “Hope, inspiration, healing”,
“description”: “Symbolizes hope and guidance”
},
“The Moon”: {
“meaning”: “Illusion, intuition, subconscious”,
“description”: “Represents subconscious and intuition”
},
“The Sun”: {
“meaning”: “Success, joy, vitality”,
“description”: “Symbolizes success and positive energy”
},
“Judgement”: {
“meaning”: “Rebirth, inner calling”,
“description”: “Represents spiritual awakening and rebirth”
},
“The World”: {
“meaning”: “Completion, achievement, fulfillment”,
“description”: “Represents goal achievement and completion”
}
}
# 初始化會話狀態
if ‘daily_usage’ not in st.session_state:
st.session_state.daily_usage = 0
if ‘language’ not in st.session_state:
st.session_state.language = ‘en’
if ‘journal_entries’ not in st.session_state:
st.session_state.journal_entries = []
def get_text(key):
“”“獲取當前語言的文本”””
return TEXTS[st.session_state.language].get(key, key)
def change_language():
“”“語言切換”””
lang_names = list(LANGUAGES.keys())
lang_codes = list(LANGUAGES.values())
```
current_index = 0
if st.session_state.language in lang_codes:
current_index = lang_codes.index(st.session_state.language)
selected_lang_name = st.selectbox(
"Language / 語言",
lang_names,
index=current_index
)
new_lang_code = LANGUAGES[selected_lang_name]
if new_lang_code != st.session_state.language:
st.session_state.language = new_lang_code
st.rerun()
```
# CSS樣式
st.markdown(”””
<style>
.main-header {
text-align: center;
background: linear-gradient(135deg, #6366F1 0%, #C084FC 100%);
color: white;
padding: 3rem 2rem;
border-radius: 20px;
margin-bottom: 2rem;
box-shadow: 0 20px 40px rgba(99, 102, 241, 0.3);
}
.main-header h1 {
font-size: 3.5rem;
font-weight: 600;
margin-bottom: 1rem;
text-shadow: 2px 2px 8px rgba(0,0,0,0.3);
}
.compass-icon {
font-size: 4rem;
margin-bottom: 1rem;
display: inline-block;
animation: compass-spin 3s ease-in-out infinite;
}
@keyframes compass-spin {
0%, 100% { transform: rotate(-10deg); }
50% { transform: rotate(10deg); }
}
.tarot-card {
background: linear-gradient(135deg, #1E3A8A 0%, #6366F1 100%);
border: 3px solid #F59E0B;
border-radius: 20px;
padding: 2rem;
color: white;
text-align: center;
margin: 1rem;
box-shadow: 0 15px 35px rgba(0,0,0,0.3);
transition: all 0.4s ease;
}
.tarot-card:hover {
transform: translateY(-5px) scale(1.02);
}
.reading-result {
background: linear-gradient(135deg, #6366F1 0%, #C084FC 100%);
color: white;
padding: 2.5rem;
border-radius: 20px;
margin: 2rem 0;
box-shadow: 0 15px 35px rgba(99, 102, 241, 0.3);
}
.quota-display {
background: linear-gradient(135deg, #F59E0B 0%, #FB923C 100%);
color: white;
padding: 1rem 2rem;
border-radius: 50px;
text-align: center;
font-weight: 600;
margin: 2rem auto;
max-width: 400px;
}
.feature-card {
background: white;
border-radius: 15px;
padding: 2rem;
box-shadow: 0 4px 15px rgba(0,0,0,0.1);
border: 2px solid transparent;
transition: all 0.3s ease;
height: 100%;
}
.feature-card:hover {
border-color: #6366F1;
transform: translateY(-2px);
}
.journal-entry {
background: #F8FAFC;
border-radius: 10px;
padding: 1.5rem;
margin: 1rem 0;
border-left: 4px solid #6366F1;
}
.ai-response {
background: linear-gradient(135deg, #E0E7FF 0%, #F3E8FF 100%);
border-radius: 15px;
padding: 1.5rem;
margin: 1rem 0;
border-left: 4px solid #6366F1;
}
</style>
“””, unsafe_allow_html=True)
# 語言選擇器
col1, col2, col3 = st.columns([2, 1, 1])
with col3:
change_language()
# 主標題
header_html = f”””
<div class="main-header">
<div class="compass-icon">🧭</div>
<h1>{get_text('title')}</h1>
<h2 style="font-size: 2rem; margin: 1rem 0;">{get_text('subtitle')}</h2>
<p style="font-size: 1.2rem; opacity: 0.9;">{get_text('features')}</p>
<div style="margin-top: 20px;">
<span style="background: rgba(255,255,255,0.2); padding: 8px 16px; border-radius: 20px; margin: 0 10px;">
15,247 users
</span>
<span style="background: rgba(255,255,255,0.2); padding: 8px 16px; border-radius: 20px; margin: 0 10px;">
💯 4.9/5 rating
</span>
</div>
</div>
"""
st.markdown(header_html, unsafe_allow_html=True)
# 剩餘額度顯示
remaining = 5 - st.session_state.daily_usage
quota_html = f”””
<div class="quota-display">
🎫 {get_text('quota_text')}: {remaining}/5
</div>
"""
st.markdown(quota_html, unsafe_allow_html=True)
# 主功能區域
tab1, tab2, tab3, tab4 = st.tabs([
f”🔮 {get_text(‘tarot_tab’)}”,
f”🔢 {get_text(‘numerology_tab’)}”,
f”📖 {get_text(‘journal_tab’)}”,
f”🤖 {get_text(‘ai_tab’)}”
])
# 塔羅占卜標籤
with tab1:
st.header(f”🔮 {get_text(‘tarot_tab’)}”)
st.markdown(”*Let ancient tarot wisdom guide your life’s direction*”)
```
question = st.text_area(
get_text('question_label'),
placeholder=get_text('question_placeholder'),
height=100
)
if question:
col1, col2 = st.columns(2)
with col1:
spread_type = st.selectbox(
"Choose Tarot Spread",
["Single Card - Quick Guidance", "Three Cards - Past Present Future", "Love Triangle - Relationship Focus"]
)
with col2:
spread_info = {
"Single Card - Quick Guidance": "Perfect for daily guidance and simple questions",
"Three Cards - Past Present Future": "Timeline reading to understand development",
"Love Triangle - Relationship Focus": "Specialized for relationship questions"
}
st.info(spread_info[spread_type])
if st.button(get_text('start_reading'), type="primary", use_container_width=True):
if st.session_state.daily_usage >= 5:
st.error(get_text('quota_exceeded'))
else:
st.session_state.daily_usage += 1
with st.spinner("🌟 Drawing tarot cards for you..."):
import time
time.sleep(2)
# 抽牌邏輯
num_cards = 1 if "Single" in spread_type else 3
drawn_cards = random.sample(list(TAROT_CARDS.keys()), num_cards)
st.success(f"✨ {get_text('reading_complete')}")
# 顯示抽到的牌
cols = st.columns(len(drawn_cards))
for i, card in enumerate(drawn_cards):
with cols[i]:
is_reversed = random.choice([True, False])
status = "Reversed" if is_reversed else "Upright"
card_html = f"""
<div class="tarot-card">
<h3>{card}</h3>
<p><strong>{status}</strong></p>
<p style="font-size: 0.9rem; opacity: 0.8;">{TAROT_CARDS[card]['meaning']}</p>
</div>
"""
st.markdown(card_html, unsafe_allow_html=True)
# 生成解讀
reading_text = f"""
```
🔮 **SoulCompass Reading for You**
**Your Question:** {question}
**Spread Used:** {spread_type}
**Cards Drawn:** {’, ’.join(drawn_cards)}
**Detailed Interpretation:**
{chr(10).join([f”**{card}:** {TAROT_CARDS[card][‘description’]}” for card in drawn_cards])}
**Overall Guidance:**
The cards reveal important insights about your situation. Trust your intuition as you move forward, and remember that you have the wisdom within you to make the right choices.
🌟 **Key Message:** Embrace the journey ahead with confidence and openness to new possibilities.
💫 **Readings used today:** {st.session_state.daily_usage}/5
“””
```
reading_html = f"""
<div class="reading-result">
{reading_text.replace(chr(10), '<br>')}
</div>
"""
st.markdown(reading_html, unsafe_allow_html=True)
```
# 數字占卜標籤
with tab2:
st.header(f”🔢 {get_text(‘numerology_tab’)}”)
st.markdown(”*Discover your life’s mysteries through the power of numbers*”)
```
col1, col2 = st.columns(2)
with col1:
st.subheader("📅 Life Path Number")
birth_date = st.date_input("Select your birth date")
if birth_date and st.button("🌟 Calculate Life Number"):
# 生命靈數計算
date_str = birth_date.strftime('%Y%m%d')
total = sum(int(digit) for digit in date_str if digit.isdigit())
while total > 9 and total not in [11, 22, 33]:
total = sum(int(digit) for digit in str(total))
life_meanings = {
1: "The Leader - Independent, pioneering, ambitious",
2: "The Cooperator - Diplomatic, peaceful, intuitive",
3: "The Communicator - Creative, expressive, optimistic",
4: "The Builder - Practical, disciplined, hardworking",
5: "The Freedom Seeker - Adventurous, energetic, curious",
6: "The Nurturer - Caring, responsible, family-oriented",
7: "The Seeker - Analytical, introspective, spiritual",
8: "The Achiever - Ambitious, organized, business-minded",
9: "The Humanitarian - Compassionate, generous, idealistic"
}
meaning = life_meanings.get(total, "Master Number - Special spiritual significance")
result_html = f"""
<div class="feature-card">
<h3>🌟 Your Life Path Number: {total}</h3>
<p><strong>{meaning}</strong></p>
<p>This number represents your core personality traits and life lessons.
It reveals the path you're meant to walk in this lifetime.</p>
</div>
"""
st.markdown(result_html, unsafe_allow_html=True)
with col2:
st.subheader("📝 Name Numerology")
name = st.text_input("Enter your full name")
if name and st.button("✨ Analyze Name Number"):
# 簡化的姓名數字計算
name_value = len(name) % 9 + 1
name_meanings = {
1: "Leadership Energy - You inspire others naturally",
2: "Harmony Energy - You bring peace and cooperation",
3: "Creative Energy - You express joy and optimism",
4: "Stability Energy - You provide structure and reliability",
5: "Freedom Energy - You bring change and adventure",
6: "Nurturing Energy - You care for and support others",
7: "Wisdom Energy - You seek deeper understanding",
8: "Success Energy - You achieve material accomplishment",
9: "Service Energy - You serve the greater good"
}
meaning = name_meanings[name_value]
result_html = f"""
<div class="feature-card">
<h3>✨ Your Name Number: {name_value}</h3>
<p><strong>{meaning}</strong></p>
<p>Your name carries this vibrational energy that influences how others
perceive you and how you express yourself in the world.</p>
</div>
"""
st.markdown(result_html, unsafe_allow_html=True)
```
# 心靈日記標籤
with tab3:
st.header(f”📖 {get_text(‘journal_tab’)}”)
st.markdown(”*Track your emotional journey and connect with your inner self*”)
```
# 今日心情記錄
st.subheader("🌈 Today's Mood Record")
col1, col2 = st.columns(2)
with col1:
mood_score = st.slider(get_text('mood_score'), 1, 10, 7)
main_emotion = st.selectbox(
"Primary emotion",
["😊 Happy", "😔 Sad", "😰 Anxious", "😡 Angry", "😌 Calm", "🤗 Grateful", "😴 Tired", "🤔 Confused"]
)
with col2:
energy_level = st.slider(get_text('energy_level'), 1, 10, 6)
gratitude = st.text_input("What are you grateful for today?", placeholder="Something that made you smile today...")
# 日記內容
journal_content = st.text_area(
"📝 Today's Soul Journal Entry",
placeholder="Write about your thoughts, feelings, experiences, or anything you want to record today...",
height=150
)
if st.button(get_text('save_journal'), type="primary"):
if journal_content:
entry = {
'date': datetime.now().strftime('%Y-%m-%d'),
'time': datetime.now().strftime('%H:%M'),
'mood': mood_score,
'emotion': main_emotion,
'energy': energy_level,
'gratitude': gratitude,
'content': journal_content
}
st.session_state.journal_entries.append(entry)
st.success(get_text('journal_saved'))
st.balloons()
else:
st.warning("Please write something in your journal entry")
# 顯示最近的日記記錄
if st.session_state.journal_entries:
st.subheader("📚 Recent Journal Entries")
for entry in reversed(st.session_state.journal_entries[-3:]): # 顯示最近3條
entry_html = f"""
<div class="journal-entry">
<div style="display: flex; justify-content: space-between; align-items: center;">
<strong>{entry['date']} {entry['time']}</strong>
<span>{entry['emotion']} | Mood: {entry['mood']}/10 | Energy: {entry['energy']}/10</span>
</div>
<p style="margin: 10px 0;"><strong>Grateful for:</strong> {entry['gratitude']}</p>
<p style="margin: 10px 0; font-style: italic;">"{entry['content'][:100]}{'...' if len(entry['content']) > 100 else ''}"</p>
</div>
"""
st.markdown(entry_html, unsafe_allow_html=True)
```
# AI療癒師標籤
with tab4:
st.header(f”🤖 {get_text(‘ai_tab’)}”)
st.markdown(”*24/7 soul guide providing warm support and guidance*”)
```
# AI療癒師介紹
ai_intro_html = """
<div style="background: linear-gradient(135deg, #F3F4F6 0%, #E5E7EB 100%); padding: 20px; border-radius: 15px; margin: 20px 0;">
<div style="display: flex; align-items: center; margin-bottom: 15px;">
<div style="font-size: 3rem; margin-right: 15px;">🤖</div>
<div>
<h4 style="margin: 0; color: #6366F1;">SoulCompass AI Therapist</h4>
<p style="margin: 5px 0; color: #6B7280;">Your dedicated soul guide, always here to provide support and companionship</p>
</div>
</div>
<div style="color: #6B7280; font-size: 0.9rem;">
💬 Emotional support 🧘 Relaxation guidance 🌱 Growth advice 🫂 24/7 companionship
</div>
</div>
"""
st.markdown(ai_intro_html, unsafe_allow_html=True)
# 對話類型選擇
conversation_type = st.selectbox(
"🎯 Choose conversation topic",
[
"💭 General Soul Conversation",
"😰 Stress & Anxiety Support",
"💔 Relationship Counseling",
"🎯 Life Goals Discussion",
"🧘 Meditation & Relaxation",
"🌱 Personal Growth Advice"
]
)
# 對話輸入
user_message = st.text_area(
"💬 Share your thoughts with the AI Therapist",
placeholder="Tell me how you're feeling, or what you'd like to discuss...",
height=100
)
if user_message and st.button("💫 Start Conversation", type="primary"):
with st.spinner("🤖 AI Therapist is listening and preparing a response..."):
import time
time.sleep(1.5)
# AI回應生成
responses = {
"💭 General Soul Conversation": [
f"Thank you for sharing with me. I can sense that what you've told me - '{user_message}' - comes from a place of genuine reflection. Your willingness to explore your inner world shows great courage.",
f"I hear you saying '{user_message}' and I want you to know that your feelings are completely valid. Sometimes the simple act of expressing our thoughts can be the first step toward greater clarity.",
f"What you've shared - '{user_message}' - resonates deeply. Every person's journey is unique, and I'm honored that you've chosen to share this part of yours with me."
],
"😰 Stress & Anxiety Support": [
f"I understand you're experiencing stress around '{user_message}'. Anxiety can feel overwhelming, but remember - you've successfully navigated 100% of your difficult days so far. Let's breathe through this together.",
f"Your stress about '{user_message}' is completely understandable. Right now, let's focus on what you can control in this moment. Take a deep breath in for 4 counts, hold for 4, and exhale for 6.",
f"Thank you for trusting me with your anxiety about '{user_message}'. You're stronger than you realize, and this feeling will pass. Let's find some small steps to help you feel more grounded."
],
"💔 Relationship Counseling": [
f"Relationships can be complex, and what you've shared about '{user_message}' shows how much you care. Love requires both vulnerability and strength - you're showing both right now.",
f"I can hear the emotion in your words about '{user_message}'. Relationships are mirrors that help us grow, even when they challenge us. Your heart's capacity for love is a gift.",
f"The situation you've described - '{user_message}' - touches on the deep human need for connection. Remember, the relationship you have with yourself sets the foundation for all others."
]
}
response_list = responses.get(conversation_type, responses["💭 General Soul Conversation"])
ai_response = random.choice(response_list)
# 顯示對話
conversation_html = f"""
<div style="margin: 20px 0;">
<div style="background: #E5E7EB; padding: 15px; border-radius: 15px 15px 5px 15px; margin-bottom: 10px;">
<strong>You:</strong> {user_message}
</div>
<div class="ai-response">
<strong>🤖 AI Therapist:</strong> {ai_response}
<br><br>
<small style="opacity: 0.8;">💙 Remember: I'm here to support you, but for serious mental health concerns, please consult a professional therapist.</small>
</div>
</div>
"""
st.markdown(conversation_html, unsafe_allow_html=True)
```
# 頁腳
st.markdown(”—”)
footer_html = “””
<div style="text-align: center; color: #6B7280; padding: 2rem;">
<p>🧭 <strong>SoulCompass</strong> - Find Your Inner North Star</p>
<p>Made with ❤️ for seekers of wisdom and growth worldwide</p>
<div style="margin: 20px 0;">
<span style="margin: 0 15px;">📧 [email protected]</span>
<span style="margin: 0 15px;">🌐 www.soulcompass.ai</span>
<span style="margin: 0 15px;">📱 @SoulCompassAI</span>
</div>
<p>💎 <a href="#" style="color: #6366F1; text-decoration: none;">Upgrade to Pro</a> for unlimited readings and advanced features</p>
</div>
"""
st.markdown(footer_html, unsafe_allow_html=True)