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

Mustafa Suleiman

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

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

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

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

    264

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

  1. إجابة Mustafa Suleiman سؤال في معالجة الخطأ التالي [section] is not a <Route> component. All component children of <Routes> must be a <Route> or <React.Fragment> في react-router-dom كانت الإجابة المقبولة   
    المشكلة بسبب وجود عنصر <section> كفرع مباشر لعنصر <Routes> داخل الكود، وفي React Router v6، يجب أن تحتوي عناصر <Routes> على عناصر <Route> فقط أو <React.Fragment> كعناصر داخلية أو كأطفال childrens.
    لذلك عليك باستخدام <Route> للـ <section> أيضًا بدلاً من وضع <Routes> داخل <section>.
    import { Route, Routes } from 'react-router-dom'; function App() { return ( <> <Navbar /> <Routes> <Route path="/" element={<Landing />} /> <Route path="/login" element={<Login />} /> <Route path="/register" element={<Register />} /> </Routes> </> ); } وبالتالي ولم يعد هناك <Routes> داخل <section> وتم وضع جميع الـ <Route> مباشرة داخل <Routes> الرئيسي، مما سيحل مشكلة الخطأ الذي كنت تواجهه.
    https://reactrouter.com/en/6.15.0/upgrading/v5
  2. إجابة Mustafa Suleiman سؤال في اقتراحات مواقع تساعدك في عمل موقع لشركتك وتخصيصها كمبرمج front end كانت الإجابة المقبولة   
    ما علاقة موقع سلة بالأمر، سلة هي منصة لإنشاء مواقع التجارة الإلكترونية وتوفر قوالب للتعديل عليها من خلال CSS وJS.
    لا يوجد منصة توفر لك أنت ترفع موقعك الخاص وتوفير بوابة دفع لك، وإذا أردت يمكنك تطوير قالبك على متجر سلة وقد تم شرح الأمر هنا:
    أفضل وأشهر بوابات الدفع أما إذا أردت إنشاء موقع من خلال HTML, CSS, JS فعليك برفعه على استضافة حتى لو مجانية، ثم استخدام أحد بوابات الدفع وقد تم شرح الأمر بالتفصيل هنا:
     
  3. إجابة Mustafa Suleiman سؤال في تحريك جميع عناصر الشاشه في pygame كانت الإجابة المقبولة   
    باستطاعتك استخدام نفس الكود الذي قدمته في الاستجابة السابقة لتحريك الشاشة لتتبع شخصية اللعبة، ولكن بإضافة بعض الخطوات الإضافية لمنع اللاعب من الخروج من الشاشة.
    أولاً، عليك إنشاء مصفوفة من القيم التي تمثل الحدود اليسرى واليمنى العلوية والسفلية للشاشة، ثم استخدام هذه المصفوفة لتحديد ما إذا كان اللاعب يتحرك خارج الشاشة أم لا.
    ثانيًا،  إضافة شرط إلى الحلقة الرئيسية للتحقق مما إذا كان اللاعب يتحرك خارج الشاشة، وإن كان اللاعب يتحرك خارج الشاشة، بإمكانك تحريك الشاشة بحيث يكون اللاعب دائمًا في المنتصف.
    وإليك مثالاً:
    import pygame # Initialize Pygame pygame.init() # Create a window screen = pygame.display.set_mode((640, 480)) # Create the player player = pygame.Rect(320, 240, 64, 64) # Load the background image background = pygame.image.load("background.png") # Create a list of the screen borders borders = [0, 0, 640, 480] # Draw the background image screen.blit(background, (0, 0)) # Draw the player screen.blit(player, player.center) # Update the display pygame.display.update() # Main loop while True: # Check for events for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() # Move the player if event.type == pygame.KEYDOWN: if event.key == pygame.K_LEFT: player.x -= 10 if event.key == pygame.K_RIGHT: player.x += 10 if event.key == pygame.K_UP: player.y -= 10 if event.key == pygame.K_DOWN: player.y += 10 # Check if the player is outside the screen if player.x < borders[0]: player.x = borders[0] if player.x > borders[2]: player.x = borders[2] if player.y < borders[1]: player.y = borders[1] if player.y > borders[3]: player.y = borders[3] # Draw the player screen.blit(player, player.center) # Update the display pygame.display.update() # Keep the game running pygame.time.delay(100)  
  4. إجابة Mustafa Suleiman سؤال في تفعيل تناوب اللعب بناءً على إجابة سؤال في لعبة XO باستخدام React.js و Node.js و socket.io كانت الإجابة المقبولة   
    const http = require('http'); const express = require('express'); const socketIO = require('socket.io'); const app = express(); const server = http.createServer(app); const io = socketIO(server); const questions = [ { question: 'ما هو عاصمة فرنسا؟', answer: 'باريس' }, { question: 'ما هو أكبر كوكب في النظام الشمسي؟', answer: 'المشتري' }, // قائمة الأسئلة والإجابات الأخرى ]; let currentPlayer = 0; // تحديد اللاعب الحالي io.on('connection', (socket) => { // عند اتصال لاعب جديد socket.emit('question', questions[currentPlayer].question); socket.on('answer', (playerAnswer) => { if (playerAnswer === questions[currentPlayer].answer) { // إذا كانت الإجابة صحيحة io.emit('correctAnswer', currentPlayer); currentPlayer = 1 - currentPlayer; // تبديل تناوب اللاعبين } }); }); server.listen(3000, () => { console.log('Server is running on port 3000'); });  
  5. إجابة Mustafa Suleiman سؤال في مشكلة عند استخدام مكتبة pafy كانت الإجابة المقبولة   
    خطأ "TypeError: unsupported operand type(s) for *: 'NoneType' and 'int'" يعني أنك تحاول ضرب كائن من نوع NoneType برقم صحيح، يحدث هذا إذا كانت وظيفة get_video_stream() تُرجع كائنًا من نوع NoneType.
    تُستخدم وظيفة get_video_stream() بواسطة وظيفة playVideo() للحصول على قائمة بجميع تيارات الفيديو المتاحة لفيديو YouTube.
    وتستخدم وظيفة get_video_stream() مكتبة pafy للحصول على معلومات حول فيديو YouTube.
    تم تحديث مكتبة pafy مؤخرًا، ومن الممكن أن تكون وظيفة get_video_stream() غير متوافقة مع الإصدار الجديد من المكتبة.
    ولإصلاح الخطأ، يمكنك محاولة تحديث مكتبة pafy، وأيضًا محاولة استخدام مكتبة مختلفة للحصول على معلومات حول مقاطع فيديو YouTube.
    أولاً قم بتحديث مكتبة pafy عن طريق تشغيل الأمر التالي في موجه الأوامر:
    pip install --upgrade pafy ثانيًا جرب استخدام مكتبة مختلفة للحصول على معلومات حول مقاطع فيديو YouTube، وهناك العديد من المكتبات المتاحة، مثل youtube-dl و pytube.
  6. إجابة Mustafa Suleiman سؤال في كيف احفظ بيانات قادمه من backend node.js الي cookies frontend كانت الإجابة المقبولة   
    من خلال الإعتماد على middleware passport.session() لحفظ البيانات من backend إلى cookies في frontend تلقائيًا.، وذلك الوسيط middleware يستخدم مكتبة cookie-session لإنشاء وإدارة جلسات المستخدم.
    وللاستخدام، أضف passport.session() إلى middleware chain الخاص بك:
    app.use(passport.session()); ثم، يمكنك استخدام استراتيجية Passport الخاصة بك لحفظ البيانات في الجلسة، مثلا في حال  كنت تستخدم استراتيجية passport.local()، تستطيع حفظ اسم المستخدم وكلمة المرور في الجلسة باستخدام الكود التالي:
    passport.use(new LocalStrategy((username, password, done) => { // Check the username and password against the database if (username === 'kerlos' && password === 'secret') { // The user is authenticated done(null, user); } else { // The user is not authenticated done(new Error('Invalid username or password')); } })); بمجرد حفظ البيانات في الجلسة، سيتم إرجاعها إلى frontend تلقائيًا.
    وبإمكانك الوصول إلى البيانات باستخدام middleware cookie-parser()، ومثلاً للحصول على على اسم المستخدم نستخدم التالي:
    const username = req.cookies.username; وباستطاعتك أيضًا استخدام middleware cookie-parser() لإزالة البيانات من الجلسة،  فلتسجيل خروج المستخدم، استخدم الكود التالي:
    req.session.destroy(); وإليك مثال كامل:
    const express = require('express'); const passport = require('passport'); const cookieSession = require('cookie-session'); // Create an Express app const app = express(); // Configure passport app.use(passport.initialize()); app.use(passport.session({ secret: 'secret', })); // Define a route that requires authentication app.get('/protected', passport.authenticate('local'), (req, res) => { // The user is authenticated res.send('Hello, ' + req.user.username); }); // Define a route that logs the user in app.post('/login', (req, res) => { // Check the username and password against the database if (req.body.username === 'johndoe' && req.body.password === 'secret') { // The user is authenticated passport.authenticate('local')(req, res, () => { res.redirect('/protected'); }); } else { // The user is not authenticated res.send('Invalid username or password'); } }); // Define a route that logs the user out app.get('/logout', (req, res) => { // Invalidate the user's session req.session.destroy(); res.redirect('/'); }); // Start the app app.listen(3000, () => { console.log('App listening on port 3000'); });  
  7. إجابة Mustafa Suleiman سؤال في كيفية حذف عنصر من قواعد البيانات مع العناصر المرتبطة بها في MongoDB؟ كانت الإجابة المقبولة   
    الطريقة الأولى لحل المشكلة هي  باستخدام مفهوم الـ "حذف المتوالي" (Cascading Delete) في MongoDB، وعند حذف عنصر من Model Product، يمكنك تعيين خاصية تؤدي إلى حذف جميع العناصر المرتبطة به في Model Cart تلقائيًا.
    والأمر يعتمد على كيفية تطبيقك للعلاقة بين Model Product و Model Cart في تطبيقك، فإذا كنت تستخدم مرجعًا يشير إلى عنصر في Model Product في Model Cart (مثل استخدام ObjectId)، فتستطيع الاستفادة من خاصية "onDelete" في واجهة العلاقة للقيام بذلك.
    وإليك مثال على كيفية تحقيق حذف المتوالي بين Model Product و Model Cart باستخدام مكتبة Mongoose في Node.js، ولنفترض أن لديك مودل Product ومودل Cart مثل التالي:
    // Product Model const mongoose = require('mongoose'); const productSchema = new mongoose.Schema({ name: String, // ... other product properties }); const Product = mongoose.model('Product', productSchema); module.exports = Product; مودل Cart:
    // Cart Model const mongoose = require('mongoose'); const cartSchema = new mongoose.Schema({ products: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Product' }], // ... other cart properties }); const Cart = mongoose.model('Cart', cartSchema); module.exports = Cart; بإمكانك إضافة خاصية "onDelete" في علاقة Model Cart مع Model Product لتحقيق حذف المتوالي:
    const cartSchema = new mongoose.Schema({ products: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Product', onDelete: 'CASCADE' }], // ... other cart properties }); وبذلك عندما يتم حذف عنصر من Model Product، سيقوم MongoDB تلقائيًا بحذف جميع العناصر المرتبطة به في Model Cart بفضل الخاصية "onDelete" التي تم تعيينها في واجهة العلاقة.
    والخاصية "onDelete" ليست جزءًا من MongoDB نفسها، بل هي خاصية تقدمها مكتبة Mongoose لتسهيل التعامل مع قواعد البيانات. لذلك، ويجب التأكد من استخدام Mongoose أو أي مكتبة أخرى تقدم تلك الخاصية حتى تتمكن من الاستفادة من الحذف المتوالي.
    الطريقة الثانية هي باستخدام طريقة deleteMany() مع استعلام يحدد كل العناصر التي تريد حذفها، وكمثال:
    const productsCollection = db.collection('products'); const cartsCollection = db.collection('carts'); // Find all products that are in the cart const productsInCart = cartsCollection.find({ productId: { $in: productsCollection.distinct('id') } }); // Delete all products that are in the cart productsInCart.deleteMany(); سيعمل الكود السابق على حذف جميع المنتجات التي توجد في عربة التسوق، بالإضافة إلى إمكانية استخدام طريقة deleteOne() لحذف عنصر واحد فقط.
    أي إن كنت تريد حذف المنتج الذي له معرف 1234567890, فالطريقة كالتالي:
    const productsCollection = db.collection('products'); // Delete the product with id 1234567890 productsCollection.deleteOne({ id: 1234567890 }); والقرار بين استخدام "حذف المتوالي" باستخدام خاصية "onDelete" في واجهة العلاقة أو استخدام deleteMany() و deleteOne() يعتمد على حاجتك الفعلية وتصميم قاعدة البيانات والتطبيق الخاص بك، وسأوضح لك الفرق بالمقارنة بينهم:
    استخدام حذف المتوالي (onDelete):
    المزايا:
    يقوم بالحفاظ على سلامة علاقات البيانات بطريقة أكثر تلقائية، وعند حذف عنصر من Model Product، ستتم إزالة العناصر المرتبطة به من Model Cart تلقائيًا دون الحاجة إلى كتابة الكود يدويًا. أكثر ملاءمة وسهولة للتطبيقات التي تعتمد بشكل كبير على العلاقات وتحتاج إلى تنظيم بياناتها بشكل جيد. العيوب:
    يتطلب استخدام مكتبة معينة (مثل Mongoose) التي تدعم هذه الخاصية، وإذا قررت استخدام مكتبة أخرى قد لا تكون تلك الخاصية متاحة. استخدام deleteMany() و deleteOne():
    المزايا:
    تحكم أكبر بالعملية وأوضح للمطورين، وتستطيع كتابة الكود بشكل دقيق لحذف العناصر المطلوبة بناءًا على متطلبات تطبيقك. قابل للتطبيق دون الحاجة إلى مكتبة خاصة بـ "حذف المتوالي". العيوب:
    أكثر تعقيداً في بعض الحالات، خاصة إذا كان لديك عدة نماذج مرتبطة بعلاقات معقدة. وببساطة إن كانت علاقاتك معقدة وتعتمد على عمليات حذف متعددة في عدة نماذج، فمن الأفضل استخدام deleteMany() و deleteOne() لتحكم أكبر في العملية، أما إذا كانت العلاقات بسيطة وترغب في تبسيط عملية الحذف، فالحذف المتوالي باستخدام "onDelete" هو الخيار الأمثل.
  8. إجابة Mustafa Suleiman سؤال في أيهما أكثر أمانًا: User::find($id) أم User::findOrFail($id) في Laravel؟ كانت الإجابة المقبولة   
    استخدام findOrFail($id) بدلاً من find($id) يعتبر عملية جيدة في بعض الحالات وذلك لضمان أمان التطبيق والتعامل مع الأخطاء بشكل أفضل.
    ولكن يجب توضيح الفرق بين الاثنين:
    User::find($id)
    تلك الطريقة تقوم بالبحث عن سجل في قاعدة البيانات باستخدام المفتاح الرئيسي للجدول (وغالبًا ما يكون الـ ID)، وإن وجد السجل، فيتم إرجاع السجل نفسه، وإذا لم يتم العثور عليه، فيتم إرجاع قيمة null.
    User::findOrFail($id)
    نفس عملية البحث السابق، ولكن في حالة عدم العثور على السجل، فيتم برفع استثناء من نوع ModelNotFoundException، وذلك يعني أنه إذا لم يتم العثور على السجل، يتم رمي استثناء وتوقف تنفيذ البرنامج، مما يتطلب التعامل مع الاستثناء في الكود.
    السبب الرئيسي لاستخدام findOrFail($id) هو تجنب الحصول على قيمة null ومعالجة تلك القيمة في حالة عدم وجود السجل المطلوب في قاعدة البيانات، وعند استخدام findOrFail($id)، تستطيع ببساطة التعامل مع الاستثناء المرتبط في الكود، مما يسهل تحديد الأخطاء والتعامل معها بشكل أفضل.
    إذا قمت بتعيين APP_DEBUG=true في ملف .env، فذلك سيساعدك في رؤية الأخطاء والاستثناءات التي تم رفعها، ولكن لا ينصح بالاعتماد على ذلك الإعداد في بيئة الإنتاج، حيث سيكشف عن معلومات حساسة.
    أي بإختصار، سيتسبب استخدام User::find($id) في تلقي المستخدمين خطأً 500 ، مما قد يكشف عن بيانات غير مقصودة، وسيتسبب استخدام User::findOrFail($id) في تلقي المستخدمين خطأ 404 ، والذي يعد أكثر أمانًا.
    بالإضافة إلى ذلك ، فإن استخدام User::findOrFail($id) سيساعد على منع الأخطاء التي قد تحدث إذا لم يكن المستخدم موجودًا، وإذا استخدمت User::find($id) ولم يكن المستخدم موجودًا ، فستتلقى خطأً 500.
    مما يؤدي إلى توقف API الخاص بك عن العمل، وسيكون من الصعب تحديد سبب المشكلة، وسيتسبب استخدام User::findOrFail($id) في تلقي خطأ 404 ، مما سيسهل تحديد سبب المشكلة وإصلاحها.
  9. إجابة Mustafa Suleiman سؤال في اين يتم تخزين الصور في المواقع كانت الإجابة المقبولة   
    من خلال الكود في موقعك، حيث تتعامل مع المجلد الخاص بتخزين الصور كما تتعامل معه في حاسوبك، عليك بالإشارة إلى مسار المجلد في الكود الخاص بك مع اسم الصور.
    وأيضًأ تتيح الاستضافة لك إمكانية توليد رابط مباشر للصورة بعد تحميلها عبر FTP، ويمكنك العثور على الصورة داخل مجلدات الاستضافة الخاصة بك ومن ثم الحصول على الرابط الكامل الذي يؤدي إلى الصورة، مثال للرابط:
    http://example.com/path/to/image.jpg  
  10. إجابة Mustafa Suleiman سؤال في كيف يمكنني تغيير جودة الفيديو إلى 360 بكسل في تطبيق أندرويد؟ كانت الإجابة المقبولة   
    عليك بإضافة مستودع JitPack  إلى إلى قسم repositories في ملف build.gradle:
    repositories { ... maven { url 'https://jitpack.io' } } ثم، تحتاج إلى إضافة تبعية FFmpegMediaMetadataRetriever إلى قسم dependencies في ملف build.gradle:
    dependencies { implementation 'com.github.wseemann.FFmpegMediaMetadataRetriever:FFmpegMediaMetadataRetriever-core:v1.0.15' } وفي حال أردت إضافة أي مستودع لمكتبة أخرى نتوجه إلى موقع https://jitpack.io ثم ألصق رابط المستودع الخاص بالمكتبة على GitHub وستظهر لك الإصدارات المتاحة ونضغط على get it وستجد الرابط بالأسفل:

    وتستطيع قراءة المستند الرسمي الخاص بالمكتبة في حال واجهتك مشكلة معينة:
    https://github.com/wseemann/FFmpegMediaMetadataRetriever
  11. إجابة Mustafa Suleiman سؤال في مشاكل في بوابات الدفع - كيف يمكن التعامل مع المشاكل المحتملة وتجنب فقدان المبلغ؟ كانت الإجابة المقبولة   
    المشاكل المعروفة هي كالآتي:
    فشل المعاملة لأسباب مختلفة ، مثل عدم وجود رصيد كافٍ في بطاقة الائتمان أو انتهاء صلاحية البطاقة أو إدخال بيانات غير صحيحة.  استخدام بوابات الدفع لعمليات الاحتيال ، مثل سرقة بطاقات الائتمان أو استخدام بيانات بطاقة الائتمان المسروقة لإجراء عمليات شراء غير مصرح بها.  اختراق بوابات الدفع ، مما يعرض بيانات بطاقات الائتمان للخطر. وعند إتمام عملية الدفع بنجاح، ستحصل عادة على استجابة (response) من بوابة الدفع، تتضمن:
    حالة الدفع: مثل "ناجح" أو "فشل". رقم المعاملة: وهو رقم مرجعي فريد للمعاملة. الرد من البنك: رسالة من بوابة الدفع أو البنك تحتوي على تفاصيل الدفع الناجح أو الفشل. رمز الاستجابة: يوحد رموز للردود تشير إلى نتيجة الدفع (مثل رمز 200 للنجاح). بعد الحصول على تلك البيانات، تستطيع تسجيل بعض المعلومات الأساسية في قاعدة البيانات للتفريق بين الدفعات الناجحة والفاشلة وتتبع حالة الطلبات، ومنها:
    رقم المعاملة. حالة الدفع (مثل "ناجح" أو "فشل"). المبلغ المدفوع. تاريخ ووقت الدفع. أخر 4 أرقام من البطاقة أو الحساب البنكي. معلومات المستخدم (اختياري، يعتمد على احتياجات موقعك). وإليك مثال للاستجابة من خلال بوابة دفع stripe:
    { "id": "ch_1234567890", "object": "charge", "created": 1582950736, "livemode": false, "currency": "usd", "amount": 1000, "description": "A test charge", "source": { "id": "src_1234567890", "object": "source", "type": "card", "last4": "1234", "exp_month": 12, "exp_year": 2023, "name": "John Doe", "address_line1": "123 Main Street", "address_line2": null, "city": "Anytown", "state": "CA", "country": "US", "zip": "91234", "cvc": "123" }, "destination": { "id": "cus_1234567890", "object": "customer" }, "status": "succeeded", "failure_message": null, "failure_code": null, "charge_back_id": null, "refunds": [ { "id": "re_1234567890", "object": "refund", "created": 1582950736, "amount": 1000, "currency": "usd", "reason": "customer_requested", "balance_transaction": "bal_1234567890" } ], "balance_transaction": { "id": "bal_1234567890", "object": "balance_transaction", "created": 1582950736, "amount": 1000, "currency": "usd", "description": "Charge succeeded", "type": "charge", "balance_delta": 1000, "available_on": 1582950736, "net_received": 1000, "fee": 0, "transfer_group": null }, "metadata": { "foo": "bar" } } وبالطبع تستطيع إجراء إختبارات على بوابة الدفع للتأكد من عملها بشكل سليم قبل نشر الموقع.
    وأيضًا لمعلوماتك علميات الاسترجاع للأموال يتم معالجتها من قبل بوابة الدفع.
  12. إجابة Mustafa Suleiman سؤال في كيفية تسجيل شاشة وكاميرا الهاتف أثناء الاختبار باستخدام Node.js و React؟ كانت الإجابة المقبولة   
    تسجيل شاشة الهاتف أثناء الاختبار
    هناك مكتبة تُدعى react-screen-recorder تستطيع الإعتماد عليها لتسجيل الشاشة أثناء الاختبار، وتلك المكتبة تعمل مع React وتُتيح للمستخدمين تسجيل شاشة هاتفهم أثناء استخدام التطبيق، ولتثبيتها استخدم الأمر التالي:
    npm install react-screen-recorder وستجد طريقة الاستخدام في المستودع الرسمي للمكتبة:
    https://github.com/DeltaCircuit/react-media-recorder وإليك مثال:
    import React, { useState } from 'react'; import { ScreenRecorder } from 'react-screen-recorder'; const ScreenRecorderComponent = () => { const [isRecording, setIsRecording] = useState(false); const handleRecording = (blob) => { // يمكنك إرسال الـ blob إلى المنصة الخاصة بك للمراجعة هنا console.log(blob); }; return ( <div> <h1>تسجيل شاشة الهاتف</h1> <ScreenRecorder onRecordingComplete={handleRecording} isRecording={isRecording}> {({ startRecording, stopRecording }) => ( <> {isRecording ? ( <button onClick={stopRecording}>إيقاف التسجيل</button> ) : ( <button onClick={startRecording}>بدء التسجيل</button> )} </> )} </ScreenRecorder> </div> ); }; export default ScreenRecorderComponent; ضع المكون في التطبيق وسيظهر زرًا يمكن للمستخدم النقر عليه لبدء تسجيل شاشة هاتفه، وبمجرد أن ينتهي المستخدم من تسجيل الشاشة، ستُستدعى وظيفة handleRecording وستُمرر لها blob الخاص بتسجيل الفيديو، هنا تستطيع إرسال الـ blob للواجهة الخلفية للمراجعة.
    تسجيل فيديو من الكاميرا الأمامية أثناء الاختبار
    وبالنسبة لتسجيل الفيديو من الكاميرا الأمامية، باستطاعتك استخدام تقنية التسجيل بواسطة MediaRecorder، والوصول إلى الكاميرا الأمامية باستخدام API "getUserMedia"، وهي API's متاحة من قبل المتصفح.
    وإليك مثال:
    async function startRecording() { const stream = await navigator.mediaDevices.getUserMedia({ video: { facingMode: 'user' }, audio: false }); const mediaRecorder = new MediaRecorder(stream); const chunks = []; mediaRecorder.ondataavailable = (e) => { if (e.data.size > 0) { chunks.push(e.data); } }; mediaRecorder.onstop = () => { const videoBlob = new Blob(chunks, { type: 'video/mp4' }); // قم بإرسال الـ videoBlob للمراجعة على المنصة الخاصة بك هنا }; mediaRecorder.start(); } function stopRecording() { mediaRecorder.stop(); } وعليك باستدعاء startRecording() عند بدء الاختبار و stopRecording() عند انتهائه.
    تحميل الفيديوهات للمراجعة
    وبمجرد انتهاء الاختبار، تستطيع إرسال الفيديوهات (شاشة الهاتف والكاميرا الأمامية) إلى المنصة الخاصة بك للمراجعة، باستخدام Node.js والمكتبات المناسبة لاستقبال الفيديوهات وتخزينها في الخادم أو قاعدة البيانات.
    وبالطبع نستخدم Express.js كإطار عمل لبناء نظام السيرفر واستقبال طلبات الفيديوهات، والإعتماد على مكتبات أخرى مثل Multer لتحميل الفيديوهات على الخادم.
    مثال:
    const express = require('express'); const multer = require('multer'); const app = express(); const upload = multer({ dest: 'uploads/' }); app.post('/upload', upload.single('video'), (req, res) => { // يتم تخزين الفيديو هنا في قاعدة البيانات أو أي مكان آخر تفضله console.log(req.file); res.send('تم تحميل الفيديو بنجاح!'); }); app.listen(3000, () => { console.log('السيرفر يعمل على منفذ 3000'); }); وبإمكانك استدعاء API نقطة النهاية /upload عند انتهاء الاختبار لتحميل الفيديوهات.
  13. إجابة Mustafa Suleiman سؤال في مشكلة سكربت لا يشتغل على php 8 كانت الإجابة المقبولة   
    بالطبع فأنت بحاجة إلى تعديل الكود ليتوافق مع التغييرات التي حدثت في الإصدار 8.0.
    لذلك حاول التحقق من ملفات السكربت والصفحات الخاصة به للتأكد من عدم وجود أخطاء قوية (Fatal Errors) أو رسائل خطأ عند تشغيلها على PHP 8، بالإَضافة إلى التأكد من عدم استخدام الوظائف المتوقفة (deprecated functions) التي قد تكون تم استبدالها بوظائف جديدة في PHP 8.
    وفي حال لم تتمكن من تحديد سبب التوافقية، بإمكانك استخدام أدوات التحويل (Migration tools) المتاحة لتحويل السكربت من PHP 7 إلى PHP 8، وتلك  الأدوات تساعد في اكتشاف التغييرات التي تحتاج إلى إجرائها لتحقيق التوافقية مع PHP 8 ومنها:
    PHP_CodeSniffer PHPCompatibility rector وستجد هنا الدليل الرسمي الذي يوضح طريقة عمل Migrating أو تحويل الكود من  PHP 7.4 إلى PHP 8.0، حيث يتم شرح التغييرات التي حدثت:
    https://www.php.net/manual/en/migration80.php
  14. إجابة Mustafa Suleiman سؤال في كيف يمكنني ارجاع الملف من ملف اخر الى سطح المكتب كانت الإجابة المقبولة   
    يوجد طريقتان لنقل مجلد من مجلد آخر إلى سطح المكتب في Linux.
    الطريقة الأولى هي استخدام واجهة المستخدم الرسومية (GUI):
    افتح مدير الملفات. انتقل إلى المجلد الذي يحتوي على المجلد الذي تريد نقله. حدد المجلد الذي تريد نقله. اسحب المجلد إلى سطح المكتب. الطريقة الثانية هي استخدام سطر الأوامر. للقيام بذلك:
    افتح نافذة موجه الأوامر. انتقل إلى المجلد الذي يحتوي على المجلد الذي تريد نقله في منفذ الأوامر terminal. اكتب الأمر التالي: mv source_folder destination_folder وبالطبع استبدل source_folder باسم المجلد أو الملف، واستبدل اسم destination_folder بالوجهة التي تريد نقل المجلد أو الملف إليها.
    أي في حال كنت تريد نقل المجلد "my_folder" إلى سطح المكتب، فستكتب الأمر التالي:
    mv my_folder ~/Desktop وسيؤدي ذلك إلى نقل المجلد "my_folder" إلى سطح المكتب.
  15. إجابة Mustafa Suleiman سؤال في سحب المال عن طريق PayPal كانت الإجابة المقبولة   
    كما أخبرتك يجب أن تكون 18 عام حيث تم ذكر ذلك في شروط الاستخدام على منصة مستقل، وأظن أن الشرط موضوع من أجل أن تمتلك بطاقة هوية، وطالما أنك تمتلكها فلا مشكلة، وذلك غير مؤكد ولتأكيد ذلك تحدث لمركز المساعدة في مستقل.
  16. إجابة Mustafa Suleiman سؤال في بحث متعدد الأشكال في قاعدة بيانات SQL باستخدام Laravel Eloquent كانت الإجابة المقبولة   
    استخدم قيمة ذلك الحقل لتنفيذ البحث في قاعدة البيانات، كالتالي:
    في ملف العرض (View) الخاص بك، أنشئ نموذج (Form) بحث بالشكل التالي:
    <form method="GET" action="/search"> <input type="text" name="query" placeholder="ابحث عن الاسم"> <button type="submit">ابحث</button> </form> ثم، في ملف التوجيه (Routes)، حدد مسار للبحث وربطه بوظيفة في وحدة التحكم (Controller)، كالتالي:
    Route::get('/search', 'SearchController@search'); وفي وحدة التحكم (Controller) الخاصة بالبحث، تستطيع استقبال الاستعلام (query) المدخل من الحقل واستخدامه في جملة البحث، كالتالي:
    use Illuminate\Http\Request; use App\Models\Table; class SearchController extends Controller { public function search(Request $request) { $query = $request->input('query'); $results = Table::where('name', 'LIKE', '%' . $query . '%')->get(); // عرض النتائج أو قم بالإجراءات المناسبة return view('search_results', ['results' => $results]); } } بحيث تستقبل الاستعلام (query) من الحقل بواسطة كائن Request، ثم استخدامه في جملة البحث للبحث عن السجلات التي تحتوي على الاستعلام في حقل الاسم، وتُرسل النتائج إلى عرض (View) المستخدم لعرضها بطريقة مناسبة.
    واستبدل Table بالاسم الصحيح للنموذج لديك، واستبدال search_results بعرض النتائج أيضًا.
  17. إجابة Mustafa Suleiman سؤال في ماذا بعد دورة علوم الحاسوب كانت الإجابة المقبولة   
    السؤال الصحيح هو، هل لديك الوقت الكافي؟ 
    عليك بتحديد الوقت المتاح لك ثم التخطيط على أساسه، وأيضًا تحديد الدورات بناءًا على الهدف والمجال الذي تنوي التخصص به، فلو أردت التأسيس في مجال البرمجة بشكل جيد ولديك الوقت الكافي، فعليك بتعلم C++ أولاً لكن البعض قد يجدها صعبة ويصاب بالإحباط بدون داعي، ولذلك ستجد أغلب دورات أساسيات البرمجة تقوم بتدريس لغة بايثون لكونها لغة قوية وشائعة الاستخدام ومطلوبة وسهلة، أي أن الأمر راجع لك وتستطيع التجربة والحكم ولا مشكلة في ذلك أبدًا لكن بشرط المحاولة.
    وقد ذكرت أنك درست CS50 ولن تحتاج إلى أكثر من ذلك حاليًا في البداية، عليك فقط بإختيار لغة البرمجة الأولى لك والتمسك بها والتعمق فيها من خلال تنفيذ المشاريع بعد دراسة الأساسيات والتطبيق عليها، وإذا أردت دراسة جافاسكريبت كلغة برمجة أولى فلا مشكلة في ذلك، لكن الصحيح هو C أو C++ ثم بايثون ثم جافاسكريبت رغم أني أفضل C++ ثم بايثون ثم جافاسكريبت، هل أنا تعلمت بتلك الطريقة؟ 
    لا، الوقت لدي كان محدود، لذلك تعلمت أساسيات البرمجة من خلال بايثون لقلة الوقت لدي ولسهولة تعلم بايثون، ثم انتقلت إلى الواجهة الأمامية وتعمقت في جافاسكريبت، ثم تعلمت إطار خاص بالواجهة الأمامية وهو React ثم تعلمت الواجهة الخلفية من خلال node.js وذلك خلال فترة 6 أشهر وبمعدل 10 ساعات يوميًا وربما أكثر، فالأمر ليس بالهين أبدًا.
    وإذا أردت نصيحة واحدة فقط، ركز على الأساسيات ما استطعت وبشدة ثم طبق عليها بأكثر من مشروع حتى تشعر أنك استوعبتها تمامًا وأصبح الأمر سهل من خلال التكرار.
    وأنت لديك الوقت كما أظن، فتعلم بالطريقة الصحيحة كما أشرت لك، ثم انتقل للغة الخاصة بالمجال الذي تنوي التخصص به.
  18. إجابة Mustafa Suleiman سؤال في ما الفرق بين auth()->user() و Auth::user() في Laravel؟ كانت الإجابة المقبولة   
    الفرق هو أن auth()->user() يرجع الكائن User الحالي بينما Auth::user() يرجع الكائن User الحالي أو null إذا لم يكن هناك مستخدم محدد.
    وتستطيع استخدام auth()->user() في المواقف التي تحتاج فيها إلى التأكد من وجود مستخدم محدد، مثلاً في حال كنت تريد عرض معلومات المستخدم الحالي ، فاستخدم:
    auth()->user()->name بينما نستخدم Auth::user() في المواقف التي لا تحتاج فيها إلى التأكد من وجود مستخدم محدد. كمثل معرفة ما إذا كان هناك مستخدم محدد متصل.
    وإليك مثال:
    // استخدام auth()->user() $user = auth()->user(); // طباعة اسم المستخدم الحالي echo $user->name; // استخدام Auth::user() if (Auth::check()) { // هناك مستخدم متصل } else { // لا يوجد مستخدم متصل }
  19. إجابة Mustafa Suleiman سؤال في شرح للكلمة المحجوزة "this" في جافاسكريبت وكيفية استخدامها بشكل مفصل كانت الإجابة المقبولة   
    لأكون واضحًا معك، لن تفهم الأمر بشكل واضح إلا إذا قمت بدراسة الدالة البانية Constructor  والسياق والنطاق Context and Scope وPrototype والتعرف على الطرق المختلفة لاستدعاء الدوال في جافاسكريبت، مثل استدعاء الدوال من كائنات، واستدعاءها كدوال عادية، واستدعاءها باستخدام الدوال السهمية، واستدعاءها باستخدام الـapply والـcall والـbind.
    و "this" ببساطة هي كلمة محجوزة تشير إلى الكائن الحالي الذي يتم تنفيذ الكود فيه، ونستخدم "this" داخل الوظائف والأساليب والأحداث للإشارة إلى الكائن الحالي الذي تم استدعاء الوظيفة أو الأسلوب منه.
    أما فائدة "this"  تكمن في القدرة على الوصول إلى الخصائص والأساليب الخاصة بالكائن الحالي، فعندما تستدعى الوظيفة أو الأسلوب باستخدام "this"، يتم تمرير الكائن الحالي كوسيط للعمليات التي يجريها الكود.
    مثلاً لنفترض أن لدينا كائنًا يُمثل سيارة، ولديه خاصية "السرعة" وأسلوب "تشغيل"، وعند استدعاء أسلوب "تشغيل"، تستخدم "this" للإشارة إلى الكائن الحالي (السيارة) وتغيير خاصية "السرعة" بناءًا على الإجراء المناسب.
    وفي جافاسكريبت، قيمة "this" تختلف بين الدوال العادية (Regular Functions) والدوال السهمية (Arrow Functions):
    الدوال العادية:
    قيمة "this" تشير إلى الكائن الذي يتم استدعاء الدالة منه، أو الكائن الذي يحتوي على الدالة، أي تعتمد قيمة "this" في الدوال العادية على سياق الاستدعاء وطريقة استدعاء الدالة.
    والتوضيح من خلال الكود أفضل، ولنبدأ باستخدام "this" في الوظائف المنفصلة:
    const person = { name: "John", age: 30, greet: function() { console.log("Hello, my name is " + this.name); } }; person.greet(); // الناتج: "Hello, my name is John" قمت بتعريف دالة greet داخل كائن person، وعند استدعاء الدالة باستخدام person.greet()، تستخدم "this" للإشارة إلى الكائن الحالي (person) والوصول إلى خاصية name لطباعة رسالة تحتوي على اسم الشخص.
    الدوال السهمية:
     قيمة "this" ليست مرتبطة بسياق الاستدعاء ولا تتأثر بطريقة الاستدعاء، ولكنها  تستمد قيمتها من النطاق الذي تم تعريف الدالة فيه كالتالي:
    const person = { name: "John", age: 30, greet: () => { console.log("Hello, my name is " + this.name); } }; person.greet(); // الناتج: "Hello, my name is undefined" وكما ترى بغض النظر عن كيفية استدعاء الدالة person.greet()، قيمة "this" في الدالة السهمية تشير إلى النطاق العلوي (lexical scope) الذي تم تعريف الدالة فيه، وفي هذه الحالة قيمة this.name ستكون غير معرفة (undefined).
    2- استخدام "this" في الأحداث (Events)
    const button = document.getElementById("myButton"); button.addEventListener("click", function() { console.log("Button clicked by " + this.textContent); }); تم تعيين حدث النقر (click event) لزر HTML بواسطة addEventListener. عند حدوث النقر، تستدعى الوظيفة المنفذة، وهنا يتم استخدام "this" للإشارة إلى العنصر الذي تم النقر عليه (الزر) وطباعة نص الزر في الكونسول.
    3- استخدام "this" في الأشياء الموروثة (Inheritance)
    والمثال التالي يفترض أنك على دراسة بالـ prototype.
    function Animal(name) { this.name = name; } Animal.prototype.greet = function() { console.log("Hello, I'm " + this.name); }; function Dog(name, breed) { Animal.call(this, name); this.breed = breed; } Dog.prototype = Object.create(Animal.prototype); Dog.prototype.constructor = Dog; const myDog = new Dog("Max", "Labrador"); myDog.greet(); // الناتج: "Hello, I'm Max" عرفت الدالة Animal وتأخذ معلمة name، ثم قمت بإنشاء دالة greet باستخدام النمط الأساسي للوظائف الموروثة (prototype inheritance).
    بالمثل، تعريف الدالة Dog التي ترث من Animal وتضيف خاصية breed، وعند إنشاء كائن Dog واستدعاء الدالة greet، تستخدم"this" للإشارة إلى الكائن الحالي (myDog) واستدعاء greet من النمط الأساسي.
  20. إجابة Mustafa Suleiman سؤال في مشكلة استخدام includes و indexOf مع قيمة prompt النصية ومصفوفة من الأرقام كانت الإجابة المقبولة   
    يجب تحويل قيمة الـ prompt إلى رقم حيث أن القيمة العائدة منه هي نص، وهناك أكثر من طريقة لفعل ذلك، الأولى هي بوضع علامة + بجانب prompt أي كالتالي:
    let x = +prompt('أدخل رقم من المصفوفة') وسيتم تحويل القيمة المدخلة إلى رقم.
    والطريقة الثانية هي باستخدام دالة parseInt كالتالي:
    let x = parseInt(prompt('أدخل رقم من المصفوفة')); والطريقة الثالثة هي باستخدام دالة Number وانتبه إلى أن حرف الـ N كبير لكونها constructor أي دالة بانية  ولكننا نستخدمها كدالة هنا لتحويل النص إلى الرقم كالتالي:
    let x = Number(prompt('أدخل رقم من المصفوفة')); الكائن Number في JavaScript
  21. إجابة Mustafa Suleiman سؤال في هل دورة بايثون مجانية؟ كانت الإجابة المقبولة   
    في الوقت الحالي، دورات أكاديمية حسوب مدفوعة وهي غير مجانية لكون الدورة تم إعدادها بعناية واستغرقت الكثير من الوقت من قبل فريق عمل لإخراجها بجودة تستحق وتليق بمشتركي أكاديمية حسوب من خلال 416 فيديو لشرح أساسيات بايثون  والتطبيق عليها ثم إطار العمل جانغو Django وFlask وتطوير تطبيقات أودو Odoo وأيضًا تحليل البيانات وأساسيات تعلم الآلة Machine Learning.
    في بعض الأوقات يوجد خصومات في المناسبات مثل شهر رمضان والجمعة البيضاء، وكوبونات في أوقات متفرقة من العام، تستطيع سؤال مركز المساعدة عن وجود خصومات حاليًا أم لا.
    وبخصوص لغة بايثون هناك دروس ومقالات في موسوعة حسوب وأكاديمية حسوب وأيضًا كتابة لتعلم بايثون:
    دروس بايثون في أكاديمية حسوب شرح لغة بايثون Python في موسوعة حسوب
  22. إجابة Mustafa Suleiman سؤال في مشكل في التنسيق كانت الإجابة المقبولة   
    أرجو منك طرح السؤال أسفل فيديو الدورة الخاص بالسؤال ليتم مساعدتك بشكل أفضل، وطرح الأسئلة العامة هنا.
  23. إجابة Mustafa Suleiman سؤال في هل من الآمن الكتابة على مجلد Windows/Temp أم يجب تركه Read-only؟ كانت الإجابة المقبولة   
    لا مشكلة في الكتابة على مجلد Windows/Temp، فهو مخصص لكي تقوم التطبيقات بكتابة الملفات المؤقتة فيه، والملفات المؤقتة هي ملفات يتم إنشاؤها بواسطة التطبيقات وتستخدم لفترة قصيرة من الزمن، ثم يتم حذفها من قبل التطبيق أو من قبل نظام التشغيل.
    وإذا أردت تغيير مكان الملفات المؤقتة إذا كنت تستخدم لاراجون قم بفتح ملف php.ini الخاص بتكوين PHP، ثم ابحث عن سطر يحتوي على "upload_tmp_dir" في ملف php.ini وقم بإلغاء تعليقه عن طريق إزالة علامة التعليق "#" في بداية السطر.
    ثم تعيين قيمة "C:/laragon/tmp" لـ "upload_tmp_dir"، ويعني ذلك أن الملفات المؤقتة التي تم رفعها ستخزن في المجلد "C:/laragon/tmp".
  24. إجابة Mustafa Suleiman سؤال في كيف ابدأ بنشر محتوى تعليمي كانت الإجابة المقبولة   
    المنصات التعليمية المشابهة لـ Udemy وغيرها قليلة في المحتوى العربي، ولذلك أمامك خيارين، الأول هو إنشاء موقع خاص بك ونشر الكورس الخاص بك عليه مع نظام إشتراك تحدده أنت في حال كنت قادر على التسويق للكورس الخاص بك ولديك متابعين أو معروف في مجالك.
    أو استخدام المنصات التي لديها مستخدمين بالفعل مثل Udemy وAlmentor و Skillshare وبالتالي سيتم العثور على الكورس الخاص بك ولكن بشرط أن توفر جودة منافسة للكورسات الموجودة بالفعل وميزة تنافسية عنهم، مثل شرح أحدث الإصدارات بطريقة عملية واستخدام السلايدات والإنفوجرافيك لتوضيح الأمر، وغيرها من الأمور التي تستطيع تحديدها بنفسك، وقد يفيدك قراءة التالي:
    وربما عليك في البداية إنشاء كورس مجاني على اليوتيوب بجودة جيدة، من أجل بناء قاعدة متابعين لك مهتمين بالكورسات التي تقدمها.
  25. إجابة Mustafa Suleiman سؤال في مشكلة "Path cannot be empty" عند استخدام دالة store() لحفظ الصورة كانت الإجابة المقبولة   
    سبب المشكلة هو أن المسار الذي تحاول استخدامه فارغ، أي عدم تعيين المسار الصحيح لحفظ الصورة المرفوعة، وأنت تستخدم الدالة store() لحفظ الصورة، وتحدد المجلد "posts" وتستخدم القرص المحلي "public".
    وللتأكد من أن المشكلة ليست بسبب خطأ في المسار، هل تحققت من وجود المجلد "posts" في القرص المحلي "public" في مشروعك؟ وإذا كان المجلد غير موجود، فتستطيع إنشائه يدويًا.
    وإذا كان المجلد موجودًا ولا تزال تواجه المشكلة، فربما هناك خطأ آخر في الطريقة التي ترفع بها الصورة، ومن الأفضل التحقق من قيمة $request['image'] والتأكد من أنها صحيحة وتحتوي على الصورة المطلوبة.
    وربما لديك مشكلة في الكتابة إلى مجلد temp في  C:\Windows\Temp عليك بالضغط بزر الفأرة الأيمن على مجلد temp ثم اختيار properties  ثم ستجد خيار باسم read-only قم بإزالة العلامة ثم ok للحفظ.

    وأيضًا تستطيع استخدام دالة dd لمعرفة المسار كالتالي:
    dd($request['image']); وسيتم عرض معلومات المتغير $request['image'] بشكل مفصل، بما في ذلك المسار وأي بيانات أخرى متعلقة بالصورة.

×
×
  • أضف...