اذهب إلى المحتوى

Mustafa Suleiman

الأعضاء
  • المساهمات

    8695
  • تاريخ الانضمام

  • تاريخ آخر زيارة

  • عدد الأيام التي تصدر بها

    264

إجابات الأسئلة

  1. إجابة Mustafa Suleiman سؤال في من لم يشكر الناس لم يشكر الله كانت الإجابة المقبولة   
    ألف مبروك يا منتصر، وسنك صغير ما شاء الله عليك صراحة، واصل إجتهاد وهتحقق أكتر بكتير إن شاء الله، وركز إنك تتعلم الأساسيات كويس ومتستعجلش إنت لسة صغير وحاول تشتغل على مشاريع بعد الأساسيات ومتركزش أوي على تعلم إطارات العمل والمكتبات وتتجاهل الأساسيات.
    لأنها هي اللي هتخليك تتعلم وتستخدم أي لغة وإطار عمل أو مكتبة بسهولة بعد كدة، وتتعلم أسرع.
    حاول بناء مشروع كبير باللغات الأساسية التي تعلمتها، مثل تنفيذ تطبيق SPA باستخدام HTML, CSS, JS فقط وستتعلم الكثير من ذلك.
  2. إجابة Mustafa Suleiman سؤال في تصحيح خطأ في الكود الخاص بتحديث بيانات الطالب في PHP كانت الإجابة المقبولة   
    الكود يحتوي على خطأ واحد في عبارة SQL المستخدمة في الجملة prepare() في السطر التالي:
    $stmt2 = $con->prepare("UPDATE student SET name = ?, Email = ?password=? WHERE id =?"); حيث أن الخطأ هو عدم وجود فاصلة بين الحقول name و Email وبين الحقول Email و password، ويجب وضع فواصل بين الحقول بطريقة صحيحة
    والصحيح هو التالي:
    $stmt2 = $con->prepare("UPDATE student SET name = ?, Email = ?, password = ? WHERE id =?");
  3. إجابة Mustafa Suleiman سؤال في مشكلة ضبط موضع الصورة واسم المستخدم في مستوى الكتابة في كود HTML و CSS كانت الإجابة المقبولة   
    سأوضح لك بمثال كيف يمكن تنسيق الصورة مع النص.
    HTML:
    <div class="user-profile"> <img src="path/to/image.jpg" alt="صورة المستخدم"> <span class="username">اسم المستخدم</span> </div> CSS:
    .user-profile { display: flex; align-items: center; gap: 10px; /* المسافة بين الصورة واسم المستخدم */ } .username { font-size: 18px; /* حجم الخط لاسم المستخدم */ } قمت بإنشاء عنصر div بالصفات user-profile والذي يحتوي على الصورة واسم المستخدم.
    واستخدمت تنسيقات CSS لتطبيق display: flex على العنصر الأب user-profile لتحقيق توزيع المحتوى في مستوى واحد.
    وحددت align-items: center لمحاذاة العناصر عموديًا، و gap لتحديد المسافة بين الصورة واسم المستخدم.
    وتستطيع ضبط قيم التنسيق وفقًا لاحتياجاتك، مثل تغيير حجم الخط أو المسافة بين العناصر، وعليك بتعديل المسار path/to/image.jpg ليتناسب مع موقع الصورة.
     
  4. إجابة Mustafa Suleiman سؤال في مشكلة جلب الصور من خلال pickImage في flutter كانت الإجابة المقبولة   
    هناك بعض الأمور التي يجب مراعاتها عند استخدام pickImage في Flutter.
    أولاً، تأكد من أنك قمت بإضافة الاعتمادية الصحيحة لحزمة image_picker في ملف pubspec.yaml الخاص بمشروعك.
    ثانياً، تأكد من أنك قمت بمعالجة صورة المعاينة التي تم اختيارها بنجاح، وتستطيع استخدام مكتبة معالجة الصور مثل flutter_image_compress لضغط الصورة وتحسين أدائها.
    ثالثاً، في الكود الحالي، يتم تخزين مسار الصورة المحلية المحددة في حقل imageUrls كقيمة واحدة في قائمة الصور filteredUsers، ولكن العرض المتوقع يتطلب أن يحتوي كل عنصر في القائمة filteredUsers على قائمة من الصور المختارة، لذا يجب تعديل بعض الأجزاء في الكود.
    في دالة _captureImage، عند إضافة الصورة المحلية الجديدة إلى filteredUsers، قم بتعديل الكود لإنشاء قائمة جديدة من الصور بدلاً من تخزين الصورة المحددة بمفردها، وبإمكانك تحقيق ذلك بتغيير السطر:
    filteredUsers.add(ImageTopicModel(imageUrls: [image.path])); إلى:
    filteredUsers.add(ImageTopicModel(imageUrls: [image.path], isLocal: true)); وذلك للإ شارة أن هذه الصورة هي صورة محلية.
    ثم في دالة build، قم بتعديل جزء إنشاء عناصر الصور داخل ListView.builder كما يلي:
    return Container( height: 150, child: ListView.builder( // ... itemBuilder: (BuildContext context, int index) { // ... return Row( children: filteredUsers[index].imageUrls!.map((imageUrl) { if (filteredUsers[index].isLocal) { // عرض الصور المحلية return GestureDetector( onTap: () { print('Local image clicked! URL: $imageUrl'); // Perform any action you want when the image is clicked }, child: Padding( padding: EdgeInsets.only(right: 10.0), child: Container( height: 100, width: 100, child: Image.file( File(imageUrl), fit: BoxFit.cover, ), ), ), ); } else { // عرض الصور من الفايربيس return GestureDetector( onTap: () { print('Firebase image clicked! URL: $imageUrl'); // Perform any action you want when the image is clicked }, child: Padding( padding: EdgeInsets.only(right: 10.0), child: Container( height: 100, width: 100, child: Image.network( imageUrl, fit: BoxFit.cover, ), ), ), ); } }).toList(), ); }, ), ); وتلك التغييرات تتيح لك عرض الصور المحلية التي تم اختيارها من خلال pickImage بشكل صحيح بجانب الصور الأخرى التي تأتي من Firebase.
  5. إجابة Mustafa Suleiman سؤال في تعلم البرمجة من الصفر: الطريقة الافضل لتعلم البرمجة كانت الإجابة المقبولة   
    أنت لا تشعر بالضياع أو التشتت عزيزي، حتى من لديه خبرة كبيرة بالبرمجة إذا انقطع لفترة طويلة سينسى بالتأكيد، فالبرمجة تحتاج إلى ممارسة، فما بالك بمن درس لفترة صغيرة وانقطع بالتأكيد سيشعر بالضياع.
    وإذا كنت قد درست بشكل صحيح وبتأني وقمت بالتطبيق مرة مع المدرب ومرة بمفردك وحاولت التغيير قليلاً في المشروع لتتعلم أشياء جديدة من المشاكل التي ستواجهك، أو تستطيع مشاهدة بعض الفيديوهات ثم توقفت وقم بالتطبيق بمفردك وحاول الإضافة أو التغيير قليلاً لتتعلم.
    فلا مشكلة كل ما تحتاجه حاليًا هو مراجعة الدورة بشكل سريع أي تشغيل الفيديو على سرعة 1.5 أو 2 حسب ما يناسبك فإذا وجدت نفسك تسترجع المعلومات وتتذكر فعليك بالتطبيق على مشروع إذًا لتثبيت ما قمت بمراجعته.
    ولكن إذا وجدت نفسك لا تتذكر كم كبير من المعلومات أو تجد صعوبة في تنفيذ المشروع من البداية ولا تعرف ماذا تفعل بالكود، هنا يجب دراسة الدورة من البداية وبتأني وعدم الإنتقال من قسم إلى قسم إلا بعد التأكد أنك فهمت وطبقت بمفردك.
    ونصيحة، حاول ألا تشعر بالقلق عند تعلم البرمجة فالجميع بدأ من نفس النقطة، فأعطي نفسك بعض الوقت وإلتزم بمسار تعليمي وخلال فترة سيتحسن مستواك بشكل كبير.
    وأيضًا إذا واجهتك مشكلة قم بتقسيمها إلى أجزاء صغيرة وحاول تنفيذها ولا تنظر للمشكلة بشكل كامل، في البداية حاول التطبيق على أجزاء صغيرة ثم قم ببناء موقع كامل وستجد في الروابط التي أرفقتها لك موقع لتحديثات وتصاميم للتطبيق على ما تعلمته.
    وقد تم النقاش حول الطريقة الصحيحة لدراسة الدورات هنا بشكل مفصل:
    ولتجنب التكرار، أنصحك بقراءة النقاشات التالية فستجد بها إجابة على الكثير من الأسئلة لديك:
     
  6. إجابة Mustafa Suleiman سؤال في استخدام العنصر الزائف ":before" في CSS لا يصلح لإضافة عنصر قبل عنصر "input" والسبب في ذلك كانت الإجابة المقبولة   
    في CSS، تعتبر ":before" عنصر زائف وتستخدم لإضافة محتوى قبل عنصر محدد، بينما ":after" تستخدم لإضافة محتوى بعد عنصر محدد، وغالبًا تستخدم هاتين الخاصيتين لإضافة عناصر مرئية إلى عناصر HTML الموجودة.
    لكن في حالة عنصر الإدخال "input"، يعتبر استخدام ":before" غير صحيح ولا يعمل على نحو صحيح.، ذلك لأنه عنصر الإدخال "input" يعتبر عنصراً فارغاً لا يحتوي على محتوى داخلي.
    مما يعني أنه لا يمكنك استخدام ":before" لإضافة محتوى قبل عنصر "input" نفسه.
    وإذا كنت ترغب في إنشاء رمز البحث داخل عنصر الإدخال "input"، تستطيع استخدام العديد من الطرق لتحقيق ذلك.
    واحدة من هذه الطرق هي وضع عنصر فرعي مستقل للعنصر "input" واستخدام الخاصية "position: absolute" لتحديد موقع الرمز بالنسبة لعنصر الإدخال، كتعيين أيقونة لرمز البحث كخلفية للعنصر الفرعي وتنسيقه بواسطة CSS ليتناسب مع المظهر المطلوب.
    وسأوضح لك الكود اللازم لإنشاء رمز البحث داخل عنصر الإدخال "input" باستخدام خاصية "position: absolute":
    HTML:
    <div class="search-container"> <input type="text" class="search-input"> <span class="search-icon"></span> </div> CSS:
    .search-container { position: relative; } .search-icon { position: absolute; top: 50%; right: 10px; transform: translateY(-50%); width: 20px; height: 20px; background-image: url('path/to/search-icon.png'); background-size: cover; } .search-input { padding-right: 30px; } حيث قمت بإنشاء عنصر <div> لتكون حاوية لعنصر الإدخال "input" وعنصر الرمز "span".
    ثم بتعيين الخاصية "position: relative" للعنصر الحاوي .search-container ليمكن تحديد موقع العناصر الفرعية بالنسبة له.
    وتحديد الخاصية "position: absolute" للعنصر الفرعي .search-icon ليمكن تحديد موقعه بالنسبة للحاوية.
    ثم استخدمت الخاصيات top, right, transform لتحديد موقع الرمز في الزاوية العلوية اليمنى ووسط العنصر، قمت أيضًا بتعيين خلفية للرمز باستخدام خاصية "background-image" وتحديد حجمها باستخدام "background-size".
    أخيرًا، تعديل حجم عنصر الإدخال "input" بإضافة الحشو على الجانب الأيمن ليسمح بوجود مساحة كافية لعرض الرمز داخل العنصر.
    ولا تنسى استبدال 'path/to/search-icon.png' بمسار الصورة الخاصة بأيقونة البحث، أو تستطيع استخدام أيقونة من Font Awesome.
    وإليك مثال إذا أردت استخدام Font Awesome:
    HTML:
    <!DOCTYPE html> <html> <head> <!-- استيراد Font Awesome --> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" integrity="sha512-iecdLmaskl7CVkqkXNQ/ZH/XLlvWZOJyj7Yy7tcenmpD1ypASozpmT/E0iPtmFIB46ZmdtAc9eNBvH0H/ZpiBw==" crossorigin="anonymous" referrerpolicy="no-referrer" /> </head> <body> <div class="search-container"> <input type="text" class="search-input"> <span class="search-icon"><i class="fas fa-search"></i></span> </div> </body> </html> قمت بتحديد الأيقونة المستخدمة لرمز البحث باستخدام العنصر <i> ومنحها الفئات المناسبة .fas و .fa-search، حيث .fas تعني استخدام الأيقونات الخطية (Solid) و.fa-search تعني استخدام أيقونة البحث.
    CSS:
    .search-container { position: relative; } .search-icon { position: absolute; top: 50%; right: 10px; transform: translateY(-50%); width: 20px; height: 20px; color: #999; /* لتغيير لون الأيقونة */ } .search-input { padding-right: 30px; }  
  7. إجابة Mustafa Suleiman سؤال في تخزين البيانات في قاعدة بيانات Firebase وكيفية تخزين الخانات الثابتة واللغات المتعددة كانت الإجابة المقبولة   
    عندما يتعلق الأمر بتخزين البيانات في قاعدة البيانات، هناك عدة طرق يمكن اتباعها، وسأقدم لك بعض الأفكار العامة حول كيفية تخزين البيانات التي تم توضيحها في استفسارك.
    بالنسبة للخانات الثابتة، بإمكانك اتخاذ قرار بين تخزين القيم المباشرة أو استخدام المعرفات والربط ببيانات أخرى.
    ولنستخدم مثالك "اسم الكتاب: أبيض وأسود".
    تستطيع أن تقرر تخزين النص "أبيض وأسود" مباشرة كقيمة في قاعدة البيانات وجعلها حقلًا في الجدول الخاص بالمواضيع، أو باستطاعتك إنشاء جدول منفصل للكتب وتخزين تفاصيل الكتب فيه، مع إضافة حقل يحمل معرف الكتاب في جدول المواضيع للإشارة إلى الكتاب المحدد.
    بالنسبة للغات المتعددة، فإذا كنت ترغب في دعم العربية والإنجليزية في التطبيق، تستطيع تخزين اسم الكتاب باللغتين في قاعدة البيانات.
    مثلاً، إضافة حقول مثل "اسم الكتاب بالعربية" و "اسم الكتاب بالإنجليزية"، وبمثل هذا النهج، يمكن للتطبيق استخدام النص المناسب بناءً على لغة تفضيل المستخدم أو اختياراته.
    وتذكر أن الطريقة الأفضل والصحيحة لتخزين البيانات تعتمد على احتياجات تطبيقك.
    ,إذا كنت تستخدم قاعدة بيانات Firebase، فإنها توفر لك بنية لتخزين البيانات تعتمد على مفهوم الوثائق والمجموعات في قاعدة البيانات.
    حيث أن في Firebase، يتم تخزين البيانات في وثائق (Documents)، وهي هيكل تخزين قابل للتنفيذ يتكون من مجموعة من الحقول وقيمها. يمكنك أن تنظر إلى الوثيقة كإدخال مستقل في قاعدة البيانات.
    وبناءً على ما تم شرحه، تستطيع تخزين الخانات الثابتة (مثل نوع المشاركة ونوع الكتاب ورقم الإصدار) كحقول في وثيقة الموضوع، وتخزين القيم المباشرة لهذه الخانات مباشرة في حقولها بقاعدة البيانات.
    مثلاً، إنشاء وثيقة لكل موضوع وتتضمن حقولًا مثل "عنوان الموضوع" و "نوع المشاركة" و "نوع الكتاب" و "رقم الإصدار"، وتخزين القيم المدخلة من المستخدمين في هذه الحقول.
    في Firebase، بإمكانك أيضًا تخزين قيم متعددة لنفس الحقل باستخدام مفهوم المصفوفات. وبالتالي، تستطيع تخزين أسماء الكتب بالعربية والإنجليزية في نفس الحقل، مثل ["أبيض وأسود", "Black and White"].
     
  8. إجابة Mustafa Suleiman سؤال في كيفية تحويل قيمة استرداد Firestore من String إلى Map<String, dynamic> في Flutter؟ كانت الإجابة المقبولة   
    في البداية الخطأ الذي تواجهه يحدث عند استخدام String بدلاً من Map<String, dynamic>، والسبب في الخطأ هو أنَّ قيمة "ImageTopic" في الكود الخاص بك ليست في صيغة JSON صحيحة.
    حاول التأكد من أن جميع القيم الموجودة في حقل "ImageTopic" تم تخزينها بصيغة JSON صحيحة، أيضًا التأكد من أن موديل "ImageTopicModel" يتوافق مع القيم الموجودة في "ImageTopic".
    ولتحديد الخطأ بشكل أدق، تستطيع تحويل الـ Map<String, dynamic> إلى String باستخدام JSON.encode() ومن ثم استخدام print() لطباعة الناتج، وهذا يمكن أن يساعد في تحديد ما إذا كانت البيانات الموجودة في حقل "ImageTopic" تتوافق مع JSON صحيح أم لا.
    استخدم الكود التالي لتحويل الـ Map<String, dynamic> إلى String:
    final jsonString = json.encode(myMap); ولتحويل الـ String إلى Map<String, dynamic> استخدام هذا الكود:
    final myMap = json.decode(jsonString); وأيضًا حاول تغيير هذا السطر في الكود:
    List<dynamic> myArray = querySnapshot.docs.first.get('ImageTopic') ?? []; إلى هذا الشكل:
    List<dynamic> myArray = List<Map<String, dynamic>>.from(querySnapshot.docs.first.get('ImageTopic') ?? []); هذا التغيير سيحول النوع المسترجع من البيانات إلى List<Map<String, dynamic>> والذي يمكن استخدامه في الخطوة التالية من تحويل العناصر إلى قائمة من Model objects.
    وبعد ذلك، يجب تحديث تابع fromJson() في ImageTopicModel ليتعامل مع Map<String, dynamic> بدلاً من String.
    استخدام الكود التالي كنموذج للتحديث:
    factory ImageTopicModel.fromJson(Map<String, dynamic> json) { return ImageTopicModel( imageTopic: json['imageTopic'], ); }  
  9. إجابة Mustafa Suleiman سؤال في هل اكثر من تطبيق في مشروع واحد في firebase سوف يودي الي تكرار الاشعارات في كل التطبيقات ؟ كانت الإجابة المقبولة   
    إذا قمت بإنشاء مشروع واحد في Firebase للاشتراك في الخدمة المشتركة بين تطبيق المستخدم وتطبيق مقدم الخدمة، فسوق يؤدي إلى تلقي الإشعارات في كلا التطبيقين، وهذا يحدث لأن المشروع في Firebase يعتبر كمنطقة مشتركة لجميع التطبيقات المرتبطة به.
    فإذا كنت ترغب في تجنب تلقي الإشعارات في كلا التطبيقين، تستطيع اتخاذ إحدى الخيارات التالية:
    1- إنشاء مشروع مستقل في Firebase لكل تطبيق (تطبيق المستخدم وتطبيق مقدم الخدمة)، مما سيفصل الإشعارات والتكوينات بين التطبيقين ويحد من تكرار الإشعارات.
    2-  استخدام العلامات Tags في Firebase لتمييز المستخدمين ومقدمي الخدمة وإرسال الإشعارات بناءً على العلامات المحددة، عن طريق تعيين علامات مختلفة لكل تطبيق واستخدامها في عمليات إرسال الإشعارات لتحديد المستلم المناسب.
    بمعنى في تطبيق المستخدم:
    عند تسجيل المستخدم في التطبيق، يتم تعيين علامة مثل "user_app" للمستخدم باستخدام دالة setUserProperty في Firebase. عند إرسال الإشعارات إلى مستخدمي التطبيق، قم بتحديد العلامة "user_app" كجزء من المستخدمين المستهدفين. في تطبيق مقدم الخدمة:
    عند تسجيل مقدم الخدمة في التطبيق، يتم تعيين علامة مثل "provider_app" لمقدم الخدمة باستخدام دالة setUserProperty في Firebase. عند إرسال الإشعارات إلى مقدمي الخدمة، قم بتحديد العلامة "provider_app" كجزء من المستخدمين المستهدفين. عمومًا، من الأفضل تصميم تطبيق Firebase بشكل منفصل لكل تطبيق، خاصة إذا كانت التطبيقات مستقلة تمامًا ولها متطلبات واحتياجات مختلفة.
  10. إجابة Mustafa Suleiman سؤال في نصيحة لتعلم مجال تعلم الآلة بعد تعلم تطوير المواقع، أم استمر في مجال تطوير المواقع؟ كانت الإجابة المقبولة   
    لا أنصحك بالاستمرار فيما تفعله، ضع شغفك جانبًا وتعلم المهارات المطلوبة في سوق العمل المحلي لديك أو مواقع العمل الحر، وتلك نصيحة دائمًا أرددها، حيث أن الكثير يقع في ذلك الفخ، وهو السعي وراء تعلم ما يريده أو  اللغة والإطار الأشهر، وفي النهاية يصبح غير قادر على الحصول على وظيفة بسبب عدم إمتلاك المهارات المطلوبة.
    أنت في الطريق الصحيح، حيث أن مجال الويب ستتعلم منه الكثير وسيفتح لك مجالات أخرى بسبب سهولة تعلمه نسبيًا وبه مجال الواجهة الأمامية والواجهة الخلفية وتصميم واجهات المستخدم، وسيسهل عليك تعلم المجالات الأخرى مثل تطوير تطبيقات الهاتف.
    بإختصار اختر مسار تعليمي يؤهلك إلى إمتلاك المهارات اللازمة للحصول على وظيفة أو تأهيلك لتنفيذ مشاريع حقيقية للعمل على مواقع العمل الحر، بعد ذلك تعلم ما تشاء في أوقات فراغك.
    وإليك بعض النقاشات التي قد تفيدك:
    عندي حب للبرمجة ولكنني لا أستمر في تعلمها .. ماهو الحل ؟  
  11. إجابة Mustafa Suleiman سؤال في كيف أضيف شعار لمدونة بلوجر ؟ كانت الإجابة المقبولة   
    أنت بذلك تقصد FavIcon أي أيقونة المفضلة، ولإضافتها  إلى مدونتك على بلوجر، عليك بإتباع التالي:
    قم بإعداد الشعار الخاص بك بتنسيق صورة صغيرة، عادةً بحجم 16x16 بكسل أو 32x32 بكسل. يجب أن يكون الشعار بتنسيق صورة مشفرة بتنسيق ICO أو PNG.
    انتقل إلى "تخطيط المدونة" (Layout) من لوحة التحكم. انقر على "تحرير" (Edit) بجانب عنصر "رأس المدونة" (Blog Header). ستنتقل إلى صفحة تحرير عنصر رأس المدونة. ابحث عن خيار "fav icon" أو "رمز الموقع" (Site Icon). انقر على زر "اختيار ملف" (Choose File) أو "استعراض" (Browse) لتحديد ملف FavIcon الذي قمت بإعداده في الخطوة الأولى. بعد اختيار الملف، انقر على زر "حفظ" (Save) أو "تحديث" (Update) لحفظ التغييرات.
  12. إجابة Mustafa Suleiman سؤال في ما هي شروط قبول مدونة بلوجر فى جوجل ادسنس ؟ كانت الإجابة المقبولة   
    أقصر طريق للقبول بسرعة في جوجل أدسنس هو إنشاء محتوى عالي الجودة وأن يضمن موقعك تجربة جيدة للزائرين من حيث السرعة المقبولة وقالب الموقع المناسب للهاتف.
    وسألخص لك الشروط:
    1- محتوى الموقع: يجب أن يكون المحتوى الذي تريد وضع الإعلانات فيه محتوى ذو جودة عالية ومفيد للمستخدمين. ويجب أن يكون المحتوى مكتوبًا بلغة صحيحة وواضحة ويتوافق مع سياسة AdSense. كما يجب أن لا يحتوي على محتوى مخل بالآداب العامة أو ينتهك القوانين الدولية.
    2- عدد الزيارات: يجب أن يكون لديك عدد كافٍ من الزيارات اليومية للموقع. لا يوجد رقم محدد للزيارات المطلوبة، ولكن عادة ما يعتبر موقعك مؤهلاً للتقديم عندما يكون لديك عدد كبير من الزيارات الفريدة كل شهر.
    3- تصميم الموقع: يجب أن يكون تصميم الموقع جذابًا وسهل الاستخدام، ويجب أن يكون متوافقًا مع متطلبات AdSense. يجب أن يتضمن محتوى الموقع صفحات مثل "الاتصال بنا" و "سياسة الخصوصية" و "الشروط والأحكام" وغيرها.
    4- العمر: يجب أن يكون عمر موقعك على الأقل 6 أشهر، وذلك للتأكد من أن الموقع يتمتع بالاستقرار والنمو.
    5- الدول المؤهلة: يتم قبول التسجيل في برنامج AdSense في بعض الدول فقط، لذلك تحتاج إلى التحقق من ما إذا كانت دولتك مؤهلة للتقديم.
    وأهم نصيحة أقدمها لك هي  الصبر والاستمرارية حيث يمكن أن تستغرق عملية الحصول على الموافقة من Google AdSense بعض الوقت، ولا ينبغي الاستسلام في حالة الرفض الأولي، ويمكن تحسين الموقع والمحتوى وإعادة تقديم الطلب، وكذلك الاستمرار في إنشاء محتوى عالي الجودة فالأمر يتطلب وقت لتحقيق عائد.
  13. إجابة Mustafa Suleiman سؤال في هل سيظل الكورس هذا مفتوح لي الى الأبد! كانت الإجابة المقبولة   
    لا مشكلة في السؤال، للحصول على شهادة إتمام الدورة ستحتاج إلى أن فهم الدورة بشكل وافي، وأيضًا رفع المشاريع التي تم تنفيذها خلال الدورة على GitHub لإرسالها للمراجعة.
    وهم:
    بناء واجهة مستخدم تشبه موقع YouTube بناء صفحات هبوط وتشمل: صفحة قريبًا الانطلاق صفحة شركة صفحة تطبيق جوال صفحة شخصية تطوير متجر إلكتروني تطوير موقع شركة تطوير لوحة تحكم بناء مواقع ثابتة باستخدم Hugo تطوير موقع أخباري وتستطيع التقدم للإمتحان بمجرد إتمام 4 مسارات أي الحد الأدنى هو عند مسار تطوير متجر إلكتروني، ولكن الأفضل هو إنهاء الدورة بالكامل ولا تستعجل.
    وأسلوب الإمتحان هو مكالمة صوتية لمدة 30 دقيقة مع أحد المدربين لسؤالك حول الدورة وعن مدى فهمك والأمور التي نفذتها أنت، وبعد ذلك سيتم تحديد مشروع لك لنفيذه لمدة تتراوح ما بين أسبوع إلى أسبوعين ثم مكالمة صوتية أخرى لمدة 30 دقيقة لمناقشة المشروع.
    ولا تقلق تستطيع التقدم للإمتحان مرة أخرى، ولكن حاول الاستعداد جيدًا توفيرًا لوقتك للنجاح من المرة الأولى.
    وقد تم شرح ذلك بشكل وافي في النقاشات التالية وبمزيد من التفاصيل وطريقة التقدم للإمتحان:
    وبخصوص العمل على مواقع العمل الحر مثل خمسات ومستقل، فطبعًا تستطيع ذلك بمجرد قدرتك على تنفيذ مشروع بمفردك بواسطة HTML,CSS,JS و مكتبة jQuery وأي مشروع يتطلب تلك المهارات تستطيع تقديم عرض عليه.
    لكن نصيحتي إليك هي بقراءة النقاش التالي لتفهم طبيعة سوق العمل:
    وبخصوص طريقة التعلم الصحيحة أنصحك بقراءة النقاش التالي:
     
  14. إجابة Mustafa Suleiman سؤال في توضيح بشأن طرق التوجيه في تطبيقات لارافيل، وما يعنيه PUT,PATCH,DELETE وغيرهم كانت الإجابة المقبولة   
    في تطبيقات Laravel، توجد طرق مختلفة للتوجيه (Routing) للوصول إلى مسارات محددة في التطبيق، وتستخدم هذه الطرق لتعريف العمليات المتاحة لتطبيقك، مثل إنشاء سجل جديد، تحديث سجل موجود، استرجاع سجل معين، أو حذف سجل. تساعدك هذه الطرق في تنظيم وترتيب واجهة تطبيقك.
    فيما يلي شرح لبعض الطرق الشائعة في Laravel والغرض منها ومتى يتم استخدامها:
    1- POST
    الغرض: تستخدم لإرسال طلب لإنشاء مورد جديد. مثال: إرسال طلب لإنشاء مستخدم جديد في تطبيقك. Route::post('/users', 'UserController@store');  
    // UserController.php public function store(Request $request) { // استلام البيانات المطلوبة لإنشاء المستخدم من الطلب $userData = $request->only(['name', 'email', 'password']); // قم بإنشاء المستخدم وحفظه في قاعدة البيانات $user = User::create($userData); // استعادة الاستجابة ببيانات المستخدم المنشأ return response()->json($user, 201); } 2- GET
    الغرض: تستخدم لاسترجاع معلومات محددة من المورد. مثال: استرجاع بيانات المستخدم الذي يحمل معرّف معين. Route::get('/users/{id}', 'UserController@show');  
    // UserController.php public function show($id) { // البحث عن المستخدم المرتبط بالمعرّف المحدد $user = User::findOrFail($id); // استعادة الاستجابة ببيانات المستخدم return response()->json($user); } 3- PUT/PATCH
    الغرض: تستخدم لتحديث مورد محدد. مثال: تحديث بيانات المستخدم الذي يحمل معرّف معين. وتستطيع استخدام PUT لتحديث جميع البيانات في المورد، بينما يمكن استخدام PATCH لتحديث جزء من البيانات فقط.
    Route::put('/users/{id}', 'UserController@update'); أو
    Route::patch('/users/{id}', 'UserController@update');  
    // UserController.php public function update(Request $request, $id) { // استلام البيانات المطلوبة لتحديث المستخدم من الطلب $userData = $request->only(['name', 'email']); // البحث عن المستخدم المرتبط بالمعرّف المحدد $user = User::findOrFail($id); // تحديث بيانات المستخدم $user->update($userData); // استعادة الاستجابة ببيانات المستخدم المحدثة return response()->json($user); } 4- DELETE
    الغرض: تستخدم لحذف مورد محدد. مثال: حذف مستخدم معين من قاعدة البيانات. الطرق الأربعة السابقة (POST، GET، PUT/PATCH، DELETE) تُعد الأكثر شيوعًا في RESTful API وتطبيقات الويب، وتستخدم في بناءً عمليات CRUD (Create، Read، Update، Delete) المتعارف عليها في تطوير البرمجيات.
    Route::delete('/users/{id}', 'UserController@destroy');  المسار  هو "/users/{id}" للوصول إلى الدالة "destroy" في "UserController"، والتي تتولى حذف المستخدم المرتبط بالمعرف الممرر كمتغير في المسار.
    ثم يمكنك تنفيذ هذا المسار عن طريق استخدام طريقة DELETE في نموذج الاستدعاء عبر الشبكة.
    مثلاً،  باستخدام إطار العمل Axios في JavaScript، يمكننا استخدام الرمز التالي لحذف المستخدم:
    axios.delete('/users/1') .then(response => { console.log('تم حذف المستخدم بنجاح'); }) .catch(error => { console.error('حدث خطأ أثناء حذف المستخدم'); }); وهناك العديد من الطرق الأخرى التي يمكن استخدامها في توجيه Laravel، إليك بعض الأمثلة الإضافية:
    OPTIONS
    الغرض: يُستخدم لاستعلام الخيارات المدعومة لمسار محدد. مثال: استعلام الخيارات المدعومة لمسار معين للاحتفاظ بمعلومات الخيارات المتاحة. Route::options('/users', 'UserController@options'); يتم تعيين المسار "/users" للوصول إلى الدالة "options" في "UserController" التي تستعرض الخيارات المدعومة لمسار المستخدم.
    HEAD
    الغرض: يُستخدم لاستعلام رأس الاستجابة فقط دون استرجاع البيانات الفعلية. مثال: التحقق من توفر المورد دون استعادة بياناته. Route::head('/users/{id}', 'UserController@head'); تم وضع المسار "/users/{id}" للوصول إلى الدالة "head" في "UserController" التي تعيد فقط رأس الاستجابة دون استرداد بيانات المستخدم.
  15. إجابة Mustafa Suleiman سؤال في ما الفرق بين master و main في GitHub؟ كانت الإجابة المقبولة   
    في GitHub، تُستخدم تعابير "master" و "main" للإشارة إلى الفرع الافتراضي الرئيسي لمستودع Git.
    والفرق بينهما هو فقط في الاسم وليس في الوظيفة أو الأداء.
    فقديمًا، كان اسم الفرع الافتراضي في GitHub هو "master"، وهذا الاسم استُخدم للإشارة إلى الفرع الرئيسي الذي يحتوي على النسخة الرئيسية من المشروع. ومع ذلك، بدأت GitHub في اعتماد مصطلح "main" بدلاً من "master" بسبب القلق المتزايد حول المصطلح "master" وتأثيره اللاحق على العنصرية والتمييز العنصري.
    لذا، لجعل GitHub أكثر شمولًا ومتعدد الثقافات، قامت GitHub بتغيير اسم الفرع الافتراضي من "master" إلى "main". ومع ذلك، لا يزال بإمكان المستخدمين استخدام اسم "master" إذا كانوا يفضلون ذلك.
    أي أن استخدام "master" أو "main" في GitHub يعتبر مسألة تفضيل شخصي، ولا يؤثر ذلك على أداء مستودع Git أو إمكانياته.
    ولتحويل اسم الفرع الافتراضي في مستودع Git من "master" إلى "main" أو العكس، يمكنك اتباع الخطوات التالية:
    قم بفتح مستودع Git الذي ترغب في تغيير اسم الفرع الافتراضي فيه على GitHub. انتقل إلى صفحة الإعدادات (Settings) للمستودع. ابحث عن قسم يسمى "Branches" أو "Default Branch"، وسيعرض الفرع الافتراضي الحالي (مثل "master" أو "main"). انقر على الزر أو الرابط المرتبط بتغيير الفرع الافتراضي. ستظهر لك قائمة تحتوي على الفروع المتاحة في المستودع، حدد الفرع الجديد الذي ترغب في جعله الافتراضي (مثل "master" أو "main"). قد يُطلب منك تأكيد التغيير وإدخال كلمة مرورك. بعد التأكيد، ستتم عملية تحويل الفرع الافتراضي، وسيتم استخدام الفرع الجديد في المستقبل. يرجى ملاحظة أن تحويل اسم الفرع الافتراضي على GitHub لا يؤثر على تاريخ أو تاريخ الالتزامات الموجودة في المستودع، وهو مجرد تغيير في الاسم المستخدم للفرع الافتراضي.
  16. إجابة Mustafa Suleiman سؤال في هل دورة علوم الحاسوب ضرورية لمبتدئ في Back-end developer؟ كانت الإجابة المقبولة   
    الأمر يتوقف على الوقت المتاح لك وعلى مستواك في البرمجة والدراية بمفاهيم مجال الحاسوب والويب.
    لذلك إذا كان لديك الوقت الكافي، فعليك بتعلم مسار علوم الحاسوب بالكامل، فالأمر يستحق فعلاً وقد تم شرح السبب في النقاشات التالية:
    وإذا كان ليس لديك وقتٍ كاف أو تريد الحصول على وظيفة في اقرب وقت، فتستطيع دراسة أساسيات جافاسكريبت فقط مع تنفيذ مشروع للتطبيق على ما تعلمته، وبدون تطبيق ما تعلمته على مشروع فأنت لم تتعلم شيئًا بكل صراحة.
    لكن قبل تعلم جافاسكريبت أنت بحاجة إلى تعلم أساسيات HTML وCSS وأنت بحاجة إلى تعلمها بلا شك سواء كنت مطور واجهات أمامية أو خلفية.
    لذلك في رأي الإنتقال مباشرًة الباك إند بدون نظرة واسعة حول مفهوم الويب وبناء مشروع في الواجهة الأمامية وتعلم الأساسيات فقط به، سيصعب عملية التعلم كثيرًا عليك.
    الأمر الذي يعود بنا إلى ضرورة تعلم الأساسيات وهو ما توفره دورة علوم الحاسوب، أردت فقط توضيح أنك ستسير في دائرة مفرغة في حالة تخطي الأساسيات.
    ودائمًا ستعود لتعلمها، فلما لا تبدأ بداية صحيحة والدورة ليست كبيرة، وبعد الإنتهاء منها ستسطيع تعلم PHP ولارافيل بسهولة أكبر حيث أنك ستكون قد تجهزت وعقلك استوعب المفاهيم البرمجية وامتلكت نظرة شاملة عن الويب وأنظمة التشغيل والتفكير المنطقي الصحيح.
    فمسارات دورة علوم الحاسب هي:
    أساسيات البرمجة أنظمة التشغيل ونظام لينكس قواعد البيانات إلى عالم الويب البرمجة كائنية التوجه الخوارزميات وبنى المعطيات أنماط التصميم أساسيات هندسة البرمجيات ومسارات دورة PHP هي: 
    أساسيات إطار العمل Laravel بناء شبكة تواصل اجتماعي تشبه إنستغرام إنشاء RESTful API باستخدام Laravel متجر إلكتروني لبيع الكتب تطوير نظام إدارة محتوى تطبيق لتقييم الأماكن على الخرائط تطبيق مشاركة فيدوهات تطوير موقع إعلانات مبوبة تطوير قوالب ووردبريس تطوير قالب ووردبريس أخباري تطوير متجر إلكتروني في ووردبريس عبر ووكومرس وكما ترى بدخولك مباشرًة إلى دورة PHP أنت تتخطى الكثير من الأساسيات وستحتاج إلى العودة لتعلمها أو ستواجه بطيء في عملية التعلم في حال عدم العودة.
     
  17. إجابة Mustafa Suleiman سؤال في خطأ "invalid date string: Unparseable date" يظهر في أندرويد ستوديو، ما هو السبب وكيفية حله؟ كانت الإجابة المقبولة   
    الخطأ بسبب تاريخ غير صالح يتم استخدامه في التطبيق الذي تحاولي تشغيله، وتحديدًا التاريخ المستخدم في التطبيق ليس قابلاً للتحليل بسبب وجود علامات غير صالحة أو أخطاء في تنسيق التاريخ.
    عليك بالتحقق من التاريخ المستخدم في التطبيق والتأكد من أنه مكتوب بشكل صحيح وفقًا لتنسيق التاريخ الصحيح.
    وتستطيعي استخدام الأدوات المتاحة في أندرويد ستوديو للتحقق من صحة التاريخ وتنسيقه، وأيضًا استخدام مكتبات Java التي تتضمن الدوال الخاصة بالتحويل بين التواريخ.
    وقد يكون السبب أن لغة النظام لديكِ باللغة العربية، لذلك حاولي أولاً تغيير لغة التاريخ إلى الإنجليزية في الويندوز وضبط المنطقة الزمنية، وإذا استمرت المشكلة حاولي تغيير لغة النظام إلى الإنجليزية وإعادة تشغيل أندرويد استوديو بعد أي تعديل مما سبق.
    وأرجو قراءة النقاش التالي، فهو يتعلق بنفس المشكلة الخاصة بك:
     
  18. إجابة Mustafa Suleiman سؤال في فهم كيف يتم نقل الصوت والفيديو في الوتس او تطبيقات المحادثة كانت الإجابة المقبولة   
    تتم عملية نقل الصوت والفيديو في تطبيقات المحادثة مثل الواتساب عبر استخدام تقنية Protocol (IP)، وتتضمن هذه التقنية تحويل الصوت والفيديو إلى تنسيق رقمي يمكن نقله عبر الانترنت، وذلك باستخدام تقنيات الضغط والتشفير لتحسين جودة الصوت والفيديو وتأمينه.
    وعندما يرسل أحد المستخدمين مقطع فيديو أو صوت عبر التطبيق، يتم تحويله إلى تنسيق رقمي و تقسيمه إلى عدة حزم صغيرة، و إرسال هذه الحزم عبر الانترنت إلى المستلم.
    وبعد ذلك، جمع هذه الحزم مرة أخرى وتحويلها إلى مقطع فيديو أو صوت وعرضها أو تشغيلها على جهاز المستلم.
    ويستخدم كل من Protocol (IP) و WebRTC في تطبيقات المحادثة ونقل الصوت والفيديو.
     Protocol (IP) كبروتوكول رئيسي لنقل البيانات عبر الإنترنت بشكل عام، ويعتمد على تجزئة البيانات إلى حزم ونقلها من خلال الشبكة. ويستخدم في تطبيقات المحادثة كأساس لنقل الصوت والفيديو من جهاز المرسل إلى جهاز المستقبل.
    أما WebRTC فهو تقنية حديثة ومفتوحة المصدر تم تطويرها خصيصاً لنقل الصوت والفيديو والبيانات الحية في الوقت الحقيقي عبر الإنترنت.
    ويتضمن WebRTC بروتوكولات مخصصة للصوت والفيديو والشات وتقنيات الضغط والتشفير وغيرها لتحسين جودة الاتصال وتأمينه. ويستخدم WebRTC في العديد من تطبيقات المحادثة عبر الإنترنت والتطبيقات الأخرى التي تحتاج إلى نقل الصوت والفيديو عبر الإنترنت بشكل سريع وآمن.
    وتستطيع إنشاء تطبيق محادثة صوتية باستخدام بايثون باستخدام بعض المكتبات المتاحة، مثل:
    PyAudio: مكتبة بايثون للعمل مع الصوت، وتتيح لك إمكانية تسجيل وتشغيل الصوت على نظام التشغيل الخاص بك. Socket: مكتبة بايثون للتواصل بين العملاء والخوادم باستخدام TCP/IP. PyQT: مكتبة بايثون لإنشاء واجهات المستخدم الرسومية (GUI)، والتي يمكن استخدامها لإنشاء واجهة المستخدم لتطبيق المحادثة الصوتية. ومن الخطوات التي يمكن اتباعها لإنشاء تطبيق محادثة صوتية باستخدام بايثون:
    تسجيل الصوت باستخدام مكتبة PyAudio. إنشاء واجهة المستخدم باستخدام مكتبة PyQT. التواصل بين العميل والخادم باستخدام مكتبة Socket. نقل بيانات الصوت بين العميل والخادم عبر الاتصال الشبكي باستخدام بروتوكولات الإنترنت مثل TCP/IP أو UDP. تشفير وفك تشفير الصوت باستخدام تقنيات التشفير المناسبة. تشغيل الصوت على العميل باستخدام مكتبة PyAudio. إنشاء موقع يتضمن مقاطع فيديو أو صوت
    تستطيع استخدام لغة البايثون في إنشاء موقع مثل هذا، بالإضافة إلى العديد من التقنيات الأخرى مثل HTML وCSS وJavaScript و Django framework لإدارة الموقع.
    وإليك مثال، أنت قمت بإنشاء مشروع دجانغو، عليك بفعل التالي:
     تحديد نموذج Django الذي سيستخدم لتمثيل الفيديو أو الصوت. يمكن إنشاء نموذج بسيط كالتالي:
    from django.db import models class Video(models.Model): title = models.CharField(max_length=200) video_file = models.FileField(upload_to='videos/') حيث تم تحديد نموذج Video الذي يحتوي على اسم الفيديو وملف الفيديو.
    بعد تحديد نموذج الفيديو، يجب إنشاء عرض (View) Django الذي يعرض الفيديو. وتستطيع إنشاء عرض بسيط باستخدام الكود التالي:
    from django.shortcuts import render def video(request, video_id): video = Video.objects.get(id=video_id) return render(request, 'video.html', {'video': video}) يتم تحديد العرض "video" الذي يستخدم نموذج Video ويسترد الفيديو الذي يحمل نفس معرف video_id.
    ويجب إنشاء قالب (Template) Django الذي يستخدم لعرض الفيديو.
    حيث تستطيع إنشاء قالب بسيط باستخدام HTML و Django Template Language، و استخدام HTML5 Video Tag لعرض الفيديو.
    <html> <head> <title>{{ video.title }}</title> </head> <body> <h1>{{ video.title }}</h1> <video controls> <source src="{{ video.video_file.url }}" type="video/mp4"> </video> </body> </html وهناك العديد من المكتبات التي يمكن استخدامها مع Django لإضافة الوسائط مثل الفيديو والصوت والصور.
    بالنسبة للفيديو والصوت، تستطيع استخدام مكتبات مثل Django-ffmpeg و Django-Video-Encoder لمعالجة وتشفير الوسائط المتحركة.
    أيضًا يمكن استخدام مكتبات مثل Pillow و Django-imagekit لمعالجة الصور.
    وهناك مكتبات JavaScript مثل Plyr و Video.js و WaveSurfer.js لتشغيل الفيديو والصوت وتحريرهم في صفحات الويب.
     
  19. إجابة Mustafa Suleiman سؤال في التعامل مع الربط بين عدد من collections في firebase كانت الإجابة المقبولة   
    الطريقة التي تستخدمها لربط عدة collections في Firebase صحيحة وليست بها خطأ، ولكن، قد يصعب إدارة العديد من عمليات الربط لأكثر من 25 مجموعة.
    ولتحسين الأداء، تستطيع استخدام دالة الاستعلامات المتعددة (Batched Writes) في Firebase التي تتيح لك إنشاء وتحديث وحذف العديد من المستندات في مجموعة واحدة في نفس الوقت.
    وبإمكانك الاطلاع على التفاصيل الكاملة عن Batched Writes في Firebase من هنا: https://firebase.google.com/docs/firestore/manage-data/transactions#batched-writes 
    أيضًا عليك بالنظر في إمكانية استخدام الرسائل الفورية (Firebase Cloud Messaging) في Firebase لتحسين الأداء وتقليل العمليات اللازمة للحصول على بيانات جديدة وإرسالها إلى التطبيق الخاص بك.
    بالإضافة إلى النظر في تحسين هيكل البيانات الخاص بك في Firebase لتقليل عدد المستندات التي تحتاج إلى الوصول إليها في كل مرة.
    مثلاً، دمج بعض المعلومات في مستند واحد بدلاً من إنشاء مستندات منفصلة لكل بيانات.
    وإليك بعض الأفكار التي يمكن استخدامها لتحسين الكود الخاص بك:
    استخدام الدوال المتعددة للحصول على بيانات متعددة بدلاً من استخدام await Future.wait، وذلك قد يحسن من الأداء ويجعل الكود أكثر وضوحًا وقابلية للصيانة، مثال: استخدام الدالة getBooksSnapshot بدلاً من await booksSnapshotFuture. تستطيع استخدام Stream للحصول على بيانات متعددة من Firebase بطريقة فعالة من حيث الأداء، من خلال إنشاء Stream واحد للحصول على جميع البيانات المطلوبة من Firebase. يمكن هيكلة قاعدة البيانات الخاصة بك بشكل أفضل لتجنب الحاجة إلى الوصول إلى عدة مجموعات للحصول على بيانات متعددة، عن طريق إنشاء مجموعات فرعية أو إضافة بيانات إضافية إلى المستندات الحالية لتجنب الحاجة إلى الوصول إلى مجموعات متعددة للحصول على بيانات متعددة.  
  20. إجابة Mustafa Suleiman سؤال في استفسار حول استضافة Firebase وكيفية تخزين البيانات وعرضها في التطبيق كانت الإجابة المقبولة   
    Firebase هي منصة شاملة تحتوي على خدمات عديدة، بما في ذلك قاعدة بيانات Realtime و Cloud Firestore، وتستطيع استخدام أي منهما بناءً على احتياجاتك.
    إذا كنت تستخدم Cloud Firestore، فإنه يستخدم نموذج قاعدة بيانات NoSQL مختلف عن نموذج MySQL الذي اعتدت عليه.
    حيث يتم تخزين البيانات في مستندات (documents) في مجموعات (collections) بدلاً من الجداول (tables). لكن يمكن الوصول إلى البيانات باستخدام العلاقات والاستعلامات التي تتطلبها تطبيقك.
    مثلاً، يمكنك إنشاء مجموعتين، واحدة لـ"الكتب" وأخرى لـ"السنوات"، ثم ربطهما معًا باستخدام مفتاح خارجي، وهذا يمكن القيام به باستخدام المراجع (references) في Firestore.
    بخصوص السؤال الثاني
    من المناسب تخزين البيانات التي تريد عرضها في القوائم المنسدلة (dropdown lists) في قاعدة البيانات، حتى يمكنك تحديث هذه البيانات وإضافة عناصر جديدة دون الحاجة إلى تحديث تطبيقك.
    وتستطيع تخزين هذه البيانات في مجموعة خاصة بها في قاعدة البيانات، أو يمكن استخدام Firebase Realtime Database لتخزينها كما أنه يسمح بتخزين بيانات في شكل JSON.
    أي يمكنك تخزين البيانات المختلفة سواء في قاعدة البيانات أو كملفات JSON داخل تطبيقك.
    ولكن إذا كانت هذه البيانات تحتوي على معلومات متغيرة بشكل مستمر أو تحتاج إلى تحديثات من الخادم، فقاعدة البيانات هي الخيار الأفضل.
  21. إجابة Mustafa Suleiman سؤال في استفسار حول استخدام Plotly.js و console.table في VSCode كانت الإجابة المقبولة   
    1- لكي تظهر رسم بياني من Plotly.js في output في VSCode، تستطيع استخدام مكتبة "plotly-nodejs" والتي تسمح بإنشاء رسوم بيانية من Plotly.js دون الحاجة إلى فتح المتصفح.
    ولتثبيت هذه المكتبة باستخدام npm، اكتب الأمر التالي:
    npm install plotly-nodejs ثم يمكنك استخدام الكود التالي كمثال لإنشاء رسم بياني من Plotly.js وطباعته في output في VSCode:
    const plotly = require('plotly-nodejs'); const data = [ { x: [1, 2, 3], y: [4, 5, 6], type: 'scatter' } ]; const layout = { title: 'My Plotly Chart' }; plotly.plot(data, layout).then((figure) => { console.log(figure); }).catch((err) => { console.error(err); }); 2- لا يمكن التحكم في جدول Console باستخدام أوامر Console مثل console.table لأنها تتحكم فقط في كيفية طباعة البيانات في Console.
    ومع ذلك، تستطيع استخدام مكتبات Node.js مثل "cli-table" لإنشاء جداول مع تحكم كامل في التنسيق والعرض. ولتثبيت هذه المكتبة باستخدام npm، اكتب الأمر التالي:
    npm install cli-table وتستطيع استخدام الكود التالي كمثال لإنشاء جدول وطباعته في output في VSCode:
    const Table = require('cli-table'); const table = new Table({ head: ['Name', 'Age', 'Gender'], style: { head: ['green'], border: ['white'] } }); table.push( ['John', 30, 'Male'], ['Jane', 25, 'Female'], ['Bob', 45, 'Male'] ); console.log(table.toString());  
  22. إجابة Mustafa Suleiman سؤال في مشاكل في تعريف المتغيرات وعدم عرض النتائج بشكل مناسب في كود JavaScript كانت الإجابة المقبولة   
    تستطيع استخدام حلقتي for بدلاً من ذلك، حيث تقوم الحلقة الداخلية بتخزين قيم h، v، a، والحلقة الخارجية بتخزين قيم phi. بعد ذلك، يمكن رسم الرسم البياني باستخدام المكتبة المناسبة، مثل  Plotly طالما أنك تستخدم JavaScript.
    وقد تبدو بعض القيم مكررة لأنك تستخدم خطوة 0.5 في الحلقة الداخلية وبعض القيم تحتوي على مجموعة من الأرقام العشوائية الصغيرة التي يمكن أن تؤدي إلى تقريب القيمة بشكل غير دقيق.
    وبالنسبة لعرض القيم كجدول ورسم بياني، تستطيع استخدام المكتبة المذكورة أعلاه أو أي مكتبة أخرى، أو ببساطة إنشاء جدول HTML يعرض القيم بطريقة منظمة وسهلة القراءة، وإنشاء رسم بياني باستخدام المكتبة التي تفضلها.
     
  23. إجابة Mustafa Suleiman سؤال في كيفية دمج البيانات من مصادر مختلفة في Firebase؟ كانت الإجابة المقبولة   
    تم التوضيح من قبل عزيزي،  يمكنك دمج البيانات المسترجعة من الجدولين في نفس القائمة باستخدام الدالة addAll() في مكانين مختلفين في الكود.
    هناك عدة طرق للقيام بذلك وهذا مثال لكيفية الدمج:
    Future<void> _fetchData() async { final FirebaseFirestore firestore = FirebaseFirestore.instance; // Fetch the first query snapshot and extract the value of 'TopicState' final QuerySnapshot topicsSnapshot = await firestore .collection('topics') .where('id', isEqualTo: widget.PostID) .get(); final int topicState = topicsSnapshot.docs.isNotEmpty ? topicsSnapshot.docs.first.get('Id_Sub_Category') : null; final QuerySnapshot subCategorySnapshot = await firestore.collection('Sub_Category').where('idSubCat', isEqualTo: topicState).get(); final List<FullListWomanModel> data = []; if (topicsSnapshot.docs.isNotEmpty) { data.addAll(topicsSnapshot.docs.map((doc) => FullListWomanModel.fromJson(doc.data() as Map<String, dynamic>)).toList()); } if (subCategorySnapshot.docs.isNotEmpty) { // Loop over the documents of the Sub_Category collection and check if the document already exists in the data list to avoid duplication subCategorySnapshot.docs.forEach((doc) { final FullListWomanModel model = FullListWomanModel.fromJson(doc.data() as Map<String, dynamic>); if (!data.contains(model)) { data.add(model); } }); } setState(() { _ListDataDisplay = data; }); } الكود يقوم بإضافة جميع الوثائق التي تم العثور عليها في الجدول الثاني Sub_Category إلى القائمة data، ولكنه يتحقق أيضًا مما إذا كانت الوثيقة موجودة بالفعل في القائمة الرئيسية لتجنب التكرار والحفاظ على وجود عناصر فريدة في القائمة المدمجة النهائية.
  24. إجابة Mustafa Suleiman سؤال في إمكانية إنشاء تطبيق هاتف متكامل باستخدام جافاسكريبت وكفاءته مقارنة باللغات الأخرى. كانت الإجابة المقبولة   
    بالإمكان ربط كود بايثون مع كود React Native باستخدام Bridge API.
    ويستخدم Bridge API لإنشاء واجهات المستخدم والتعامل مع قواعد البيانات والاتصال بخدمات الويب والتحكم في التحليلات والأدوات الأخرى التي تعمل بلغة بايثون.
    ويتم تنفيذ Bridge API باستخدام وظيفة "native modules" في React Native و "Python modules" في بايثون. ويجب معرفة أنه يمكن استخدام Bridge API لتوفير القدرة على إعادة استخدام برامج بايثون الموجودة بالفعل وإضافة ميزات جديدة إلى تطبيقات React Native باستخدام لغة بايثون.
    مثلاً، تستطيعي استخدام بايثون لإنشاء نماذج التعلم الآلي والتفاعل معها في تطبيق React Native، وذلك من خلال مكتبة TensorFlow المتاحة في بايثون لإنشاء نماذج تعلم الآلة وتدريبها على البيانات.
    وبعد ذلك نستخدم Bridge API لربط تطبيق React Native مع تلك النماذج وتوفير واجهة المستخدم اللازمة لتفاعل المستخدمين معها.
    مثال بسيط على طريقة الربط بين بايثون وReact Native
    في البداية، عليك بإنشاء وحدة بايثون بسيطة تُسمى "calculator.py" وضعي بها الكود التالي:
    def add(a, b): return a + b الآن سنقوم بإنشاء Native Module في React Native لاستدعاء هذه الوحدة. يمكنك إنشاء ملف جديد يسمى "CalculatorModule.js" وضعي به التالي:
    import { NativeModules } from 'react-native'; const { Calculator } = NativeModules; export default { add: (a, b) => { return Calculator.add(a, b); }, }; وتأكدي من تحديد اسم Native Module كـ "Calculator"، ثم يمكنك استخدام هذا Native Module في كود React Native الخاص بك.
    من خلال إنشاء شاشة جديدة تُسمى "CalculatorScreen.js" كالتالي:
    import React, { useState } from 'react'; import { View, Text, TextInput, Button } from 'react-native'; import Calculator from './CalculatorModule'; const CalculatorScreen = () => { const [a, setA] = useState(''); const [b, setB] = useState(''); const [result, setResult] = useState(''); const handleAdd = () => { const res = Calculator.add(Number(a), Number(b)); setResult(res.toString()); }; return ( <View> <TextInput value={a} onChangeText={setA} /> <TextInput value={b} onChangeText={setB} /> <Button title="Add" onPress={handleAdd} /> <Text>{result}</Text> </View> ); }; export default CalculatorScreen; وكما ترين يتم استدعاء Native Module "Calculator" واستخدامه في دالة "handleAdd" لجمع الأعداد المدخلة، وعرض نتيجة الجمع في عنصر "Text".
    والمثال بسيط لكنه يوضح كيفية استخدام Bridge API لربط كود بايثون مع كود React Native، وبنفس المبدأ تستطيعي تطوير تطبيقات React Native متكاملة مع قواعد البيانات والتحكم في التحليلات والأدوات الأخرى.
  25. إجابة Mustafa Suleiman سؤال في استفسار حول استضافة firebase كانت الإجابة المقبولة   
    من الأفضل تخزين البيانات في صورة Lowercase من البداية في قاعدة البيانات.، ثم البحث عنها لحل لتلك المشكلة، أي سنبحث عن البيانات بعد أن قمنا بتخزينها في صورة حروف صغيرة:
    String nameCountryLower = NameContry.toLowerCase(); FirebaseFirestore.instance .collection('my_collection') .where('Country', isEqualTo: nameCountryLower) .get() .then((querySnapshot) { // يمكنك استخدام querySnapshot.docs للوصول إلى النتائج // ... }); أو استخدام أدوات أخرى للبحث في قاعدة البيانات وقد تم ذكرها في الرابط التالي:
    https://firebase.google.com/docs/firestore/solutions/search
    وهناك حل آخر:
    من خلال تحويل الاستعلام البحثي إلى مجموعة من القيم المتغيرة (variations) والتي يتم البحث عنها جميعها في الحقل الذي يراد البحث عنه.
    مثا: إذا كان البحث هو "oman" ، فسيتم تحويله إلى مجموعة ["oman"، "OMAN"، "Oman"] والتي تشمل جميع الحالات الممكنة لهذا الاستعلام بغض النظر عن حجم الأحرف.
    ثم يتم إجراء استعلام "in" حيث يتم البحث عن جميع هذه القيم المتغيرة في الحقل الذي يراد البحث عنه. يدعم استعلام "in" ما يصل إلى 10 مساواة (==) بين القيم مع عامل التشغيل "OR" اللوجيكي. وبهذا يمكن الاحتفاظ بحقل واحد فقط "name" والبحث فيه باستخدام التغييرات المحتملة عليه.
    List<String> variations = ["oman", "OMAN", "Oman"]; // TODO: write a function that converts the query string into this kind of Array QuerySnapshot search = await FirebaseFirestore.instance.collection("users").where("name", whereIn: variations).get(); وهنا يتم استخدام متغير القائمة (List) بدلاً من مصفوفة (Array) وكذلك الاستعلام البحثي whereIn بدلاً من "in"، وبعد ذلك يتم استخدام الدالة get() للحصول على نتائج الاستعلام.
×
×
  • أضف...