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

Mustafa Suleiman

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

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

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

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

    407

كل منشورات العضو Mustafa Suleiman

  1. التربح من المنصة يتم من خلال الإعلانات مثل وضع إعلانات بواسطة حسابك على google adsense أو أي مقدم إعلانات آخر للتربح. أيضًا تستطيع إنشاء قناة يوتيوب وشرح المحتوى العلمي الخاص بك بشكل مرئي ومسموع وعرض إعلانات على الفيديوهات. هناك وسيلة أخرى للربح وهي من خلال اشتركات المستخدمين، أي المساح للمستخدمين بالوصول لمحتوى معين قيم من خلال اشتراك شهري أو سنوي.
  2. لاحظ أن مجلد الملفات المؤقتة في النظام Temp يستخدم بواسطة Strapi لتخزين الملفات التي يتم رفعها بشكل مؤقت قبل معالجتها أو نقلها إلى وجهتها النهائية وهي Cloudinary، وبعد نقل الملفات بنجاح إلى Cloudinary، يحاول Strapi تنظيف الملفات المؤقتة بإزالتها من النظام المحلي. لكن يحدث خطأ ENOTEMPTY: directory not empty, rmdir ويعني أن هناك محاولة لحذف مجلد غير فارغ. حاول تشغيل vscode كمسؤول لتتمكن من حذف الملفات من قرص الـ C في مجلد Temp كالتالي:
  3. كل منهما له نقاط قوة وضعف، فالتعلم العميق يتفوق في التعامل مع البيانات المعقدة والغير منظمة مثل الصور، الفيديو، والنصوص، والشبكات العصبية العميقة مثل الشبكات العصبية التلافيفية (CNN) والشبكات العصبية المتكررة (RNN) تكون فعالة جدًا في تلك الحالات. بينما تعلم الآلة التقليدي أفضل في الحالات التي تكون فيها البيانات بسيطة ومنظمة، مثل الجداول والمصفوفات، ومن الأمثلة على خوارزميات تعلم الآلة التقليدية فلديك الانحدار الخطي، أشجار القرار، والـ SVM. أيضًا التعلم العميق يحتاج إلى كميات ضخمة من البيانات للتدريب بشكل فعال، فكلما زادت البيانات، كلما كانت النتائج أفضل، وهو يعتبر "صندوق أسود" إلى حد كبير، مما يجعل من الصعب تفسير كيفية اتخاذ القرارات. ويتطلب موارد حسابية كبيرة، بما في ذلك وحدات معالجة الرسوميات GPU وأحيانًا وحدات معالجة متخصصة أخرى، ويحتاج وقتًا طويلاً للتدريب وتكلفة مالية عالية بسبب متطلبات الأجهزة والبيانات. بجانب أنه أكثر دقة في بعض التطبيقات، خاصة تلك التي تتطلب التعرف على الأنماط المعقدة. على العكس في تعلم الآلة التقليدي فيعمل بشكل جيد مع كميات أصغر من البيانات، وغالبًا ما تكون النماذج أكثر شفافية وأسهل في التفسير. وأقل تطلبًا من حيث الموارد المطلوبة لمعالجة البيانات، وأسرع وأقل تكلفة، خاصة في المراحل الأولية من المشروع، وفي بعض التطبيقات، يكون الأداء مشابهًا أو حتى أفضل من التعلم العميق، خصوصًا عندما تكون البيانات محدودة.
  4. في بداية تعلمك لا حاجة لأن تشغل بالك بالكود النظيف، بل تعلم الطريقة الصحيحة والنظيفة لكتابة الكود لكن لا تجعل تركيز منصب على ذلك، بل على تنفيذ المطلوب فقط بغض النظر عن جودة الكود، وبعد الوصول لمستوى متقدم تستطيع الإهتمام بجودة الكود. وبخصوص الإختبارات فلن تجد لها أهمية في المشاريع البسيطة، لكن في المشاريع المتوسطة والمعقدة تظهر أهميتها. وبالطبع الكود النظيف يجعل الأمر أسهل وأسرع بمراحل ويجنبك الكثير من الأخطاء ويزيد من أداء الكود، فكيف ستقوم بإختبار كود وهو غير منظم ومكتوب بشكل جيد؟ للتوضيح يوجد أنواع كثيرة جدًا من الإختبارات وهي: اختبار الوحدة Unit Testing: يتمثل في اختبار الأجزاء الصغيرة من الكود بشكل مستقل، مثل الدوال أو الأساليب، للتأكد من أنها تعمل بشكل صحيح. اختبار التكامل Integration Testing: يهدف إلى اختبار كيفية تفاعل الوحدات المختلفة مع بعضها البعض لضمان أن النظام ككل يعمل بشكل صحيح عند دمج الوحدات. اختبار النظام System Testing: يشمل اختبار النظام بأكمله، بما في ذلك جميع مكوناته، للتأكد من أنه يلبي المواصفات المطلوبة ويعمل كما هو متوقع. اختبار القبول Acceptance Testing: يتم إجراء هذا الاختبار للتأكد من أن النظام يلبي معايير القبول التي حددها العميل أو المستخدم النهائي، مما يضمن رضاهم عن المنتج. اختبار الانحدار Regression Testing: يتمثل في إعادة اختبار النظام بعد إجراء تغييرات أو تحديثات لضمان أن التعديلات الجديدة لم تقدم أخطاء جديدة إلى النظام. اختبار الوظائف Functional Testing: يهدف إلى ضمان أن النظام يؤدي الوظائف المقصودة ويلبي المواصفات المطلوبة، من خلال اختبار كل وظيفة على حدة. اختبار الأداء Performance Testing: يتم اختبار النظام للتأكد من قدرته على التعامل مع الحمل المتوقع وأدائه الجيد تحت ظروف الضغط. اختبار الأمان Security Testing: يهدف إلى تحديد نقاط الضعف في النظام وضمان أمانه ضد الوصول غير المصرح به والهجمات الخبيثة. اختبار القابلية للاستخدام Usability Testing: يهدف إلى ضمان أن النظام سهل الاستخدام وملائم للمستخدم النهائي، مما يحسن من تجربة المستخدم. اختبار التوافقية Compatibility Testing: يتم إجراء هذا الاختبار للتأكد من أن النظام يعمل بشكل صحيح على مختلف البيئات والمنصات والأجهزة. اختبار الاستكشاف Exploratory Testing: يتمثل في اختبار النظام بطريقة غير مهيكلة وإبداعية بهدف اكتشاف مشكلات قد لا يتم اكتشافها عبر الاختبارات المهيكلة. اختبار الصندوق الأسود Black Box Testing: يتم اختبار النظام بدون معرفة تفاصيل الكود الداخلي، والتركيز فقط على المدخلات والمخرجات. اختبار الصندوق الأبيض White Box Testing: يتم اختبار النظام مع معرفة تفاصيل الكود الداخلي، والتركيز على هيكل الكود وتصميمه. اختبار الصندوق الرمادي Gray Box Testing: يتم اختبار النظام مع معرفة جزئية بتفاصيل الكود الداخلي، والتركيز على كيفية تفاعل المكونات مع بعضها البعض. اختبار قبول المستخدم User Acceptance Testing UAT: يتم إجراء هذا الاختبار مع المستخدمين الحقيقيين لضمان أن النظام يلبي احتياجاتهم وتوقعاتهم. اختبار بيتا Beta Testing: يتم إصدار النظام لمجموعة محدودة من المستخدمين في بيئة حقيقية لاختباره قبل الإطلاق النهائي. اختبار ألفا Alpha Testing: يتم اختبار النظام داخليًا من قبل فريق التطوير أو فريق مختبرات الجودة قبل إصداره للمستخدمين الخارجيين. اختبار الدخان Smoke Testing: يتم إجراء اختبارات أولية للتأكد من أن النظام يمكنه أداء وظائفه الأساسية وأنه مستقر بما يكفي لمزيد من الاختبارات. اختبار الصحة أو الاستقرار Sanity Testing: يتم إجراء اختبارات سريعة للتأكد من أن النظام يعمل بشكل صحيح بعد إجراء تغييرات أو تصحيحات. اختبار نهاية إلى نهاية End-to-End Testing: يشمل اختبار النظام من البداية إلى النهاية، محاكاة سيناريوهات واقعية وتفاعلات المستخدمين لضمان أن جميع الخطوات تعمل بشكل صحيح. هل يجب القيام بكل ما سبق؟ بالطبع لا، حسب طبيعة المشروع، لكن في كل مشروع هناك 5 إختبارات ضرورية وهم: Unit Testing Integration Testing System Testing Acceptance Testing Regression Testing بالطبع أنت ربما لا تستطيع القيام بالخمس اختبارات معًا، لذا Unit Testing لا غنى عنه ثم Integration Testing.
  5. ستجدي أسفل فيديو الدرس في نهاية الصفحة صندوق تعليقات كما هنا، أرجو طرح الأسئلة أسفل الدرس وليس هنا في قسم الأسئلة البرمجة حيث نطرح الأسئلة العامة الغير متعلقة بمحتوى الدورة أو الدرس لمساعدتك بشكل أفضل.
  6. بخصوص الدورات الحالية فيتم تحديثها كل فترة إن لزم الأمر لمتابعة التطورات التي تحدث. أما بخصوص إضافة دورات جديدة، فالأمر يعتمد على عدّة عوامل منها مدى الإحتياج ليها والطلب عليها، وهل محتوى الدورة مناسب لسوق العمل أم الطلب عليه ضعيف وهكذا، لذا الأمر راجع لإدارةالأكاديمية في تلك النقطة. ما هي الدورة التي تريد أن تتواجد بالأكاديمية؟
  7. النقطة المهمة هي توفير تصميم جيد قبل البدء بالتطوير، فبدونه سيبدوا الأمر كما لو أنك لم تقم بشيء، فالتصميم الجيد دلالة على كود جيد وذلك ليس صحيح دائمًا لكن ذلك هو الإنطباع الأول عند النظر للموقع. أيضًا يجب أن يكون القالب متجاوباً مع مختلف الأجهزة (موبايل، تابلت، حاسوب)، والقسم المخصص لعرض المشاريع مُصمم بشكل منظم وجذاب، ويتضمن الميزات التالية: تخطيط الشبكة Grid أو الماسونية masonry layout لعرض الصور المصغرة للمشاريع بشكل شبكي أو ماسوني، مما يساعد على تنظيم المشاريع بطريقة جذابة. خيارات التصفية والتصنيف Filtering and categorization options بحيث يمكن للمستخدمين تصفية المشاريع وعرضها حسب النوع، الصناعة، أو التاريخ. نوافذ منبثقة Lightbox or modal windows لعرض تفاصيل المشروع والصور بشكل موسع دون مغادرة الصفحة الرئيسية. إمكانية إضافة وصف المشروع، الوسوم، وروابط إلى العروض الحية أو مستودعات GitHub. ثم قسم المعلومات الشخصية والسيرة الذاتية أو صفحة التعريف وتحتوي على وصف مختصر وصورة شخصية أو لا حسب الرغبة. ثم قسم معلومات الاتصال مثل البريد الإلكتروني، رقم الهاتف، وروابط وسائل التواصل الاجتماعي. بعد ذلك إضافة صفحة خاصة بالمدونة لكتابة المقالات والدروس والتدوينات الشخصية مع خيارات تنسيق المنشورات مثل العناوين، القوائم، والصور، دعم للتصنيفات، الوسوم، والأرشفة لتنظيم المقالات وتسهيل البحث، ونظام تعليقات مدمج لتفاعل القراء مع محتواك. أيضًا إضافة إمكانية التخصيص تشمل مخططات ألوان وخطوط قابلة للتعديل، دعم تحميل الشعار وأيقونة التفضيلات، وإمكانية إضافة CSS أو JavaScript مخصص لتخصيص القالب حسب احتياجاتك. مع دعم الـ SEO من خلال عناوين وصفية، أوصاف، وكلمات مفتاحية مخصصة، ودعم البيانات المنظمة (schema.org) لتحسين ظهور موقعك في نتائج محركات البحث. و دعم متعدد اللغات من خلال تكامل مع إضافات الترجمة الشهيرة مثل WPML و Polylang. وستجد على مواقع مثل theme forest الكثير من القوالب للاستلهام منها ابحث على تلك المنصة عن Personal Portfolio WordPress Theme وستجد تصميم مثل التالي مثلاً:
  8. ليس بذلك المفهوم، فلا يوجد مبرمج متفهم لأساسيات البرمجة بشكل جيد ومتعمق ومتمرس في اللغة البرمجية التي اختارها نستطيع أن نُطلق عليه مبرمج ضعيف أو صاحب لغة ضعيفة. الفكرة أنّ لغة بايثون تقوم بعمل تجريف أو abstraction بحيث تحجب عنك الكثير من الأمور التي تحدث في الخلفية، لذا في حال المقارنة مع مبرمج لديه دراية بلغة C++ فستصبح الأفضلية له، لكونه على دراية بالأمور التي تحدث في الخلفية وكيفية تفاعل اللغة مع النظام والعتاد وبالأخص الذاكرة العشوائية والمعالج. وبذلك سيستطيع كتابة كود ذو أداء أفضل أو تحسين الكود الذي يعمل عليه ليصبح أفضل في حال واجه مشكلة متعلقة بالأداء. وكمبرمج بايثون تستطيع اكتساب تلك المعرفة بدراسة لغة مثل C++ حيث ستتعلم ما معنى إدارة الذاكرة واستخدام المؤشرات pointers، والتعامل مع الذاكرة الديناميكية dynamic memory allocation باستخدام new وdelete، أيضًا البرمجة متعددة الخيوط Multithreading. لكن هل عليك دراسة ذلك أو كل شخص عليه ذلك؟ بالطبع لا، تعلم ذلك في حال احتجت إليه وكنت تعمل على مشاريع أو مجال برمجي بحاجة إليها.
  9. ستجد أسفل فيديو الدرس في نهاية الصفحة صندوق تعليقات كما هنا، أرجو طرح الأسئلة أسفل الدرس وليس هنا في قسم الأسئلة البرمجة حيث نطرح الأسئلة العامة الغير متعلقة بمحتوى الدورة أو الدرس، وذلك لمساعدتك بشكل أفضل.
  10. ما هي المنصات المقصودة؟ أم أنك تبحث عن منصات لذلك؟
  11. ستجد أسفل فيديو الدرس في نهاية الصفحة صندوق تعليقات كما هنا، أرجو طرح الأسئلة أسفل الدرس وليس هنا في قسم الأسئلة البرمجة حيث نطرح الأسئلة العامة الغير متعلقة بمحتوى الدورة أو الدرس، وذلك لمساعدتك بشكل أفضل.
  12. عليك توضيح المقصود من السؤال، فلو تقصد منصات العمل الحر فتستطيع سحب رصيدك من خلال باي بال أو حساب بنكي، والمنصات الأخرى التي تعمل عليها تسير بنفس الآلية أي توفر وسائل سحب معينة تستطيع من خلالها سحب رصيدك بها.
  13. المقصود هو طباعة الرابط أو العنوان الذي تقوم بتمريره إلى src، أي من خلال console.log مع حذف مُشغل ? الخاص بـ optional chaining من العنوان. وبتفقد الكائن العائد من الطلب في الصورة، ستجد أن data هي مصفوفة بينما انت تحاول استخدامها ككائن من خلال النقطة . والصحيح هو استخدام القوسين [] لاستخراج العنصر الذي نريده وهو العنصر 0 أي [0] وذلك العنصر هو كائن بينما data هي مصفوفة بها كائنات.
  14. لا تسمح ويكيبيديا بنشر السير الذاتية بشكل عام، فهي تهدف إلى توفير محتوى موسوعي، وليس للترويج الذاتي. لكن يتم قبول السير الذاتية العلمية فقط في حالات استثنائية، مثل أن يكون الشخص الذي تنوي كتابة سيرة ذاتية له قد حقق إنجازات علمية بارزة وذات تأثير كبير في مجاله، ويجب أن تستوفي السيرة الذاتية معايير ويكيبيديا الصارمة للمحتوى. ستجد تفصيل هنا بخصوص معايير ويكيبيديا للسير الذاتية العلمية: https://ar.wikipedia.org/wiki/ويكيبيديا:السير_الذاتية وإن لم يكن الشخص مؤهلاً، فلا تحاول إنشاء سيرة ذاتية له على ويكيبيديا. وإن كان مؤهلاً عليك بالتالي: اكتب مسودة للسيرة الذاتية تتضمن جميع المعلومات ذات الصلة عن الشخص وإنجازاته. تأكد من استخدام لغة محايدة وموضوعية. استشهد بمصادر موثوقة لدعم جميع المعلومات التي تقدمها. قم بتنسيق السيرة الذاتية بشكل واضح وسهل القراءة. ثم إنشاء حساب ويكيبيديا (إذا لم يكن لديك حساب): انتقل إلى الرابط هنا انقر فوق "إنشاء حساب". اتبع التعليمات لإنشاء حسابك. ثم قم بتسجيل الدخول. بعد ذلك عليك إنشاء صفحة جديدة للسيرة الذاتية، انقر فوق "إنشاء" في شريط القائمة العلوي، ثم اكتب عنوان الصفحة باسم الشخص الذي تنوي كتابة سيرة ذاتية له، وانقر فوق "إنشاء صفحة". ثم رفع المسودة وتحريرها وتنسيقها واستخدام الصور ومقاطع الفيديو إن لزم الأمر والمصادر ذات الصلة والتأكد من أنها خالية من الأخطاء اللغوية، ثم قم بطلب مراجعة السير من قبل محرر ويكيبيديا (انقر فوق "طلب مراجعة" في شريط الأدوات الموجود أعلى الصفحة). سيقوم محررو ويكيبيديا بمراجعة الصفحة وتقديم ملاحظاتهم، قم بإجراء أي تعديلات ضرورية بناءً على ملاحظاتهم، وبمجرد موافقة المحررين على الصفحة، سيتم نشرها على ويكيبيديا. دليل المبتدئين في إنشاء صفحة ويكيبيديا: https://ar.wikipedia.org/wiki/ويكيبيديا:إنشاء_سيرة_شخصية
  15. عليك إذن طباعة الرابط الذي تقوم بتمريره إلى src وإن ظهر غير معرف أو به مشكلة، قم بطباعة الكائن نفسه الذي تحاول قراءته منه. فأن أرى أنك قد وضعت optional chaining وذلك ليس صحيح، فأنت تقوم بتمرير رابط ويجب تمريره فهو ليس اختياري، إذن يجب إزالة ذلك المعامل وتفقد هل يتم تمرير الرابط أم لا.
  16. في جميع دورات الأكاديمية تم مراعاة أنها موجهة لمتحدثي اللغة العربية، لذا لا يوجد شرط خاص باللغة الإنجليزية، حيث يتم شرح كل شيء بالعربية مع ذكر المصطلحات الإنجليزية أحيانًا للمعرفة. لكن في مجال البرمجة نفسه، فستحتاج بالطبع إلى الوصول لمستوى جيد في القراءة والاستماع لأن المصادر باللغة الإنجليزية والمستندات والشروحات الخاصة بالمكتبات وإطارات العمل واللغة البرمجية ستجدها كلها بالإنجليزية. لذا كبداية تستطيع البدء بدون مشكلة بالعربية لكن ضع في إعتبارك ما ذكرته وهو ضرورة تطوير مهارة القراءة والاستماع بالإنجليزية.
  17. ستجد أسفل فيديو الدرس في نهاية الصفحة صندوق تعليقات كما هنا، أرجو طرح الأسئلة أسفل الدرس وليس هنا في قسم الأسئلة البرمجة حيث نطرح الأسئلة العامة الغير متعلقة بمحتوى الدورة أو الدرس، وذلك لمساعدتك بشكل أفضل.
  18. لا داعي لذكر مدة زمنية محددة وإلزام نفسك بها، بل اطرح ما تستطيع فعله وذكر المهارات التي تمتلكها وما الفائدة التي ستعود على العميل من تلك المهارات فهو لا يدري ما معنى Full-Stack. ويجب أن تظهر بمظهر إحترافي ومنظم وعدم الإنجراف وراء ما يطرحه الآخرين. مع ذكر شرط أنه يتم تحديد مدة المشروع بناءًا على المتطلبات ومدى تعقيد المشروع، وعند إعطاء مدة زمنية للعميل قم بمضاعفتها ففي البداية لن تكون لديك خبرة بتحديد المدة اللازمة، وفي حال قمت بإنجاز المشروع في أقل من ذلك فستكون تلك نقطة جيدة لصالحك وليس العكس. يمكنك ذكر مثلاً أن تطبيق بسيط مكون من 5 صفحات يستغرق مدة زمنية تساوي كذا
  19. قم بتثبيت مديز الحزم snap من خلال تنفيذ الأوامر التالية بالترتيب: sudo mv /etc/apt/preferences.d/nosnap.pref ~/Documents/nosnap.backup sudo apt update sudo apt install snapd ثم قم بتسجيل الخروج من حسابك وتسجيل الدخول مجددًا في النظام أو أعد تشغيل النظام. ثم تثبيت البرنامج من خلال: sudo snap install gabutdm
  20. لا يوجد بديل مماثل تمامًا، لكن لتحميل الفيديوهات من اليوتيوب يوجد أداة stacher توجه إلى موقع stacher.io لتحميلها. أما بالنسبة لبرامج تحميل ملفات مشابهة لبرنامج IDM، فيوجد: Motrix Gabut Download Manager jdownloader2
  21. لا حاجة إلى ذلك، في حال لديك البيانات الخاصة بالحساب وتتذكريها جيدًا، تستطيعي استرجاع الحساب من خلال مراسلة الدعم، توجهي للصفحة التالية من خلال هاتفك: https://www.instagram.com/hacked/ ثم اختاري my account was hacked ثم اضغطي على next، بعد ذلك عليك إدخال اسم المستخدم أو رقم الهاتف أو البريد للبحث عن حسابك ثم اضغطي على next. وسيتم سؤالك عن رفع صور للتعرف عليك وإثبات أنك صاحبة الحساب عليك الضغط على yes i have photos ثم سيطلب منك بريد إلكتروني أدخليه للتواصل معك وإرسال رابط إليه. بعد ذلك سيطلب منك تصوير نفسك بالكاميرا الأمامية للتعرف عليك وإتباع تعليمات التصوير مثل تدوير الوجه وخلافه. والآن انتظري يوم إلى يومين وسيتم إرسال بريد على الإيميل الذي أدخلتيه به رابط لاسترجاع الحساب.
  22. أولاً لديك خطأ في حساب متوسط التقييمات في السطر الذي يحسب فيه المتوسط النهائي finalRate. فالمتغير rate ربما يتم إرساله كقيمة غير صحيحة مثل قيمة نصية من الواجهة الأمامية، لذا لنتأكد من أن rate يتم تحويله إلى رقم صحيح قبل استخدامه في الحساب، وأيضًا التأكد من صحة قيم التقييم المرسلة من الواجهة الأمامية. أيضًا بعد إضافة المراجعة إلى قاعدة البيانات، عليك إعادة بيانات الكتاب المحدثة إلى الواجهة الأمامية، بما في ذلك التقييم الجديد، وبعد تلقي بيانات الكتاب المحدثة من الخادم، يجب تحديث حالة الكتاب في الواجهة الأمامية لتعكس التقييم الجديد. ثم استخدام البيانات المحدثة للكتاب في المكون لعرض التقييم الجديد. إليك التعديلات مع تعليقات لتوضيح أماكن التعديل. تعديل في bookController.js: const addReview = asyncHandler(async(req, res) => { const { id } = req.params const { comment, rate } = req.body const book = await Book.findById(id) const user = await User.findById(req.userId) // التحقق من وجود الكتاب if (!book) { return res.status(404).json({ message: "Book Not Found" }) } // التحقق من أن المستخدم لم يقيم الكتاب مسبقاً const isRated = book.reviews.findIndex(m => m.user == req.userId) if (isRated > -1){ return res.status(403).send({ message: "Review Is Already Added" }); } // تحويل تقييم المستخدم إلى رقم صحيح والتحقق من صحته const numericRate = parseInt(rate, 10); if (isNaN(numericRate) || numericRate < 1 || numericRate > 5) { return res.status(400).send({ message: "Invalid rating value" }); } // حساب التقييم النهائي const totalRate = book.reviews.reduce((sum, review) => sum + review.rate ,0) const finalRate = (totalRate + numericRate) / (book.reviews.length + 1) // تحديث بيانات الكتاب بإضافة المراجعة الجديدة وتحديث التقييم await Book.updateOne( { _id: id }, { $push: { reviews: { user: req.userId, username: user.name, comment, rate: numericRate } }, $set: { rate: finalRate } } ) // إعادة بيانات الكتاب المحدثة بعد الإضافة const updatedBook = await Book.findById(id); res.status(201).json(updatedBook) }) تحديث الدالة postReview في apiCall: export function postReview(bookId, review) { return async (dispatch, getState) => { try { dispatch(bookActions.setLoading()) const {data} = await axios.post(`${BOOK_URL}/${bookId}/reviews`, review, { headers: { "authorization": getState().auth.user.accessToken } }); // عرض رسالة نجاح باستخدام toast toast.success(data?.message) // تحديث بيانات الكتاب المحدثة في الحالة dispatch(bookActions.updateBook(data)); dispatch(bookActions.clearLoading()); } catch (error) { // عرض رسالة خطأ باستخدام toast toast.error(error?.response?.data.message); dispatch(bookActions.clearLoading()); } }; } تعديل في الواجهة الأمامية Modal.js const Modal = ({ showModal, handleClose, book }) => { const [rate, setRating] = useState(0); const [comment, setComment] = useState(""); const dispatch = useDispatch(); const navigate = useNavigate(); const submitReview = (e) => { e.preventDefault(); if (comment === "") { // التحقق من وجود تعليق وعرض رسالة خطأ في حال عدم وجوده return toast.error("Comment is required") } // تحويل تقييم المستخدم إلى رقم صحيح والتحقق من صحته const numericRate = parseInt(rate, 10); if (isNaN(numericRate) || numericRate < 1 || numericRate > 5) { return toast.error("Invalid rating value"); } // إرسال المراجعة باستخدام الدالة postReview dispatch(postReview(book._id, { rate: numericRate, comment })) }; return ( <div className={`modal ${showModal ? "show" : ""}`}> <div className="modal-content"> <span className="close" onClick={handleClose}>&times;</span> <h2>Submit Your Review</h2> <form onSubmit={submitReview}> <div className="rating-input"> <label>Rating:</label> <select value={rate} onChange={(e) => setRating(e.target.value)} required> <option value="" disabled>Select a rating</option> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> <option value="4">4</option> <option value="5">5</option> </select> </div> <div className="comment"> <label>Comment:</label> <textarea value={comment} onChange={(e) => setComment(e.target.value)} required /> </div> <button className='modal-btn' type="submit">Submit</button> </form> </div> </div> ); }; export default Modal; تحديث bookSlice لتضمين الدالة updateBook: const bookSlice = createSlice({ name: "book", initialState: { books: [], error: false, loading: false, }, reducers: { getBooks(state, action) { state.books = action.payload; }, findBook(state, action) { state.books = action.payload; }, addReviews(state, action) { state.books = action.payload; }, updateBook(state, action) { // البحث عن الكتاب المحدث وتحديثه const updatedBook = action.payload; const index = state.books.findIndex(book => book._id === updatedBook._id); if (index !== -1) { state.books[index] = updatedBook; } }, setLoading(state) { state.loading = true; }, clearLoading(state) { state.loading = false; }, setError(state) { state.error = true; }, clearError(state) { state.error = false; }, } }); export const bookActions = bookSlice.actions; export default bookSlice.reducer;
  23. في البداية بدون دراية برمجية لن تتمكن من التعديل والتطوير، يجب الإلمام بلغة PHP لفعل ذلك بجانب لغات الويب HTML, CSS, JS. أولاً، عليك تثبيت Smarty: composer require smarty/smarty ثم قم بتهيئة Smarty في ملف PHP الرئيسي، ولنفترض أن ملفك الرئيسي هو index.php. <?php require_once 'vendor/autoload.php'; $smarty = new Smarty(); $smarty->setTemplateDir(__DIR__ . '/template'); $smarty->setCompileDir(__DIR__ . '/template_c'); $smarty->setCacheDir(__DIR__ . '/cache'); $smarty->setConfigDir(__DIR__ . '/configs'); ثم لنقم بكتابة كود PHP لقراءة القوالب المتاحة في مجلد القوالب. <?php // تابع للخطوة 2 $templateDir = __DIR__ . '/template'; $templateFolders = array_filter(glob($templateDir . '/*'), 'is_dir'); $templates = []; foreach ($templateFolders as $folder) { $templateName = basename($folder); $templates[] = $templateName; } $smarty->assign('templates', $templates); $smarty->display('admin.tpl'); بعد ذلك إنشاء ملف قالب Smarty يسمى admin.tpl لعرض القوالب في جدول. <!-- admin.tpl --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Admin Panel - Templates</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"> </head> <body> <div class="container"> <h1>Available Templates</h1> <table class="table table-bordered"> <thead> <tr> <th>Template Name</th> <th>Action</th> </tr> </thead> <tbody> {foreach from=$templates item=template} <tr> <td>{$template}</td> <td> <form method="post" action="install_template.php"> <input type="hidden" name="template_name" value="{$template}"> <button type="submit" class="btn btn-primary">Install Template</button> </form> </td> </tr> {/foreach} </tbody> </table> </div> </body> </html> ثم إنشاء ملف PHP يسمى install_template.php لتنفيذ عملية تركيب القالب. <?php if ($_SERVER['REQUEST_METHOD'] === 'POST') { $templateName = $_POST['template_name']; // نفذ عملية تركيب القالب هنا // تستطيع نسخ الملفات إلى مجلد آخر أو تحديث إعدادات قاعدة البيانات echo "Template '{$templateName}' has been installed!"; } else { echo "Invalid request."; } بذلك ستتمكن من عرض القوالب المتاحة في مجلد template على شكل جدول في صفحة لوحة التحكم، مع زر لتركيب كل قالب، وعند النقر على زر "تركيب القالب"، سيتم إرسال طلب POST إلى install_template.php لتنفيذ عملية التركيب، تستطيع تعديل عملية التركيب حسب متطلباتك.
  24. في البداية ستحتاج بالطبع إلى إنشاء حساب مطور على Google Cloud Vision API أو Amazon Rekognition. ثم ضبط إعدادات متغيرات البيئة في المشروع في ملف .env وأهما مفاتيح الـ API، عليك إضافة إعدادات Google Cloud Vision API أو Amazon Rekognition فقط، وإليك كلاهما: GOOGLE_CLOUD_VISION_API_KEY=google_api_key AWS_ACCESS_KEY_ID=aws_access_key AWS_SECRET_ACCESS_KEY=aws_secret_key AWS_REGION=aws_region ثم أنشئ نموذج وقاعدة بيانات لتخزين بيانات الصور: php artisan make:model Image -m في ملف التهجير: Schema::create('images', function (Blueprint $table) { $table->id(); $table->string('image_path'); $table->json('features'); // لتخزين بيانات الميزات (features) $table->timestamps(); }); أيضًا اعتمد على مكتبة مثل intervention/image لمعالجة الصور وضغط حجمها قبل إرسالها. ثم استخدام مكتبة google/cloud-vision أو aws/aws-sdk-php للتواصل مع المنصة. وإليك مثال لكلاهما اختر ما تريد: // ImageController.php use Illuminate\Http\Request; use Intervention\Image\Facades\Image; use Google\Cloud\Vision\V1\ImageAnnotatorClient; // or Aws\Rekognition\RekognitionClient; public function uploadImage(Request $request) { $image = $request->file('image'); // Process and resize the image $image->resize(300, 300); // Analyze the image using Google Cloud Vision API or Amazon Rekognition $visionClient = new ImageAnnotatorClient(); // or $rekognitionClient = new RekognitionClient(); $response = $visionClient->annotateImage(file_get_contents($image->getPathname()), ['LABEL_DETECTION']); // or $rekognitionClient->detectLabels(['Image' => ['Bytes' => file_get_contents($image->getPathname())]]); $features = $response->getLabelAnnotations(); // or $response->getLabels(); // Store the features in the database $imageFeatures = new ImageFeatures(); $imageFeatures->features = json_encode($features); $imageFeatures->save(); return response()->json(['message' => 'Image uploaded and analyzed successfully']); } بعد ذلك اعتمد على مكتبة doctrine/dbal للتفاعل مع قاعدة البيانات، حيث تتوفر cosine similarity أو Euclidean distance لقياس التشابه بين ميزات الصور. use App\ImageFeatures; use Illuminate\Http\Request; public function searchByImage(Request $request) { $searchImage = $request->file('image'); $searchFeatures = $this->analyzeImage($searchImage); // Query the database to find similar images $similarImages = ImageFeatures::all()->filter(function ($imageFeature) use ($searchFeatures) { $storedFeatures = json_decode($imageFeature->features, true); return $this->cosineSimilarity($searchFeatures, $storedFeatures) > 0.5; }); return response()->json(['similar_images' => $similarImages]); } private function analyzeImage($image) { // هنا يجب أن تضع الكود الخاص بتحليل الصورة والحصول على الميزات // سأضع مثال بسيط لتحليل الصورة return [/* array of features */]; } private function cosineSimilarity($features1, $features2) { $dotProduct = 0; $magnitude1 = 0; $magnitude2 = 0; foreach ($features1 as $index => $feature1) { $dotProduct += $feature1 * $features2[$index]; $magnitude1 += $feature1 * $feature1; $magnitude2 += $features2[$index] * $features2[$index]; } $magnitude1 = sqrt($magnitude1); $magnitude2 = sqrt($magnitude2); if ($magnitude1 * $magnitude2 == 0) { return 0; } return $dotProduct / ($magnitude1 * $magnitude2); } لتحسين الأداء، باستطاعتك استخدام تقنيات مثل الفهرسة المكانية أو مكتبات متخصصة في البحث عن الصور مثل Elasticsearch.
  25. افتحي مشروع Unity الذي تريدين تصديره كمكتبة، وانتقلي إلى File > Build Settings، وفي نافذة Build Settings، اختاري المنصة المستهدفة (Android أو iOS). وفي حال تستهدفي Android، اختاري Android من القائمة. ثم اضغطي على Player Settings في الزاوية السفلية اليسرى من نافذة Build Settings، وضبط الإعدادات اللازمة مثل اسم الحزمة (Package Name) وغيرها. وفي نافذة Build Settings، تأكدي من اختيار المنصة الصحيحة ثم اضغطي على Export في الزاوية اليمنى السفلى. وعندما تظهر نافذة التصدير، عليك تحديد خيار Export as a Library (أو خيار مشابه يعبر عن تصدير كمكتبة)، ثم اختيار مكان حفظ المجلد الذي سيحتوي على مكتبة Unity والضغط على Export لبدء عملية التصدير. بعد اكتمال التصدير، ستجدي مجلد يحتوي على مكتبة Unity في المسار الذي اخترتيه، باستطاعتك الآن دمج تلك المكتبة في مشروع Flutter كما هو موضح في الخطوات التي شرحها سابقًا.
×
×
  • أضف...