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("""👋با سلام و درود
پیشاپیش بابت زمانی که برای پاسخ به سوالات این پرسشنامه و پیشبرد اهداف علمی دانشجویان میگذارید، متشکرم.
جهت تقدیر از شرکتکنندگان، به دو نفر به قید قرعه جایزه 5 میلیون ریالی تقدیم خواهد شد.
این پرسشنامه بخشی از یک پایاننامه کارشناسی ارشد در دانشگاه صنعتی شریف است که به بررسی ادراک انصاف در قیمتگذاری در پلتفرمهای درخواست تاکسی اینترنتی میپردازد.
پاسخهای شما به سوالات کاملاً محرمانه خواهد بود و فقط در جهت اهداف علمی استفاده خواهد شذ.
جهت شروع روی دکمه زیر کلیک کنید 👇🏻
در صورت تمایل به شرکت در قرعهکشی میتوانید آیدی تلگرام، شماره تماس یا ایمیل خود را وارد کنید:
همراه سفرهای درونشهری شما، راهی مطمئن، راهی روشن، رهیار
""", unsafe_allow_html=True) st.markdown("### سناریوی تحقیق") if st.session_state.scenario_type == "control": st.markdown("""شما قصد دارید سفری را از مبدأ میدان ونک به مقصد میدان تجریش درخواست کنید.
قیمت پیشنهادی این سفر 200,000 تومان است.
فرض کنید یک اپلیکیشن حملونقل آنلاین ایرانی به اسم رهیار طراحی شده، چیزی شبیه اسنپ یا تپسی، اما جدیدتر و با شعار "همراه سفرهای شما، راهی مطمئن، راهی روشن، رهیار"
در یک روز عادی، شما قصد دارید برای سفری از طریق این پلتفرم اقدام کنید..
با کلیک بر دکمه ادامه، اطلاعات سفر را مشاهده کنید.
همراه سفرهای درونشهری شما، راهی مطمئن، راهی روشن، رهیار
""", unsafe_allow_html=True) st.markdown("### مسیر سفر شما") folium_static(create_ride_map(), width=800, height=400) 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.user_contact = None st.session_state.demographic_data = None st.session_state.transparency_answers = [] st.session_state.fairness_answers = [] # نمایش صفحه فعلی pages = { "welcome": welcome_page, "contact": user_contact, "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()