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

Mustafa Suleiman

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

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

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

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

    263

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

  1. إجابة Mustafa Suleiman سؤال في ماهي أفضل مواقع ومنصات عربية لتسويق الخدمات الرقمية كانت الإجابة المقبولة   
    السؤال عام جدًا، ما هي الخدمات الرقمية التي تحتاج إلى تسويقها؟ فإذا كان لديك خدمات تقدمها فإما عليك بإنشاء موقع شخصي وعرض تلك الخدمات عليه مع توفير إمكانية لشراء تلك الخدمات أو رابط لموقع آخر تعمل عليه لحجز الخدمة مثلاً.
    أما إذا كنت تريد التسويق لخدمة تقدمها، فعليك بتعلم المهارات الخاصة بالتسويق وبناء العلامة الشخصية، وكيفية بناء متابعين لك عن طريق نشر معرفتك في المكان الصحيح بغرض الإفادة فعلاً لفترة وتعريف الناس بنفسك.
    أما إذا كنت تريد العمل في مواقع العمل الحر وعرض خدماتك، فلديك مواقع مثل مستقل وخمسات وموقع بعيد.
    وبخصوص عرض المنتجات الرقمية للبيع والتربح منها، فلديك منصة بيكاليكا.
    قسم مقالات التسويق والمبيعات في أكاديمية حسوب قسم مقالات التسويق الذاتي في أكاديمية حسوب  
  2. إجابة Mustafa Suleiman سؤال في معمارية RESTful API: مفهومها وكيفية استخدامها في تطوير الواجهات البرمجية كانت الإجابة المقبولة   
    ببساطة مهارة REST API أو RESTful API تعني قدرتك على تصميم وتطوير وتفهم واجهات برمجة التطبيقات (API) باستخدام نمط REST (Representational State Transfer). REST هو نمط معماري يستخدم في تطوير الويب للتواصل بين العميل (Client) والخادم (Server) من خلال استخدام مجموعة من الأساليب المحددة مثل GET وPOST وPUT وDELETE.
    ويستند REST إلى مجموعة من المبادئ والقيود التي تسهل الاتصال والتفاعل بين العميل والخادم:
    تمثيل الموارد (Resources): يتم تمثيل البيانات والموارد في النظام عن طريق معرفات فريدة (مثل عناوين URL) ويتم الوصول إليها والتعامل معها عن طريق طلبات HTTP. واجهات معيارية (Standardized Interfaces): يستخدم REST مجموعة من طرق الطلبات المعيارية في HTTP مثل GET وPOST وPUT وDELETE للتفاعل مع الموارد. إنعدام الحالة (Stateless): كل طلب منفصل بذاته ولا يتم تخزين حالة العميل على الخادم بين الطلبات، وترسل كافة المعلومات اللازمة للخادم في كل طلب. التفاعل المستقل (Self-contained Interactions): تشمل طلبات REST كل المعلومات اللازمة لإجراء العملية المطلوبة، بما في ذلك أي بيانات إضافية أو تعليمات مطلوبة. التوجيه المحدود (Limited Coupling): يعتمد REST على فصل العميل والخادم بشكل مستقل، ولا يعتمد على المعرفة المسبقة للعميل بشأن تفاصيل الخادم، وبالعكس. أي من يمتلك مهارة REST API قادر على العمل في كلا الجانبين: جانب العميل وجانب الخادم. وفيما يلي توضيح للدورين:
    1- جانب العميل (Client-side)
    يطور تطبيق أو موقع ويب يتفاعل مع API الخادم. يستخدم طلبات HTTP المختلفة مثل GET وPOST للتواصل مع الخادم. يقوم ببناء واجهة المستخدم (UI) لعرض البيانات المستردة من الخادم باستخدام بيانات المستجيبة التي تم تلقيها عبر API. 2- جانب الخادم (Server-side)
    ينشئ API باستخدام تقنيات RESTful للسماح للعملاء بالتواصل مع البيانات والخدمات التي يقدمها الخادم. يعمل على تصميم وتطوير واجهات البرمجة API التي توفر الوصول إلى مجموعة محددة من البيانات أو العمليات. ينشئ نماذج البيانات ويحدد طرق الوصول إلى هذه البيانات بما يتوافق مع مبادئ REST. وفي العمل، يمكن للمبرمجين أن يكونوا متخصصين في جانب واحد من REST API، مثل مطوري الواجهة الأمامية (Front-end Developers) الذين يتعاملون بشكل رئيسي مع API الخادم على الطرف العميل، أو مطوري الخادم (Back-end Developers) الذين ينشئون ويديرون ال API نفسها على الطرف الخادم. 
    وإليك مثال لكود JavaScript يوضح كيفية تنفيذ REST API لمصادر المستخدمين باستخدام إطار عمل Express.js أي في الواجهة الخلفية:
    const express = require('express'); const app = express(); // بيانات المستخدمين المؤقتة let users = [ { id: 1, name: 'John' }, { id: 2, name: 'Jane' } ]; // استرداد جميع المستخدمين app.get('/users', (req, res) => { res.json(users); }); // إنشاء مستخدم جديد app.post('/users', (req, res) => { const newUser = { id: users.length + 1, name: req.body.name }; users.push(newUser); res.status(201).json(newUser); }); // تشغيل الخادم app.listen(3000, () => { console.log('Server started on port 3000'); }); أما التعامل مع REST API في الواجهة الأمامية فهو كالتالي:
    // استدعاء API لاسترداد جميع المستخدمين async function getUsers() { try { const response = await fetch('/users'); const data = await response.json(); // استخدام البيانات المستلمة console.log(data); // يتم طباعة المستخدمين في وحدة التحكم } catch (error) { console.error('Error:', error); } } // استدعاء API لإنشاء مستخدم جديد async function createUser() { const newUser = { name: 'Alice' }; try { const response = await fetch('/users', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(newUser) }); const data = await response.json(); // استخدام البيانات المستلمة console.log(data); // يتم طباعة المستخدم الجديد في وحدة التحكم } catch (error) { console.error('Error:', error); } } // استدعاء الدوال المحددة getUsers(); createUser(); وبالإضافة إلى REST، هناك عدة معماريات أخرى تستخدم في تطوير وتصميم واجهات برمجة التطبيقات، مثل:
    معمارية SOAP (Simple Object Access Protocol): تستخدم في تطوير واجهات برمجة التطبيقات المبنية على نمط XML وتتطلب بروتوكولات معقدة للتواصل. معمارية GraphQL: تسمح للعميل بتحديد البيانات المحددة التي يُرغب في استردادها، مما يزيد من كفاءة استرداد البيانات ويقلل من حمولة الشبكة. معمارية gRPC: تعتمد على نمط RPC (Remote Procedure Call) للتواصل بين العميل والخادم، وتستخدم تسلسل البيانات بتنسيق Protocol Buffers.  
  3. إجابة Mustafa Suleiman سؤال في تحويل السيشن الى كوكيز session to cookies php كانت الإجابة المقبولة   
    الكود بعد التعديل سيصبح كالتالي:
    <?php $passwords = array('123456', 'xxxx', '7777', '8888', '9999'); if (isset($_POST['password'])) { if (in_array($_POST['password'], $passwords)) { setcookie('loggedIn', true, time() + (30 * 24 * 60 * 60)); // تعيين الكوكيز header('Location: ' . $_SERVER['PHP_SELF']); // إعادة توجيه الصفحة بعد تعيين الكوكيز exit(); } else { die ('Incorrect password'); } } if (!isset($_COOKIE['loggedIn']) || !$_COOKIE['loggedIn']): ?> <html> <head> <title>Login</title> </head> <body> <p>You need to login</p> <form method="post"> Password: <input type="password" name="password"> <br /> <input type="submit" name="submit" value="Login"> </form> </body> </html> <?php exit(); endif; echo '<h1>Hello world... Logged in successfully.</h1>'; ?> وما تم هو تعيين قيمة الكوكيز "loggedIn" إلى true باستخدام الدالة setcookie() عند تسجيل الدخول بكلمة المرور الصحيحة، ثم تحديد صلاحية الكوكيز لمدة 30 يومًا باستخدام time() + (30 * 24 * 60 * 60)، حيث يتم ضرب 30 (عدد الأيام) في 24 (عدد الساعات في اليوم) في 60 (عدد الدقائق في الساعة) في 60 (عدد الثواني في الدقيقة) للحصول على الوقت المستقبلي الذي ينتهي فيه صلاحية الكوكيز.
    وفي حالة عدم وجود قيمة الكوكيز "loggedIn" أو إذا كانت قيمتها false، فسيعرض نموذج تسجيل الدخول، وعند تسجيل الدخول الصحيح، سيتم تعيين الكوكيز وإعادة توجيه الصفحة لعرض رسالة تأكيد تسجيل الدخول بنجاح.
    وعليك بتأمين الاتصال باستخدام SSL والتحقق من صحة البيانات المرسلة قبل تعيين الكوكيز.
  4. إجابة Mustafa Suleiman سؤال في ما هو ASCII وكيف يتم تمثيل الحروف والأرقام فيه؟ كانت الإجابة المقبولة   
    ASCII ببساطة هو اختصار لـ "American Standard Code for Information Interchange" ويشير إلى مجموعة محددة من الرموز المستخدمة لتمثيل الحروف والأرقام والرموز الأخرى في الحواسيب وأنظمة الاتصالات.
    تم تطوير ASCII في الأصل في عام 1963 كمعيار لتبادل البيانات بين أجهزة الكمبيوتر المختلفة والشبكات.
    وتتضمن مجموعة ASCII الأصلية 128 رمزًا، حيث يمثل  كل حرف بواحد من هذه الرموز، وتتضمن الرموز الأساسية الأبجدية اللاتينية الكبيرة والصغيرة، والأرقام من 0 إلى 9، ورموز ترقيم ورموز تحكم مثل المسافة والترقيم والعلامات القوسية والأقواس.
    ومع مرور الوقت، تطورت مجموعة ASCII لتشمل مجموعة أوسع من الرموز تسمح بتمثيل الأحرف والرموز الإضافية بما في ذلك الحروف غير اللاتينية والرموز الخاصة. يتكون ASCII الموسع من 8 بت، مما يعني وجود 256 رمزًا ممكنًا.
    وحاليًا تُستخدم ASCII بشكل واسع في البرمجة وعند نقل البيانات بين الأجهزة المختلفة، حيث يمكن تمثيل النصوص والرموز باستخدام تلك المجموعة المحددة من الأرقام والحروف.
    مثال للتوضيح:
    حرف "A" بالأحرف الكبيرة: يتم تمثيله بالرقم 65 في ASCII. حرف "a" بالأحرف الصغيرة: يتم تمثيله بالرقم 97 في ASCII. الرقم "5": يتم تمثيله بالرقم 53 في ASCII. الرمز "$": يتم تمثيله بالرقم 36 في ASCII. الرمز التحكم للمسافة الفارغة: يتم تمثيله بالرقم 32 في ASCII. والغرض هو توحيد تلك التمثيلات في جميع أنحاء الأنظمة التي تدعم ASCII لضمان التوافق وتبادل البيانات بسهولة.
    وتفقد النقاش التالي لمزيد من المعلومات:
  5. إجابة Mustafa Suleiman سؤال في 08. تسجيل الدخول والخروج كانت الإجابة المقبولة   
    أرجو منك طرح السؤال أسفل فيديو الدورة الخاص بالسؤال ليتم مساعدتك بشكل أفضل، وطرح الأسئلة العامة هنا.
  6. إجابة Mustafa Suleiman سؤال في هل يمكن معرفة mac address للزائر بلغة php كانت الإجابة المقبولة   
    لن تستطيع الحصول على عنوان MAC للزائر باستخدام لغة PHP، فعناوين MAC تكون مرتبطة بالأجهزة المادية مثل بطاقات الشبكة والراوترات، ولا يتم إرسالها عبر الإنترنت في طبقة التطبيق، وتُستخدم عناوين MAC في الشبكات المحلية فقط لتوجيه حركة البيانات بين الأجهزة المتصلة في الشبكة المحلية.
    وستجد على الإنترنت كود مثل التالي:
    <?php // PHP code to get the MAC address of Server $MAC = exec('getmac'); // Storing 'getmac' value in $MAC $MAC = strtok($MAC, ' '); // Updating $MAC value using strtok function, // strtok is used to split the string into tokens // split character of strtok is defined as a space // because getmac returns transport name after // MAC address echo "MAC address of Server is: $MAC"; ?> لكنه يستخدم للحصول على عنوان MAC للسيرفر الذي يقوم بتشغيل كود PHP، وليس للزائر، أو المستخدمين على نفس الشبكة المحلية لديك.
    وبإمكانك فقط الحصول على عنوان IP للزائر باستخدام PHP من خلال استخدام المتغير المدمج:
    $_SERVER['REMOTE_ADDR'] ويعيد هذا المتغير عنوان IP للزائر الحالي الذي يقوم بالوصول إلى صفحة الويب، ويجب أن تكون مدركًا أن عناوين IP متغيرة وغير دائمة بطبيعتها، ويمكن تغييرها أو تخطيها باستخدام بروكسي أو شبكات VPN، وبالتالي قد لا تكون دقيقة بنسبة 100% لتحديد هوية الزائر.
  7. إجابة Mustafa Suleiman سؤال في فوائد تعلم النظامين الثنائي والسداسي عشري وتمثيل ASCII للمبرمجين كانت الإجابة المقبولة   
    بعض الاستخدامات الشائعة للنظامين الثنائي والسداسي عشري، بالإضافة إلى ASCII هي كالتالي:
    1- بخصوص النظام الثنائي (Binary)
    يستخدم في تمثيل البيانات والمعلومات في الحواسيب والأجهزة الإلكترونية، ويعمل الحاسوب الحديث بنظام ثنائي حيث يستخدم الصفر والواحد لتمثيل البتات (Bits) التي تشكل البيانات والتعليمات. يستخدم في عمليات الحساب الثنائي والمنطق المعالجات المنطقية الرقمية والأبواب المنطقية والدوائر المنطقية، وهو مفيد في تصميم الدوائر الإلكترونية والشبكات الرقمية. 2- النظام السداسي عشري (Hexadecimal)
    يستخدم في تمثيل الأرقام والبيانات في الحواسيب وأنظمة التشغيل والبرمجة. يسهل استخدام الأرقام من 0 إلى 9 والأحرف من A إلى F لتمثيل القيم الثنائية بطريقة مدمجة وقصيرة.
    يسهل تمثيل عناوين الذاكرة والعناصر في الذاكرة الحاسوبية. على سبيل المثال، في برمجة الحواسيب، يمكن استخدام الأرقام السداسية عند التعامل مع العناوين الذاكرة أو تمثيل الألوان في الرسومات الحاسوبية.
    3- ASCII (American Standard Code for Information Interchange)
    يستخدم لتمثيل الأحرف والرموز المستخدمة في الكمبيوتر والاتصالات، ويعطي كل حرف رمزًا فريدًا في النظام الثنائي (مكون من 8 بت) يمكن تفسيره واستخدامه من قبل الحواسيب. يستخدم في برمجة الحواسيب لتمثيل النصوص والبيانات النصية، وتحويل الحروف والرموز إلى أكواد ASCII يسهل عملية تخزين ومعالجة النصوص في الحواسيب. هل هناك فائدة من تعلم ما سبق كمبرمج؟
    ستحتاج إلى تعلم ذلك إذا كنت تريد التخصص في مجال الـ Embedded system أي مجال برمجة الأجهزة المضمنة، وإليك بعض الفوائد:
    تعلم النظامين الثنائي والسداسي عشري يمكن أن يساعدك في فهم كيفية تمثيل البيانات والأرقام في الحواسيب، ويعتبر النظام الثنائي الأساسي في التعامل مع البيانات الرقمية، ومعرفة كيفية تمثيله قد يفيدك في فهم عمليات الحساب والتخزين والمعالجة داخل الحاسوب. ربما  تتعامل مع النظام الثنائي وتمثيل البيانات بشكل مباشر، وفهم النظام الثنائي يساعدك في فهم بنية البيانات وتنسيقها والتعامل معها بشكل صحيح. في حالة وجود مشكلات في البرامج أو الأنظمة، قد تحتاج احيانًأ إلى تحليل البيانات والتعامل معها على مستوى البتات أو الأرقام السداسية عشرية، وتعلم تلك النظم يمكن أن يمكنك من تحليل الأخطاء وتصحيحها بشكل أكثر فعالية. في مجال برمجة الأجهزة المضمنة، قد تحتاج إلى التعامل مع المعالجات والمكونات الإلكترونية المنخفضة المستوى، وفهم النظام الثنائي والسداسي عشري يمكن أن يسهل عليك تطوير وبرمجة هذه الأجهزة بشكل أفضل. قد تحتاج أحيانًا للتعامل مع بيانات أو أجهزة تستخدم تمثيل ثنائي أو سداسي عشري، مثل قراءة وكتابة بيانات في ملفات ثنائية أو التواصل مع الأجهزة الخارجية عبر منافذ التسلسلية (Serial ports) أو بروتوكولات الاتصال المبنية على النظام الثنائي.
  8. إجابة Mustafa Suleiman سؤال في حل مشكلة عدم طباعة قيمة x في الحلقة التكرارية كانت الإجابة المقبولة   
    بالشكل التالي:
    const mm = ['ahmed', 'mete', 'sahlab']; for (let i = mm.length - 1; i >= 0; i--) { console.log(i, mm[i]); } let x = mm.length - 1; while (x >= 0) { console.log('WHILE: ', x, mm[x]); x--; }  
  9. إجابة Mustafa Suleiman سؤال في ما هي المواقع العربية الأخرى للعمل الحر عبر الإنترنت بخلاف مستقل وخمسات؟ كانت الإجابة المقبولة   
    بخصوص المواقع العربية، لا يوجد سوى مستقل وخمسات وموقع بعيد، أما بقيةالمواقع العربية إن وجدت فهى غير إحترافية بكل صراحة وليست مصدر ثقة للعمل عليها وبذل وقت وجهد بها.
    وإذا كنتي واجهتي صعوبة في قبول عرضك على تلك المواقع، فعليك بالتوقف قليلاً والبحث في سبب المشكلة، هل طريقة كتابة عرضي غير إحترافية؟ هل معرض الأعمال الخاص بي غير جيد وغير متخصص ويوحي بأني شخص مبتدأ؟ هل طريقة عرض نفسي في ملفي الشخصي غير جيدة؟
    ولكي تتمكني من معرفة الإجابة على تلك الأسئلة، عليك بمعرفة الطريقة الصحيحة لفعل ذلك، وستجدي في مدونة مستقل مقالات رائعة بخصوص ذلك.
    دليلك الشامل إلى العمل الحر عبر الإنترنت نصائح للمستقلين  
  10. إجابة Mustafa Suleiman سؤال في ربط ملف جافاسكريبت في HTML وتشغيل السكريبت بشكل صحيح كانت الإجابة المقبولة   
    عليك أولاً بحفظ التغييرات، ثانيًا تأكد من أنك قمت بربط ملف index.js في ملف index.html بشكل صحيح وذلك عن طريق عنصر script كالتالي:
    <script defer src="index.js"></script> ويتم وضع ذلك الجزء داخل عنصر header أو في نهاية عنصر body لكن لا حاجة إلى ذلك حيث أنني قمت بوضع defer من أجل تحميل السكريبت بعد إنتهاء تحميل أكواد HTML وستجد شرح لذلك هنا:
    الآن داخل ملف السكريبت حاول تجنب كتابة اسم المتغير باسم name لكونه تابع لخاصية في الكائن Window وهي window.name ولكن تلك الخاصية أصبحت deprecated أي لم تصبح مدعومة بعد الآن وسيتم إزالتها بعد فترة، وستجد خط كما لو أنه شطب على اسم المتغير كما ترى في الكود لديك.
    ولطباعة اسم المتغير بعد تغييره سنقوم بكتابة السكريبت كالتالي:
    'use strict'; let personName; personName = 'mohamed'; console.log(personName); وسيتم طباعة الاسم في الكونسول.
    ولاحظ أنني قمت بكتابة 'use strict' أو الوضع الصارم  في البداية وأنصحك باستخدامها عند كتابة سكريبت عادي وليس module حيث يتم تفعيله بشكل إفتراضي في الـ modules وفائدتها كالتالي:
    في الوضع الصارم، يجب عليك تعريف المتغيرات قبل استخدامها، فإذا قمت بتعيين قيمة لمتغير غير معرف، سيتم إلقاء استثناء. ولا يمكنك استخدام مفاتيح الكلمات المحجوزة كمعرفات، مما يحميك من تعديل قيمة المفاتيح الداخلية للغة. يجبرك على اتباع بعض الممارسات الأفضل في البرمجة، مما يساعد في تجنب بعض الأخطاء الأمنية الشائعة. يتم منع الوصول إلى خصائص الكائنات غير المعرفة، مما يساعد في تجنب الأخطاء الناتجة عن التعامل مع كائنات لا تحتوي على الخصائص المطلوبة. في بعض الحالات، الوضع الصارم يساعد في تحسين أداء الكود، حيث يمكن للمترجم أن يقوم بتنفيذ بعض الأمور بشكل أسرع وأكثر فعالية. أيضًا ستتم معالجة بعض الأخطاء التي تكون صامتة في الوضع العادي Silent Errors، مثلاً ستحصل على أخطاء عند استخدام المتغيرات غير المعرفة بدلاً من إنشاء متغيرات عالمية ضمن نطاق Global. وهناك أمور أخرى لكن لا تشغل بالك بها حاليًا.
  11. إجابة Mustafa Suleiman سؤال في مقارنة بين بيئة العمل على الحاسوب الشخصي وGoogle Colab لتعلم الآلة وتحليل البيانات كانت الإجابة المقبولة   
    ببساطة إذا كانت مواصفات حاسوبك غير كافية بالنسبة للمشروع الذي تعمل عليه، فتستطيع استخدام Google Colab،  حيث  المستخدمين المجانيين على Google Colab يحصلون على وصول مجاني إلى وحدات المعالجة الرسومية (GPU) ووحدات المعالجة الرسومية المتخصصة (TPU) لمدة تصل إلى 12 ساعة.
    ويتم توفير GPU runtime في Colab مع المواصفات التالية: وحدة المعالجة المركزية Intel Xeon @2.20 جيجاهرتز، 13 جيجابايت من ذاكرة الوصول العشوائي (RAM)، وحدة Tesla K80 للتسريع، و 12 جيجابايت من ذاكرة الوصول العشوائي GDDR5 VRAM.
    أما TPU runtime في Colab، فهو يتألف من وحدة المعالجة المركزية Intel Xeon @2.30 جيجاهرتز، 13 جيجابايت من ذاكرة الوصول العشوائي (RAM)، وحدة TPU سحابية بقوة حوسبة تصل إلى 180 تيرافلوبس.
    باختصار، يعني ذلك أنه يمكنك الاستفادة من قدرات GPU و TPU القوية لتنفيذ العمليات الحسابية المكثفة والمتقدمة في مجال التعلم الآلي وتحليل البيانات.
    وتتوفر موارد الحاسوب هذه مجانًا لمدة تصل إلى 12 ساعة، والتي يمكن استخدامها لتشغيل النماذج وتدريبها وتحليل البيانات بشكل فعال.
    بعد انتهاء الـ 12 ساعة على Google Colab، يتم إلغاء جلسة العمل الحالية ويتعين عليك إعادة تشغيلها، ويعني ذلك أن أي عمل غير محفوظ سيتم فقده، بما في ذلك البيانات والنماذج والتعديلات التي تم إجراؤها خلال الجلسة.
    وتستطيع يمكنك حفظ النتائج والملفات الضرورية قبل انتهاء الجلسة الحالية، عن طريق حفظ البيانات في حساب Google Drive الخاص بك أو تنزيلها إلى جهاز الكمبيوتر الشخصي الخاص بك.
     أيضًا استخدام الوظيفة "Save a copy in Drive" في Google Colab لحفظ الدفتر الحالي في Google Drive قبل انتهاء الوقت المحدد.
    معالجات m مصممة بواسطة Apple ومبنية على تقنية ARM، تتميز بأداء مذهل وكفاءة عالية في استخدام الطاقة.
    فمع معالج M2،  ستستفيد من أداء محسّن وتسارع لعمليات التعلم الآلي، ويحتوي المعالج M2 على مجموعة متنوعة من وحدات المعالجة المركزية ووحدات المعالجة الرسومية المتكاملة، مما يسمح بتنفيذ عمليات التعلم العميق بسرعة وكفاءة. بالإضافة إلى ذلك، يشتمل على وحدة Neural Engine التي توفر قدرات تسريع متقدمة لعمليات التعلم الآلي.
    ومن المهم أيضًا أن تنظر إلى الذاكرة والتخزين في الجهاز، حيث توفر MacBook الجديدة غالبًا ذواكر وتخزين فائقة السرعة، مما يساعد على تسريع عمليات التعلم الآلي وتحليل البيانات.
    ولكن إذا كان لديك كرت شاشة قوي على نظام الويندوز فستحصل على أداء مشابه حيث أن العامل الأساسي هو كرت الشاشة، يأتي بعده المعالج ثم الرامات.
     
  12. إجابة Mustafa Suleiman سؤال في تخزين البيانات في متصفح الويب باستخدام JavaScript و localStorage كانت الإجابة المقبولة   
    عليك باستخدام localStorage لحفظ القيم المدخلة في حقول الإدخال، وذلك بتعديل السكريبت لديك بالشكل التالي:
    let submit = document.getElementById('submit'); let text = document.getElementById('text'); let password = document.getElementById('password'); // عرض البيانات المحفوظة عند تحميل الصفحة window.onload = function() { let savedText = localStorage.getItem('text'); if (savedText) { text.value = savedText; } let savedPassword = localStorage.getItem('password'); if (savedPassword) { password.value = savedPassword; } }; submit.onclick = function () { if (text.value === 'محمد عماد احمد' && password.value === '10203') { alert('نعم'); // حفظ القيم في localStorage localStorage.setItem('text', text.value); localStorage.setItem('password', password.value); } else { alert('لا'); } let screenWidth = screen.availWidth; if (screenWidth > 1000) { alert('فقط الهواتف المحمولة، من فضلك'); } else { alert('الهاتف المحمول المناسب'); } }; يستخدم localStorage.setItem(key, value) لحفظ القيم في ذاكرة التخزين المحلية للمتصفح.
    وعند تحميل الصفحة، يستخدم localStorage.getItem(key) لاسترداد القيم المحفوظة وتعيينها في حقول الإدخال، وستظل القيمة محفوظة حتى بعد تحديث الصفحة.
     
  13. إجابة Mustafa Suleiman سؤال في كيفية العمل على مواقع العمل الحر كمبرمج فلاتر وتحديد السعر المناسب للساعة والمشروع كانت الإجابة المقبولة   
    إذا كنت قد تعلمت فلاتر بالفعل وتريد العمل على موقع العمل الحر، فأمامك مساحة واسعة للإختيار من بينها، ومنها مواقع مثل مستقل وخمسات وبعيد، وعلى تلك الموقع يتم العمل بتكلفة ثابتة Fixed للمشروع قابلة للزيادة والتعديل في حالة وجود ميزات إضافية لم يتم الإتفاق عليها.
    أما عن نظام الساعة، فعليك بتفقد الأسعار لمبرمجي فلاتر من حيث سعر الساعة، ثم ضع احسب متوسط السعر وضع سعر ساعة منخفض قليلاً عن المتوسط في البداية وقدم جودة عمل جيدة أعلى من المطلوب ولكن لا تفرض على نفسك ذلك أي التزم بالمطلوب وقم بتقديم أكثر منه وهناك مبدأ دائمًا أحب الإلتزام به في العمل الحر، ألا وهوUnder Promise And Over Deliver بمعنى أن الجميع يسرد أشعار للعميل وسيفعل وسيفعل وذلك خطأ.
    بل التزم بما هو مطلوب منك أو أعلى قليلاً للمنافسة في البداية، ثم وفر أكثر مما هو ممطلوب وستجد أن العميل سعيد جدًا بذلك وأيضًا لم تفرض على نفسك أي شيء.
    وبخصوص كيفية حساب الساعة فإليك بعض النقاط التي ستساعدك:
    قم بتحديد ما هي نوعية العمل التي ستقدمها؟ هل تعمل على تطوير تطبيقات بسيطة أو معقدة؟ ما هو مستوى الخبرة المطلوبة؟ إجراء بحث عن أسعار الساعة المعتادة لمبرمجي فلاتر على منصات العمل الحر، وتستطيع الاطلاع على مشاريع مماثلة والتحقق من الأسعار المقدمة من قبل المطورين الآخرين. احتسب سنوات الخبرة التي تمتلكها كمبرمج فلاتر، فستتمكن من تحقيق سعر أعلى إذا كنت تمتلك خبرة واسعة ومشاريع ناجحة في معرض أعمالك. تحديد تكاليف العمل الخاصة بك، وتشمل هذه العناصر تكاليف المعدات والبرمجيات والوقت الذي ستستغرقه في إكمال المشروع. مع الوقت سيكون لديك فكرة تقريبية عن الوقت المستغرق لإكمال مشروع معين، فقم بتحديد عدد الساعات المتوقعة للعمل على المشروع. تحديد المبلغ الذي ترغب في كسبه من العمل الحر، فيمكن أن يكون المبلغ مبنيًا على احتساب قيمة ساعة العمل الأساسية وإضافة الربح المرغوب. ولكن عدد الساعات لا يعني أبدًا التكلفة الحقيقية للمشروع، فمثلاً بعد سنوات خبرة، ستستطيع إنهاء مشروع في وقت أقل وبجودة أعلى فهل ذلك يعني أنك تتقاضى مبلغ أقل، بالطبع لا، هنا عليك إما بحساب تكلفة ثابتة للمشروع أو وضع عدد ساعات مناسب ومرضي لك.
    وأنصحك بقراءة التالي:
     
  14. إجابة Mustafa Suleiman سؤال في أشهر البوتات في Discord ووظائفها المفيدة كانت الإجابة المقبولة   
    هناك كم هائل من الوظائف التي بإمكان تلك الروبوتات القيام بها ومنها:
     إنشاء وحذف وتحرير القنوات، وتعيين الأذونات اللازمة للأعضاء.  تتبع نشاط المستخدمين ومنحهم مستويات وأدوار مخصصة بناءً على تفاعلهم في الخادم.  تشغيل الموسيقى في قنوات الصوت من مصادر مثل YouTube أو Spotify، ويمكنها التحكم في مستوى الصوت وتشغيل قوائم التشغيل. إرسال إشعارات وتذكيرات للأعضاء في الخادم، مثل تذكير بالأحداث المهمة أو مواعيد الاجتماعات.  تقديم ألعاب تفاعلية للأعضاء، مثل ألعاب الكلمات المتقاطعة أو ألعاب الأدوار البسيطة. البحث عن معلومات عبر الإنترنت وتقديمها للأعضاء، مثل الأخبار أو توقعات الطقس أو معلومات عامة.  الترحيب بالأعضاء الجدد في الخادم وتوديع الأعضاء الذين يغادرون. مراقبة النشاط في الخادم والكشف عن المخالفات والسلوك غير الملائم، وتنفيذ تدابير الأمان المطلوبة مثل حظر الأعضاء المخالفين.  تنظيم مسابقات وألعاب تفاعلية للأعضاء، مثل ألعاب الألغاز أو ألعاب الأدوار المتقدمة.  توفير الدعم الفني والإجابة على الأسئلة الشائعة للأعضاء، وتقديم التوجيه والمساعدة في استخدام الخادم.  الاتصال بمنصات أخرى مثل Twitter أو Reddit وتقديم تحديثات مباشرة للأعضاء. توفير أوامر خاصة بتخصيص واجهة الخادم، مثل تغيير الألوان والخلفيات وإضافة الرموز التعبيرية المخصصة. بالنسبة لأشهر البوتات في Discord، فهناك العديد من البوتات المشهورة ومنها:
    Dyno: بوت متعدد الاستخدامات يوفر ميزات إدارة الخادم ونظام المستويات والموسيقى والأدوار. MEE6: يوفر نظام المستويات والأدوار والموسيقى والترحيب والإشعارات والمسابقات. Tatsumaki: يقدم نظام المستويات والأدوار والألعاب والإحصائيات والترحيب والتوديع. Dank Memer: للترفيه يقدم ألعاب الكلمات والميمات والنكات والصور المضحكة. Rythm: لتشغيل الموسيقى من مصادر مثل YouTube وSpotify وSoundCloud.
  15. إجابة Mustafa Suleiman سؤال في شرح استخدام الفئة المجردة abstract class في فلاتر BLOC كانت الإجابة المقبولة   
    السبب وراء وضع الـ abstract class في بداية قائمة الـ states في فلاتر BLOC هو لتوفير واجهة مشتركة لجميع حالات الحالة (states) المحتملة التي يمكن أن يتبعها Cubit أو Bloc.
    وباستخدام الـ abstract class ، تستطيع تعريف مجموعة محددة من الحالات الأساسية التي قد يعتمدها Cubit أو Bloc دون الحاجة إلى إعادة تعريف الأساليب الأساسية في كل مرة.
    والكود في الصورة، تم به تعريف NewestBooksState كـ abstract class وتنفيذها من قبل عدة حالات محددة، مثل NewestBooksInitial و NewestBooksLoading و NewestBooksFailure و NewestBooksSuccess.
    ومن خلال استخدام abstract class، تستطيع توحيد النهج وتطبيق المنطق المشترك بين حالات الحالة المختلفة، مثل توفير قائمة الممتلكات (props) المشتركة وأي أساليب أخرى ترغب في تعريفها لجميع حالات الحالة.
    أيضًا بوجود abstract class، بإمكانك استخدام المتغيرات من نوع NewestBooksState للإشارة إلى أي حالة من حالات الحالة، مما يسهل تحديد الحالة الحالية واتخاذ الإجراءات المناسبة في الـ Cubit أو Bloc الخاص بك.
    وسأقدم لك مثالًا يوضح كيفية استخدام الفئة المجردة (abstract class) في فلاتر BLOC، ولنفترض أن لدينا Cubit لإدارة حالة قائمة أحدث الكتب في تطبيق مكتبة.
    فتستطيع كتابة الفئات المختلفة على النحو التالي:
    import 'package:equatable/equatable.dart'; abstract class NewestBooksState extends Equatable { const NewestBooksState(); @override List<Object> get props => []; } class NewestBooksInitial extends NewestBooksState {} class NewestBooksLoading extends NewestBooksState {} class NewestBooksFailure extends NewestBooksState { final String error; const NewestBooksFailure(this.error); @override List<Object> get props => [error]; } class NewestBooksSuccess extends NewestBooksState { final List<Book> books; const NewestBooksSuccess(this.books); @override List<Object> get props => [books]; } هنا لدينا الفئة المجردة NewestBooksState التي تم تنفيذها من قبل عدة حالات محددة.
    وNewestBooksState يحتوي على المنطق المشترك لجميع حالات الحالة، والذي يشمل تنفيذ props لإعطاء معرف فريد لكل حالة، وذلك لتمكين المقارنة والتعامل مع التغييرات في الحالة بشكل فعال.
    NewestBooksInitial: حالة البداية، ويمثل الحالة الأولية للقائمة. NewestBooksLoading: حالة التحميل، ويشير إلى أن القائمة تحمل البيانات حاليًا. NewestBooksFailure: حالة الفشل، ويشير إلى حدوث خطأ أثناء جلب البيانات، ويحتوي على رسالة الخطأ المحددة. NewestBooksSuccess: حالة النجاح، ويشير إلى أن البيانات تم جلبها بنجاح، ويحتوي على قائمة الكتب الأحدث. وباستخدام الفئة المجردة NewestBooksState وحالاتها المحددة، يمكنك توحيد المنطق وإدارة حالة قائمة الكتب في Cubit الخاص بك، وإصدار حالة معينة باستخدام emit داخل Cubit بناءً على المنطق والأحداث التي تحدث في التطبيق.
  16. إجابة Mustafa Suleiman سؤال في خطأ في نشر تطبيق فلاتر على ابل ستور كانت الإجابة المقبولة   
    App ID
    هو هوية فريدة تُعرف في بيئة تطوير Apple وتُستخدم لتمييز التطبيقات الخاصة بك عند توزيعها أو تحديثها. يحتوي App ID على سلسلة نصية مميزة تُعبر عن هوية التطبيق.
    عند إنشاء تطبيق جديد، يتم إنشاء App ID خاص به ويكون له تكوين معين يشمل معلومات مثل Bundle Identifier والخدمات المرتبطة بالتطبيق مثل Push Notifications وApp Groups وغيرها.
    Bundle Identifier
     مُعرّف فريد للتطبيق في إطار التطوير ويستخدم لتمييز التطبيق على نظام iOS، ويتم تعريف Bundle Identifier في مشروعك في Xcode ويتم استخدامه كمعرّف للتطبيق أثناء عملية التطوير والبناء.
    وقد يحتوي Bundle Identifier على نفس القيمة التي تستخدمها في App ID، ولكنها ليست نفس الشيء.
    باختصار، Bundle Identifier هو المعرّف الذي يتم استخدامه أثناء تطوير وبناء التطبيق في Xcode، في حين أن App ID هو المعرّف الفريد في بيئة تطوير Apple ويستخدم لتمييز التطبيق أثناء توزيعه على Apple App Store أو استخدام الخدمات المرتبطة بالتطبيق.
    لذلك تأكد من استخدام Bundle Identifier الصحيح في Xcode  و وجود App ID صحيح مقابله في حسابك على موقع مطوري Apple.
  17. إجابة Mustafa Suleiman سؤال في تفسير عدم حدوث استثناء عند استخدام Column داخل SingleChildScrollView كانت الإجابة المقبولة   
    عند وضع Column داخل SingleChildScrollView، بإمكان لـ Column أن يتمدد بشكل لا محدود في الاتجاه الرأسي داخل SingleChildScrollView. وبالتالي، لن يتم رمي استثناء عند تمرير المحتوى.
    وهناك بعض التناقض في الشروط التي يتم فيها رمي استثناء عند استخدام Expanded داخل SingleChildScrollView. في الواقع، إذا وضعت Expanded داخل SingleChildScrollView، ستحدث استثناءات لأن Expanded يحاول التمدد لاستغلال المساحة المتبقية، في حين يسمح SingleChildScrollView بالتمدد غير المحدود.
    ففي حالة وضع Column بداخل SingleChildScrollView، يتم تطبيق تمدد Column على العناصر الموجودة داخلها فقط، وليس على الـ SingleChildScrollView نفسه. ببساطة، SingleChildScrollView يعمل على إظهار المحتوى الذي يتجاوز المساحة المتاحة على الشاشة بواسطة التمرير، في حين يتمدد Column فقط بناءً على المحتوى الذي يحتويه.
    وإليك مثالًا بسيطًا يوضح استخدام Column داخل SingleChildScrollView بدون حدوث استثناء:
    import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Example', home: Scaffold( appBar: AppBar( title: Text('Example'), ), body: SingleChildScrollView( child: Column( children: [ Container( height: 200, // ارتفاع ثابت للمثال color: Colors.blue, ), Container( height: 200, color: Colors.green, ), Container( height: 200, color: Colors.red, ), // يمكنك إضافة المزيد من العناصر هنا ], ), ), ), ); } } تم وضع Column داخل SingleChildScrollView وتحديد ارتفاع ثابت لكل عنصر في Column، بغض النظر عن عدد العناصر، ستظهر جميعها داخل SingleChildScrollView ويمكن التمرير لعرض المحتوى الكامل.
  18. إجابة Mustafa Suleiman سؤال في نمط Repository أم نمط MVVM: الأفضل لتطوير مشاريع فلاتر؟ وما هو الفارق بينهما؟ كانت الإجابة المقبولة   
    عند العمل على مشاريع فلاتر (Flutter)، باستطاعتك استخدام أنماط مختلفة لتنظيم وإدارة الكود، وهناك نمطين شائعين في عالم فلاتر هما MVVM و Repository.
    سأوضح لك الفارق بينهما وسأشرح كل نمط على حدة
    1- MVVM (Model-View-ViewModel)

    يعتبر MVVM من أنماط التصميم الأكثر شيوعًا في تطوير تطبيقات الهواتف المحمولة بما في ذلك فلاتر، وينقسم هذا النمط إلى ثلاثة أجزاء رئيسية:
    Model: يمثل البيانات والمنطق الخاصة بالتطبيق، ويمكن أن يكون لديك مثيلات للنماذج التي تحتوي على بيانات يستخدمها التطبيق. View: تمثل واجهة المستخدم، وتعرض البيانات المنتجة من ViewModel وتتفاعل مع المستخدم. ViewModel: يعمل كوسيط بين Model و View، ويتولى استرجاع البيانات من Model وتحويلها إلى شكل مناسب للعرض على الـ View، أيضًا يحتوي على المنطق اللازم للتعامل مع استجابة المستخدم. الفكرة الرئيسية وراء MVVM هي فصل الواجهة البصرية عن البيانات والمنطق الخاصة بها، مما يتيح تبسيط عملية اختبار وصيانة التطبيق وسهولة إضافة ميزات جديدة.
    2- Repository Pattern

    يستخدم نمط Repository لإدارة استرجاع البيانات وحفظها في التطبيق، ويقدم هذا النمط واجهة وسيطة (Interface) تحدد العمليات الممكنة مع البيانات مثل الاسترجاع والحفظ والتحديث والحذف، ويقوم المستودع (Repository) الفعلي بتنفيذ هذه العمليات باستخدام مصادر البيانات المناسبة مثل قواعد البيانات أو خدمات الويب.
    وفي سياق فلاتر، يمكن أن يكون المستودع هو الجزء الذي يسترجع البيانات من قواعد البيانات أو يتصل بخدمات الويب لجلب البيانات، وبإمكانك استخدام Repository Pattern بشكل مستقل أو مع نمط آخر مثل MVVM لتوفير واجهة بين النمطين.
    أي الفكرة الأساسية وراء Repository Pattern هي تجنب تكرار كود الوصول للبيانات في مختلف أجزاء التطبيق، وتوفير واجهة واحدة للتعامل معها، بدلاً من أن يتم استدعاء وكتابة الاستعلامات المباشرة في أجزاء مختلفة من التطبيق، ويستخدم المستودع كوسيط للتفاعل مع البيانات.
    الأسلوب الأكثر احترافية
    الأمر يعتمد على نوع المشروع وحجمه وتعقيده،  فعادةً ما ينصح باستخدام نمط MVVM لأنه يفصل واجهة المستخدم عن البيانات ويسهل اختبار وصيانة التطبيق.
    أما إذا كنت تعمل على مشروع بسيط وغير معقد، فتستطيع استخدام نمط Repository بشكل مستقل، وإذا اقتضى الأمر تستطيع أيضًا استخدام كلا النمطين معًا.
     
  19. إجابة Mustafa Suleiman سؤال في كيفية الحصول على وظيفة في شركات FAANG؟ كانت الإجابة المقبولة   
    ما يؤهلك للعمل في تلك الشركات هو تعلم مجالك بإحترافية وسنوات الخبرة المطلوبة في وصف الوظيفة والأمر مختلف من وظيفة لأخرى، لكن ما يهم حقًا هو تعلم Data Structure وAlgorithms وSystem Design والـ Problem Solving.
    حيث أنه يتم إختبارك في تلك المهارات بشكل قوي، وستجد العديد من الكورسات التي تؤهلك لإجتياز تلك الإختبارات من خلال تعلم تلك المهارات بشكل قوي وعلى أسس صحيحة، لا أن تحقظ حل بعض الأسئلة الشهيرة فقط فبذلك أنت تخدع نفسك.
    وأيضًا مهارات الـ Soft skills وتستطيع البحث عنها على اليوتيوب وهي هامة جدًا في مقابلات العمل، بالإضافة إلى تعلم مهارة إنشاء CV قوي أي مهارة كيف تعرض وتسوق لنفسك بشكل مختصر وتلك مهارة هامة سواء في الـ  CV أو مقابلة العمل.
    والأمر سيسير كالتالي:
    أولاً عليك الحصول على مقابلة عمل، وإليك بعض النقاط حول ذلك:
    يحتاج المرشح للحصول على مقابلة عمل في إحدى شركات FAANG. تكون هناك الكثير من السير الذاتية التي ترسل لشركات تكنولوجيا المعلومات، ومعظمها سيئة التنسيق ولا تشتمل على تعليم في علوم الحاسوب أو خبرة. هناك بعض الطرق الفعالة لتميز سيرتك الذاتية هنا، مثل: 1. الحصول على توصية من موظف داخل الشركة، 2. وجود خبرة عمل كمبرمج، 3. حصولك على شهادة في علوم الحاسوب، و 4. تقديم سيرة ذاتية تبدو جميلة (قليل من الأخطاء الإملائية، تنسيق جيد، وربما تحتوي على عدة لغات برمجة أو شيء مشابه). والتركيز يجب أن يكون على أسهل طريقة وهي الحصول على توصية، قم ببناء شبكتك الاجتماعية وابحث عن أشخاص يعملون في تلك الشركات الكبرى الذين يمكنهم تقديم سيرتك الذاتية، وهذه خطوة جيدة لك ولهم أيضًا لأن تلك الشركات تدفع مكافآت مالية للمهندسين الذين يوصون بمزيد من المهندسين البرمجيين. بعد ذلك، قم بالتركيز على النقطة الثانية. النقطة الثانية: أداء جيد في المقابلة.
    بعد تحقيق النقطة الأولى، ستحصل على مقابلات في الشركات الخمس. لاحظ أن معدل نجاح هذه المقابلات منخفض، فعادةً ما تبدأ بامتحان تلقائي أو مكالمة هاتفية لمدة ساعة مع مهندس برمجي أو اثنين، وسيطرحون عليك سؤالًا مأخوذًا مباشرة من "Cracking the Coding Interview"، وستكتب إجابة وتقول "هذا O(N log N)" وسيشيدون بك لأنك واحد من بين خمسة أشخاص تقريبًا تجتازوا تلك الاختبارات الهاتفية وتستمرون في المراحل التالية. وللنجاح في تلك المرحلة، يجب دراسة الخوارزميات وهياكل البيانات، وحل مشاكل مماثلة لـ LeetCode، ونأمل أن يقوم أحد أصدقائك الذين قدمت لهم توصية بإجراء بعض المكالمات التجريبية للممارسة.
    وهذا النوع من الممارسة سيكون جزءًا كبيرًا من تركيزك خلال فترة العمل لمدة عامين، وهذا هو المعيار الرئيسي الذي ستقيم عليه، إلى احترافيتك أثناء المقابلة والتجهيز الجيد لها.
    بعد ذلك، ستأتي مرحلة المقابلة في المكان الفعلي (on-site interview) وستكون مشابهة للمقابلة الهاتفية باستثناء أنك ستجري خمسة مقابلات متتالية.
    وقد يكون لديك فرصة 1 من بين 6 لاجتياز هذه المرحلة، في المتوسط.
    وستساعدك الممارسة بشكل كبير. الأخبار الجيدة هي أن العملية تعتمد إلى حد كبير على الصدفة، بفرض أنك جيد جدًا في الإجابة على هذا النوع من المشكلات، فإذا ما قمت بالمقابلة في الشركات الخمس، فإن الفرص جيدة جدًا أن يتم اجتيازك في إحداها، وسوف تتحسن قدرتك على المقابلة مع الوقت.
    بالإضافة إلى ذلك، تتوفر لدى بعض هذه الشركات فرصة لإعادة المقابلة بعد ستة أشهر إلى سنة.
    لذا، فإن الفرصة لاجتياز المقابلة الأولى ضئيلة، ولكن الفرصة جيدة في الواقع لاجتياز إحدى المقابلات في النهاية، وتحتاج فقط إلى اجتياز المقابلة مرة واحدة.
    وهل أنت مرتاح في التحدث أمام عدة أشخاص؟ عليك بأن تصبح مرتاحًا من خلال إجراء مقابلات عمل والتعود عليها، وانتبه إلى أن حل مشكلة خوارزمية في المنزل شيء، وحل مشكلة خوارزمية على لوح أبيض أمام عدة أشخاص ومهنة تحقق من ستة أرقام مالية هي شيء آخر تمامًا.
    وبالطبع عليك العمل على اللغة الإنجليزية الخاصة بك، وأنصحك بمشاهدة الفيديو التالي على اليوتيوب:
    كيف تصل للشركات العالمية؟ || بودكاست مع المهندس أحمد علي - مهندس برمجيات في شركة فيسبوك. وستتعلم الكثير خلال مقابلة مدتها ساعة ونص من المعلومات المفيدة حقًا.
  20. إجابة Mustafa Suleiman سؤال في أهمية الترتيب في pseudo-classes لتنسيق الروابط في CSS كانت الإجابة المقبولة   
    أولاً سأشرح لك ما معنى كل من الـ pseudo-classes الآتية:
    وقبل ذلك لنفهم ما معنى pseudo-class في CSS، وهي تعبير يستخدم لتحديد حالة محددة أو حالة خاصة لعنصر HTML، وتسمح pseudo-classes بتطبيق أنماط وتنسيقات مختلفة للعناصر بناءً على حالتها أو عنصر معين.
    {}a:link هذا يحدد النمط الذي ستظهر به الروابط التي لم يتم النقر عليها بعد (روابط لم يتم زيارتها). {}a:visited يحدد النمط الذي ستظهر به الروابط التي تم النقر عليها مسبقًا (روابط تم زيارتها أي النقر عليها). {}a:focus تحدد النمط الذي ستظهر به الروابط عندما تكون محددة بواسطة المستخدم (جرب الضغط على Tab في الكيبورد وستجد أنه يتم التنقل بين عناصر الصفحة إلى أن تصل للروابط).
    {}a:hover يحدد النمط الذي ستظهر به الروابط عندما يتم تحريك المؤشر فوقها. {}a:active يحدد النمط الذي ستظهر به الروابط عندما يتم النقر عليها (الضغط بالفأرة دون الإفلات أي بشكل مستمر أي اللحظة التي تضغط فيها بالفأرة). والترتيب الذي يشترط في هذه القواعد هو أمر مهم لأنه يُحدد ترتيب تطبيق الأنماط وتعديلات الشكل على الروابط وفقًا لحالة الروابط وتفاعل المستخدم معها.
    ولكن ذلك ليس ضروري حيث أن التنسيق هنا يتم بناءًا على حالة العنصر وليس موقعه في الكود المكتوب، وفي حال قمت بكتابة مثلاً focus أو hover في البداية فلن يتغير شيء، حيث يطبق التنسيق بناءًا على حالة العنصر فقط.
    ولتوضيح أفضل، إليك مثالًا على كيفية استخدام هذه القواعد:
    a:link { color: blue; } a:visited { color: purple; } a:focus { color: DarkTurquoise; } a:hover { color: red; } a:active { color: green; } وستكون الروابط غير المزارة باللون الأزرق (a:link)، وعندما يتم النقر على الرابط ويتم تحويله إلى حالة مزارة، سيتغير لونه إلى اللون البنفسجي (a:visited).
    وعند التنقل بين عناصر الصفحة عند الضغط على Tab سيكون اللون هو DarkTurquoise.
    وعند تحريك المؤشر فوق الرابط، سيتغير لونه إلى اللون الأحمر (a:hover)، وعند النقر عليه، سيتغير لونه إلى اللون الأخضر (a:active) وجرب عدم الإفلات أي اضغط بشكل مستمر وستجد أن لونه أخضر.
    وإليك مثال:
    <!DOCTYPE html> <html> <head> <title>تنسيق الروابط</title> <style> a { color: blue; } a:visited { color: p; } a:focus { color: DarkTurquoise; } a:hover { color: red; } a:active { color: green; } </style> </head> <body> <h1>تنسيق الروابط</h1> <p> <a href="#">روابط الصفحة</a> <br> <a href="#">رابط آخر</a> <br> <a href="#">رابط إضافي</a> </p> </body> </html>
  21. إجابة Mustafa Suleiman سؤال في إضافة إشعارات في تطبيق Android Studio كانت الإجابة المقبولة   
    سأوضح لك الخطوات التي أشار إليك بها عدنان:
    1- إنشاء ملف XML لتصميم إشعارك، باستخدام عنصر RelativeLayout أو LinearLayout لتحديد تخطيط الإشعار الخاص بك وتضمين العناصر المختلفة مثل الصورة والنص.
    مثال:
    <!-- notification.xml --> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content"> <ImageView android:id="@+id/notification_icon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/notification_icon" /> <TextView android:id="@+id/notification_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@id/notification_icon" android:text="عنوان الإشعار" /> <TextView android:id="@+id/notification_message" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/notification_title" android:layout_toRightOf="@id/notification_icon" android:text="رسالة الإشعار" /> </RelativeLayout> 2- في فئة النشاط (Activity) أو الخدمة (Service) التي ترغب في استخدام الإشعار، أنشئ كائنًا من فئة NotificationCompat.Builder لبناء الإشعار.
    مثال:
    // في الأعلى من الفئة، قم بإضافة استيرادات التالية: // import androidx.core.app.NotificationCompat; // import androidx.core.app.NotificationManagerCompat; public class MyActivity extends AppCompatActivity { // ... private static final String CHANNEL_ID = "my_channel_id"; // قم بتعيين قيمة فريدة لهذا المعرف private void showNotification() { // بناء الإشعار NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID) .setSmallIcon(R.drawable.notification_icon) .setContentTitle("عنوان الإشعار") .setContentText("رسالة الإشعار") .setPriority(NotificationCompat.PRIORITY_DEFAULT); // قم بإنشاء النقرة النائبة (PendingIntent) للتعامل مع نقرة المستخدم على الإشعار (اختياري) Intent intent = new Intent(this, MyActivity.class); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0); builder.setContentIntent(pendingIntent); // إنشاء الإشعار NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this); notificationManager.notify(notificationId, builder.build()); } // ... } 3- إنشاء قناة الإشعار (Notification Channel) في طراز الأندرويد الذي يدعم قنوات الإشعارات (Android 8.0 أو أعلى).
    مثال:
    public class MyApplication extends Application { private static final String CHANNEL_ID = "my_channel_id"; // يجب أن يتطابق مع القيمة المستخدمة في الخطوة السابقة @Override public void onCreate() { super.onCreate(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { // إنشاء قناة الإشعار CharSequence name = "اسم القناة"; String description = "وصف القناة"; int importance = NotificationManager.IMPORTANCE_DEFAULT; NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance); channel.setDescription(description); // تهيئة إعدادات قناة الإشعار NotificationManager notificationManager = getSystemService(NotificationManager.class); notificationManager.createNotificationChannel(channel); } } } 4. تنفيذ دالة showNotification() عند الحاجة لعرض الإشعار.
    بمجرد تنفيذ دالة showNotification()، ستقوم ببناء الإشعار وعرضه للمستخدم، وتستطيع استدعاء هذه الدالة من أي مكان في تطبيقك وفي أي سياق مناسب.
    مثلاً استدعاء showNotification() عندما يتم اكتشاف حدث جديد في التطبيق، مثل وصول رسالة جديدة أو تحديث مهم، أيضًا استدعائها من داخل خدمة (Service) لعرض إشعارات دورية أو قائمة بالتحديثات الجديدة.
    مثال على استدعاء showNotification():
    public class MyActivity extends AppCompatActivity { // ... private void checkForNewMessages() { // افحص على وجود رسائل جديدة // إذا تم العثور على رسالة جديدة، عرض إشعار if (hasNewMessages()) { showNotification(); } } // ... } تأكد من تعيين القيم المناسبة لكائن NotificationCompat.Builder في دالة showNotification() واستخدم الأساليب المناسبة لتخصيص الإشعار حسب احتياجات تطبيقك.
    من الهام جدًا أن تتذكر أنه بدءًا من Android 8.0 (API level 26)، يجب عليك إنشاء قناة إشعارات (Notification Channel) وتعيينها لكائن NotificationCompat.Builder حتى يتم عرض الإشعار بنجاح.
    وتأكد من استدعاء الدالة createNotificationChannel() في الوقت المناسب، كما تم شرحه في الخطوة 3 في الإجابة السابقة.
     
  22. إجابة Mustafa Suleiman سؤال في سبب خطأ Base table or view already exists في مشروع لارافيل كانت الإجابة المقبولة   
    الخطأ يعني أن الجدول 'posts' موجود بالفعل في قاعدة البيانات ولا يمكن إنشاؤه مرة أخرى، وذلك أمر طبيعي يحدث عندما تحاول تشغيل عملية إنشاء جدول عن طريق التهجير والجدول بالفعل موجود في قاعدة البيانات.
    لذلك الأمر الصحيح هو التالي:
    php artisan migrate:fresh --seed فهو يستخدم في Laravel لإعادة إنشاء وتحديث قاعدة البيانات بالجداول والبيانات الأولية، و يتكون من عدة أجزاء:
    "php artisan": يشير إلى تشغيل أمر Laravel عبر واجهة سطر الأوامر. "migrate:fresh": يعني أنه سيتم إعادة إنشاء كل الجداول في قاعدة البيانات، ويتم حذف جميع الجداول الموجودة في قاعدة البيانات وإعادة إنشائها بناءًا على ملفات الترحيل (migrations) الموجودة في مشروع Laravel. "--seed": يشير إلى أنه سيتم تشغيل ملفات بزر البيانات الأولية (seeds) بعد إعادة إنشاء الجداول، وملفات البزر تستخدم لإضافة بيانات افتراضية أو تجريبية إلى قاعدة البيانات بعد إعادة إنشاء الجداول.
  23. إجابة Mustafa Suleiman سؤال في إضافة ميزة محرر النصوص في تطبيق Flutter لإضافة وتحرير النصوص وإضافة الصور والروابط كانت الإجابة المقبولة   
    في دالة onSave التي قمت بتعريفها  في المثال السابق في RichTextField، قم بتنفيذ الخطوات التالية لحفظ النص والصور والروابط في Firebase:
    استخدم Firebase Auth للتحقق من هوية المستخدم والتأكد من أنه مسجل دخوله. استخدم Firebase Firestore لإنشاء وثيقة جديدة وحفظ النص والصور والروابط في حقول مناسبة، وباستطاعتك تخزين الصور في تخزين Firebase Storage وتخزين روابطها في Firestore، وتخصيص الطريقة التي تحفظ بها البيانات في Firebase حسب طبيعة تطبيقك. مثلاً، لحفظ محتوى المحرر (النص والصور والروابط) في Firebase Firestore، من الممكن تعريف حقول كالتالي:
    حقل "نص" (Text field) لتخزين النص الذي يتم إدخاله أو تحريره. حقل "صورة" (Image field) لتخزين الصورة المحملة من المحرر. حقل "روابط" (Links field) لتخزين الروابط المدخلة.
  24. إجابة Mustafa Suleiman سؤال في حل مشكلة GitHub لا يقبل رفع أكثر من 100 ملف في المرة الواحدة كانت الإجابة المقبولة   
    السبب هو أنك لم تقم بإنشاء ملف باسم  .gitignore والذي يتجاهل كافة الملفات والمجلدات ما عدا الكود المصدري الخاص بالمشروع، أي لا يتم رفع مجلد venv مثلاً فبه البيئة الإفتراضية الخاصة بك وأيضًا المكتبات التي تم تثبيتها.
    ولذلك عليك بإنشاء ملف بالاسم التالي في مجلد المشروع:
    .gitignore ولاحظ وجود نقطة في بداية الاسم، أي ذلك الملف يتم إنشائه بجوار مجلد venv لديك ومجلد taskaty الخاص بالمشروع.
    وضع به التالي:
    ولكن يجب التوضيح نص الملف gitignore التالي خاص ببايثون، وسأقوم بإرفاق ملف خاص بمشاريع الويب في المرفقات أي التي تستخدم HTML, CSS, JS.
    ### Python ### # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] *$py.class # C extensions *.so # Distribution / packaging .Python build/ develop-eggs/ dist/ downloads/ eggs/ .eggs/ lib/ lib64/ parts/ sdist/ var/ wheels/ pip-wheel-metadata/ share/python-wheels/ *.egg-info/ .installed.cfg *.egg MANIFEST .history/ # PyInstaller # Usually these files are written by a python script from a template # before PyInstaller builds the exe, so as to inject date/other infos into it. *.manifest *.spec # Installer logs pip-log.txt pip-delete-this-directory.txt # Unit test / coverage reports htmlcov/ .tox/ .nox/ .coveage .coverage.* .cache nosetests.xml coverage.xml *.cover *.py,cover .hypothesis/ .pytest_cache/ pytestdebug.log # Translations *.mo *.pot # Django stuff: *.log local_settings.py db.sqlite3 db.sqlite3-journal # Flask stuff: instance/ .webassets-cache # Scrapy stuff: .scrapy # Sphinx documentation docs/_build/ doc/_build/ # PyBuilder target/ # Jupyter Notebook .ipynb_checkpoints # IPython profile_default/ ipython_config.py # pyenv .python-version # pipenv # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. # However, in case of collaboration, if having platform-specific dependencies or dependencies # having no cross-platform support, pipenv may install dependencies that don't work, or not # install all needed dependencies. #Pipfile.lock # PEP 582; used by e.g. github.com/David-OConnor/pyflow __pypackages__/ # Celery stuff celerybeat-schedule celerybeat.pid # SageMath parsed files *.sage.py # Environments .env .venv env/ venv/ ENV/ env.bak/ venv.bak/ pythonenv* # Spyder project settings .spyderproject .spyproject # Rope project settings .ropeproject # mkdocs documentation /site # mypy .mypy_cache/ .dmypy.json dmypy.json # Pyre type checker .pyre/ # pytype static type analyzer .pytype/ # profiling data .prof # Virtualenv # http://iamzed.com/2009/05/07/a-primer-on-virtualenv/ .Python [Bb]in [Ii]nclude [Ll]ib [Ll]ib64 [Ll]ocal [Ss]cripts pyvenv.cfg .venv pip-selfcheck.json ثم عليك بتنفيذ الأمر التالي:
    git rm -r --cached من أجل إزالة التعقب عن الملفات والمجلدات التي لا نريد تعقبها كما أشرنا إليها في الملف .gitignore وبعد ذلك قم بإعادة أوامر رفع المشروع وهي:
    1- قم بإضافة كل ملفات المشروع لرفعها من خلال الأمر التالي:
    git add . 2- عمل commit من خلال الأمر التالي:
    git commit -m "Upload files" 3- إضافة العنوان البعيد (remote URL) لمستودع GitHub الخاص بك مع الأمر التالي:
    git remote add origin https://github.com/moazzant226/react.git أخيرًا، استخدم الأمر التالي لرفع التحديثات إلى مستودع GitHub الخاص بك:
    git push -u origin main  
    .gitignore
  25. إجابة Mustafa Suleiman سؤال في من لم يشكر الناس لم يشكر الله كانت الإجابة المقبولة   
    ألف مبروك يا منتصر، وسنك صغير ما شاء الله عليك صراحة، واصل إجتهاد وهتحقق أكتر بكتير إن شاء الله، وركز إنك تتعلم الأساسيات كويس ومتستعجلش إنت لسة صغير وحاول تشتغل على مشاريع بعد الأساسيات ومتركزش أوي على تعلم إطارات العمل والمكتبات وتتجاهل الأساسيات.
    لأنها هي اللي هتخليك تتعلم وتستخدم أي لغة وإطار عمل أو مكتبة بسهولة بعد كدة، وتتعلم أسرع.
    حاول بناء مشروع كبير باللغات الأساسية التي تعلمتها، مثل تنفيذ تطبيق SPA باستخدام HTML, CSS, JS فقط وستتعلم الكثير من ذلك.
×
×
  • أضف...