Alide21 commited on
Commit
f278b50
·
verified ·
1 Parent(s): 18efb04

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +52 -75
app.py CHANGED
@@ -14,7 +14,7 @@ api = HfApi()
14
 
15
  SURAH_NAMES = ["الفاتحة", "البقرة", "آل عمران", "النساء", "المائدة", "الأنعام", "الأعراف", "الأنفال", "التوبة", "يونس", "هود", "يوسف", "الرعد", "إبراهيم", "الحجر", "النحل", "الإسراء", "الكهف", "مريم", "طه", "الأنبياء", "الحج", "المؤمنون", "النور", "الفرقان", "الشعراء", "النمل", "القصص", "العنكبوت", "الروم", "لقمان", "السجدة", "الأحزاب", "سبأ", "فاطر", "يس", "الصافات", "ص", "الزمر", "غافر", "فصلت", "الشورى", "الزخرف", "الدخان", "الجاثية", "الأحقاف", "محمد", "الفتح", "الحجرات", "ق", "الذاريات", "الطور", "النجم", "القمر", "الرحمن", "الواقعة", "الحديد", "المجادلة", "الحشر", "الممتحنة", "الصف", "الجمعة", "المنافقون", "التغابن", "الطلاق", "التحريم", "الملك", "القلم", "الحاقة", "المعارج", "نوح", "الجن", "المزمل", "المدثر", "القيامة", "الإنسان", "المرسلات", "النبأ", "النازعات", "عبس", "التكوير", "الانفطار", "المطففين", "الانشقاق", "البروج", "الطارق", "الأعلى", "الغاشية", "الفجر", "البلد", "الشمس", "الليل", "الضحى", "الشرح", "التين", "العلق", "القدر", "البينة", "الزلزلة", "العاديات", "القارعة", "التكاثر", "العصر", "الهمزة", "الفيل", "قريش", "الماعون", "الكوثر", "الكافرون", "النصر", "المسد", "الإخلاص", "الفلق", "الناس"]
16
 
17
- # --- التنسيق البصري ---
18
  custom_css = """
19
  @import url('https://fonts.googleapis.com/css2?family=Amiri:wght@400;700&family=Reem+Kufi:wght@400;700&display=swap');
20
  :root { --gold: #D4AF37; --dark-green: #064635; }
@@ -29,27 +29,26 @@ body { direction: rtl; background-color: #f4f6f9; }
29
  padding: 50px 20px;
30
  border-radius: 0 0 40px 40px;
31
  text-align: center;
32
- color: white !important;
33
  }
34
 
35
- .hero-header h1, .hero-header p, .hero-header span { color: white !important; }
36
-
37
- .real-count {
38
- font-size: 4rem;
39
- color: #FFFFFF !important;
40
- font-weight: bold;
41
- text-shadow: 2px 2px 8px rgba(0,0,0,0.3);
42
- }
43
 
44
  .instruction-box {
45
  background: #fff9e6;
46
- border-right: 6px solid var(--gold);
47
- padding: 20px;
48
  border-radius: 15px;
49
  margin: 20px 0;
50
  text-align: right;
51
  direction: rtl;
52
- box-shadow: 0 4px 6px rgba(0,0,0,0.05);
 
 
 
 
 
 
 
53
  }
54
 
55
  .custom-card {
@@ -57,28 +56,18 @@ body { direction: rtl; background-color: #f4f6f9; }
57
  border-radius: 20px !important;
58
  padding: 25px !important;
59
  box-shadow: 0 8px 20px rgba(0,0,0,0.06) !important;
60
- margin-bottom: 20px !important;
61
  }
62
 
63
  .ayah-text {
64
  font-family: 'Amiri', serif !important;
65
- font-size: 2.3rem !important;
66
  color: var(--dark-green);
67
  line-height: 1.8 !important;
68
  text-align: center;
69
  }
70
-
71
- /* ضبط اتجاه رسائل الحالة */
72
- .status-msg { direction: rtl !important; text-align: right !important; }
73
  """
74
 
75
- # --- المنطق الخلفي ---
76
- def get_real_total():
77
- try:
78
- files = api.list_repo_files(repo_id=REPO_ID, repo_type="dataset", token=HF_TOKEN)
79
- return len([f for f in files if f.startswith("data/")])
80
- except: return 0
81
-
82
  def clean_text(text): return re.sub(r'<[^>]*>', '', text).strip()
83
 
84
  def fetch_surah(s_idx):
@@ -95,76 +84,68 @@ ALL_AYAT = [item for sublist in results for item in sublist]
95
  def validate_ayah(v):
96
  return len(v['text']) <= 200
97
 
98
- # دالة لاختيار آية عشوائية صالحة
99
- def get_random_valid_ayah():
100
  while True:
101
  idx = random.randint(0, len(ALL_AYAT)-1)
102
- if validate_ayah(ALL_AYAT[idx]):
103
- return idx
104
-
105
- def jump_to_ayah(s_name, a_num):
106
- try:
107
- target_num = int(a_num)
108
- for i, v in enumerate(ALL_AYAT):
109
- if v['surah_name'] == s_name and v['ayah'] == target_num:
110
- if not validate_ayah(v):
111
- return "⚠️ الآية المختارة طويلة جداً (تتجاوز 200 رمز).", gr.update(), gr.update(), gr.update()
112
- # الرسالة هنا RTL
113
- return "✅ تم العثور على الآية بنجاح", f"<div class='ayah-text'>{v['text']}</div>", f"### {v['surah_name']} | آية {v['ayah']}", i
114
- return "⚠️ الآية غير موجودة في هذه السورة.", gr.update(), gr.update(), gr.update()
115
- except:
116
- return "⚠️ يرجى التأكد من رقم الآية.", gr.update(), gr.update(), gr.update()
117
 
118
  def on_submit(audio, current_idx):
119
  if not audio: return "⚠️ سجل صوتك أولاً", gr.update(), gr.update(), current_idx
120
  v = ALL_AYAT[current_idx]
121
  try:
122
  api.upload_file(path_or_fileobj=audio, path_in_repo=f"data/s{v['surah']}_a{v['ayah']}_{uuid.uuid4().hex[:6]}.wav", repo_id=REPO_ID, repo_type="dataset", token=HF_TOKEN)
123
- next_idx = get_random_valid_ayah()
124
- nv = ALL_AYAT[next_idx]
125
- return "✅ تم الحفظ بنجاح، جزاك الله خيراً", f"<div class='ayah-text'>{nv['text']}</div>", f"### {nv['surah_name']} | آية {nv['ayah']}", next_idx
126
  except Exception as e: return f"❌ فشل الرفع: {str(e)}", gr.update(), gr.update(), current_idx
127
 
128
- # --- بناء الواجهة ---
 
 
 
 
 
 
 
 
 
 
 
129
  with gr.Blocks(title="منصة تلاوة") as demo:
130
- # الآن سيتم اختيار آية جديدة في كل مرة يتم فيها بناء الـ Blocks (أي عند التحديث)
131
- idx_state = gr.State(get_random_valid_ayah())
 
 
132
 
133
  gr.HTML(f"""
134
  <div class="hero-header">
135
- <h1>مِنَصَّة التِّلَاوَة</h1>
136
- <p>بناء قاعدة بيانات صوتية لتدريب الذكاء الاصطناعي على تصحيح التلاوة</p>
137
  <div style="margin-top:20px;">
138
- <span style="font-size: 1.3rem;">مساهمات الأمة</span>
139
- <div class="real-count">{get_real_total()}</div>
140
  </div>
141
  </div>
142
  """)
143
 
144
  with gr.Column(elem_classes="gradio-container"):
 
145
  gr.HTML("""
146
  <div class="instruction-box">
147
- <strong>💡 تنبيه للجودة:</strong>
148
- يرجى قراءة الآية بنفس واحد.
149
- <br>نقبل الآيات التي لا تتجاوز 200 رمز لضمان دقة التحليل.
150
  </div>
151
  """)
152
 
153
  with gr.Row():
154
  with gr.Column(scale=2):
155
  with gr.Column(elem_classes="custom-card"):
156
- # نستخدم دالة لتهيئة العرض الأول بناءً على idx_state
157
- def load_initial_ayah(idx):
158
- v = ALL_AYAT[idx]
159
- return f"<div class='ayah-text'>{v['text']}</div>", f"### {v['surah_name']} | آية {v['ayah']}"
160
-
161
- # إنشاء المكونات بقيم فارغة ثم تعبئتها
162
- info_text = gr.Markdown()
163
- text_html = gr.HTML()
164
- status_msg = gr.Markdown(elem_classes="status-msg")
165
-
166
  with gr.Row():
167
- send_btn = gr.Button("🎤 إرسال التسجيل", variant="primary")
168
  rnd_btn = gr.Button("🔄 آية عشوائية", variant="secondary")
169
 
170
  with gr.Column(scale=1):
@@ -175,17 +156,13 @@ with gr.Blocks(title="منصة تلاوة") as demo:
175
  with gr.Column(elem_classes="custom-card"):
176
  gr.Markdown("### 🔍 اختيار آية")
177
  s_drop = gr.Dropdown(choices=SURAH_NAMES, label="السورة", value="الفاتحة")
178
- a_num = gr.Number(label="رقم الآية", value=1, precision=0)
179
  go_btn = gr.Button("انتقال")
180
 
181
- # حدث لتحميل الآية عند فتح الصفحة لأول مرة
182
- demo.load(load_initial_ayah, inputs=[idx_state], outputs=[text_html, info_text])
183
-
184
- # أحداث الأزرار
185
  rnd_btn.click(
186
- lambda: (idx := get_random_valid_ayah()) and (v := ALL_AYAT[idx]) and
187
- (f"<div class='ayah-text'>{v['text']}</div>", f"### {v['surah_name']} | آية {v['ayah']}", idx, ""),
188
- outputs=[text_html, info_text, idx_state, status_msg],
189
  show_progress="hidden"
190
  )
191
 
@@ -204,4 +181,4 @@ with gr.Blocks(title="منصة تلاوة") as demo:
204
  )
205
 
206
  if __name__ == "__main__":
207
- demo.launch(css=custom_css)
 
14
 
15
  SURAH_NAMES = ["الفاتحة", "البقرة", "آل عمران", "النساء", "المائدة", "الأنعام", "الأعراف", "الأنفال", "التوبة", "يونس", "هود", "يوسف", "الرعد", "إبراهيم", "الحجر", "النحل", "الإسراء", "الكهف", "مريم", "طه", "الأنبياء", "الحج", "المؤمنون", "النور", "الفرقان", "الشعراء", "النمل", "القصص", "العنكبوت", "الروم", "لقمان", "السجدة", "الأحزاب", "سبأ", "فاطر", "يس", "الصافات", "ص", "الزمر", "غافر", "فصلت", "الشورى", "الزخرف", "الدخان", "الجاثية", "الأحقاف", "محمد", "الفتح", "الحجرات", "ق", "الذاريات", "الطور", "النجم", "القمر", "الرحمن", "الواقعة", "الحديد", "المجادلة", "الحشر", "الممتحنة", "الصف", "الجمعة", "المنافقون", "التغابن", "الطلاق", "التحريم", "الملك", "القلم", "الحاقة", "المعارج", "نوح", "الجن", "المزمل", "المدثر", "القيامة", "الإنسان", "المرسلات", "النبأ", "النازعات", "عبس", "التكوير", "الانفطار", "المطففين", "الانشقاق", "البروج", "الطارق", "الأعلى", "الغاشية", "الفجر", "البلد", "الشمس", "الليل", "الضحى", "الشرح", "التين", "العلق", "القدر", "البينة", "الزلزلة", "العاديات", "القارعة", "التكاثر", "العصر", "الهمزة", "الفيل", "قريش", "الماعون", "الكوثر", "الكافرون", "النصر", "المسد", "الإخلاص", "الفلق", "الناس"]
16
 
17
+ # --- التنسيق البصري المحسن ---
18
  custom_css = """
19
  @import url('https://fonts.googleapis.com/css2?family=Amiri:wght@400;700&family=Reem+Kufi:wght@400;700&display=swap');
20
  :root { --gold: #D4AF37; --dark-green: #064635; }
 
29
  padding: 50px 20px;
30
  border-radius: 0 0 40px 40px;
31
  text-align: center;
 
32
  }
33
 
34
+ .real-count { font-size: 4rem; color: #FFFFFF !important; font-weight: bold; }
 
 
 
 
 
 
 
35
 
36
  .instruction-box {
37
  background: #fff9e6;
38
+ border-right: 8px solid var(--gold);
39
+ padding: 25px;
40
  border-radius: 15px;
41
  margin: 20px 0;
42
  text-align: right;
43
  direction: rtl;
44
+ box-shadow: 0 4px 10px rgba(0,0,0,0.08);
45
+ }
46
+
47
+ /* تكبير خط الملاحظة */
48
+ .instruction-box strong, .instruction-box span {
49
+ font-size: 1.3rem !important;
50
+ line-height: 1.8;
51
+ color: #444;
52
  }
53
 
54
  .custom-card {
 
56
  border-radius: 20px !important;
57
  padding: 25px !important;
58
  box-shadow: 0 8px 20px rgba(0,0,0,0.06) !important;
 
59
  }
60
 
61
  .ayah-text {
62
  font-family: 'Amiri', serif !important;
63
+ font-size: 2.5rem !important;
64
  color: var(--dark-green);
65
  line-height: 1.8 !important;
66
  text-align: center;
67
  }
 
 
 
68
  """
69
 
70
+ # --- المنطق ---
 
 
 
 
 
 
71
  def clean_text(text): return re.sub(r'<[^>]*>', '', text).strip()
72
 
73
  def fetch_surah(s_idx):
 
84
  def validate_ayah(v):
85
  return len(v['text']) <= 200
86
 
87
+ def get_random_valid_ayah_data():
 
88
  while True:
89
  idx = random.randint(0, len(ALL_AYAT)-1)
90
+ v = ALL_AYAT[idx]
91
+ if validate_ayah(v):
92
+ return f"<div class='ayah-text'>{v['text']}</div>", f"### {v['surah_name']} | آية {v['ayah']}", idx
 
 
 
 
 
 
 
 
 
 
 
 
93
 
94
  def on_submit(audio, current_idx):
95
  if not audio: return "⚠️ سجل صوتك أولاً", gr.update(), gr.update(), current_idx
96
  v = ALL_AYAT[current_idx]
97
  try:
98
  api.upload_file(path_or_fileobj=audio, path_in_repo=f"data/s{v['surah']}_a{v['ayah']}_{uuid.uuid4().hex[:6]}.wav", repo_id=REPO_ID, repo_type="dataset", token=HF_TOKEN)
99
+ text, info, idx = get_random_valid_ayah_data()
100
+ return "✅ تم الحفظ بنجاح، بارك الله فيك", text, info, idx
 
101
  except Exception as e: return f"❌ فشل الرفع: {str(e)}", gr.update(), gr.update(), current_idx
102
 
103
+ def jump_to_ayah(s_name, a_num):
104
+ try:
105
+ target_num = int(a_num)
106
+ for i, v in enumerate(ALL_AYAT):
107
+ if v['surah_name'] == s_name and v['ayah'] == target_num:
108
+ if not validate_ayah(v):
109
+ return "⚠️ الآية طويلة جداً (أكثر من 200 رمز).", gr.update(), gr.update(), gr.update()
110
+ return "✅ تم العثور على الآية", f"<div class='ayah-text'>{v['text']}</div>", f"### {v['surah_name']} | آية {v['ayah']}", i
111
+ return "⚠️ الآية غير موجودة.", gr.update(), gr.update(), gr.update()
112
+ except: return "⚠️ خطأ في البيانات.", gr.update(), gr.update(), gr.update()
113
+
114
+ # --- واجهة المستخدم ---
115
  with gr.Blocks(title="منصة تلاوة") as demo:
116
+ # استخدام دالة get_random_valid_ayah_data مباشرة في القيم الابتدائية لضمان التغيير في كل لود
117
+ init_text, init_info, init_idx = get_random_valid_ayah_data()
118
+
119
+ idx_state = gr.State(init_idx)
120
 
121
  gr.HTML(f"""
122
  <div class="hero-header">
123
+ <h1 style="color:white">مِنَصَّة التِّلَاوَة</h1>
124
+ <p style="color:white">بناء قاعدة بيانات صوتية لتدريب الذكاء الاصطناعي</p>
125
  <div style="margin-top:20px;">
126
+ <span style="color:white; font-size: 1.3rem;">مساهمات الأمة</span>
127
+ <div class="real-count">100</div>
128
  </div>
129
  </div>
130
  """)
131
 
132
  with gr.Column(elem_classes="gradio-container"):
133
+ # ملاحظة بخط كبير وRTL
134
  gr.HTML("""
135
  <div class="instruction-box">
136
+ <strong>💡 تنبيه هام للجودة:</strong><br>
137
+ <span>يرجى قراءة الآية بنفس واحد. <b>في حال الوقف والابتداء، يرجى عدم إعادة الكلمات السابقة</b>؛ ابدأ فوراً من الكلمة التالية للوقف لضمان دقة تدريب النموذج.</span>
 
138
  </div>
139
  """)
140
 
141
  with gr.Row():
142
  with gr.Column(scale=2):
143
  with gr.Column(elem_classes="custom-card"):
144
+ info_text = gr.Markdown(init_info)
145
+ text_html = gr.HTML(init_text)
146
+ status_msg = gr.Markdown("", elem_id="status-msg")
 
 
 
 
 
 
 
147
  with gr.Row():
148
+ send_btn = gr.Button("🎤 إرسال المساهمة", variant="primary")
149
  rnd_btn = gr.Button("🔄 آية عشوائية", variant="secondary")
150
 
151
  with gr.Column(scale=1):
 
156
  with gr.Column(elem_classes="custom-card"):
157
  gr.Markdown("### 🔍 اختيار آية")
158
  s_drop = gr.Dropdown(choices=SURAH_NAMES, label="السورة", value="الفاتحة")
159
+ a_num = gr.Number(label="الآية", value=1, precision=0)
160
  go_btn = gr.Button("انتقال")
161
 
162
+ # أحداث
 
 
 
163
  rnd_btn.click(
164
+ get_random_valid_ayah_data,
165
+ outputs=[text_html, info_text, idx_state],
 
166
  show_progress="hidden"
167
  )
168
 
 
181
  )
182
 
183
  if __name__ == "__main__":
184
+ demo.launch()