import streamlit as st import folium from streamlit_folium import folium_static from datetime import datetime import gspread from google.oauth2.service_account import Credentials import os import json import random # تنظیمات اولیه st.set_page_config(layout="wide", page_title="راهیار - تحلیل انصاف قیمتی", page_icon="🚖") # ========== تنظیمات دیتا ========== SHEET_ID = "1mmdWAyOCYq4yXMgP53Duq712AnlqZWLkfIo76JqM7wM" SHEET_NAME = "Condition1" # ========== استایل‌های سفارشی ========== st.markdown(""" """, unsafe_allow_html=True) # ========== توابع اصلی ========== def create_ride_map(): """ایجاد نقشه سفر با Folium""" # مختصات تهران (میدان ونک تا میدان تجریش) start_point = [35.7698, 51.4116] # میدان ونک end_point = [35.8044, 51.4258] # میدان تجریش m = folium.Map(location=[35.7871, 51.4187], zoom_start=13) # اضافه کردن مبدأ و مقصد folium.Marker( start_point, popup="مبدأ: میدان ونک", icon=folium.Icon(color="green", icon="flag", prefix="fa") ).add_to(m) folium.Marker( end_point, popup="مقصد: میدان تجریش", icon=folium.Icon(color="red", icon="flag", prefix="fa") ).add_to(m) # خط مسیر folium.PolyLine( [start_point, end_point], color="#6a0dad", weight=3, opacity=1 ).add_to(m) return m def show_explanation(exp_type): """نمایش توضیحات قیمت""" explanations = { "input": [ "سطح تقاضا در منطقه: زیاد", "تعداد رانندگان فعال: کم", "زمان روز: ساعت اوج ترافیک", "شرایط جوی: هوای بارانی" ], "counterfactual": [ "اگر این سفر را ۳۰ دقیقه زودتر یا دیرتر درخواست می‌کردید، قیمت ۱۵٪ کمتر می‌شد", "اگر تعداد رانندگان فعال دو برابر بود، قیمت‌گذاری نوسانی اعمال نمی‌شد" ] } if exp_type != "control": st.markdown("

علت قیمت گذاری:

", unsafe_allow_html=True) for item in explanations.get(exp_type, []): st.markdown(f"

• {item}

", unsafe_allow_html=True) # ========== توابع مدیریت داده‌ها ========== def get_credentials(): """دریافت اعتبارنامه از Secrets""" try: service_account_json = os.environ.get('GCP_SERVICE_ACCOUNT') if not service_account_json: st.error("مقدار GCP_SERVICE_ACCOUNT در محیط یافت نشد") return None service_account_info = json.loads(service_account_json) creds = Credentials.from_service_account_info( service_account_info, scopes=[ "https://www.googleapis.com/auth/spreadsheets", "https://www.googleapis.com/auth/drive.file" ] ) return creds except Exception as e: st.error(f"خطا در دریافت اعتبارنامه: {str(e)}") return None def save_to_sheet(data): try: creds = get_credentials() if not creds: return False client = gspread.authorize(creds) spreadsheet = client.open_by_key(SHEET_ID) worksheet = spreadsheet.worksheet(SHEET_NAME) row_data = [ datetime.now().strftime("%Y-%m-%d %H:%M:%S"), data.get("scenario_type"), data.get("price"), data.get("age"), data.get("gender"), data.get("education"), data.get("ride_frequency"), *data.get("transparency_answers", []), *data.get("fairness_answers", []) ] worksheet.append_row(row_data) return True except Exception as e: st.error(f"خطا در ذخیره‌سازی: {str(e)}") return False # ========== بخش‌های فرم ========== def welcome_page(): """صفحه خوشامدگویی""" st.markdown("""

تحلیل انصاف قیمتی در پلتفرم‌های اشتراک سفر

این تحقیق به بررسی تأثیر توضیحات قیمت بر ادراک انصاف می‌پردازد

درباره تحقیق:

این پرسشنامه بخشی از یک پژوهش علمی است که به بررسی ادراک انصاف در قیمت‌گذاری پویا می‌پردازد.

پس از مشاهده سناریو، لطفاً به سوالات پاسخ دهید.

""", unsafe_allow_html=True) if st.button("شروع پرسشنامه", key="start_btn", type="primary"): st.session_state.current_page = "demographic" st.rerun() def demographic_form(): """فرم اطلاعات دموگرافیک""" with st.form("demographic"): st.header("📝 اطلاعات دموگرافیک") age = st.number_input("سن", min_value=18, max_value=100) gender = st.selectbox("جنسیت", ["مرد", "زن", "سایر"]) education = st.selectbox("تحصیلات", ["دیپلم", "لیسانس", "فوق لیسانس", "دکترا"]) ride_frequency = st.selectbox("دفعات استفاده از سرویس‌های اشتراک سفر در ماه", ["کمتر از 5 بار", "5-10 بار", "بیش از 10 بار"]) if st.form_submit_button("ادامه"): st.session_state.demographic_data = { "age": age, "gender": gender, "education": education, "ride_frequency": ride_frequency } st.session_state.current_page = "scenario_explanation" st.rerun() def scenario_explanation(): """توضیح سناریو""" st.markdown("""
لوگوی راهیار

راهیار 🚖

سفرهای درون شهری سریع و مطمئن

""", unsafe_allow_html=True) st.markdown("### سناریوی تحقیق") if st.session_state.scenario_type == "control": st.markdown("""

شما قصد دارید سفری را از مبدأ میدان ونک به مقصد میدان تجریش درخواست کنید.

قیمت پیشنهادی این سفر 200,000 تومان است.

""", unsafe_allow_html=True) else: st.markdown("""

شما قصد دارید سفری را از مبدأ میدان ونک به مقصد میدان تجریش درخواست کنید.

قیمت پیشنهادی این سفر 200,000 تومان است.

پلتفرم توضیحاتی درباره علت این قیمت ارائه می‌دهد.

""", unsafe_allow_html=True) if st.button("ادامه", key="continue_btn", type="primary"): st.session_state.current_page = "map_view" st.rerun() def map_view(): """نمایش نقشه و قیمت""" st.markdown("""

راهیار 🚖

سفرهای درون شهری سریع و مطمئن

""", unsafe_allow_html=True) st.markdown("### مسیر سفر شما") folium_static(create_ride_map(), width=800, height=400) st.markdown(f"""
راهیار به صرفه {st.session_state.price:,} تومان
""", unsafe_allow_html=True) show_explanation(st.session_state.scenario_type) if st.button("درخواست راهیار", key="request_btn", type="primary"): st.session_state.current_page = "transparency_questions" st.rerun() def create_likert_question(question, key): """سوال لیکرت با دکمه‌ها""" st.markdown(f"

{question}

", unsafe_allow_html=True) cols = st.columns(5) options = { 1: "کاملاً مخالفم", 2: "مخالفم", 3: "نظری ندارم", 4: "موافقم", 5: "کاملاً موافقم" } selected = st.session_state.get(key, None) for value, label in options.items(): with cols[value-1]: if st.button( label, key=f"{key}_{value}", on_click=lambda v=value: st.session_state.update({key: v}), type="primary" if selected == value else "secondary" ): pass if selected: st.markdown(f"

پاسخ شما: {options[selected]}

", unsafe_allow_html=True) return selected def transparency_questions(): """سوالات شفافیت""" st.header("📊 پرسشنامه شفافیت قیمت") st.markdown("**لطفاً میزان موافقت خود با جملات زیر را مشخص کنید:**") questions = [ "پلتفرم به صورت صادقانه دلایل تغییر قیمت (مثل افزایش تقاضا یا شرایط جوی) را توضیح داد.", "پلتفرم به طور کامل عوامل مؤثر بر قیمت (مثل ترافیک، تعداد رانندگان) را شرح داد.", "دلایل ارائه‌شده برای تغییر قیمت منطقی و قابل قبول بود.", "توضیحات درباره قیمت بلافاصله و در زمان مناسب نمایش داده شد.", "توضیحات پلتفرم متناسب با شرایط سفر من (مثل مسیر یا ساعت درخواست) بود." ] answers = [] for i, question in enumerate(questions): answer = create_likert_question(question, f"transparency_q{i}") answers.append(answer) if None not in answers: st.session_state.transparency_answers = answers if st.button("ادامه به سوالات بعدی", type="primary"): st.session_state.current_page = "fairness_questions" st.rerun() def fairness_questions(): """سوالات انصاف""" st.header("📊 پرسشنامه ادراک انصاف") st.markdown("**لطفاً میزان موافقت خود با جملات زیر را مشخص کنید:**") questions = [ "قیمتی که به شما ارائه شد، منصفانه است.", "قیمتی که به شما ارائه شد، معقول است.", "قیمتی که به شما ارائه شد، قابل قبول است.", "فرآیند و رویه قیمت‌گذاری پلتفرم قابل قبول است.", "فرآیند و رویه قیمت‌گذاری پلتفرم منصفانه است.", "فرآیند و رویه قیمت‌گذاری پلتفرم معقول است." ] answers = [] for i, question in enumerate(questions): answer = create_likert_question(question, f"fairness_q{i}") answers.append(answer) if None not in answers: st.session_state.fairness_answers = answers if st.button("ارسال پاسخ‌ها", type="primary"): all_data = { "scenario_type": st.session_state.scenario_type, "price": st.session_state.price, **st.session_state.demographic_data, "transparency_answers": st.session_state.transparency_answers, "fairness_answers": st.session_state.fairness_answers } if save_to_sheet(all_data): st.session_state.current_page = "thank_you" st.rerun() def thank_you_page(): """صفحه تشکر""" st.success("✅ پاسخ‌های شما با موفقیت ثبت شد. با تشکر از مشارکت شما در این تحقیق!") st.balloons() if st.button("بازگشت به ابتدا"): st.session_state.clear() st.rerun() # ========== مدیریت وضعیت و صفحه‌بندی ========== def main(): if 'current_page' not in st.session_state: st.session_state.current_page = "welcome" st.session_state.scenario_type = random.choice(["control", "input", "counterfactual"]) st.session_state.price = 200000 # قیمت ثابت 200 هزار تومان st.session_state.demographic_data = None st.session_state.transparency_answers = [] st.session_state.fairness_answers = [] # نمایش صفحه فعلی pages = { "welcome": welcome_page, "demographic": demographic_form, "scenario_explanation": scenario_explanation, "map_view": map_view, "transparency_questions": transparency_questions, "fairness_questions": fairness_questions, "thank_you": thank_you_page } pages[st.session_state.current_page]() if __name__ == "__main__": main()