Spaces:
Paused
Paused
Maryam Ilka commited on
Update app.py
Browse files
app.py
CHANGED
|
@@ -7,6 +7,7 @@ from google.oauth2.service_account import Credentials
|
|
| 7 |
import os
|
| 8 |
import json
|
| 9 |
import random
|
|
|
|
| 10 |
|
| 11 |
# تنظیمات اولیه
|
| 12 |
st.set_page_config(layout="wide", page_title="راهیار - تحلیل انصاف قیمتی", page_icon="🚖")
|
|
@@ -260,19 +261,20 @@ def show_explanation(exp_type):
|
|
| 260 |
for item in explanations.get(exp_type, []):
|
| 261 |
st.markdown(f"<p class='explanation-item'>• {item}</p>", unsafe_allow_html=True)
|
| 262 |
|
| 263 |
-
def create_likert_question(question, key):
|
| 264 |
"""سوال لیکرت با دکمهها"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 265 |
st.markdown(f"<p style='margin-bottom: 10px;'>{question}</p>", unsafe_allow_html=True)
|
| 266 |
|
| 267 |
cols = st.columns(5)
|
| 268 |
-
options = {
|
| 269 |
-
1: "کاملاً مخالفم",
|
| 270 |
-
2: "مخالفم",
|
| 271 |
-
3: "نظری ندارم",
|
| 272 |
-
4: "موافقم",
|
| 273 |
-
5: "کاملاً موافقم"
|
| 274 |
-
}
|
| 275 |
-
|
| 276 |
selected = st.session_state.get(key, None)
|
| 277 |
|
| 278 |
for value, label in options.items():
|
|
@@ -321,9 +323,22 @@ def save_to_sheet(data):
|
|
| 321 |
client = gspread.authorize(creds)
|
| 322 |
spreadsheet = client.open_by_key(SHEET_ID)
|
| 323 |
worksheet = spreadsheet.worksheet(SHEET_NAME)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 324 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 325 |
row_data = [
|
| 326 |
-
datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
| 327 |
data.get("scenario_type"),
|
| 328 |
data.get("price"),
|
| 329 |
data.get("age"),
|
|
@@ -331,11 +346,14 @@ def save_to_sheet(data):
|
|
| 331 |
data.get("education"),
|
| 332 |
data.get("ride_frequency"),
|
| 333 |
st.session_state.get("user_contact", ""),
|
| 334 |
-
*
|
| 335 |
-
|
|
|
|
| 336 |
st.session_state.get("explanation_data", {}).get("explanation_received", ""),
|
| 337 |
st.session_state.get("explanation_data", {}).get("explanation_type", ""),
|
| 338 |
-
data.get("price_accepted", 0)
|
|
|
|
|
|
|
| 339 |
]
|
| 340 |
|
| 341 |
worksheet.append_row(row_data)
|
|
@@ -372,6 +390,7 @@ def welcome_page():
|
|
| 372 |
|
| 373 |
if st.button("شروع پرسشنامه", key="start_btn", type="primary"):
|
| 374 |
st.session_state.current_page = "contact"
|
|
|
|
| 375 |
st.rerun()
|
| 376 |
|
| 377 |
|
|
@@ -476,61 +495,133 @@ def map_view():
|
|
| 476 |
with col1:
|
| 477 |
if st.button("درخواست راهیار", key="accept_btn", use_container_width=True):
|
| 478 |
st.session_state.price_accepted = 1
|
| 479 |
-
st.session_state.current_page = "
|
| 480 |
st.rerun()
|
| 481 |
|
| 482 |
with col2:
|
| 483 |
if st.button("رد قیمت", key="reject_btn", use_container_width=True):
|
| 484 |
st.session_state.price_accepted = 0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 485 |
st.session_state.current_page = "transparency_questions"
|
| 486 |
st.rerun()
|
| 487 |
-
|
| 488 |
-
|
| 489 |
-
|
| 490 |
-
|
| 491 |
-
|
| 492 |
-
|
| 493 |
-
|
| 494 |
-
|
| 495 |
-
|
| 496 |
-
|
| 497 |
-
"
|
| 498 |
-
"ت
|
| 499 |
-
|
| 500 |
-
|
| 501 |
-
|
| 502 |
-
|
| 503 |
-
|
| 504 |
-
|
| 505 |
-
|
| 506 |
-
|
| 507 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 508 |
st.session_state.current_page = "fairness_questions"
|
| 509 |
st.rerun()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 510 |
|
| 511 |
def fairness_questions():
|
| 512 |
-
"""سوالات انصاف"""
|
| 513 |
-
|
| 514 |
-
|
| 515 |
-
|
| 516 |
-
|
| 517 |
-
|
| 518 |
-
|
| 519 |
-
|
| 520 |
-
|
| 521 |
-
|
| 522 |
-
|
| 523 |
-
|
| 524 |
-
|
| 525 |
-
|
| 526 |
-
|
| 527 |
-
|
| 528 |
-
|
| 529 |
-
|
| 530 |
-
|
| 531 |
-
if
|
| 532 |
-
st.session_state.
|
|
|
|
| 533 |
st.rerun()
|
|
|
|
|
|
|
|
|
|
| 534 |
|
| 535 |
|
| 536 |
def explanation_questions():
|
|
@@ -582,8 +673,8 @@ def explanation_questions():
|
|
| 582 |
"scenario_type": st.session_state.scenario_type,
|
| 583 |
"price": st.session_state.price,
|
| 584 |
**st.session_state.demographic_data,
|
| 585 |
-
"transparency_answers": st.session_state.
|
| 586 |
-
"fairness_answers": st.session_state.
|
| 587 |
"explanation_received": explanation_received,
|
| 588 |
"explanation_type": explanation_type if explanation_received == "بله" else "N/A",
|
| 589 |
"price_accepted": st.session_state.get("price_accepted", 0)
|
|
@@ -626,6 +717,8 @@ def main():
|
|
| 626 |
"demographic": demographic_form,
|
| 627 |
"scenario_explanation": scenario_explanation,
|
| 628 |
"map_view": map_view,
|
|
|
|
|
|
|
| 629 |
"transparency_questions": transparency_questions,
|
| 630 |
"fairness_questions": fairness_questions,
|
| 631 |
"explanation_questions": explanation_questions,
|
|
|
|
| 7 |
import os
|
| 8 |
import json
|
| 9 |
import random
|
| 10 |
+
import time
|
| 11 |
|
| 12 |
# تنظیمات اولیه
|
| 13 |
st.set_page_config(layout="wide", page_title="راهیار - تحلیل انصاف قیمتی", page_icon="🚖")
|
|
|
|
| 261 |
for item in explanations.get(exp_type, []):
|
| 262 |
st.markdown(f"<p class='explanation-item'>• {item}</p>", unsafe_allow_html=True)
|
| 263 |
|
| 264 |
+
def create_likert_question(question, key, options=None):
|
| 265 |
"""سوال لیکرت با دکمهها"""
|
| 266 |
+
if options is None:
|
| 267 |
+
options = {
|
| 268 |
+
1: "کاملاً مخالفم",
|
| 269 |
+
2: "مخالفم",
|
| 270 |
+
3: "نظری ندارم",
|
| 271 |
+
4: "موافقم",
|
| 272 |
+
5: "کاملاً موافقم"
|
| 273 |
+
}
|
| 274 |
+
|
| 275 |
st.markdown(f"<p style='margin-bottom: 10px;'>{question}</p>", unsafe_allow_html=True)
|
| 276 |
|
| 277 |
cols = st.columns(5)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 278 |
selected = st.session_state.get(key, None)
|
| 279 |
|
| 280 |
for value, label in options.items():
|
|
|
|
| 323 |
client = gspread.authorize(creds)
|
| 324 |
spreadsheet = client.open_by_key(SHEET_ID)
|
| 325 |
worksheet = spreadsheet.worksheet(SHEET_NAME)
|
| 326 |
+
|
| 327 |
+
# تبدیل پاسخهای لیکرت به فرمت مناسب
|
| 328 |
+
likert_answers = {}
|
| 329 |
+
for q in st.session_state.likert_questions:
|
| 330 |
+
likert_answers[q['key']] = st.session_state.get(q['key'], None)
|
| 331 |
|
| 332 |
+
# ترتیب سوالات بر اساس لیبلها
|
| 333 |
+
ordered_answers = {}
|
| 334 |
+
for label in st.session_state.question_labels:
|
| 335 |
+
for q in st.session_state.likert_questions:
|
| 336 |
+
if q['label'] == label:
|
| 337 |
+
ordered_answers[label] = likert_answers[q['key']]
|
| 338 |
+
break
|
| 339 |
+
|
| 340 |
row_data = [
|
| 341 |
+
datetime.now().strftime("%Y-%m-%d %H:%M:%S"), # زمان شروع
|
| 342 |
data.get("scenario_type"),
|
| 343 |
data.get("price"),
|
| 344 |
data.get("age"),
|
|
|
|
| 346 |
data.get("education"),
|
| 347 |
data.get("ride_frequency"),
|
| 348 |
st.session_state.get("user_contact", ""),
|
| 349 |
+
*ordered_answers.values(), # پاسخهای لیکرت به ترتیب لیبلها
|
| 350 |
+
st.session_state.get("attention_check1", None),
|
| 351 |
+
st.session_state.get("attention_check2", None),
|
| 352 |
st.session_state.get("explanation_data", {}).get("explanation_received", ""),
|
| 353 |
st.session_state.get("explanation_data", {}).get("explanation_type", ""),
|
| 354 |
+
data.get("price_accepted", 0),
|
| 355 |
+
datetime.now().strftime("%Y-%m-%d %H:%M:%S"), # زمان پایان
|
| 356 |
+
(datetime.now() - st.session_state.start_time).total_seconds() # مدت زمان تکمیل
|
| 357 |
]
|
| 358 |
|
| 359 |
worksheet.append_row(row_data)
|
|
|
|
| 390 |
|
| 391 |
if st.button("شروع پرسشنامه", key="start_btn", type="primary"):
|
| 392 |
st.session_state.current_page = "contact"
|
| 393 |
+
st.session_state.start_time = datetime.now()
|
| 394 |
st.rerun()
|
| 395 |
|
| 396 |
|
|
|
|
| 495 |
with col1:
|
| 496 |
if st.button("درخواست راهیار", key="accept_btn", use_container_width=True):
|
| 497 |
st.session_state.price_accepted = 1
|
| 498 |
+
st.session_state.current_page = "attention_check1"
|
| 499 |
st.rerun()
|
| 500 |
|
| 501 |
with col2:
|
| 502 |
if st.button("رد قیمت", key="reject_btn", use_container_width=True):
|
| 503 |
st.session_state.price_accepted = 0
|
| 504 |
+
st.session_state.current_page = "attention_check1"
|
| 505 |
+
st.rerun()
|
| 506 |
+
|
| 507 |
+
def attention_check1():
|
| 508 |
+
"""سوال توجه اول"""
|
| 509 |
+
st.markdown("### سوال توجه")
|
| 510 |
+
|
| 511 |
+
options = {
|
| 512 |
+
1: "قرمز",
|
| 513 |
+
2: "سبز",
|
| 514 |
+
3: "بنفش",
|
| 515 |
+
4: "آبی",
|
| 516 |
+
5: "زرد"
|
| 517 |
+
}
|
| 518 |
+
|
| 519 |
+
answer = create_likert_question(
|
| 520 |
+
"رنگ سازمانی اپلیکیشن رهیار چه رنگی بود؟",
|
| 521 |
+
"attention_check1",
|
| 522 |
+
options
|
| 523 |
+
)
|
| 524 |
+
|
| 525 |
+
if answer:
|
| 526 |
+
if answer == 3: # پاسخ صحیح (بنفش)
|
| 527 |
st.session_state.current_page = "transparency_questions"
|
| 528 |
st.rerun()
|
| 529 |
+
else:
|
| 530 |
+
st.error("پاسخ صحیح نبود. لطفاً دقت بیشتری به خرج دهید.")
|
| 531 |
+
time.sleep(2) # تاخیر برای خواندن پیام
|
| 532 |
+
st.rerun()
|
| 533 |
+
|
| 534 |
+
def attention_check2():
|
| 535 |
+
"""سوال توجه دوم"""
|
| 536 |
+
st.markdown("### سوال توجه")
|
| 537 |
+
|
| 538 |
+
options = {
|
| 539 |
+
1: "اسنپ",
|
| 540 |
+
2: "تپسی",
|
| 541 |
+
3: "راهیار",
|
| 542 |
+
4: "ماکسیم",
|
| 543 |
+
5: "دیگر"
|
| 544 |
+
}
|
| 545 |
+
|
| 546 |
+
answer = create_likert_question(
|
| 547 |
+
"نام اپلیکیشنی که در این تحقیق بررسی میشود چیست؟",
|
| 548 |
+
"attention_check2",
|
| 549 |
+
options
|
| 550 |
+
)
|
| 551 |
+
|
| 552 |
+
if answer:
|
| 553 |
+
if answer == 3: # پاسخ صحیح (راهیار)
|
| 554 |
st.session_state.current_page = "fairness_questions"
|
| 555 |
st.rerun()
|
| 556 |
+
else:
|
| 557 |
+
st.error("پاسخ صحیح نبود. لطفاً دقت بیشتری به خرج دهید.")
|
| 558 |
+
time.sleep(2) # تاخیر برای خواندن پیام
|
| 559 |
+
st.rerun()
|
| 560 |
+
|
| 561 |
+
def transparency_questions():
|
| 562 |
+
"""سوالات شفافیت (informational fairness)"""
|
| 563 |
+
if 'likert_questions' not in st.session_state:
|
| 564 |
+
# تعریف سوالات با لیبلهای منحصر به فرد
|
| 565 |
+
st.session_state.likert_questions = [
|
| 566 |
+
{"key": "t1", "question": "پلتفرم به صورت صادقانه دلایل تغییر قیمت (مثل افزایش تقاضا یا شرایط جوی) را توضیح داد.", "label": "informational_1"},
|
| 567 |
+
{"key": "t2", "question": "پلتفرم به طور کامل عوامل مؤثر بر قیمت (مثل ترافیک، تعداد رانندگان) را شرح داد.", "label": "informational_2"},
|
| 568 |
+
{"key": "t3", "question": "دلایل ارائهشده برای تغییر قیمت منطقی و قابل قبول بود.", "label": "informational_3"},
|
| 569 |
+
{"key": "t4", "question": "توضیحات درباره قیمت بلافاصله و در زمان مناسب نمایش داده شد.", "label": "informational_4"},
|
| 570 |
+
{"key": "t5", "question": "توضیحات پلتفرم متناسب با شرایط سفر من (مثل مسیر یا ساعت درخواست) بود.", "label": "informational_5"}
|
| 571 |
+
]
|
| 572 |
+
|
| 573 |
+
# لیست لیبلها برای ترتیب ذخیرهسازی
|
| 574 |
+
st.session_state.question_labels = [
|
| 575 |
+
"informational_1", "informational_2", "informational_3", "informational_4", "informational_5",
|
| 576 |
+
"distributive_1", "distributive_2", "distributive_3",
|
| 577 |
+
"procedural_1", "procedural_2", "procedural_3"
|
| 578 |
+
]
|
| 579 |
+
|
| 580 |
+
# تصادفیسازی ترتیب سوالات
|
| 581 |
+
random.shuffle(st.session_state.likert_questions)
|
| 582 |
+
st.session_state.current_question = 0
|
| 583 |
+
|
| 584 |
+
if st.session_state.current_question < len(st.session_state.likert_questions):
|
| 585 |
+
q = st.session_state.likert_questions[st.session_state.current_question]
|
| 586 |
+
|
| 587 |
+
st.markdown(f"### سوال {st.session_state.current_question + 1} از {len(st.session_state.likert_questions)}")
|
| 588 |
+
answer = create_likert_question(q["question"], q["key"])
|
| 589 |
+
|
| 590 |
+
if answer:
|
| 591 |
+
st.session_state.current_question += 1
|
| 592 |
+
time.sleep(0.5) # تاخیر کوتاه برای UX بهتر
|
| 593 |
+
st.rerun()
|
| 594 |
+
else:
|
| 595 |
+
st.session_state.current_page = "attention_check2"
|
| 596 |
+
st.rerun()
|
| 597 |
|
| 598 |
def fairness_questions():
|
| 599 |
+
"""سوالات انصاف (distributive و procedural)"""
|
| 600 |
+
if 'fairness_questions' not in st.session_state:
|
| 601 |
+
st.session_state.fairness_questions = [
|
| 602 |
+
{"key": "d1", "question": "قیمتی که به شما ارائه شد، منصفانه است.", "label": "distributive_1"},
|
| 603 |
+
{"key": "d2", "question": "قیمتی که به شما ارائه شد، معقول است.", "label": "distributive_2"},
|
| 604 |
+
{"key": "d3", "question": "قیمتی که به شما ارائه شد، قابل قبول است.", "label": "distributive_3"},
|
| 605 |
+
{"key": "p1", "question": "فرآیند و رویه قیمتگذاری پلتفرم قابل قبول است.", "label": "procedural_1"},
|
| 606 |
+
{"key": "p2", "question": "فرآیند و رویه قیمتگذاری پلتفرم منصفانه است.", "label": "procedural_2"},
|
| 607 |
+
{"key": "p3", "question": "فرآیند و رویه قیمتگذاری پلتفرم معقول است.", "label": "procedural_3"}
|
| 608 |
+
]
|
| 609 |
+
random.shuffle(st.session_state.fairness_questions)
|
| 610 |
+
st.session_state.current_fairness_question = 0
|
| 611 |
+
|
| 612 |
+
if st.session_state.current_fairness_question < len(st.session_state.fairness_questions):
|
| 613 |
+
q = st.session_state.fairness_questions[st.session_state.current_fairness_question]
|
| 614 |
+
|
| 615 |
+
st.markdown(f"### سوال {st.session_state.current_fairness_question + 1} از {len(st.session_state.fairness_questions)}")
|
| 616 |
+
answer = create_likert_question(q["question"], q["key"])
|
| 617 |
+
|
| 618 |
+
if answer:
|
| 619 |
+
st.session_state.current_fairness_question += 1
|
| 620 |
+
time.sleep(0.5)
|
| 621 |
st.rerun()
|
| 622 |
+
else:
|
| 623 |
+
st.session_state.current_page = "explanation_questions"
|
| 624 |
+
st.rerun()
|
| 625 |
|
| 626 |
|
| 627 |
def explanation_questions():
|
|
|
|
| 673 |
"scenario_type": st.session_state.scenario_type,
|
| 674 |
"price": st.session_state.price,
|
| 675 |
**st.session_state.demographic_data,
|
| 676 |
+
"transparency_answers": [st.session_state.get(q['key'], None) for q in st.session_state.likert_questions],
|
| 677 |
+
"fairness_answers": [st.session_state.get(q['key'], None) for q in st.session_state.fairness_questions],
|
| 678 |
"explanation_received": explanation_received,
|
| 679 |
"explanation_type": explanation_type if explanation_received == "بله" else "N/A",
|
| 680 |
"price_accepted": st.session_state.get("price_accepted", 0)
|
|
|
|
| 717 |
"demographic": demographic_form,
|
| 718 |
"scenario_explanation": scenario_explanation,
|
| 719 |
"map_view": map_view,
|
| 720 |
+
"attention_check1": attention_check1,
|
| 721 |
+
"attention_check2": attention_check2,
|
| 722 |
"transparency_questions": transparency_questions,
|
| 723 |
"fairness_questions": fairness_questions,
|
| 724 |
"explanation_questions": explanation_questions,
|