File size: 18,995 Bytes
9324460
a5344e7
 
9324460
 
 
 
 
52c4f98
9324460
 
f261783
9324460
 
 
 
 
a5344e7
 
 
901ba48
 
 
 
f261783
6bb8f00
 
 
 
 
f261783
 
 
 
 
 
 
 
6bb8f00
f261783
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6bb8f00
f261783
3e69f41
 
 
 
 
 
901ba48
 
3e69f41
 
 
a5344e7
901ba48
a5344e7
 
 
 
 
 
0db1c6d
 
 
 
 
 
 
 
 
 
2d25226
 
 
 
 
 
 
 
 
 
 
5b2a67d
 
 
019a41d
5b2a67d
 
 
 
 
 
 
 
 
 
2d25226
a5344e7
 
 
 
 
f261783
 
901ba48
0db1c6d
901ba48
0db1c6d
901ba48
 
f261783
 
 
 
 
901ba48
f261783
 
 
 
 
c7cccd2
f261783
 
 
 
 
 
 
a5344e7
 
 
 
 
 
 
901ba48
 
 
 
a5344e7
 
 
 
 
 
 
 
2d25226
3e69f41
2d25226
a5344e7
 
9324460
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a5344e7
 
9324460
 
 
 
3e69f41
 
9324460
 
 
 
 
 
 
 
 
a5344e7
3e69f41
 
 
 
d579640
 
 
 
3e69f41
 
 
 
d579640
 
 
3e69f41
 
 
 
15a4217
3e69f41
 
d579640
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ef9917f
2fcbac2
6cf32ac
15a4217
d579640
 
a5344e7
 
 
 
 
 
 
 
 
 
3e69f41
 
a5344e7
 
 
 
 
3e69f41
 
9324460
3e69f41
 
897a647
44231f7
897a647
 
 
 
44231f7
 
b0eb4d9
5b2a67d
44231f7
9324460
3e69f41
9324460
3e69f41
dab26a6
3e69f41
 
 
dab26a6
 
3e69f41
 
 
5b2a67d
 
 
3e69f41
 
 
 
 
 
a5344e7
3e69f41
 
897a647
607c219
897a647
 
 
 
607c219
 
5b2a67d
 
607c219
3e69f41
 
 
 
 
34a39f5
f261783
 
 
 
3e69f41
f261783
 
3e69f41
5b2a67d
 
 
 
 
 
 
3e69f41
5b2a67d
3e69f41
 
a5344e7
3e69f41
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0db1c6d
3e69f41
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a5344e7
9324460
3e69f41
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2d25226
 
 
 
 
6cf32ac
2d25226
 
 
3e69f41
2d25226
 
 
e8b5c94
2d25226
 
 
 
 
 
 
3e69f41
2d25226
3e69f41
9324460
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
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("""
<style>
    @font-face {
        font-family: 'Vazir';
        src: url('https://cdn.jsdelivr.net/gh/rastikerdar/vazir-font@v30.1.0/dist/Vazir.woff') format('woff');
    }
    
    * {
        font-family: 'Vazir', sans-serif !important;
        text-align: right !important;
        direction: rtl !important;
    }
    
    .rahyar-header {
        background-color: #6a0dad;
        padding: 15px;
        border-radius: 10px;
        color: white;
        margin-bottom: 20px;
        text-align: center;
    }
    
    .price-container {
        background-color: #f8f9fa;
        border-radius: 10px;
        padding: 15px;
        margin: 15px 0;
        border-right: 5px solid #6a0dad;
    }
    
    .rahyar-price {
        color: #6a0dad;
        font-size: 28px;
        font-weight: bold;
        text-align: center;
        margin: 10px 0;
    }
    
    .rahyar-btn {
        background-color: #6a0dad !important;
        color: white !important;
        border: none !important;
        padding: 10px 20px !important;
        border-radius: 8px !important;
        font-weight: bold !important;
        margin: 5px 0 !important;
        width: 100% !important;
    }
    
    .likert-btn {
        margin: 5px;
        padding: 10px 15px;
        border-radius: 8px;
        border: 1px solid #ddd;
        background-color: white;
    }
    
    .likert-btn-selected {
        border: 2px solid #6a0dad !important;
        background-color: #f0e6ff !important;
    }
    
    .survey-section {
        background-color: #f0f2f6;
        border-radius: 10px;
        padding: 20px;
        margin-top: 30px;
    }
    
    .rahyar-badge {
        background-color: #e6e6fa;
        color: #6a0dad;
        padding: 5px 10px;
        border-radius: 15px;
        font-size: 14px;
        display: inline-block;
        margin-left: 10px;
    }
    
    .explanation-title {
        color: #6a0dad;
        font-weight: bold;
        margin-top: 20px;
    }
    
    .explanation-item {
        margin: 10px 0;
        padding-right: 15px;
        border-right: 3px solid #6a0dad;
        
    .fake-btn {
        background-color: #6a0dad !important;
        color: #6a0dad !important;
        border: none !important;
        padding: 12px 24px !important;
        border-radius: 8px !important;
        font-weight: bold !important;
        cursor: pointer;
        transition: transform 0.2s;
    }
    .fake-btn:active {
        transform: scale(0.95);
    }
    }
</style>
""", 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="<b>مبدأ:</b> میدان ونک",
        icon=folium.Icon(color="green", icon="flag", prefix="fa")
    ).add_to(m)
    
    folium.Marker(
        end_point,
        popup="<b>مقصد:</b> میدان تجریش",
        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("<p class='explanation-title'>علت قیمت گذاری:</p>", unsafe_allow_html=True)
        for item in explanations.get(exp_type, []):
            st.markdown(f"<p class='explanation-item'>• {item}</p>", 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("""
    <div style="text-align: center; margin-bottom: 30px;">
        <h2> 🚖 قیمت‌گذاری در پلتفرم‌های درخواست تاکسی اینترنتی</h2>
        <p>👋با سلام و درود</p>
        <p>پیشاپیش بابت زمانی که برای پاسخ به سوالات این پرسشنامه و پیش‌برد اهداف علمی دانشجویان می‌گذارید، متشکرم.</p>
        <p>جهت تقدیر از شرکت‌کنندگان، به دو نفر به قید قرعه جایزه 5 میلیون ریالی تقدیم خواهد شد.</p>
    </div>
    
    <div style="background-color: #f0f2f6; border-radius: 10px; padding: 20px;">
        <h3>درباره تحقیق:</h3>
        <p>این پرسشنامه بخشی از یک پایان‌نامه کارشناسی ارشد در دانشگاه صنعتی شریف است که به بررسی ادراک انصاف در قیمت‌گذاری در پلتفرم‌های درخواست تاکسی اینترنتی می‌پردازد.</p>
        <p>پاسخ‌های شما به سوالات کاملاً محرمانه خواهد بود و فقط در جهت اهداف علمی استفاده خواهد شذ.</p>
        <p>جهت شروع روی دکمه زیر کلیک کنید 👇🏻</p>
    </div>
    """, unsafe_allow_html=True)
    
    if st.button("شروع پرسشنامه", key="start_btn", type="primary"):
        st.session_state.current_page = "contact"
        st.rerun()


def user_contact():
    """راه ارتباطی ساده"""
    st.markdown("""
    <div style="margin-bottom: 20px;">
        <h3 style="color: #6a0dad;">📩 راه ارتباطی شما (اختیاری)</h3>
        <p>در صورت تمایل به شرکت در قرعه‌کشی می‌توانید آیدی تلگرام، شماره تماس یا ایمیل خود را وارد کنید:</p>
    </div>
    """, unsafe_allow_html=True)

    contact_info = st.text_input(
        "راه ارتباطی (اختیاری)",
        placeholder="مثال: @username یا 09123456789 یا example@email.com",
        key="user_contact_input"
    )

    if st.button("ادامه", key="continue_btn", type="primary"):  # تغییر کلید
        st.session_state.user_contact = contact_info
        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():
    """توضیح سناریو"""
    col1, col2 = st.columns([1, 4])
    with col1:
        try:
            st.image("rahyar.png", width=80)
        except:
            st.image("https://via.placeholder.com/80/6a0dad/FFFFFF?text=LOGO", width=80)
    with col2:
        st.markdown("""
        <h2 style="color: #6a0dad; margin: 0;">رهیار 🚖</h2>
        <p style="color: #6a0dad; margin: 0;">همراه سفرهای درون‌شهری شما، راهی مطمئن، راهی روشن، رهیار</p>
        """, unsafe_allow_html=True)
    
    st.markdown("### سناریوی تحقیق")
    
    if st.session_state.scenario_type == "control":
        st.markdown("""
        <div style="background-color: #f8f9fa; padding: 15px; border-radius: 10px;">
            <p>شما قصد دارید سفری را از مبدأ میدان ونک به مقصد میدان تجریش درخواست کنید.</p>
            <p>قیمت پیشنهادی این سفر 200,000 تومان است.</p>
        </div>
        """, unsafe_allow_html=True)
    else:
        st.markdown("""
        <div style="background-color: #f8f9fa; padding: 15px; border-radius: 10px;">
            <p>فرض کنید یک اپلیکیشن حمل‌ونقل آنلاین ایرانی به اسم  رهیار طراحی شده، چیزی شبیه اسنپ یا تپسی، اما جدیدتر و با شعار "همراه سفرهای شما، راهی مطمئن، راهی روشن، رهیار"</p>
            <p>در یک روز عادی، شما قصد دارید برای سفری از طریق این پلتفرم اقدام کنید..</p>
            <p>با کلیک بر دکمه ادامه، اطلاعات سفر را مشاهده کنید.</p>
        </div>
        """, unsafe_allow_html=True)
    
    if st.button("ادامه", key="continue_btn", type="primary"):
        st.session_state.current_page = "map_view"
        st.rerun()

def map_view():
    """نمایش نقشه و قیمت"""
    col1, col2 = st.columns([1, 4])
    with col1:
        try:
            st.image("rahyar.png", width=80)
        except:
            st.image("https://via.placeholder.com/80/6a0dad/FFFFFF?text=LOGO", width=80)
    with col2:
        st.markdown("""
        <h2 style="color: #6a0dad; margin: 0;">رهیار 🚖</h2>
        <p style="color: #6a0dad; margin: 0;">همراه سفرهای درون‌شهری شما، راهی مطمئن، راهی روشن، رهیار</p>
        """, unsafe_allow_html=True)
    
    st.markdown("### مسیر سفر شما")
    folium_static(create_ride_map(), width=800, height=400)
    
    st.markdown(f"""
    <div class="price-container">
        <div style="display: flex; justify-content: space-between; align-items: center;">
            <span>راهیار <span class="rahyar-badge">به صرفه</span></span>
            <span class="rahyar-price">{st.session_state.price:,} تومان</span>
        </div>
    </div>
    """, unsafe_allow_html=True)
    
    show_explanation(st.session_state.scenario_type)

    
    st.markdown("""
    <div style="text-align: center;">
        <button class="fake-btn">درخواست راهیار</button>
    </div>
    """, unsafe_allow_html=True)
    
    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"<p style='margin-bottom: 10px;'>{question}</p>", 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"<p style='color: #6a0dad;'>پاسخ شما: {options[selected]}</p>", 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()