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

Chihab Hedidi

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

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

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

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

    13

كل منشورات العضو Chihab Hedidi

  1. إذا كنت تريد هذا الأمر بدون إستخدام قاعدة البيانات، يمكنك استخدام حلقة تكرار لانهائية لتخزين بيانات المستخدمين حيث تستخدم هيكل بيانات مثل قائمة أو قاموس لتخزين بيانات المستخدمين داخل الذاكرةـ في كل دورة من الحلقة، يمكنك إعطاء المستخدم خيار عرض جميع البيانات المخزنة، و يمكنك إضافة شرط داخل الحلقة لإنهاءها بناء على إدخال المستخدم (مثل إدخال "خروج"). أما بإستخدام قاعدة البيانات يمكنك استخدام قواعد بيانات مثل MySQL، PostgreSQL، أو SQLite. تقوم بإنشاء جدول لتخزين بيانات المستخدمين. على سبيل المثال، قد يحتوي الجدول على أعمدة مثل id, name, email, password, وغيرها، و عندما يقوم المستخدم بإدخال بياناته، يجب أن يتم إرسال هذه البيانات إلى قاعدة البيانات وتخزينها فيها، و هذا يتطلب كتابة كود للتعامل مع البيانات المرسلة وحفظها في قاعدة البيانات، و لعرض جميع المستخدمين، ستحتاج إلى استعلام قاعدة البيانات لاسترجاع بيانات جميع المستخدمين وعرضها في واجهة المستخدم. ستقوم بكتابة كود لاسترجاع البيانات وعرضها بشكل مناسب.
  2. نفترض أنك تستخدم مكتبة للتعامل مع بوابة دفع مثل Stripe، سسقوم بإعداد دالة لتحصيل المبلغ من العميل، ثم دالة لتوزيع المبالغ بين المنصة والمبرمج، و يمكنك استخدام واجهة برمجة تطبيقات لبوابة الدفع لتحصيل المبلغ، هذا هو مثال مبسط لتحصيل المبلغ: import stripe def charge_customer(customer_id, amount): try: charge = stripe.Charge.create( amount=int(amount * 100), # المبلغ بالـ cents currency="usd", customer=customer_id, description="Payment for services" ) return charge except stripe.error.StripeError as e: print(f"Error charging customer: {e}") return None # تحصيل المبلغ من العميل charge = charge_customer("cus_J5hPjXxU8bF7Zk", total_amount) بعد تحصيل المبلغ، نحتاج الآن لتحويل النسب لكل من المنصة والمبرمج، بهذا الشكل: def transfer_funds(to_account_id, amount): try: transfer = stripe.Transfer.create( amount=int(amount * 100), # المبلغ بالـ cents currency="usd", destination=to_account_id, description="Transfer to account" ) return transfer except stripe.error.StripeError as e: print(f"Error transferring funds: {e}") return None # تحويل العمولة إلى حساب المنصة platform_transfer = transfer_funds("acct_1J5hPj2eZvKYlo2C", platform_fee) # تحويل المبلغ المتبقي إلى حساب المبرمج programmer_transfer = transfer_funds("acct_1J6hKl2eZvKYlo2K", programmer_fee) و يجب أيضا تسجيل جميع العمليات في قاعدة بيانات لمتابعة السجلات ومعالجة أي مشكلات لاحقا، يمكنك استخدام قاعدة بيانات مثل PostgreSQL أو MySQL لتخزين البيانات.
  3. عندما يدفع العميل المبلغ، يتم تحصيله عبر بوابة دفع مثل Stripe أو PayPal، و في هذه المرحلة المبلغ يتم تحويله إلى حساب المنصة، بعدها تقوم المنصة بحساب النسبة التي سيتم أخذها كعمولة، و يمكن تخزين هذه النسب في متغيرين أو حقول في قاعدة البيانات بهذا الشكل: platform_fee_percentage = 0.15 programmer_fee_percentage = 0.85 total_amount = 1000 # المبلغ المدفوع من قبل العميل platform_fee = total_amount * platform_fee_percentage programmer_fee = total_amount * programmer_fee_percentage بعد حساب النسب، هناك طريقتان لتوزيع المبلغ، حيث يمكن للمنصة، أن تقوم بتحويل المبلغ تلقائيا إلى حساب المبرمج على بوابة الدفع بعد خصم العمولة، في هذه الحالة يتم إجراء تحويلين، تحويل العمولة إلى حساب المنصة، و تحويل المبلغ المتبقي إلى حساب المبرمج. و بعض الأنظمة تحتفظ بالمبلغ بالكامل في حساب المنصة لفترة معينة حتى يتم تأكيد انتهاء العمل، وبعد ذلك يتم توزيع المبالغ، و عند تأكيد العمل يتم تحويل النسبة المستحقة للمبرمج بشكل تلقائي.
  4. إذا فهمتهم بالشكل المطلوب فلن تجد مشكلة سواء كان في لغة سي شارب أو أي لغة أخرى، Polymorphism هو مفهوم في البرمجة الكائنية يسمح لك باستخدام كائنات من فئات مختلفة بشكل يمكن التنبؤ به، يوجد نوعان رئيسيان من Polymorphism، أولا Compile-time Polymorphism أو التعددية الشكلية في وقت الترجمة مثل تعدد الدوال وتعدد المعاملات. و يوجد أيضا Run-time Polymorphism التي تسمى التعددية الشكلية في وقت التشغيل مثل إعادة تعريف الدوال، و يحدث هذا النوع عندما يتم تعريف دالة في الفئة الأساسية ويتم إعادة تعريفها في الفئة المشتقة و هذا مثال بسيط عليه: public class Animal { public virtual void Speak() { Console.WriteLine("Animal makes a sound."); } } public class Dog : Animal { public override void Speak() { Console.WriteLine("Dog barks."); } } public class Cat : Animal { public override void Speak() { Console.WriteLine("Cat meows."); } } // استخدام Polymorphism Animal myAnimal = new Dog(); myAnimal.Speak(); // سيطبع "Dog barks." بالنسبة ل Abstract Class هي فئة لا يمكن إنشاء كائنات منها بشكل مباشر، و تحتوي على دوال يمكن أن تكون مجردة أي بدون تنفيذ، ويجب على الفئات المشتقة أن تعيد تعريفها، و يمكن للفئة المجردة أن تحتوي على دوال عادية مع تنفيذ كامل بهذا الشكل: public abstract class Animal { public abstract void Speak(); // دالة مجردة public void Sleep() { Console.WriteLine("Animal is sleeping."); } } public class Dog : Animal { public override void Speak() { Console.WriteLine("Dog barks."); } } // لا يمكن إنشاء كائن من الفئة المجردة مباشرة // Animal myAnimal = new Animal(); // سيؤدي هذا إلى خطأ Dog myDog = new Dog(); myDog.Speak(); // سيطبع "Dog barks." myDog.Sleep(); // سيطبع "Animal is sleeping." أما Interface هي عقد يحدد مجموعة من الدوال أو الخصائص التي يجب على الفئة التي تنفذ الواجهة أن تعرفها، و الواجهة لا تحتوي على تنفيذ فعلي، فقط تعريف للدوال والخصائص، و يمكن للفئة أن ترث من واجهات متعددة بهذا الشكل: public interface IAnimal { void Speak(); void Sleep(); } public class Dog : IAnimal { public void Speak() { Console.WriteLine("Dog barks."); } public void Sleep() { Console.WriteLine("Dog is sleeping."); } } IAnimal myDog = new Dog(); myDog.Speak(); // سيطبع "Dog barks." myDog.Sleep(); // سيطبع "Dog is sleeping." و الفرق بين Abstract Class و Interface هو أن Abstract Class يمكن أن تحتوي على دوال عادية مع تنفيذ فعلي، بينما Interface لا يمكنها احتواء أي تنفيذ، و يمكن للفئة أن ترث من فئة مجردة واحدة فقط، ولكن يمكن أن تنفذ واجهات متعددة.
  5. عليك البحث عن مواقع متخصصة توفر بث مباشر من كاميرات الويب الخاصة بالطقس، يمكنك تجربة موقع EarthCam، حيث توجد فيه بعض محطات الطقس والتي توفر بث كاميرات ويب يمكن استخدامه، و أيضا عند العثور على كاميرا ويب تريد تضمينها، تحقق مما إذا كان الموقع يوفر رابطاً للتضمين، عادة ما يكون هذا الرابط عبارة عن كود HTML يمكنك نسخه، و إذا لم يكن هناك خيار للتضمين المباشر، يمكنك محاولة العثور على رابط البث المباشر نفسه.
  6. هو نوع من البيانات في بايثون يمثل غياب قيمة أو عدم تعيين قيمة لمتغير، عندما يتم تعيين متغير إلى None، فهذا يعني أن المتغير لا يحتوي على أي قيمة فعلية، عند تعريف متغير دون إعطائه قيمة محددة، يمكن تعيينه إلى None كقيمة افتراضية: x = None if x is None: print("x ليس لديه قيمة محددة بعد") إذا لم ترجع دالة معينة أي قيمة صريحة باستخدام return، فإنها بشكل افتراضي تعود بـ None: def greet(): print("Hello!") result = greet() # لن ترجع هذه الدالة قيمة print(result) # ستظهر None None مفيد لأنه يوفر طريقة معيارية للإشارة إلى غياب القيمة في بايثون، بدلا من استخدام قيم مثل 0، أو سلسلة فارغة، أو قائمة فارغة للإشارة إلى غياب القيمة، يمكنك استخدام None كإشارة واضحة إلى أن المتغير ليس لديه قيمة معينة بعد أو أن الدالة لم ترجع نتيجة.
  7. في حالة استخدام flex مع justify-content: center و align-items: center لتحقيق المحاذاة المركزية في الصفحة، إذا كان هناك خلل في التمحور المركزي بسبب تغير العرض، قد يكون السبب هو أن العنصر الفرعي مثل الفقرة <p> يتجاوز الحدود الطبيعية للعرض نتيجة التفاف النص، لحل هذه المشكلة، يمكنك تحديد عرض أقصى للفقرة باستخدام خاصية max-width بحيث لا يتجاوز النص مساحة معينة بهذا الشكل: .parent { display: flex; justify-content: center; align-items: center; height: 100vh; } .child { max-width: 80%; text-align: center; } و تأكد من عدم وجود حدود margin أو padding غير ضرورية قد تؤثر على التمحور.
  8. يجب التأكد من أن كود JavaScript يتفاعل بشكل صحيح مع الصفحة التي تحتوي على نموذج التعديل، يمكن أن تكون هناك بعض التحديات مثل تأكيد تحميل JavaScript بعد تحميل النموذج أو استخدام مكتبات معينة، لهذا قلت أنه يجب تعديل الكود بما يتناسب مع مشروعك.
  9. يمكنك استخدام JavaScript لإخفاء أو إظهار الكود بناء على اختيار الجنس، حيث إذا كنت ترغب في إخفاء عنصر بناء على اختيار "ذكر" أو "أنثى" يمكنك استخدام كود مشابه للتالي و غيره على حسب مشروعك: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Gender Based Display</title> <script> function updateVisibility() { var gender = document.getElementById('gender').value; var imgContainer = document.getElementById('profilePicContainer'); if (gender === 'male') { imgContainer.style.display = 'none'; // إخفاء الصورة إذا كان الاختيار ذكر } else { imgContainer.style.display = 'block'; // إظهار الصورة إذا كان الاختيار أنثى } } </script> </head> <body> <select id="gender" onchange="updateVisibility()"> <option value="male">ذكر</option> <option value="female">أنثى</option> </select> <div id="profilePicContainer"> <img src="<?php echo $imagePath; ?>" alt="Profile Picture" style="width: 100px;"> </div> </body> </html> حيث نستخدم عنصر <select> لاختيار الجنس، عندما يختار المستخدم "ذكر"، سيتم إخفاء العنصر الذي يحتوي على الصورة، وعندما يختار "أنثى"، سيتم إظهار العنصر، و تأكد من تعديل <?php echo $imagePath; ?> ليشير إلى المسار الصحيح للصورة.
  10. بالنسبة لمشروعك يمكنك إستخدام PHP حيث تعمل على الخادم وتستخدم بشكل رئيسي للتفاعل مع قواعد البيانات وإنشاء صفحات ويب ديناميكية. في مشروعك، يمكنك استخدام PHP بدلا من استخدام HTML ثابت، يمكنك استخدام PHP لجعل صفحات الويب تتفاعل مع قاعدة البيانات، مثل عرض قائمة الكتب أو تشغيل ملفات الصوت بناء على طلب المستخدم، و أيضا يمكنك استخدام PHP للتواصل مع قاعدة البيانات، مثل إضافة كتب جديدة أو استرداد معلومات كتاب معين. بالنسبة للإختلاف نعم هناك اختلافات جوهرية بين هذه اللغات مثل HTML, CSS, JavaScript تعمل على الجانب الأمامي للبنية، CSS للتصميم والتنسيق، وJavaScript لإضافة التفاعل. بينما تعمل PHP على الجانب الخلفي و تستخدم لمعالجة البيانات وتوليد المحتوى الديناميكي والتواصل مع قواعد البيانات، حيث مثلا إذا أراد المستخدم البحث عن كتاب معين في مكتبتك الإلكترونية، سيقوم بإدخال اسم الكتاب في نموذج بحث، باستخدام PHP ستقوم بكتابة كود يتصل بقاعدة البيانات للبحث عن الكتب المتوافقة مع اسم الكتاب المدخل، ثم تعرض النتائج باستخدام HTML.
  11. يمكنك استخدام موقع Typeform، وهو أحد الخيارات الممتازة لإنشاء استبيانات بتصميمات جذابة ولوحة تحكم قوية.، حيث يتيح لك تصدير البيانات إلى ملفات Excel، ويمكنك أيضا إضافة فلاتر بحث لتحليل النتائج بشكل أكثر دقة، و يقدم الموقع الرسمي لـ Typeform شروحات شاملة لكيفية إنشاء استبيانات وتحليل البيانات. يمكنك بدء التعلم من صفحة التعليمات الخاصة بهم و يمكنك العثور على شروحات مرئية على YouTube عن كيفية استخدام Typeform، فقط ابحث عن "Typeform tutorial" وستجد العديد من الفيديوهات التعليمية.
  12. هذه الدالة تقوم بقص النص إلى طول معين، ولكن لا تأخذ بعين الاعتبار إغلاق تاقات HTML المفتوحة، مما يؤدي إلى عدم إغلاق التاقات بشكل صحيح وقد يتسبب في مشاكل في التصميم، يمكنك استخدام مكتبة أو دالة تقوم بقص النصوص مع مراعاة تاقات HTML مثل حزمة voku/portable-utf8 التي توفر الدالة Html::cut() المخصصة لهذا الغرض. حيث يجب عليك تثبيت حزمة voku/portable-utf8 باستخدام Composer: composer require voku/portable-utf8 بعد تثبيت الحزمة، يمكنك استخدام دالة Html::cut لقص النصوص مع الحفاظ على التاقات المفتوحة والمغلقة بشكل صحيح. use voku\helper\HtmlDomParser; use voku\helper\Html; $htmlContent = $project->discription; $limitedContent = Html::cut($htmlContent, 200); echo $limitedContent; بهذه الطريقة سيتم قص النص مع الحفاظ على التاقات مغلقة بشكل صحيح، مما يمنع حدوث مشاكل في التصميم.
  13. قبل البدء في الدورة، حدد هدفك الرئيسي من التعلم بحيث عند الإنتهاء يجب أن تكون حققت هذا الهدف، و أثناء مشاهدة الفيديوهات أو قراءة المواد، حاول أن تتفاعل مع المحتوى بشكل فعال، يجب عليك تدوين الملاحظات، ولا تتردد في التوقف وإعادة مشاهدة الأجزاء التي لم تفهمها جيدا. و أيضا لا تكتفي بالمشاهدة فقط بل طبق مع المدرب في نفس الوقت و حاول أن لا تقوم بنسخ الكود مباشرة فالبرمجة تحتاج إلى ممارسة يومية لتترسخ لديك المعلومات بشكل أفضل و أسرع، و حاول بناء مشاريع صغيرة باستخدام ما تعلمته.
  14. في نهاية الصفحة ستجد مكان مخصص لطرح التعليقات هناك بهذا الشكل:
  15. بما أنك تمتلكين خلفية متوسطة في البرمجة بلغة بايثون وتعرفين الأساسيات، فإنك في وضع جيد للبدء في البرمجة التنافسية، لكن الأساسيات وحدها قد لا تكون كافية، ومع ذلك يمكنك البدء فوراً في حل المسائل البسيطة على المنصات المختلفة مثل LeetCode و HackerRank، والتي توفر بيئة تدريبية رائعة، أثناء حل هذه المسائل ستكتشفين المفاهيم التي تحتاجين إلى تطويرها أكثر، و من المهم الاستمرار في التدريب وحل المسائل بانتظام، لأن هذا هو المفتاح الأساسي لتحسين مهاراتك، أما بالنسبة للمصادر يمكنك البدء بمراجعة المواضيع الأساسية مثل الخوارزميات وهياكل البيانات، وهناك العديد من الكتب والمقالات في الأكاديمية التي تغطي هذه المواضيع بشكل جيد. أما بالنسبة للوقت الذي قد تحتاجينه للتعلم، فهذا يعتمد على مدى التزامك ووقتك المخصص للتدريب، بعض الأشخاص يحققون تقدما كبيرا في بضعة أشهر، بينما قد يستغرق الأمر سنوات للبعض الآخر للوصول إلى مستوى عال من الكفاءة، يمكنك أن تطلعي على هذه المقالات التي يمكن أن تساعدك:
  16. Chihab Hedidi

    سؤال

    يمكنك ذلك حيث تحتاج إلى ملف upload.php و الذي يحتوي على الدالة الخاصة بحفظ الصور ثم تستخدمه داخلا المشروع بهذا الشكل: <form action="upload.php" method="post" enctype="multipart/form-data"> <label for="name">الاسم:</label> <input type="text" id="name" name="name" required> <br> <label for="img0">اختر صورة:</label> <input type="file" id="img0" name="img0" accept="image/*" required> <br> <input type="submit" value="ارسال"> </form> أما بالنسبة لملف upload.php فيجب أن يكون هكذا: <?php if ($_SERVER['REQUEST_METHOD'] == 'POST') { if (isset($_POST['name']) && isset($_FILES['img0'])) { $name = $_POST['name']; $image = $_FILES['img0']; // تعيين مسار المجلد لحفظ الصورة $target_dir = "BMW/"; $imageFileType = strtolower(pathinfo($image['name'], PATHINFO_EXTENSION)); $target_file = $target_dir . $name . "." . $imageFileType; // التحقق من نوع الملف (هل هو صورة أم لا) $check = getimagesize($image["tmp_name"]); if($check !== false) { // نقل الصورة إلى المجلد المطلوب if (move_uploaded_file($image["tmp_name"], $target_file)) { echo "تم رفع الصورة بنجاح."; } else { echo "حدث خطأ أثناء رفع الصورة."; } } else { echo "الملف الذي تم رفعه ليس صورة."; } } else { echo "الرجاء إدخال الاسم واختيار صورة."; } } ?> بالنسبة ل form في HTML يحتوي على مدخلين واحد للإسم وآخر للصورة، و يتم إرسال البيانات إلى ملف upload.php، حيث في هذا الملف يتم التحقق من أن الاسم والصورة تم إدخالهما، ثم يتم تعيين مسار مجلد BMW/ لحفظ الصورة، و استخراج الامتداد من اسم الصورة الأصلية للحفاظ على نوع الصورة و في الأخير يتم تغيير اسم الصورة إلى اسم الشخص، مع إضافة الامتداد، بعدها يتم نقل الصورة إلى المجلد المحدد إذا كانت الصورة صالحة.
  17. يوجد في الدورة كل ما تحتاجه، بما أنه لديك تجربة بسيطة مع أساسيات الويب فهذا أمر جيد لأنه يوجد بعض المشاريع في دورة الذكاء الإصطناعي التي نستخدم فيها هذا الأمر و بالتالي سيكون الأمر سهل بالنسبة لك، أما بخصوص مجال الذكاء الإصطناعي فهو يعتمد بشكل كبير على لغة البايثون و في الدورة نفسها يوجد مسار بأكمله من أجل تعلم البايثون لذا سيكون هذا الأمر كافي لك لتتقدم فيها.
  18. يوجد العديد منها و إستخدامها يبقى تفضيل شخصي و لكن أشهرها و التي أستخدمها شخصيا هي الآتي: HTML CSS Support: لتحسين تجربة كتابة HTML وCSS. PHP Intelephense: لتحسين تجربة تطوير PHP من خلال توفير التكملة التلقائية والتحقق من الأخطاء. Prettier - Code formatter: لتنسيق الكود تلقائيا. Live Server: لتشغيل خادم محلي وعرض التغييرات في المتصفح فور حفظ الملف. Bracket Pair Colorizer: لتلوين الأقواس المتطابقة في الكود، مما يسهل قراءة الكود. JavaScript (ES6) code snippets: لتوفير مقتطفات سريعة من كود JavaScript. إذا كنت تريد إضافات أخرى يمكنك تصفح ال Marketplace الخاص ب Vs Code أو من خلال علامة Extensions على اليسار و كتابة إسم أي إضافة لتستطيع تثبيتها.
  19. يمكنك تحميله من الموقع الرسمي الخاص ب Scratch و هذا حسب نظام التشغيل الخاص بك، أو يمكنك إنشاء حساب بشكل مباشرة في الموقع و العمل به أونلاين.
  20. نعم ستكون شغالة.
  21. نعم مثل الكود الذي أرسلته يمكنك نسخه أو أضافة هذا السطر: fprintf($output, "\xEF\xBB\xBF");
  22. المشكلة بسبب الترميز و يجب التأكد من أن ملف Excel الناتج يتم ترميزه بشكل صحيح بتنسيق UTF-8، و هذا يتطلب القيام ببعض الخطوات البسيطة في الكود لضمان ترميز النصوص بشكل صحيح عند كتابتها إلى ملف CSV، عند إنشاء ملف CSV يجب إضافة BOM (Byte Order Mark) في بداية الملف، هذه العلامة تساعد Excel على التعرف على أن النصوص في الملف مرمزة بـ UTF-8 وبالتالي تعرض الحروف العربية بشكل صحيح.
  23. يجب التأكد من أن الملف الناتج يحفظ بالترميز الصحيح UTF-8، يمكنك القيام بذلك عن طريق التأكد من استخدام الترميز الصحيح عند كتابة البيانات إلى ملف CSV بهذا الشكل: <?php include('conn.php'); if (isset($_POST['disease_type'])) { $disease_type = $_POST['disease_type']; $sql = "SELECT * FROM UN WHERE disease_type = '$disease_type'"; $result = $conn->query($sql); if ($result->num_rows > 0) { $filename = "data_from_UN_$disease_type.csv"; header('Content-Type: text/csv; charset=utf-8'); header('Content-Disposition: attachment; filename=' . $filename); $output = fopen('php://output', 'w'); fprintf($output, "\xEF\xBB\xBF"); $header = ['الاسم', 'عنوان', 'نوع']; fputcsv($output, $header); while ($row = $result->fetch_assoc()) { fputcsv($output, $row); } fclose($output); exit(); } else { echo "No data found for this disease type."; } } $conn->close(); ?> حيث نقوم بإضافة الـ BOM (\xEF\xBB\xBF) في بداية ملف CSV. هذا يساعد في تأكيد أن Excel سيتعرف على الترميز UTF-8 ويعرض النصوص العربية بشكل صحيح.
  24. نعم يوجد شرح لهذا الأمر في مشروع تطبيق يشبه WhatsApp يمكنك الدخول إلى مسار تطبيق الويب و من ثم الدرس رقم 7 ستجدين الفيديو الخاص بتسجيل الدخول بإستخدام و يمكنك العثور داخل هذا المشروع على كل العمليات التي يمكنك القيام بها الخاصة بتسجيل الدخول و الخروج أو تغيير كلمة السر أو غيرها من العمليات، و لكن يجب عليك التغيير من الكود البرمجي المستخدم بما يتناسب مع مشروعك.
  25. لا يوجد مدة محددة يمكنك الدراسة في أوقات فراغك يوميا، و للتقديم على الإختبار والحصول علي الشهادة يجب : إتمام أربعة مسارات تعليمية كاملة على الأقل التطبيق العملي مع المدرب والاحتفاظ بالمشاريع العملية الناتجة لإرسالها للمراجعة رفع المشاريع على حسابك على GitHub حتي يتم مشاركتها. بعد الإنتهاء من الدورة تقوم بمراسلة مركز المساعدة وتوفير روابط المشاريع على GitHub أي التطبيقات العملية ليتم مراجعتها، ثم تحديد موعد للإختبار.
×
×
  • أضف...