Spaces:
Paused
Paused
Maryam Ilka commited on
Update app.py
Browse files
app.py
CHANGED
|
@@ -261,9 +261,9 @@ def show_explanation(exp_type):
|
|
| 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,
|
| 265 |
"""سوال لیکرت با دکمهها"""
|
| 266 |
-
if
|
| 267 |
options = {
|
| 268 |
1: "کاملاً مخالفم",
|
| 269 |
2: "مخالفم",
|
|
@@ -271,14 +271,25 @@ def create_likert_question(question, key, options=None):
|
|
| 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(
|
| 278 |
selected = st.session_state.get(key, None)
|
| 279 |
|
| 280 |
-
|
| 281 |
-
|
|
|
|
| 282 |
if st.button(
|
| 283 |
label,
|
| 284 |
key=f"{key}_{value}",
|
|
@@ -324,36 +335,46 @@ def save_to_sheet(data):
|
|
| 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 |
-
|
| 342 |
-
data.get("scenario_type"),
|
| 343 |
-
data.get("price"),
|
| 344 |
-
data.get("age"),
|
| 345 |
-
data.get("gender"),
|
| 346 |
-
data.get("education"),
|
| 347 |
-
data.get("ride_frequency"),
|
| 348 |
-
|
| 349 |
-
|
| 350 |
-
|
| 351 |
-
|
| 352 |
-
|
| 353 |
-
|
| 354 |
-
|
| 355 |
-
|
| 356 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 357 |
]
|
| 358 |
|
| 359 |
worksheet.append_row(row_data)
|
|
@@ -390,7 +411,7 @@ def welcome_page():
|
|
| 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 |
|
|
@@ -519,12 +540,12 @@ def attention_check1():
|
|
| 519 |
answer = create_likert_question(
|
| 520 |
"رنگ سازمانی اپلیکیشن رهیار چه رنگی بود؟",
|
| 521 |
"attention_check1",
|
| 522 |
-
|
| 523 |
)
|
| 524 |
|
| 525 |
if answer:
|
| 526 |
if answer == 3: # پاسخ صحیح (بنفش)
|
| 527 |
-
st.session_state.current_page = "
|
| 528 |
st.rerun()
|
| 529 |
else:
|
| 530 |
st.error("پاسخ صحیح نبود. لطفاً دقت بیشتری به خرج دهید.")
|
|
@@ -546,84 +567,59 @@ def attention_check2():
|
|
| 546 |
answer = create_likert_question(
|
| 547 |
"نام اپلیکیشنی که در این تحقیق بررسی میشود چیست؟",
|
| 548 |
"attention_check2",
|
| 549 |
-
|
| 550 |
)
|
| 551 |
|
| 552 |
if answer:
|
| 553 |
if answer == 3: # پاسخ صحیح (راهیار)
|
| 554 |
-
st.session_state.current_page = "
|
| 555 |
st.rerun()
|
| 556 |
else:
|
| 557 |
st.error("پاسخ صحیح نبود. لطفاً دقت بیشتری به خرج دهید.")
|
| 558 |
time.sleep(2) # تاخیر برای خواندن پیام
|
| 559 |
st.rerun()
|
| 560 |
|
| 561 |
-
def
|
| 562 |
-
"""سوالات
|
| 563 |
-
if '
|
| 564 |
-
# تعریف سوالات با لیبل
|
| 565 |
-
st.session_state.
|
| 566 |
-
|
| 567 |
-
{"key": "
|
| 568 |
-
{"key": "
|
| 569 |
-
{"key": "
|
| 570 |
-
{"key": "
|
| 571 |
-
|
| 572 |
-
|
| 573 |
-
|
| 574 |
-
|
| 575 |
-
"
|
| 576 |
-
"
|
| 577 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 578 |
]
|
| 579 |
|
| 580 |
# تصادفیسازی ترتیب سوالات
|
| 581 |
-
random.shuffle(st.session_state.
|
| 582 |
-
st.session_state.
|
| 583 |
|
| 584 |
-
if st.session_state.
|
| 585 |
-
q = st.session_state.
|
| 586 |
|
| 587 |
-
st.markdown(f"### سوال {st.session_state.
|
| 588 |
-
answer = create_likert_question(q["question"], q["key"])
|
| 589 |
|
| 590 |
if answer:
|
| 591 |
-
st.session_state.
|
| 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():
|
| 628 |
"""سوالات درباره توضیحات قیمت"""
|
| 629 |
st.markdown("""
|
|
@@ -669,16 +665,31 @@ def explanation_questions():
|
|
| 669 |
"explanation_type": explanation_type if explanation_received == "بله" else "N/A"
|
| 670 |
}
|
| 671 |
|
| 672 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 673 |
"scenario_type": st.session_state.scenario_type,
|
| 674 |
"price": st.session_state.price,
|
| 675 |
-
|
| 676 |
-
"
|
| 677 |
-
"
|
|
|
|
| 678 |
"explanation_received": explanation_received,
|
| 679 |
"explanation_type": explanation_type if explanation_received == "بله" else "N/A",
|
| 680 |
-
|
| 681 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 682 |
st.session_state.current_page = "thank_you"
|
| 683 |
st.rerun()
|
| 684 |
else:
|
|
@@ -706,9 +717,6 @@ def main():
|
|
| 706 |
st.session_state.price = 200000
|
| 707 |
st.session_state.user_contact = None
|
| 708 |
st.session_state.demographic_data = None
|
| 709 |
-
st.session_state.transparency_answers = []
|
| 710 |
-
st.session_state.fairness_answers = []
|
| 711 |
-
st.session_state.explanation_data = None
|
| 712 |
st.session_state.price_accepted = 0
|
| 713 |
|
| 714 |
pages = {
|
|
@@ -719,8 +727,7 @@ def main():
|
|
| 719 |
"map_view": map_view,
|
| 720 |
"attention_check1": attention_check1,
|
| 721 |
"attention_check2": attention_check2,
|
| 722 |
-
"
|
| 723 |
-
"fairness_questions": fairness_questions,
|
| 724 |
"explanation_questions": explanation_questions,
|
| 725 |
"thank_you": thank_you_page
|
| 726 |
}
|
|
|
|
| 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, scale_type="5point"):
|
| 265 |
"""سوال لیکرت با دکمهها"""
|
| 266 |
+
if scale_type == "5point":
|
| 267 |
options = {
|
| 268 |
1: "کاملاً مخالفم",
|
| 269 |
2: "مخالفم",
|
|
|
|
| 271 |
4: "موافقم",
|
| 272 |
5: "کاملاً موافقم"
|
| 273 |
}
|
| 274 |
+
else: # 7-point scale
|
| 275 |
+
options = {
|
| 276 |
+
1: "کاملاً مخالفم",
|
| 277 |
+
2: "مخالفم",
|
| 278 |
+
3: "تا حدی مخالفم",
|
| 279 |
+
4: "نظری ندارم",
|
| 280 |
+
5: "تا حدی موافقم",
|
| 281 |
+
6: "موافقم",
|
| 282 |
+
7: "کاملاً موافقم"
|
| 283 |
+
}
|
| 284 |
|
| 285 |
st.markdown(f"<p style='margin-bottom: 10px;'>{question}</p>", unsafe_allow_html=True)
|
| 286 |
|
| 287 |
+
cols = st.columns(len(options))
|
| 288 |
selected = st.session_state.get(key, None)
|
| 289 |
|
| 290 |
+
# نمایش گزینهها از کاملاً موافقم (راست) تا کاملاً مخالفم (چپ)
|
| 291 |
+
for value, label in reversed(options.items()):
|
| 292 |
+
with cols[len(options) - value]:
|
| 293 |
if st.button(
|
| 294 |
label,
|
| 295 |
key=f"{key}_{value}",
|
|
|
|
| 335 |
spreadsheet = client.open_by_key(SHEET_ID)
|
| 336 |
worksheet = spreadsheet.worksheet(SHEET_NAME)
|
| 337 |
|
| 338 |
+
# آمادهسازی دادهها برای ذخیرهسازی
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 339 |
row_data = [
|
| 340 |
+
data.get("start_time", ""), # زمان شروع
|
| 341 |
+
data.get("scenario_type", ""),
|
| 342 |
+
data.get("price", ""),
|
| 343 |
+
data.get("age", ""),
|
| 344 |
+
data.get("gender", ""),
|
| 345 |
+
data.get("education", ""),
|
| 346 |
+
data.get("ride_frequency", ""),
|
| 347 |
+
data.get("user_contact", ""),
|
| 348 |
+
data.get("price_accepted", ""),
|
| 349 |
+
|
| 350 |
+
# سوالات توجه
|
| 351 |
+
data.get("attention_check1", ""),
|
| 352 |
+
data.get("attention_check2", ""),
|
| 353 |
+
|
| 354 |
+
# سوالات informational (5 گزینهای)
|
| 355 |
+
data.get("informational_1", ""),
|
| 356 |
+
data.get("informational_2", ""),
|
| 357 |
+
data.get("informational_3", ""),
|
| 358 |
+
data.get("informational_4", ""),
|
| 359 |
+
data.get("informational_5", ""),
|
| 360 |
+
|
| 361 |
+
# سوالات distributive (7 گزینهای)
|
| 362 |
+
data.get("distributive_1", ""),
|
| 363 |
+
data.get("distributive_2", ""),
|
| 364 |
+
data.get("distributive_3", ""),
|
| 365 |
+
|
| 366 |
+
# سوالات procedural (7 گزینهای)
|
| 367 |
+
data.get("procedural_1", ""),
|
| 368 |
+
data.get("procedural_2", ""),
|
| 369 |
+
data.get("procedural_3", ""),
|
| 370 |
+
|
| 371 |
+
# سوالات explanation
|
| 372 |
+
data.get("explanation_received", ""),
|
| 373 |
+
data.get("explanation_type", ""),
|
| 374 |
+
|
| 375 |
+
# زمانسنجی
|
| 376 |
+
data.get("end_time", ""), # زمان پایان
|
| 377 |
+
data.get("completion_time", "") # مدت زمان تکمیل (ثانیه)
|
| 378 |
]
|
| 379 |
|
| 380 |
worksheet.append_row(row_data)
|
|
|
|
| 411 |
|
| 412 |
if st.button("شروع پرسشنامه", key="start_btn", type="primary"):
|
| 413 |
st.session_state.current_page = "contact"
|
| 414 |
+
st.session_state.start_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
| 415 |
st.rerun()
|
| 416 |
|
| 417 |
|
|
|
|
| 540 |
answer = create_likert_question(
|
| 541 |
"رنگ سازمانی اپلیکیشن رهیار چه رنگی بود؟",
|
| 542 |
"attention_check1",
|
| 543 |
+
"5point"
|
| 544 |
)
|
| 545 |
|
| 546 |
if answer:
|
| 547 |
if answer == 3: # پاسخ صحیح (بنفش)
|
| 548 |
+
st.session_state.current_page = "random_likert_questions"
|
| 549 |
st.rerun()
|
| 550 |
else:
|
| 551 |
st.error("پاسخ صحیح نبود. لطفاً دقت بیشتری به خرج دهید.")
|
|
|
|
| 567 |
answer = create_likert_question(
|
| 568 |
"نام اپلیکیشنی که در این تحقیق بررسی میشود چیست؟",
|
| 569 |
"attention_check2",
|
| 570 |
+
"5point"
|
| 571 |
)
|
| 572 |
|
| 573 |
if answer:
|
| 574 |
if answer == 3: # پاسخ صحیح (راهیار)
|
| 575 |
+
st.session_state.current_page = "explanation_questions"
|
| 576 |
st.rerun()
|
| 577 |
else:
|
| 578 |
st.error("پاسخ صحیح نبود. لطفاً دقت بیشتری به خرج دهید.")
|
| 579 |
time.sleep(2) # تاخیر برای خواندن پیام
|
| 580 |
st.rerun()
|
| 581 |
|
| 582 |
+
def random_likert_questions():
|
| 583 |
+
"""نمایش تصادفی سوالات لیکرت"""
|
| 584 |
+
if 'all_questions' not in st.session_state:
|
| 585 |
+
# تعریف تمام سوالات با نوع مقیاس و لیبل مربوطه
|
| 586 |
+
st.session_state.all_questions = [
|
| 587 |
+
# سوالات informational (5 گزینهای)
|
| 588 |
+
{"key": "informational_1", "question": "پلتفرم به صورت صادقانه دلایل تغییر قیمت (مثل افزایش تقاضا یا شرایط جوی) را توضیح داد.", "scale": "5point", "label": "informational_1"},
|
| 589 |
+
{"key": "informational_2", "question": "پلتفرم به طور کامل عوامل مؤثر بر قیمت (مثل ترافیک، تعداد رانندگان) را شرح داد.", "scale": "5point", "label": "informational_2"},
|
| 590 |
+
{"key": "informational_3", "question": "دلایل ارائهشده برای تغییر قیمت منطقی و قابل قبول بود.", "scale": "5point", "label": "informational_3"},
|
| 591 |
+
{"key": "informational_4", "question": "توضیحات درباره قیمت بلافاصله و در زمان مناسب نمایش داده شد.", "scale": "5point", "label": "informational_4"},
|
| 592 |
+
{"key": "informational_5", "question": "توضیحات پلتفرم متناسب با شرایط سفر من (مثل مسیر یا ساعت درخواست) بود.", "scale": "5point", "label": "informational_5"},
|
| 593 |
+
|
| 594 |
+
# سوالات distributive (7 گزینهای)
|
| 595 |
+
{"key": "distributive_1", "question": "قیمتی که به شما ارائه شد، منصفانه است.", "scale": "7point", "label": "distributive_1"},
|
| 596 |
+
{"key": "distributive_2", "question": "قیمتی که به شما ارائه شد، معقول است.", "scale": "7point", "label": "distributive_2"},
|
| 597 |
+
{"key": "distributive_3", "question": "قیمتی که به شما ارائه شد، قابل قبول است.", "scale": "7point", "label": "distributive_3"},
|
| 598 |
+
|
| 599 |
+
# سوالات procedural (7 گزینهای)
|
| 600 |
+
{"key": "procedural_1", "question": "فرآیند و رویه قیمتگذاری پلتفرم قابل قبول است.", "scale": "7point", "label": "procedural_1"},
|
| 601 |
+
{"key": "procedural_2", "question": "فرآیند و رویه قیمتگذاری پلتفرم منصفانه است.", "scale": "7point", "label": "procedural_2"},
|
| 602 |
+
{"key": "procedural_3", "question": "فرآیند و رویه قیمتگذاری پلتفرم معقول است.", "scale": "7point", "label": "procedural_3"}
|
| 603 |
]
|
| 604 |
|
| 605 |
# تصادفیسازی ترتیب سوالات
|
| 606 |
+
random.shuffle(st.session_state.all_questions)
|
| 607 |
+
st.session_state.current_question_index = 0
|
| 608 |
|
| 609 |
+
if st.session_state.current_question_index < len(st.session_state.all_questions):
|
| 610 |
+
q = st.session_state.all_questions[st.session_state.current_question_index]
|
| 611 |
|
| 612 |
+
st.markdown(f"### سوال {st.session_state.current_question_index + 1} از {len(st.session_state.all_questions)}")
|
| 613 |
+
answer = create_likert_question(q["question"], q["key"], q["scale"])
|
| 614 |
|
| 615 |
if answer:
|
| 616 |
+
st.session_state.current_question_index += 1
|
| 617 |
time.sleep(0.5) # تاخیر کوتاه برای UX بهتر
|
| 618 |
st.rerun()
|
| 619 |
else:
|
| 620 |
st.session_state.current_page = "attention_check2"
|
| 621 |
st.rerun()
|
| 622 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 623 |
def explanation_questions():
|
| 624 |
"""سوالات درباره توضیحات قیمت"""
|
| 625 |
st.markdown("""
|
|
|
|
| 665 |
"explanation_type": explanation_type if explanation_received == "بله" else "N/A"
|
| 666 |
}
|
| 667 |
|
| 668 |
+
# جمعآوری تمام دادهها برای ذخیرهسازی
|
| 669 |
+
end_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
| 670 |
+
start_time = datetime.strptime(st.session_state.start_time, "%Y-%m-%d %H:%M:%S")
|
| 671 |
+
completion_time = (datetime.now() - start_time).total_seconds()
|
| 672 |
+
|
| 673 |
+
save_data = {
|
| 674 |
+
"start_time": st.session_state.start_time,
|
| 675 |
+
"end_time": end_time,
|
| 676 |
+
"completion_time": completion_time,
|
| 677 |
"scenario_type": st.session_state.scenario_type,
|
| 678 |
"price": st.session_state.price,
|
| 679 |
+
"user_contact": st.session_state.get("user_contact", ""),
|
| 680 |
+
"price_accepted": st.session_state.get("price_accepted", 0),
|
| 681 |
+
"attention_check1": st.session_state.get("attention_check1", None),
|
| 682 |
+
"attention_check2": st.session_state.get("attention_check2", None),
|
| 683 |
"explanation_received": explanation_received,
|
| 684 |
"explanation_type": explanation_type if explanation_received == "بله" else "N/A",
|
| 685 |
+
**st.session_state.demographic_data
|
| 686 |
+
}
|
| 687 |
+
|
| 688 |
+
# اضافه کردن پاسخهای لیکرت
|
| 689 |
+
for q in st.session_state.all_questions:
|
| 690 |
+
save_data[q["label"]] = st.session_state.get(q["key"], None)
|
| 691 |
+
|
| 692 |
+
if save_to_sheet(save_data):
|
| 693 |
st.session_state.current_page = "thank_you"
|
| 694 |
st.rerun()
|
| 695 |
else:
|
|
|
|
| 717 |
st.session_state.price = 200000
|
| 718 |
st.session_state.user_contact = None
|
| 719 |
st.session_state.demographic_data = None
|
|
|
|
|
|
|
|
|
|
| 720 |
st.session_state.price_accepted = 0
|
| 721 |
|
| 722 |
pages = {
|
|
|
|
| 727 |
"map_view": map_view,
|
| 728 |
"attention_check1": attention_check1,
|
| 729 |
"attention_check2": attention_check2,
|
| 730 |
+
"random_likert_questions": random_likert_questions,
|
|
|
|
| 731 |
"explanation_questions": explanation_questions,
|
| 732 |
"thank_you": thank_you_page
|
| 733 |
}
|