GSMEthesis commited on
Commit
149a9ed
·
verified ·
1 Parent(s): ab64c63

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +50 -94
app.py CHANGED
@@ -5,7 +5,6 @@ import streamlit.components.v1 as components
5
  from datetime import datetime
6
  import gspread
7
  from google.oauth2.service_account import Credentials
8
- import plotly.graph_objects as go
9
  import os
10
  import json
11
  import random
@@ -734,106 +733,63 @@ h3 {
734
  [data-testid="stAppViewContainer"] p:not(.stButton p):not(.stDownloadButton p):not(.stFormSubmitButton p) {
735
  margin-bottom: 1em !important;
736
  line-height: 1.8 !important;
737
- }
738
  </style>
739
  """, unsafe_allow_html=True)
740
 
741
  # ========== توابع اصلی ==========
742
  def custom_likert_slider(question_data):
743
- """نمایش سوال لیکرت با طیف رنگی Plotly و بدون اسلایدر قابل مشاهده"""
744
  question = question_data["question"]
745
  key = question_data["key"]
746
  points = question_data["scale"]
747
- labels = question_data.get("labels", ["کاملاً مخالفم", "کاملاً موافقم"])
748
 
749
  # مقدار پیش‌فرض (وسط طیف)
750
- default_value = st.session_state.answers.get(key, (points - 1) // 2)
751
-
752
- st.markdown(f"**{question}**")
753
-
754
- # ایجاد یک container برای نمایش طیف
755
- container = st.container()
756
-
757
- # نمایش طیف با رنگ بنفش روی گزینه انتخاب‌شده
758
- fig = go.Figure()
759
-
760
- positions = list(range(points))
761
-
762
- # اضافه کردن نقاط به نمودار
763
- fig.add_trace(go.Scatter(
764
- x=positions,
765
- y=[0]*points,
766
- mode='markers+text',
767
- marker=dict(
768
- size=30,
769
- color=['#d1c4e9' if i != st.session_state.answers.get(key, default_value) else '#6a0dad' for i in positions],
770
- line=dict(width=2, color='#6a0dad')
771
- ),
772
- text=labels if len(labels) == points else [str(i+1) for i in positions],
773
- textposition="top center",
774
- textfont=dict(size=14)
775
- ))
776
-
777
- # خط اتصال نقاط
778
- fig.add_trace(go.Scatter(
779
- x=positions,
780
- y=[0]*points,
781
- mode='lines',
782
- line=dict(color='#d1c4e9', width=2),
783
- hoverinfo='none'
784
- ))
785
-
786
- # تنظیمات layout
787
- fig.update_layout(
788
- xaxis=dict(
789
- tickmode='array',
790
- tickvals=positions,
791
- ticktext=labels if len(labels) == points else [str(i+1) for i in positions],
792
- showgrid=False,
793
- zeroline=False,
794
- range=[-0.5, points-0.5]
795
- ),
796
- yaxis=dict(showticklabels=False, showgrid=False, zeroline=False, range=[-0.1, 0.1]),
797
- margin=dict(l=20, r=20, t=40, b=20),
798
- height=150,
799
- showlegend=False,
800
- hovermode=False,
801
- clickmode='event+select'
802
- )
803
 
804
- # نمایش نمودار در container
805
- with container:
806
- selected_point = st.plotly_chart(
807
- fig,
808
- use_container_width=True,
809
- config={'staticPlot': False},
810
- key=f"plot_{key}"
811
- )
812
-
813
- # استفاده از st.slider مخفی برای مدیریت انتخاب
814
- selected_value = st.slider(
815
- "",
816
- min_value=0,
817
- max_value=points-1,
818
- value=st.session_state.answers.get(key, default_value),
819
- step=1,
820
- key=f"hidden_slider_{key}",
821
- label_visibility="collapsed"
822
- )
 
 
 
 
 
 
 
 
 
 
 
823
 
824
- # ذخیره مقدار انتخاب شده
825
- st.session_state.answers[key] = selected_value
826
- st.session_state[key] = selected_value
827
 
828
- # نمایش انتخاب کاربر
829
- selected_label = labels[selected_value] if len(labels) > selected_value else str(selected_value+1)
830
- st.markdown(
831
- f"<p style='text-align:center; color:#6a0dad; font-weight:bold;'>پاسخ شما: <strong>{selected_label}</strong></p>",
832
- unsafe_allow_html=True
833
- )
834
 
835
- return selected_value
 
836
 
 
 
837
  def create_ride_map():
838
  """ایجاد نقشه سفر با Folium - نسخه اصلاح شده با مناطق عمومی"""
839
  # نقاط تقریبی برای مناطق عمومی جنوب و غرب تهران
@@ -906,7 +862,10 @@ def show_explanation(exp_type):
906
  elif exp_type == "counterfactual":
907
  st.markdown("<p class='explanation-title'>علت قیمت گذاری:</p>", unsafe_allow_html=True)
908
  for item in explanations.get(exp_type, []):
909
- st.markdown(f"<p class='explanation-item'>• {item}</p>", unsafe_allow_html=True)
 
 
 
910
 
911
  def create_likert_question(question, key, scale_type="5point"):
912
  """نمایش سوال لیکرت با اسلایدر نقطه‌ای"""
@@ -1251,7 +1210,7 @@ def random_likert_questions():
1251
  "key": "distributive_1",
1252
  "question": "قیمتی که به شما ارائه شد، چگونه بود؟",
1253
  "scale": 7,
1254
- "labels": ["کاملاً نامنصفانه", "کاملاً منصفانه"]
1255
  },
1256
  {
1257
  "key": "distributive_2",
@@ -1271,7 +1230,7 @@ def random_likert_questions():
1271
  "title": "سوال توجه",
1272
  "key": "attention_check",
1273
  "questions": [
1274
- {"key": "attention_check2", "question": "تا چه مقدار با دقت به سوالات پاسخ می‌دهید؟", "scale": 7, "labels": ["خیلی کم", "خیلی زیاد"]}
1275
  ]
1276
  },
1277
  {
@@ -1296,6 +1255,7 @@ def random_likert_questions():
1296
  }
1297
  ]
1298
 
 
1299
  # مقداردهی اولیه
1300
  if 'current_likert_group' not in st.session_state:
1301
  st.session_state.current_likert_group = 0
@@ -1331,16 +1291,12 @@ def random_likert_questions():
1331
  for question in current_group['questions']:
1332
  answer = custom_likert_slider(question)
1333
  st.session_state.answers[question["key"]] = answer
 
1334
 
1335
  # دکمه ادامه/اتمام
1336
  button_label = "ادامه به گروه بعدی" if st.session_state.current_likert_group < len(question_groups)-1 else "اتمام پرسشنامه"
1337
 
1338
  if st.button(button_label):
1339
- # ذخیره پاسخ‌ها قبل از رفتن به گروه بعدی
1340
- for question in current_group['questions']:
1341
- if question["key"] in st.session_state:
1342
- st.session_state.answers[question["key"]] = st.session_state[question["key"]]
1343
-
1344
  # رفتن به گروه بعدی یا صفحه پایانی
1345
  if st.session_state.current_likert_group < len(question_groups) - 1:
1346
  st.session_state.current_likert_group += 1
 
5
  from datetime import datetime
6
  import gspread
7
  from google.oauth2.service_account import Credentials
 
8
  import os
9
  import json
10
  import random
 
733
  [data-testid="stAppViewContainer"] p:not(.stButton p):not(.stDownloadButton p):not(.stFormSubmitButton p) {
734
  margin-bottom: 1em !important;
735
  line-height: 1.8 !important;
736
+ }
737
  </style>
738
  """, unsafe_allow_html=True)
739
 
740
  # ========== توابع اصلی ==========
741
  def custom_likert_slider(question_data):
742
+ """نمایش سوال لیکرت با اسلایدر نقطه‌ای و لیبل‌های سفارشی"""
743
  question = question_data["question"]
744
  key = question_data["key"]
745
  points = question_data["scale"]
746
+ labels = question_data.get("labels", ["کمترین", "بیشترین"]) # لیبل‌های پیش‌فرض
747
 
748
  # مقدار پیش‌فرض (وسط طیف)
749
+ default_value = st.session_state.get(key, (points + 1) // 2)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
750
 
751
+ # HTML و JavaScript
752
+ html = f"""
753
+ <div id="container_{key}" style="direction: ltr; font-family: 'B Nazanin'; margin-bottom: 30px;">
754
+ <label style="font-size: 16px; font-weight: bold; display: block; text-align: right;">{question}</label>
755
+ <div style="display: flex; justify-content: space-between; font-size: 12px; margin-bottom: 5px;">
756
+ <span>{labels[0]}</span>
757
+ <span>{labels[1]}</span>
758
+ </div>
759
+ <input type="range" id="{key}" min="1" max="{points}" step="1" value="{default_value}"
760
+ style="width: 100%; height: 10px; accent-color: #6a0dad; margin-bottom: 15px;"
761
+ oninput="updateSlider('{key}')">
762
+ <div style="text-align: center; margin-top: 10px; direction: rtl;">
763
+ پاسخ انتخاب‌شده: <strong><span id="output_{key}">{default_value}</span></strong>
764
+ </div>
765
+ </div>
766
+
767
+ <script>
768
+ function updateSlider(key) {{
769
+ const value = parseInt(document.getElementById(key).value);
770
+ document.getElementById('output_' + key).innerText = value;
771
+
772
+ // ارسال مقدار به Streamlit
773
+ window.parent.postMessage({{
774
+ type: 'streamlit:setComponentValue',
775
+ key: key,
776
+ value: value
777
+ }}, '*');
778
+ }}
779
+ </script>
780
+ """
781
 
782
+ # نمایش ک��مپوننت
783
+ components.html(html, height=150)
 
784
 
785
+ # مقدار نهایی
786
+ value = st.session_state.get(key, default_value)
 
 
 
 
787
 
788
+ # ذخیره مقدار جدید در session_state
789
+ st.session_state[key] = value
790
 
791
+ return value
792
+
793
  def create_ride_map():
794
  """ایجاد نقشه سفر با Folium - نسخه اصلاح شده با مناطق عمومی"""
795
  # نقاط تقریبی برای مناطق عمومی جنوب و غرب تهران
 
862
  elif exp_type == "counterfactual":
863
  st.markdown("<p class='explanation-title'>علت قیمت گذاری:</p>", unsafe_allow_html=True)
864
  for item in explanations.get(exp_type, []):
865
+ st.markdown(f"<p class='explanation-item'>• {item}</p>", unsafe_allow_html=True)
866
+
867
+
868
+
869
 
870
  def create_likert_question(question, key, scale_type="5point"):
871
  """نمایش سوال لیکرت با اسلایدر نقطه‌ای"""
 
1210
  "key": "distributive_1",
1211
  "question": "قیمتی که به شما ارائه شد، چگونه بود؟",
1212
  "scale": 7,
1213
+ "labels": ["کاملاً نامنصفانه", "کاملاً منصفانه"] # لیبل‌های سفارشی برای این سوال
1214
  },
1215
  {
1216
  "key": "distributive_2",
 
1230
  "title": "سوال توجه",
1231
  "key": "attention_check",
1232
  "questions": [
1233
+ {"key": "attention_check2", "question": "تا چه مقدار با دقت به سوالات پاسخ می‌دهید؟", "scale": 7,"labels": ["خیلی کم", "خیلی زیاد"]}
1234
  ]
1235
  },
1236
  {
 
1255
  }
1256
  ]
1257
 
1258
+
1259
  # مقداردهی اولیه
1260
  if 'current_likert_group' not in st.session_state:
1261
  st.session_state.current_likert_group = 0
 
1291
  for question in current_group['questions']:
1292
  answer = custom_likert_slider(question)
1293
  st.session_state.answers[question["key"]] = answer
1294
+
1295
 
1296
  # دکمه ادامه/اتمام
1297
  button_label = "ادامه به گروه بعدی" if st.session_state.current_likert_group < len(question_groups)-1 else "اتمام پرسشنامه"
1298
 
1299
  if st.button(button_label):
 
 
 
 
 
1300
  # رفتن به گروه بعدی یا صفحه پایانی
1301
  if st.session_state.current_likert_group < len(question_groups) - 1:
1302
  st.session_state.current_likert_group += 1