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

ياسر مسكين

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

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

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

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

    2

كل منشورات العضو ياسر مسكين

  1. بما أنك تستخدم JavaScript في الفرونتأند، فستحتاج إلى تكامل الباك إند (بايثون) مع الواجهة الأمامية باستخدام نقاط النهاية (API) و AJAX، بما أنك لم ترفق ملف الفرونت أند الخاص بك، سأشرح لك عبر مثال عملي لربط الباك إند بالواجهة الأمامية (HTML) باستخدام AJAX. هنا نستخدم أجاكس من أجل إرسال الطلبات واستلام البيانات. فلنفترض أن لديك ملف بايثون اسمه `backend.py` يحتوي على الكود الخاص بالباك إند، وملف HTML اسمه `index.html` للواجهة الأمامية. أولا، تقوم بإنشاء نقطة النهاية في الباك إند، مثلا باستخدام فلاسك تكون بهذا الشكل: from flask import Flask, jsonify, request app = Flask(__name__) @app.route('/api/play', methods=['POST']) def play_game(): decision = request.json.get('decision') # Assuming JSON data is sent # Add your game logic here result = {"result": "Game result based on decision: " + decision} return jsonify(result) if __name__ == '__main__': app.run(debug=True) ثم نستخدم AJAX في ملف HTML (`index.html`)، بهذا الشكل: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Prisoner's Dilemma Game</title> </head> <body> <h1>Prisoner's Dilemma Game</h1> <button id="cooperate-btn">Cooperate</button> <button id="defect-btn">Defect</button> <div id="result"></div> <script> document.getElementById('cooperate-btn').addEventListener('click', function() { playGame(1); }); document.getElementById('defect-btn').addEventListener('click', function() { playGame(0); }); function playGame(decision) { var xhr = new XMLHttpRequest(); xhr.open("POST", "/api/play", true); xhr.setRequestHeader("Content-Type", "application/json"); xhr.onreadystatechange = function () { if (xhr.readyState === 4 && xhr.status === 200) { var response = JSON.parse(xhr.responseText); document.getElementById('result').innerText = response.result; } }; var data = JSON.stringify({"decision": decision}); xhr.send(data); } </script> </body> </html> هنا قمت باستخدام XMLHttpRequest في JavaScript لإرسال طلب POST إلى نقطة نهاية /api/play في الباك إند، ثم قمت بتحديث عنصر div مع النتيجة المستلمة من السيرفر.
  2. لا يوجد جواب سحري لتساؤلك حول إيجاد الفكرة، لكن يمكنني مساعدتك. إيجاد الفكرة الإبداعية قد يكون صعبا خاصة في هذا الوقت، وإنشائها من الصفر، لهذا فأول خطوة يمكنك البدء فيها هي عن طريق عمل نسخ (Clones) لتطبيقات مشهورة أو أفكار موجودة في السوق هذا يمكن أن يوفر لك العديد من الفوائد كفهم عملية التطوير فعند عمل نسخ لتطبيقات مشهورة، ستحصلين على فرصة لفهم كيفية بناء التطبيقات الناجحة وتنظيمها ويمكن أن تتمكني من اكتساب الخبرة العملية خاصة في عملية التطوير وحل المشاكل التقنية. والعديد من المبرمجين والمطورين بدؤوا بهذا الشكل، عن طريق استخدام النسخ التي قاموا بإنشائها ثم قاموا بعرضها كجزء من معرض أعمالهم الشخصي أو الاحترافي، مما عزز من فرص الحصول على عمل مستقبلي. الطريقة الأفضل لإيجاد الأفكار هي عن طريق الخروج إلى الواقع والبحث عن المشاكل التي تواجه الناس، والمؤسسات وتعيق تقدمهم فالتقنية والبرمجة أتت لهذا الغرض لتسهل حياة الناس، وتحل مشاكلهم عن طريق برمجيات نقوم ببرمجتها نحن كمبرمجين.
  3. معرض أعمالك لا يزال جديدا، ويمكنك أن تقوم بالتحسين منه كي يظهر بشكل جيد، على سبيل المثال، إذا كنت ترغب في إظهار مهاراتك في بناء واجهات برمجة التطبيقات (APIs)، يمكنك إنشاء مشروع API بسيط يقوم بإرجاع بيانات حول المستخدمين، مثل اسم المستخدم والبريد الإلكتروني، ويمكنك إنشاء مشروع لإدارة قاعدة بيانات SQLite بواجهة بسيطة تسمح بإضافة وحذف البيانات، وهذا مثال ليس للحصر، يمكنك إضافة أية مشاريع قمت بإنجازها من قبل، وإن لم تكن يمكنك إرفاق هذه المشاريع الصغيرة. النقطة الأهم هي إرفاق كل مشروع بملف README.md بحيث يكون يحتوي على تفاصيل المشروع وكيفية استخدامه. فمثلا في حالة وضع مشروع ال API، يمكن توضيح كيفية استخدام كل نقطة نهاية (endpoints) مع البيانات المتوقعة للإرجاع. اللمسة السرحية في البرمجة هي استخدام أساليب "Clean Code" لجعل الأكواد البرمجية أكثر تنظيما. الكثيرون لا يعرفون كيفية إنشاء ملف README جيد، عليك أن تضبطه بحيث تقوم بشرح كيفية تثبيت المشروع وتشغيله واستخدامه بشكل واضح ومبسط، حتى أنه يمكن إضافة صور شاشة لتوضيح كيفية عمل التطبيق. لاحظت أنك عملت عدة Commits لكن يبدو أنها غير منتظمة، لهذا الحساب الجيد يمكنك الحرص عليه من خلال عمل Commits منتظمة وواضحة مع رسائل شرح للتغييرات التي قمت بها أو تلك التي قمت بإضافتها أو أضافها زملاؤك في المشروع. وبعد أن تتمكن جيدا يمكنك نشر مشاريعك عبر منصات الاستضافة السحابية لتمكين الآخرين من تجربتها أو المساهمة فيها.
  4. أي متصفح تعمل عليه؟ العديد من المستخدمين واجهوا عدة مشاكل عند العمل ب Google Chrome ولم تكن يظهر لهم تبويب ال Keys حاول أن تغير المتصفح إلى سفاري. في حالة ذلك هذه هي الطريقة الأصح والآمنة للحصول على المفتاح: يجب أن تمتلك صلاحيات الأدمين وتكون مالك الحساب الفعلي كي تظهر لك التبويبة. يمكنك التوجه إلى تبويب: المستخدمون والوصول ثم حينما تظهر لك قائمة المفاتيح يمكنك النقر فوق الزر "+" لإنشاء المفتاح بسهولة. يمكنك إعطاؤه اسما ودورا وتحديد المهام المنوطة إليه. في حال لم يعمل معك توجد طريقة أخرى عبر التوجه مباشرة إلى تبويب: Integration ثم سيظهر لك زر طلب المفتاح وطلبه مباشرة، هي تظهر لأغلب المستخدمين في أغلب المتصفحات.
  5. بالطبع يجب أن تقوم ببعض التعديلات كي تعمل خاصية ال Height بشكل عادي، يمكنك استخدام قيمة `auto` لارتفاع العنصر الأساسي (`main`) بدلا من `max-content` أو `()minmax`، مع تعيين `height` للعنصر الأب (`wrapper`) ليكون بنفس ارتفاع العنصر الأساسي. ههذا سيؤدي إلى تحقيق الهدف أيضا يمكنك التعديل عليه بهذا الشكل: * { box-sizing: border-box; } .wrapper { display: grid; grid-template-columns: repeat(5, 1fr); grid-template-areas: "main main main aside aside"; gap: 20px; height: auto; } .main { background-color: red; grid-area: main; min-height: 400px; height: auto; } .aside-bar { background-color: blue; grid-area: aside; } بهذا التعديل، العنصر الأساسي (`main`) سيحصل على ارتفاع مرن بناء على احتياجات المحتوى، في حين يكون ارتفاع العنصر الأب (`wrapper`) متناسبا مع ارتفاع العنصر الأساسي.
  6. بالطبع، يمكنك تعريف الكلاس (Class) داخل دالة (Function) في Python فهذا يعتبر من الأمور الممكنة في لغة Python بسبب طبيعتها الديناميكية وقابليتها للتعامل مع العديد من الهياكل المرنة، وهذا مثال ممكن على ذلك: def create_class(): class MyClass: def __init__(self, name): self.name = name def greet(self): print("Hello,", self.name) return MyClass # تعريف الكلاس باستخدام الدالة MyClass1 = create_class() obj1 = MyClass1("Yasse") obj1.greet() # سيطبع: Hello, Yasser # تعريف كلاس جديدة MyClass2 = create_class() obj2 = MyClass2("Yasser") obj2.greet() # سيطبع: Hello, Yasser ففي هذا المثال، تم تعريف الفئة `MyClass` داخل الدالة `()create_class`. ثم تم إرجاع هذه الفئة من الدالة. وعند استدعاء `()create_class`، يتم إنشاء فئة جديدة في كل مرة. وهذا ما يسمح بإنشاء عدة فئات مختلفة باستخدام نفس التعريف الأساسي.
  7. المشكلة تكمن في كون TinyMCE لا يقوم بتوليد اللغة تلقائيا، لذلك يجب عليك النظر في حزم اللغات الخاصة به عبر هذا الرابط من أجل تغيير واجهة المستخدم الخاصة بـ TinyMCE للعربية: https://www.tiny.cloud/docs/configure/localization/#language بحيث يمكنك تحميلها والعمل بها في مشروعك بشكل عادي: https://www.tiny.cloud/get-tiny/language-packages/ ولأنه لا يوجد قيمة افتراضية لخيار content_langs فإذا لم يتم تحديد قيمة، فإن زر شريط الأدوات وعنصر القائمة للغة لن يكون متاحا، توفر إضافة Spell Checker Pro قيمة افتراضية لهذا الخيار. وهذا مثال على استخدام content_langs: tinymce.init({ selector: 'textarea', // قم بتغيير هذا وفقًا لـ HTML الخاص بك toolbar: 'language', content_langs: [ { title: 'الإنجليزية', code: 'en' }, { title: 'الإسبانية', code: 'es' }, { title: 'الفرنسية', code: 'fr' }, { title: 'الألمانية', code: 'de' }, { title: 'البرتغالية', code: 'pt' }, { title: 'الصينية', code: 'zh' } ] }); أما بخصوص التوجيه أو ال directionality: فيوجد خيار لهذا بالفعل، ويسمح لك بتحديد الاتجاه الأساسي للنص الذي لا يحمل توجيها محددا (أي النص الذي لا يحمل توجيها ثابتا كما هو معرف في Unicode) داخل المحرر. هذا يشبه استخدام السمة 'dir' عند استخدام عناصر قابلة للتحرير بمفردها. القيم الافتراضية: 'ltr' القيم الممكنة: 'ltr', 'rtl' وهذا مثال على استخدام ال directionality: tinymce.init({ selector: 'textarea', // قم بتغيير هذه القيمة وفقًا لـ HTML الخاص بك directionality : 'ltr' }); ويحدد هذا الخيار اللغة المستخدمة لواجهة مستخدم TinyMCE، مثل عناصر القائمة والحوارات والتلميحات. بشكل افتراضي، بحيث يتم تعيين واجهة مستخدم TinyMCE باللغة المعينة. وفي حال واجهت مشاكل أكثر يوجد بدائل تم ذكرها ومناقشتها في هذا الرابط:
  8. شكرا على إرفاقك لملفات المشروع. لقد تصفحتها، ووجدت أن المشكلة تكون بعد الضغط على أي منتج لتصفحه، هنا يظهر لك الخطأ الأول وهو عبارة عن خطأ [ERR_HTTP_HEADERS_SENT]: ويعني أنه لا يمكن تعيين الرؤوس بعد إرسالها إلى العميل في errorMiddleware.js ويحدث هذا الخطأ عادة عند محاولة إرسال أكثر من استجابة واحدة لطلب واحد، وغالبًا ما يكون السبب في ذلك هو إرسال استجابة في middleware أو معالجات الطرق ثم محاولة إرسال استجابة أخرى لاحقًا. حللت المشكلة من خلال التأكد من إرسال استجابة واحدة فقط لكل طلب، وهنا في ` ، نقوم بتجنب إرسال استجابة إذا تم بالفعل إرسال الرؤوس.من خلال إضافة هذين السطرين في برمجية errorHandler في ملف errorMiddlware.js: if (res.headersSent) { return next(err); // تمرير الخطأ إلى middleware التالي إذا تم بالفعل إرسال الرؤوس } بهذا الشكل: const errorHandler = (err, req, res, next) => { if (res.headersSent) { return next(err); // تمرير الخطأ إلى middleware التالي إذا تم بالفعل إرسال الرؤوس } let statusCode = res.statusCode === 200 ? 500 : res.statusCode; let message = err.message; res.status(statusCode).json({ message: message, stack: process.env.NODE_ENV === "production" ? null : err.stack, }); }; export { errorHandler }; بعد حل المشكل يظهر الخطأ التالي كما هو موضح في الصورة، وهو متعلق بالمورد فهو غير موجود والخطأ يكمن في ملف productController.js، ويحدث هذا الخطأ عندما يُتوقع وجود مورد (في هذه الحالة ، هو عبارة عن منتج) ولكنه لا يتم العثور عليه.لضمان التعامل الصحيح مع الأخطاء وإرجاع الاستجابات المناسبة عند عدم العثور على الموارد، يمكن تصحيح الكود من خلال استرداد المنتج باستخدام ال Id بالشكل الصحيح بهذا الشكل في ملف productController.js، import asyncHandler from "../middlewares/asyncHandler.js"; import Product from "../models/productModel.js"; /** * desc Fetch All Products * route Get /api/products * access Public */ const getProducts = asyncHandler( async(req, res) => { const products = await Product.find({}) res.json(products) }); /** * desc Fetch Product By Id * route Get /api/products/id * access Public */ const getProductById = asyncHandler(async (req, res) => { const product = await Product.findById(req.params.id); if (product) { res.json(product); return; // Add return here to exit the function after sending the response } res.status(404).json({ message: 'Resource not found' }); // Use 404 status for resource not found }); export { getProducts, getProductById }; وهكذا لن تظهر أي مشكلة.
  9. الخوارزمية التي أعددتها جيدة بشكل عام هي تقوم بعرض مكونات اللعبة الرئيسية، ثم تقوم تحديد الإجراءات بناءً على المدخلات، فيتم التحقق من الزر الذي يتم الضغط عليه وتحديد الإجراء المناسب، أما بالنسبة لتحديد الحركة فيكون ذلك اعتمادا على الزر المضغوط وبناء عليه يتم توجيه حركة الدبابة، وإذا تم الضغط على زر المسطرة، تظهر قذيفة الدبابة وتتحرك في نفس الاتجاه الذي كانت تتجه إليه الدبابة. وفي النهاية يتم التحقق مما إذا تم تدمير الدبابات الصغيرة أو لا وفقا لعدد مرات اللمس. هل هي على هذا النحو؟ بالنسبة للخوازمية بشكل عام يمكنك تحسينها من خلال إضافة مستويات صعوبة متعددة للعبة، مثل زيادة عدد الدبابات الصغيرة أو زيادة سرعة حركتها، مما يجعل اللعبة أكثر تحديًا وإثارة، يمكنك كتطوير لها مثلا أن تقوم بتصميم بيئة متعددة الأبعاد بحيث تتيح للاعب استكشاف بيئة ثلاثية الأبعاد أو بيئة أكثر تفاعلية، مما يجعل التجربة أفضل.
  10. توجد العديد من المواقع والمنصات التي يمكن التعلم منها، لكني شخصيا أفضل مقالات الأكاديمية لأنها تقدم شرحا مبسطا وشاملا وكافيا يغنيني من تشعب الدروس من موقع إلى آخر، يمكنك مثلا إيجاد ما تبحث عنه حول لغة جافا سكريبت في هذه المقالات: https://academy.hsoub.com/programming/javascript ومن خلال هذه المقالة يمكنك تعلم أساسيات البحث وخوارزميات البحث المختلفة:
  11. أتمنى إرفاق الكود كاملا لتجربته كي أفحصه جيدا. بشكل عام، الخطأ في الكود هنا نشأ عندما تمت محاولة تعيين رأس الاستجابة بعدما تم بالفعل إرسال الاستجابة إلى العميل، ففي الكود يتم استخدام دالة `()res.status().json` لإرسال الرد في `errorHandler` عند حدوث خطأ ال middleware. فالمشكلة تتضمن التالي: الموقع: يمكن تحديده من خلال المسار الذي يشير إليه الخطأ. في هذه الحالة، يتم إظهار الموقع كمسار الملف `errorMiddleware.js`. الخطأ: يتم توضيح الخطأ الذي يحدث. في هذه الحالة، يشير الخطأ إلى أنه لا يمكن تعيين رأس الاستجابة بعد إرسالها للعميل، والذي يُطلق الاستثناء `Error [ERR_HTTP_HEADERS_SENT]`. حاولت أن أشرح رسالة الخطأالتي ظهرت فعند حدوث خطأ في التطبيق، يتم استدعاء `()res.status().json` في ملف `errorMiddleware.js` لإرسال استجابة JSON. ومع ذلك، يحدث خطأ "Cannot set headers after they are sent to the client" لأن الاستجابة قد تم بالفعل إرسالها، وبالتالي يتعذر تعيين رأس الاستجابة مرة أخرى. ولتجنب هذا الخطأ، يُنصح بالتحقق مما إذا كانت الرؤوس قد تم إرسالها بالفعل قبل تعديلها. يمكن ذلك عن طريق التحقق من خاصية res.headersSent فإذا لم تكن الرؤوس قد تم إرسالها بالفعل، يمكن تعديل الاستجابة بشكل طبيعي، وإلا فإنه يُستدعى () next لتمرير التحكم إلى المنطقة التالية في سلسلة وسائط Express. وهذا هو الكود الصحيح: const errorHandler = (err, req, res, next) => { let statusCode = res.statusCode === 200 ? 500 : res.statusCode; let message = err.message; if (!res.headersSent) { res.status(statusCode).json({ message: message, stack: process.env.NODE_ENV === "production" ? null : err.stack, }); } next(); }; export { errorHandler }; ويمكنك استخدامه للتحقق مما إذا كانت الرؤوس قد تم إرسالها بالفعل قبل تعديلها، وفقط إذا لم تكن قد تم إرسالها بالفعل، وهنا يتم تعديل الاستجابة وإرسالها إلى العميل بشكل عادي.
  12. بالطبع يمكن إنشاء بوت داخل الواتساب باستخدام Python، بحيث يكون لهذا البوت القدرة على قراءة الرسائل والتفاعل معها باستخدام بعض المكتبات، مثل: pywhatkit: تُستخدم لإرسال واستقبال الرسائل عبر واتساب. twilio: تستخدم للاتصال بخدمات الرسائل النصية، بما في ذلك واتساب. whatsapp-web: تستخدم للتفاعل مع واجهة واتساب عبر الويب. selenium: تستخدم للتحكم في المتصفح وتنفيذ الإجراءات التفاعلية على واجهة واتساب عبر الويب. وهذا مثال عملي باستخدام pywhatkit بحيث سننشئ به بوتا بسيطا يقوم بالترحيب بالمستخدمين الجدد: import pywhatkit def reply_to_message(message): if message.lower() == "مرحبا": return "مرحبا! كيف يمكنني مساعدتك؟" else: return "آسف، لم أفهم ما تعنيه. يمكنك محاولة شيء آخر." def receive_and_reply(): while True: message = input("أدخل رسالتك: ") reply = reply_to_message(message) print("الرد:", reply) receive_and_reply() هذه فكرة بسيطة عن كيفية استخدام Python ومكتبة pywhatkit لإنشاء بوت بسيط يستجيب لرسائل WhatsApp. وهنا تساؤل ونقاش مفيد جدا حول كيفية إنشاء بوت واتساب باستخدام إطار دجانغو أعتقد أنه سيفيدك كثيرا:
  13. مشكلة "Travelling Salesman Problem" أو (مشكلة البائع المتجول) هي إحدى أشهر المشكلات في عالم البرمجة وعلوم الحاسوب، فهي تمثل مشكلة تحديد أقصر مسار يمر عبر مجموعة من النقاط (مثل المدن أو العقد) مرة واحدة وثم العودة إلى النقطة الأصلية، هذه المشكلة تندرج ضمن مجال الرياضيات وعلم الحاسوب، وهي مشكلة معروفة في الأمثلة التجارية والصناعية أيضا. للإجابة عن تساؤلك، يمكنني أن أقول بأن المشكلة معروفة بصعوبتها في إيجاد الحل الأمثل بسبب طبيعتها التصاعدية، حيث تزداد صعوبة حساب الحل بزيادة عدد النقاط. على سبيل المثال، عندما يكون هناك عدد صغير من النقاط، فإنه من الممكن حساب كل الطرق المحتملة واختيار الأمثل. ولكن مع زيادة عدد النقاط، يصبح عدد الطرق الممكنة كبيرا، وبالتالي يصبح من الصعب بشكل كبير حساب الحل الأمثل في وقت معقول. من الجدير بالذكر أنه لا يوجد حتى الآن خوارزمية فعالة تعطي الحل الأمثل للمشكلة في زمن معقول بغض النظر عن عدد النقاط لهذا يتم التركيز على تطوير خوارزميات تقريبية تقدم حلول جيدة بالقرب من الحل الأمثل دون الحاجة إلى استكشاف كل الطرق المحتملة. أعتقد أنني أجبت عن استفسارك.
  14. لا يمكن معرفة المشكلة إلا من خلال تحليل كامل وعملي، فمن الممكن أن تكون المشكلة التي تواجهها ناتجة عن عدة عوامل مختلفة، لهذا يجب أن نتبع عدة خطوات أيضا لمعرفة المشكلة بالضبط: أولا، يمكنك البدء بالتحقق من الاضافات، فقد تواجه مشكلة في التوافق بين إضافات أخرى قد تؤثر على عمل Elementor. كحل كنت أستخدمه من قبل وهو تجربة تعطيل جميع الإضافات الأخرى. ثم يمكنك التحقق من القالب الحالي، فقد يكون هناك تضارب بين القالب الحالي والإضافة ربما سينفع أن تجرب استخدام قالب افتراضي مثل Twenty Twenty-One والتحقق مما إذا كانت المشكلة مستمرة. قد ينفع أيضا التحقق من النسخة الحالية من Elementor وWordPress و التأكد من أنك تستخدم أحدث نسخة منهما يمكن أن يحل التحديث المشكلة في بعض الأحيان. أيضا كحل مقترح هو تفعيل وتعطيل الإعدادات الخاصة بالجوال في Elementor فقد يكون هناك إعدادات خاصة بالجوال قمت بتعطيلها عن طريق الخطأ لهذا ينصح بالتحقق من إعدادات الجوال والتأكد من أنها مفعلة بشكل صحيح. البعض لا يفضل التعامل مع هذه المشاكل ويتوجه مباشرة إلى الدعم الخاص بالإضافة فأحيانا يكون المشكل منهم مباشرة ويتم حله في أقرب وقت ممكن.
  15. إحدى الطرق الأخرى التي يمكن استخدامها لتوفير ملفات CSS و JavaScript على المدونة في Bloggerهي عن طريق استخدام خدمة الاستضافة المجانية GitHub Pages بدلا من Google Drive: يمكنك أولا، إنشاء مستودع على GitHub. ثم إنشاء مستودع جديد لملفات CSS و JavaScript الخاصة بك. ثم تقوم برفع ملفات CSS و JavaScript إلى مستودع GitHub. بمجرد رفع الملفات، تقوم بالانتقال إلى كل ملف والنقر على الزر "Raw" للحصول على رابط مباشر للملف. بعدها ستكون قادرا على تضمين الملفات في مدونتك على Blogger بسهولة من خلال: فتح Blogger والانتقال إلى تحرير القالب الذي تريد تعديله. استخدام عناصر `<link>` لتضمين ملفات CSS وعناصر `<script>` لتضمين ملفات JavaScript في القالب، واستخدام روابط الملفات التي حصلت عليها من GitHub. بعدها تقوم بحفظ التغييرات، فبمجرد إضافة الروابط وتعديل القالب، يجب أن تحفظ التغييرات ويمكنك أن تعاين المدونة للتأكد من عمل الملفات بشكل صحيح.
  16. عندما ننشئ كلاس باستخدام الكلمة الأساسية "abstract" قبل تعريف الكلاس، فإننا نقوم بإنشاء كلاس يُعرف كـ "abstract class" وهذا النوع من الكلاسات لا يمكن إنشاء كائنات منها مباشرة، بل يستخدم فقط كقالب للتمديد من قبل كلاسات أخرى. في الكلاس الذي يتم تعريفه كـ "abstract class"، يمكن أن يحتوي على طرقٍ (methods) مجردة (abstract methods)، وهي طرق لم يتم تقديم تنفيذ لها داخل الكلاس نفسه. بدلاً من ذلك، يترك تنفيذ هذه الطرق للكلاسات التي تمتد من الكلاس الـ "abstract". لتعريف كلاس بشكل مبسط باستخدام الـ "abstract"، وبما أنك لم تحدد لغة البرمجة فيمكن استخدام الكود التالي بلغة Java لفهم المبدء جيدا: abstract class Shape { // مثال على طريقة مجردة abstract double area(); // مثال على طريقة غير مجردة void display() { System.out.println("This is a shape."); } } class Circle extends Shape { double radius; Circle(double r) { radius = r; } // تنفيذ الطريقة المجردة double area() { return Math.PI * radius * radius; } } class Main { public static void main(String[] args) { Circle circle = new Circle(5); circle.display(); System.out.println("Area of the circle: " + circle.area()); } } وفي هذا المثال قمت باستخدام كلاس مجرد "Shape" لتحديد سلوك عام للأشكال الهندسية، مع ترك تنفيذ الطرق الخاصة بكل شكل محدد (مثل الدائرة في هذه الحالة) للكلاسات التي تمتد من "Shape".
  17. لأنه عند استخدامنا لدالة `merge` في C++ وكانت البيانات الداخلة مرتبة بالفعل، فإن الناتج سيكون أيضا مرتبا، وهذا يعني أنه عند دمج `firstnumbers` و `secondnumbers` في `total`، سيتم ترتيب الأرقام بشكل طبيعي. السبب الرئيسي لذلك هو أن `merge` لا تقوم فقط بدمج العناصر بل تقوم بترتيبها أثناء الدمج. في الحقيقة، الدالة `merge` تتوقع أن يكون كل من `firstnumbers` و `secondnumbers` مرتبا مسبقا، وتقوم بالمزامنة بين القيم في كل فهرس لإنتاج فهرس مرتب. ففي الكود التي قدمته، الأرقام في `firstnumbers` و `secondnumbers` مرتبة بالفعل بشكل صاعد، لهذا فإن الدالة `merge` ستقوم بدمجها بشكل مرتب في `total`.وهذا هو السبب في أن الناتج النهائي كان مرتبًا بشكل صاعد. بمعنى آخر، الترتيب الذي حصلت عليه هو نتيجة مباشرة من طريقة عمل دالة `merge` والتي تتوقع بدورها بأن البيانات المدخلة مرتبة بالفعل.
  18. حسنا سأشرح لك الأمر والفرق، ال GitHub هو موقع يستخدمه المطورون لتحميل وإدارة مشاريعهم البرمجية، بحيث يمكننا كمطورين أن نقوم برفع ملفات المشروع إلى GitHub وإدارتها باستخدام نظام التحكم في الإصدارات Git، على سبيل المثال يمكن استخدام خدمة GitHub Pages المدمجة لنشر موقع ما على الويب مجانا. بحيث نحصل على رابط مشابه لهذا: `https://username.github.io`. أما بالنسبة للاستضافة التقليدية ووضع الدومين، فهذا يعني استخدام خدمات الاستضافة المدفوعة لوضع الموقع على الإنترنت وطريقة عمله بسيطة بحيث نشتري خدمة استضافة ونحصل مقابلها على مساحة على الخادم لوضع موقعنا عليه أي أنه يمكن شراء دومين بمعنى (عنوان الموقع على الإنترنت) وربطه بموقعنا، والرابط المخصص الذي سنحصل عليه سيكون على هذا الشكل: `https://www.yourdomain.com`. أما فيما يتعلق بـ SEO (تحسين محركات البحث)، يمكن استخدام GitHub Pages بنجاح لأن محركات البحث تتعامل معها بشكل جيد تمامًا كما تفعل مع مواقع الويب الأخرى. لذا، بإمكاننا تقديم رابط GitHub لعملية SEO دون مشاكل كبيرة، ولكن يجب أن نعرف أن GitHub قد يكون له بعض القيود بالمقارنة مع الاستضافة التقليدية، وهذا يعتمد على احتياجات مشروعنا.
  19. الخوارزميةالتي قدمتها هي عبارة عن وصف مكتوب يصف واجهة لعبة برمجيةوتبدو صحيحة، حسبما فهمته فهو يتضمن تحكما بحركة القط داخل متاهة معينة، حيث يمكن للمستخدم التحكم في حركة القط باستخدام أسهم لوحة المفاتيح، مع وجود تفاعلات معينة عند اصطدام القط بجدران المتاهة أو عند وصوله إلى قطعة الخبز. بصراحة لعبة جميلة، حاولت تجسيدها باستخدام لغة البرمجة بايثون، وهذا تجسيد بسيط للواجهة المحتملة للعبتك باستخدام مكتبة Pygame أين يتم عرض القط والمتاهة دون تفاصيل تفاعلية كبيرة فقط كي نفهم الوصف الذي قدمته: import pygame import sys # تهيئة Pygame pygame.init() # الألوان WHITE = (255, 255, 255) BLACK = (0, 0, 0) # حجم الشاشة SCREEN_WIDTH = 800 SCREEN_HEIGHT = 600 # إنشاء النافذة screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) pygame.display.set_caption("Cat Maze Game") # تحميل الصور cat_image = pygame.image.load("cat.png") # يجب تغيير اسم الملف وتوفره maze_image = pygame.image.load("maze.png") # يجب تغيير اسم الملف وتوفره cheese_image = pygame.image.load("cheese.png") # يجب تغيير اسم الملف وتوفره # الموقع الابتدائي للقط وقطعة الجبن cat_x = 50 cat_y = 50 cheese_x = 700 cheese_y = 500 # حلقة اللعبة while True: screen.fill(WHITE) # رسم المتاهة والقط وقطعة الجبن screen.blit(maze_image, (0, 0)) screen.blit(cat_image, (cat_x, cat_y)) screen.blit(cheese_image, (cheese_x, cheese_y)) # التحقق من الأحداث for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() # تحديث الشاشة pygame.display.flip()
  20. المشكلة في الكود السابق هي أنه تم استخدام قيم مختلفة في الـ "attribute " name لعناصر الـ radio button، مما أدى إلى عدم تكونها جزءا من نفس المجموعة، يجب أن يكون لجميع الـ radio buttons نفس القيمة في الـ "attribute "name لتحقيق السلوك المطلوب. وهذا هو الكود المصحح: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Registration Form</title> </head> <body> <h1>Registration Form</h1> <form> <table> <tr> <td> <label for="username">Username</label> </td> <td> <input type="text" id="username"><br> </td> </tr> <tr> <td> <label for="pwd">Password</label> </td> <td> <input type="password" id="pwd" name="pwd"><br> </td> </tr> <tr> <td> <label>Registration Plan</label> </td> <td> <div> <input type="radio" id="starter" name="plan" value="starter"> <label for="starter">Starter</label> </div> <div> <input type="radio" id="business" name="plan" value="business"> <label for="business">Business</label> </div> <div> <input type="radio" id="premium" name="plan" value="premium"> <label for="premium">Premium</label> </div> </td> </tr> <tr> <td> <label for="description">Description</label> </td> <td> <textarea name="description" id="description" cols="30" rows="10"></textarea> </td> </tr> <tr> <td> <label for="agree">Agree</label> </td> <td> <input type="checkbox" id="agree" name="agree"> <label for="agree">I agree to terms and conditions</label> </td> </tr> <tr> <td colspan="2"> <input type="submit" value="Register"> <input type="button" value="Clear"> </td> </tr> </table> </form> </body> </html> وفيه تم تصحيح الكود بحيث تم توحيد قيم الـ "attribute "name لعناصر الـ radio button لتكون "plan" لجميع العناصر، مما جعلها جزءا من نفس المجموعة كما قمت بإضافة عناصر <tr> لكل صف في الجدول لتوضيح هيكل البيانات بشكل أفضل.
  21. بعد تحميلك للمشروع من غيتهاب، يمكنك فتح المجلد في Visual Studio Code، تضغط على Open File ثم اختر المجلد المطلوب، بعد ذلك، تقوم بفتح ال Terminal ثم تقوم بتثبيت ال Packages التي يعمل بها المشروع، من خلال هذا ال Command: npm install يجب أن تتأكد من أنك ضمن المشروع المحدد كما في الصورة. ثم يمكنك تشغيل المشروع من خلال هذا ال Command: npm start في حالة ما واجهتك أي مشكلة بعد هذه الخطوة، اترك لي تعليق هنا وسأساعدك في حله.
  22. من أجل تحميل البيانات من قاعدة البيانات إلى ListBox في التطبيق، يمكن استخدام دورة للحلقة (loop) على البيانات التي تريد عرضها في ListBox وإضافتها واحدة تلو الأخرى. هناك عدة طرق لفعل ذلك، لو نتحدث عن الطريقة التي تستخدم الحلقة foreach فسيكون الكود كالتالي: lbx_work_history.Items.Clear(); // يجب مسح العناصر الحالية أولاً لتحديثها foreach(var item in p.SPECIALIST_WORKED_BEFORE) { lbx_work_history.Items.Add(item); // إضافة كل بند من البيانات إلى ListBox } وهنا يفترض أن `p.SPECIALIST_WORKED_BEFORE` هو مصفوفة أو قائمة تحتوي على البيانات التي تريد عرضها في ListBox، لكن هنا يجب أن نقوم بتعديل هذا الجزء من الكود بناء على كيفية تنظيم البيانات في قاعدة البيانات الخاصة بك وبعد تطبيق هذا التغيير، من المفترض أنه سنتمكن من عرض البيانات في ListBox بعد تحديد سجل معين في DataGridView.
  23. الكود الذي قدمته ناقص قليلا، وذلك لأنه يبدو أنك نسيت توجيه الليست بوكس إلى القيم التي تريد إضافتها إلى حقل `SPECIALIST_WORKED_BEFORE`. لهذا يمكنك استخدام حلقة `foreach` لتكرار عناصر الليست بوكس وإضافتها إلى الحقل المناسب. بهذه الطريقة: formes.DB.TBL_SPECIALIST p = new formes.DB.TBL_SPECIALIST(); p.SPECIALIST_DATE = DateTime.Now; p.SPECIALIST_NAME = edt_name.Text; p.SPECIALIST_BIRTHDATE = edt_brith_date.Value; p.SPECIALIST_AGE_NOW = edt_age.Text; p.SPECIALIST_EDUCATION = edt_education.Text; p.SPECIALIST_ID_NUMBER = edt_id_num.Text; p.SPECIALIST_PHONE = edt_phone.Text; p.SPECIALIST_ADDRESS = edt_address.Text; p.SPECIALIST_ACTIVE = edt_active.Text; فهنا قد استخدمت حلقة foreach لإضافة عناصر الليست بوكس إلى الحقل المناسب: foreach (var item in lbx_work_history.Items) { p.SPECIALIST_WORKED_BEFORE += item.ToString() + ", "; } // الآن يمكن إضافة الكائن p إلى الداتا تابل ويجب التأكد من تغيير "SPECIALIST_WORKED_BEFORE" بناءً على نوع البيانات في الداتا تابل. لكن تبقى هذه الطريقة تقليدية، فبالطبع، يمكن تحسين الكود ببعض الطرق، منها استخدام StringBuilder بدلاً من الانضمام المتكرر للنصوص، وكذلك تجنب استخدام foreach إذا كنت تستخدم LINQ وبناء النص بطريقة أكثر إتقانًا. بهذا الشكل: formes.DB.TBL_SPECIALIST p = new formes.DB.TBL_SPECIALIST() { SPECIALIST_DATE = DateTime.Now, SPECIALIST_NAME = edt_name.Text, SPECIALIST_BIRTHDATE = edt_brith_date.Value, SPECIALIST_AGE_NOW = edt_age.Text, SPECIALIST_EDUCATION = edt_education.Text, SPECIALIST_ID_NUMBER = edt_id_num.Text, SPECIALIST_PHONE = edt_phone.Text, SPECIALIST_ADDRESS = edt_address.Text, SPECIALIST_ACTIVE = edt_active.Text, SPECIALIST_WORKED_BEFORE = string.Join(", ", lbx_work_history.Items.Cast<object>()) }; هنا هذا الكود يستخدم مباشرة LINQ لتجنب استخدام حلقة foreach، ويستخدم StringBuilder ضمن ()string.Join تحت الغطاء للأداء الأفضل في حالة وجود عدد كبير من العناصر.
  24. بالطبع يمكن تحقيق ذلك في لغة JavaScript كما فعلت أنت: let arry = ['****', '***', '**', '*']; for (let value of arry) { console.log(value); } فهذا الكود ينشئ مصفوفة `arry` تحتوي على سلسلات نجوم، ثم يستخدم حلقة `for...of` للتكرار عبر العناصر في المصفوفة ويقوم بطباعة كل قيمة في المصفوفة.
  25. حسنا، توجد عدة مكتبات للترجمة في Vue.js، وتختلف في الميزات والاستخدام لهذا فالاختيار يعتمد على احتياجات مشروعك ومستوى التكامل المطلوب، بعض المكتبات الشهيرة: Vue I18n: وهي المكتبة الرسمية للترجمة في Vue.js. VeeValidate: بالإضافة إلى التحقق من البيانات، توفر VeeValidate أيضا دعما للترجمة لرسائل التحقق. Vue-Translate: تقدم وظائف بسيطة للترجمة. Vue-Multilanguage: توفر طريقة بسيطة لإضافة دعم للغات متعددة داخل التطبيق. ولتضمين أيٍ من هذه المكتبات في مشاريعنا، يمكن اتباع هذه الخطوات: تثبيت المكتبة: من خلال استخدام npm أو yarn لتثبيت المكتبة التي نرغب في استخدامها. على سبيل المثال:، `npm install vue-i18n` من أجل تثبيت Vue I18n. ولاستيرادها في المشروع: نتوجه إلى ملف الدخول الرئيسي للتطبيق (مثل main.js)، ثم نقوم بتضمين المكتبة عن طريق استيرادها. استخدامها في مكونات Vue: نقوم بتكوين واستخدام مكتبة الترجمة وفقا للتوثيقات والأمثلة المقدمة من قِبل المكتبة. هذا مثال على كيفية استيرادها في المشروع: import Vue from 'vue'; import VueI18n from 'vue-i18n'; Vue.use(VueI18n); وهذا مثال آخر على كيفية استخدامها في مكونات Vue: على سبيل المثال نقوم بإنشاء ملف للرسائل المترجمة مثل `messages.js` ونملؤه بالرسائل لكل لغة: // messages.js export default { en: { greeting: 'Hello!', welcome: 'Welcome to my Vue.js app.' }, ar: { greeting: 'مرحبًا!', welcome: 'مرحباً بك في تطبيقي Vue.js.' } }; بعدها نباشر في تكوين الترجمة، في ملف `main.js`، نقوم بتكوين VueI18n وتحميل الرسائل المترجمة: import Vue from 'vue'; import VueI18n from 'vue-i18n'; import messages from './messages'; Vue.use(VueI18n); const i18n = new VueI18n({ locale: 'en', // اللغة الافتراضية fallbackLocale: 'en', // اللغة الاحتياطية messages, // الرسائل المترجمة }); new Vue({ i18n, render: h => h(App) }).$mount('#app'); كما يمكن استخدام الترجمة في مكونات Vue الخاصة بنا عن طريق فلاتر معينة (filters) أو دوال خاصة بالترجمة. وهنا مثال على استخدامها في قالب: <template> <div> <p>{{ $t('greeting') }}</p> <p>{{ $t('welcome') }}</p> </div> </template>
×
×
  • أضف...