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

شرف الدين حفني

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

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

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

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

    2

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

  1. إجابة شرف الدين حفني سؤال في شرح التعامل مع jwt في node.js كانت الإجابة المقبولة   
    الjwt (json web token) هي طريقة لتخزين البيانات بشكلٍ أمن حيث أنها تقوم بإستخدام البصمة الرقمية(digital signature) وهي طريقة لضمان عدم التﻻعب في محتويات الtoken مما يضمن للخادم أن الtoken ليست مزيفة وأنها صالحة للإستخدام
    الطريقة المتعارفة عليها في التعامل في مثل هذا السيناريو الذي وضعتها تتم كالتالي
    أن يقوم المُستخدم بعد تسجيل الدخول بإستﻻم token من الخادم ويقوم المُستخدم بتخزينه في كل مرة يُحاول المُستخدم إرسال الtoken يقوم الخادم بالتأكد من صﻻحيته ومن عدم التﻻعب فيه  ﻻ يمكن لأحد إنشاء منشور إإﻻ عند تضمين الtoken في الheaders الخاصة بالhttp requests  عند إنشاء المنشور يقوم الخادم بمعرفة مُعرف(id) صاحب المنشور عن طريق الtoken ومن ثم يقوم بتخزينه في قاعدة البيانات مع المنشور عند محاولة تعديل المنشور يقوم الخادم بالتأكد من وجود الtoken header إن لم يجده يُرسل رسالة خطأ للمُستخدم, إن وجده يتأكد إن المُعرف الموجود في الtoken هو ذاته الموجود في قاعدة البيانات للمنشور المُراد تعديله أو حذفه, إن وجد أنهم ليسوا نفس المُعرف يقوم بإرسال رسالة خطأ ويمكن البدأ في إستخدامها عبر أولا تثبيت الباكدج jsonwebtoken من npm 
    npm install jsonwebtoken ونقوم بتشفير البيانات بالشكل التالي 
    var privateKey = "secret"; var token = jwt.sign(userObj, privateKey); حيث نستبدل userObj بأوبجكت يُمثل بيانات المستخدم المُراد تخزينها ونستبدل الprivatekey بكلمة خاصة بك لصنع البصمة الرقمية
    ومن أجل التأكد من صحة الtoken عند إستقبالها من المستخدم 
    jwt.verify(token, 'secret', function(err, decoded) { console.log("succeed"); });  
  2. إجابة شرف الدين حفني سؤال في رفع مشروع Node.js على استضافة مجانية كانت الإجابة المقبولة   
    من الممكن رفعه على منصة heroku 
    نبدأ أولاً بتحميل heroku-cli وهي عبارة عن أداة تعمل في الcommand line وستجد الرابط مرفق بالأسفل
    بعد ذلك نقوم بتنفيذ الخطوات التالية بداخل مجلد المشروع المُراد رفعه: 
    نقوم بالتسجيل إلى heroku عبر الأمر التالي heroku login  
    بعد ذلك نقوم بتهيئة مستودع git 
    git init  
    نقوم بإنشاء مشروع على منصة heroku مع مﻻحظة إستبدال <app-name> بإسم مشروعك
    heroku create <app-name>  
    نقوم بعد ذلك بتنفيذ الأمر
    git add .  
    ثم نقوم بتنفيذ الأمر 
    commit -m "first"  
    ثم نقوم بتنفيذ تلك التغييرات إلى المشروع على منصة heroki 
    git push heroku master  وستجد في النهاية رسالة بنجاح عملية الرفع ومرفق معها رابط المشروع
  3. إجابة شرف الدين حفني سؤال في الفرق بين معمارية 32 bit و 64 bit في ويندوز كانت الإجابة المقبولة   
    يوجد في جهاز الحاسب الألي وحدة معالجة مركزية CPU وذاكرة mamory ويوجد ما يُسمى بالbus
    ال bus هي مجموعة من الموصلات أو أشباه الموصلات التي تقوم بحمل البيانات ويوجد ثﻻث أنواع
    control bus : والتي تقوم بإرسال الإشارات من المعالج إلى باقي وحدات الإدخال والإخراج data bus : والتي تقوم بإرسال البيانات من المعالج إلى باقي وحدات الإدخال والإخراج والعكس صحيح  address bus : والتي تقوم بإرسال عناوين الذاكرة من المعالج إلى الذاكرة حتى تقوم بعد ذلك الذاكرة بإرسال تلك البيانات المُضمنة في تلك العناوين إلى المُعالج الaddress bus يتم إرسال العناوين من خﻻله على هيئة إشارات كهربية 0 أو 1 مما يعني أننا إن أردنا أن نرسل عنوان مُكون من 8 أجزاء فبالتالي سنحتاج إلى 8 بيتات أي نحتاج إلى 8 سلوك لتمر من خﻻلها الإشارة الكهربية
    وبالتالي إن كان لدينا 8 سلوك نستطيع القول أن أقصى عدد من البيتات نستطيع إرسالها يكون 2 مرفوعة لأس 8
    وبالتالي إن كان لدينا 32 سلك فأقصى عنوان يمكننا الإشارة إليه هو 2 مرفوع لأس32 أي ما يساوي 4 جيجا , أي إن كان لدينا ذاكرة مساحتها أكبر من 4 جيجا لن نستطيع الإستفادة إلا من 4 جيجا منها فقط
    ولذلك تم إستخدام معمارية ال64 والتي ترمز إلى أنه يمكننا إرسال 64 بيت مما يوفر لنا إستخدام لموارد ذاكرة أكبر.
    إذا ماذا مقصود بالويندوز 64 بيت؟
    المقصود بالويندوز 64 بيت أنه تم تصميمه ليتمكن من إستهﻻك ال64 بيت الخاصيين بعناوين الذاكرة وﻻ يمكن تشغيله إلا على معمارية تسمح بذلك
    المقصود بويندوز 32 بيت أو نظام تشغيل 32 بيت بوجه عام أنه تم تصميمه ليتمكن من إستهﻻك 32 بيت فقط أي 4 جيجا رام وﻻ يمكنه الوصول إلى باقي الذاكرة
  4. إجابة شرف الدين حفني سؤال في ما الفرق بين switch و router كانت الإجابة المقبولة   
    أولاً نتكلم عن الفرق بين الdata link layer و الnetwork layer
    تتكون الشبكات من سبع طبقات يُطلق عليهم الOSI layers سنتكلم عن ثﻻثة منهم
    physical layer مسؤلة عن نقل البيانات عبر الأسﻻك وتردد الموجات والأشياء الفيزيائية أو المادية بوجهٍ عام data-link layer مسؤلة عن ربط كروت الشبكة ببعضهم البعض وصنع شبكة محلية بين الأجهزة network layer: مسؤلة عن ربط الشبكات ببعض  Switch
    الswitch ينتمي للطبقة الثانية Data-link kayer مما يعني أنه يتعامل مع كروت الشبكة (network card) أي أنه يقوم بتوجيه البيانات إستناداً على الmac address مما يعني أنه فقط يقوم بربط الأجهزة ببعضها البعض ولكن ﻻ يستطيع ربط الأجهزة ذات الشبكة الواحدة بالأجهزة في الشبكة الأخرى
    Router
    ينتمي الراوتر إلى  الطبقة الثالثة Network layer مما يعني أنه يتعامل مع الشبكات, ﻻ يفهم الmac address وإنما يفهم عنوان الشبكة IP Adress مما يعني أنه ﻻ يهتم بربط الأجهزة نفسها وإنما وظيفته ربط الشبكات , مثال لدي شبكة تحتوي على خمسة أجهزة متصلين بسويتش مما يجعلهم قادرين على الإتصال ببعضهم البعض
    ولديك خمسة أجهزة أيضاً أخرين متصلين بسويتش أخر ويتصلون ببعضهم, لكي نجعل أجهزتي تتصل مع أجهزتك نحتاج هنا أن نقوم بربط الشبكتين سوياً بواسطة راوتر 
    (ملحوظة ﻻ عﻻقة للراوتر الذي نتحدث هنا عن الراوتر المنزلي الموجود في المنزل المُقدم من شركات الانترنت, حيث أن الراوتر المنزلي يحتوي بداخله على أكثر من جهاز معاً راوتر, سويتش, موديم modem)
  5. إجابة شرف الدين حفني سؤال في ما المقصود ب subnet mask كانت الإجابة المقبولة   
    subnet mask هي عملية لتجزئة الشبكة
    ما المقصود بتجزئة الشبكة؟
    يجب أولاً أن نعلم أن عنوان الشبكة يكون به جزأ خاص بالشبكات وجزأ خاص بالأجهزة ويختلف هذا الجزأ حسب تصنيف الشبكة, فيوجد للشبكة تصنيفات :
    التصنيف A:  ويكون من 1.0.0.1 إلى 126.255.255.254 التصنيف B: يكون من 128.1.0.1 إلى 191.255.255.254 التصنيف C: يكون من 192.0.1.1 إلى 223.255.254.254  التصنيف D: يكون من 224.0.0.0 إلى 239.255.255.255 سنأخذ مثال على الip الذي رقمه 192.168.0.0 والذي هو من التصنيف C
    كما تﻻحظ فإن العنوان ينقسم إلى أربع خانات, في هذا التصنيف يكون أول ثﻻث خانات محجوزين للشبكات بينما أخر خانة محجوزة  للأجهزة
    كل خانة من تلك الخانات تُمثل 8 بيتات أي أن أقصى رقم في كل خانة هو 255 أي 256 جهاز (لأننا نأخذ رقم 0 في الحسبان)
    فمثلاً الشبكة التي عنوانها 192.168.1.0 تستطيع إضافة 256 جهاز من 192.168.1.0 إلى 192.168.1.255 
    كيف يتم كتابة الsubnet mask؟
    يتم كتابة الأجزاء الخاصة بالشبكات على هيئة 8 بيتات ممتلئة (255) والأجزاء الخاصة بالأجهزة يتم كتابتها على هيئة أصفار
    إذا الشبكة 192.168.1.0 يكون الsubnet mask الخاص بها 
    255.255.255.0  الأن ماذ لو كاانت تلك الشبكة تريد فقط إضافة 8 أجهزة, هل سنترك باقي الخانات فارغة وغير مستغلة؟ هذا يُعد تضيع للموارد إذا يجب أن نعيد تجزئة تلك الشبكة لنجعل خانات الأجهزة أقل وخانات الشبكات أكثر
    كيف يتم التجزئة
    دعنا نعلم أولاً أن  255.255.255.0 هي في الأصل 
    1111 1111. 1111 1111. 1111 1111. 0000 0000 ولكن لتسهيل التعامل نقوم بكتابتها على الصورة الثمانية بدلاً من الصورة الثنائية,  لنزيد عدد الشبكات نقوم بزيادة الخانات التي قيمتها 1 وتقليل الخانات التي قيمتها 0, فمثلاً إن كنا نريد أن نجعل عدد الأجهزة المتاحة 6 أجهزة نقوم بحساب أقرب أس للعدد 2 يعطينا 6 سنجد أن 3 يعطينا 8 ,ويوجد ععنوانين ﻻ يمكننا إستخدامهم لانهم دوماً محجوزين فإذا يعطينا 6, فهنا نترك فقط ثﻻث بيتات من أجل الأجهزة والباقي للشبكات 
    1111 1111. 1111 1111. 1111 1111. 1111 1000 ويتم ترجمته إلى 255.255.255.248 مما يعني توفر 8 عناوين للإستخدام والباقي من أجل الشبكات , فبهذا نقوم زدنا من عدد الشبكات وقللنا من عدد الأجهزة 
  6. إجابة شرف الدين حفني سؤال في متى نستخدم الtriggers في قواعد البيانات كانت الإجابة المقبولة   
    هذا يعتمد على عدد من العوامل  والإجابة عليه تكون حسب النظام الذي تقوم بإنشاؤه فﻻ توجد إجابة ثابتة, ولكن يمكنك إستنباط الحل الأفضل عبر ذكر العيوب والمميزات لإستخدام الtriggers:
    هل يقوم أكثر من تطبيق بإستخدام نفس قاعدة البيانات أم ﻻ يوجد إلا تطبيق واحد يقوم بالعمليات عليها؟؟ في تلك الحالة تكون نقطة للtriggers  إن كان أداء قاعدة البيانات هو امر حرج ومهم إذاً فإن الtriggers تفوز هنا أيضاً, حيث أنك ﻻ تحتاج أن تقوم بإرسال أكثر من إستعﻻم لقاعدة البيانات مما يساهم في خفض ال traffic  على قاعدة البيانات  ومن عيوب إستخدام الtriggers :
    يقوم بإنشاء طبقة من الغموض للمطور, حيث تقوم بكتابة جملة إستعﻻمية وتتفاجأ بتغيير في قاعدة البيانات غير الذي كنت تتوقعه كتابة الsql أحيانا يكون أصعب من التعامل مع البيانات من خﻻل لغات البرمجة العامة
  7. إجابة شرف الدين حفني سؤال في رفع الصور إلى المجلد ب PHP كانت الإجابة المقبولة   
    من الممكن أن يكون السبب في ذلك هو مسار الصور, جرب أن تكتب المصار بالشكل التالي
    $_SERVER['DOCUMENT_ROOT']."المسار بالنسبة لمجلد الhtdocs" حيث أن العنصر DOCUMENT_ROOT في المصفوفة $_SERVER تحتوي على المسار الخاص بالخادم
    إن لم يعمل برجاء التأكد من الصﻻحيات 
    يمكنك التأكد من أن المشكلة ليست من الصﻻحيات عن طريق الذهاب إلى مجلد الصور وتقوم بالتالي
    file > Right click > Get info 
    ومن ثم جعل الصﻻحيات read&write ومن ثم تجربة الملف مرة أخرى
  8. إجابة شرف الدين حفني سؤال في ما هو الفرق بين Docker و Kubernetes؟ كانت الإجابة المقبولة   
    docker هو حاوية, أي أنها تعمل كنظام تشغيل وهمي أو بيئة عمل يتم وضع المشروع بها حتى يتم التأكد من أن المشروع يعمل على نفس بيئة العمل ونفس الإعدادات عند كل المستخدمين فﻻ يحتاج أحد أن يُعدل في بيئة عمله لتتوافق مع المشروع
    بينما Kubernetes هو أداة لإدارة الحاويات وتنفيذ عمليات تلقائية عليها بشكل أوتوماتيك مثل النشر( deployment) والتشغيل 
     
  9. إجابة شرف الدين حفني سؤال في ما الفرق بين حالة http status code 415 و 501 كانت الإجابة المقبولة   
    كلا الخطأين يدلان على عدم إمكانية إرسال الطلب بهذا النوع من الطريقة, مثلا أن يكون لدينا ال endpoint التالية
    http://example.com/user وﻻ يكون بإمكان إرسال طلب عن طريق الhttp method delete فمن الممكن وقتها أن يأتيك أحدى الخطأين  ولكن الفرق بينهما كالتالي
    415 الطريقة غير مسموح بها method not allowed
    ـــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــ
    هذه الرسالة تعني أن تصميم الapi نفسه لا يدعم هذه الطريقة على هذا النوع من الموارد , مثلاً في الendpoint بالأعلى من الممكن أن يكون تصميم الapi ﻻ يدعم وجود خاصية حذف المُستخدم, ففي هذه الحالة يكوون الخطأ من العميل حيث أرسل طلب بطريقة غير موجودة في الapi من الأساس
    501 الطريقة لم تُدعم بعد method not implemented
    ـــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــ
    في هذه الرسالة تكون الapi مُصممة لإستقبال هذه الطريقة على هذا النوع من الموارد ولكن لم يتم دعممه في الوقت الحالي ولكن من الممكن دعمه في المستقبل, ففي المثال السابق إن كان يوجد بالفعل دالة تستمع للطريقة delete على الuser ولكن لم يتم تفعيل تلك الخاصية بعد(خاصية حذف المُستخدم) سيكون الرد برسالة 501 حيث أن الخطأ هنا من الخادم وليس العميل حيث أن الخادم يستمع إلى تلك الطريقة delete للuser ولكن فقط لم يقم بدعم تلك الخاصية في الوقت الحالي(لم يقوم بعمل implementation للدالة المسؤلة عن تلك الوظيفة)
  10. إجابة شرف الدين حفني سؤال في الفرق بين الhttp status code 401 و 403 كانت الإجابة المقبولة   
    الخطأ 401 يُعبر عن أن العميل يفتقر في طلبه إلى إثبات هويته
    بينما الخطأ 403 يُعبر عن أن العميل قد قدم إثبات هويته ولكن ليس له الحق في هذا الطلب
    فمثلاً إن حاولت إرسال طلب إلى api وكان الapi يشترط وجود header بإسم Authorization يحتوي على الjwt token وقمت بإرسال الطلب دون إرفاق الheader في هذه الحالة ستقوم الapi بإرسال حالة 401
    بينما إن قمت بإرسال طلب إلى الapi وحاولت الوصول إلى بيانات لا يمكن الوصول لها إلا من قِبل المدير( admin) وقمت بإرفاق header ال Authorization الذي يحتوي على الjwt خاصتك التي تحمل بياناتك وانت مُستخدم عادي ولست مدير, في هذه الحالة سترد عليك الapi بحالة 403 والتي تعني أن طلبك مفهوم ويحتوي على إثبات الهوية , ولكن هويتك غير مؤهلة لهذا الطلب
  11. إجابة شرف الدين حفني سؤال في كيفية إستخدام firebase مع react js كانت الإجابة المقبولة   
    طريقتك لإستعمال الfirebase هي طريقة الإصدار 8 , بينما في الغالب أنت تعمل بإستخدام الإصدار9
    في الإصدار التاسع تختلف طريقة عمل الfirebase مع react حيث نقوم بدلاً من 
    import firebase from '@firebase/app'; import '@firebase/storage';  نقوم بإستيراد 
    import { initializeApp } from "firebase/app"; import {getStorage, ref} from "firebase/storage"; ونقوم بإعداد الfirebase بإستخدام دالة الinitializeApp وتمرير الإعدادات الخاصة بالمشروع
    const app = initializeApp(firebaseConfig) ويجب أن يكون لديك كائن للإعدادات(firebaseConfig) حيث يحتوي على اعدادات المشروع كما بالشكل التالي
    const firebaseConfig = { apiKey: "your api key", authDomain: "your authDoomain", databaseURL: "your database", projectId: "project id", storageBucket: "storage bucket", messagingSenderId: "message id", appId: "your app id", measurementId: "measurement id" }; وللحصول على ذلك الملف يمكنك الدخول إلى موقع فاير بيز وأختيار مشروعك ومن ثم تذهب إلى قائمة ال project settings
    ومن ثم يمكنك الحصول على كائن التخزين storage والref بالشكل التالي
    const storage = getStorage(app); const image_ref = ref(storage,"/images");  
  12. إجابة شرف الدين حفني سؤال في كيفية إعداد النسخ الاحتياطي باستخدام rsync كانت الإجابة المقبولة   
    rsync هو برنامج يُستخدم لعمل مزامنة بين المجلدات, حيث يجعل المجلد 1 نسخة طبق الأصل من المجلد 2 , ينسخ الملفات الناقصة, ويحذف الملفات الزائدة
    أولا نقوم بتثبيت البرنامج عبر الterminal  sudo apt-get install rsync  
    بعد ذلك يمكننا إستخدامه بالشكل التالي 
    rsync -av --delete /Directory1/ /Directory2/ الخيار a يجعل البرنامج ينسخ المجلدات أيضاً وليس الملفات فقط, الأمر v جعل البرنامج يقوم بطباعة رسالة يشرح فيها ما حدث تحديداً في التنفيذ, الخيار --delete يخبر البرنامج أن يقوم بحذف أي ملفات زائدة, يمكننا إزالة هذا الخيار إن لم نريد تلك الوظيفة
    لجعل هذا البرنامج يعمل بشكل تلقائي كل يوم, يمكننا إستخدام برنامج cron وهو برنامج من أجل عمل مهام دورية في نظام لينكس
    crontab -e ذلك الأمر سيقوم بفتح جدول مهام الcron 
    يمكننا تعديل الجدول ليوافق إحتياجاتنا ونضع به المهام التي نريدها 
    0 20 * * * rsync -av --delete /hsoub1/ /hsoub2/ هذا الأمر سيجعل البرنامج يتم تنفيذه كل يوم في الساعة 20(الثامنة ليلاً) في الدقيقة صفر 
  13. إجابة شرف الدين حفني سؤال في كيف يمكنني دمج نتائج استعلامين من جدولين لهما نفس البنية في SQL كانت الإجابة المقبولة   
    يُمكنك تنفيذ ذلك عبر إستخدام الإتحاد(union) حيث وظيفة خاصية الإتحاد أن تقوم بدمج عناصر مجموعتين ليصبحو ع هيئة مجموعة واحدة فمثلاً
    {1, 3, 7, 5} union {2, 4, 6, 8} = {1, 2, 3, 4, 5, 6, 7, 8} ويتم تنفيذه في لغة sql بالشكل التالي
    (SELECT * FROM a) UNION (SELECT * FROM b) وتقوم بتبديل a و b بإسم الجداول المُراد دمجها
  14. إجابة شرف الدين حفني سؤال في كيفية تحويل مصفوفة إلى ملف json بدون إضافة رقم الفهرس في php كانت الإجابة المقبولة   
    تلك المشكلة تحدث عند التﻻعب بالمصفوفة وإنتاج مصفوفة تحتاج إلى إعادة الفهرسة (re-indexing) مما يجعل الjson_encode ﻻ يعتبر أن تلك الأرقم هي فهرس للمصفوفة بل يعتبرها مفاتيح نظراً لأنها مفهرسة بشكل غير سليم, الحل أن تقوم بإعادة الفهرسة ويمكنك القيام بذلك ببساطة عبر إستخدام الدالة array_values والتي تأخذ مُعامل واحد عبارة عن المصفوفة المُراد إعادة فهرستها وتُنتج مصفوفة بدون مفاتيح بل بفهرس سليم كما في الشكل التالي
    $arr = array_values($arr); var_dump(json_encode($arr))  
  15. إجابة شرف الدين حفني سؤال في كيف يمكنني دمج قيم الحقول ضمن الاستعلام SELECT في SQL؟ كانت الإجابة المقبولة   
    يمكنك إستخدام الدالة CONCAT والتي تأخذ مُعاملان وتدمجهم ليصبحو معامل واحد كما في الشكل 
    select concat(fname,lname) as fullname from employee ولكن هذا إن كان كلاً من الحقل الأول والثاني من نوع السلسلة النصية , إن كان أحد الحقول أو كﻻهما من نوع بيانات أخر يجب أولاً تغيير هذا النوع وتحويله إلى سلسلة نصية, وتتم تلك العملية بشكلٍ مختلف حسب قاعدة البيانات المُستخدمة 
    في SQL-SERVER: يمكنك إستخدام الدالة CONVERT  كما في الشفرة 
    SELECT CONCAT( CONVERT(varchar(10), salary) , fname) as 'salary / name' FROM employee في postgres يمكنك إستخدام الدالة cast 
    SELECT CONCAT(CAST(salary AS text),fname) AS name_salary في mysql ﻻ يجب فعل شيئ فستقوم دالة concat بتحويل الأرقام إلى نصوص بشكلٍ تلقائي 
    select concat(salary, fname) as name_salary  
  16. إجابة شرف الدين حفني سؤال في خطأ عند إستخدام دالة rank في قاعدة بيانات postgres كانت الإجابة المقبولة   
    سبب تلك المشكلة أنك تقوم بإعطاء دالة الرتب(rank) معاملات (parameters) بينما تلك الدالة تعمل دون تمرير أي معاملات لها, إن كنت تريد ترتيب الموظفين بناءاً على مرتبهم إذا يجب عليك إعطاء الدالة over معامل order by salary لتصبح في النهاية الجملة كالتالي
    select rank() over(partition by gender order by salary) from employee وبوجه عام, نقوم بإعطاء دالة الover كمعامل أول العمود المُراد تقسيم الصفوف إلى مجموعات طبقاً لقيمته مسبوقاً بكلمة partition
    في حالتك هنا تريد تقسيم البيانات إلى مجموعات طبقاً لجنسهم , أي طبقاً لقيمة العمودgender
    ومن ثم نقوم بترتيب العناصر طبقاً للعمود المُراد حساب الرتبة بناءاً عليه بإستخدام جملة order by متوبعةً بإسم العمود
  17. إجابة شرف الدين حفني سؤال في كيفية إزالة الفواصل الناتجة عن الدالة Array.toString في "Javascript" كانت الإجابة المقبولة   
    ﻻ يمكنك تحقيق ذلك مباشرةً من خﻻل الدالة Array.toString ولكن يمكنك تحقيق ذلك عن طريق الدالة join
    وتقوم دالة join بضم العناصر بداخل المصفوفة وتحويلهم إلى سلسلة نصية , وتعريف الدالة كالتالي
    join() join(separator) من الواضح كما ترى أن يمكن إعطاء مُعامل إلى الدالة أو إستدعائها بدون معاملات, المعامل هنا هو الفاصل بين العناصر seperator, بشكل إفتراضي تكون قيمة الفاصل بفاصلة 
    const arr=["a","b","c"]; const str=arr.join(); console.log(str);////a,b,c ومن الممكن إعطاء قيمة للفاصل حتى يتغير سلوك الدالة 
    const arr=["a","b","c"]; const str=arr.join("+"); console.log(str);////a+b+c وفي حالة كنت تريد طباعة العناصر بجانب بعضها البعض دون أي فواصل يمكنك وضع عﻻمتي تنصيص فارغتين 
    const arr=["a","b","c"]; const str=arr.join(""); console.log(str);////abc  
  18. إجابة شرف الدين حفني سؤال في لا تقوم إعادة توجيه NextJS بإعادة التوجيه عند استخدام url كانت الإجابة المقبولة   
    هذا لأنك تقوم بكتابة الصيغة بشكل خاطئ, حيث من المفترض أن تتم كتابة الصيغة على النحو التالي
    async redirects() { return [ { source, has, destination, permanent, }, ] } بينما قمت انت بكتابتها على النحو التالي
    async redirects() { { source:, has, permanent: destination, }, } فأولاً أنت لم تقم بوضع كلمة return لتحدد القيمة التي يتم إرجاعها من تلك الدالة, ثانياً لم تقم بتغليف الكائن في مصفوفة, فيجب عليك إعادة كتابتها لتصبح مﻻئمة , مثلاً تكن هكذا 
    async redirects() { return[ { source: '/shop', has: [ { type: 'query', key: 'q', value: '(<sef>)', }, ], permanent: false, destination: '/shop/:sef', }, ] }  
  19. إجابة شرف الدين حفني سؤال في ﻻ أستطيع فتح صفحة phpmyadmin في xampp أوبونتو كانت الإجابة المقبولة   
    تلك الرسالة تظهر بسبب تغيير الصﻻحيات الخاصة بملف ال config.inc.php أو المجلد الحامل لهذا الملف,
    من الممكن أن تكون قد قمت بتنفيذ أمرٍ ما لتغيير الصﻻحيات مثل
    sudo chmod -R 777 /opt/lampp/ أو قمت بتغييره بطريقة أخرى , ولكن بوجهٍ عام فإن الطريقة الصحيحة لتغيير الصﻻحيات هي أن تقوم بتغيير صﻻحيات مجلد المشروع وليس مجلد البرنامج كلهُ , وتقوم بتغيير صﻻحيات مجلد المشروع عبر تنفيذ نفس الأمر السابق ولكن تضع مسار مجلد المشروع بدلاً من مسار البرنامج الأب 
    sudo chmod -R 777 /opt/lampp/php_project/ وبالنسبة لحل المشكلة التي تواجهك يمكنك تغيير الصﻻحيات من أجل حل المشكلة عن طريق الأمر التالي
    sudo chmod 755 /opt/lampp/phpmyadmin/config.inc.php وفي ذلك السؤال المرفق ستجد إجابة أستاذ وائل بها شرح كافي ووافي لكيفية تغيير الصﻻحيات بطريقة صحيحة 
     
  20. إجابة شرف الدين حفني سؤال في ماهي وظيفة over(partition) في لغة sql كانت الإجابة المقبولة   
    جملة over(partition)  تقوم بتوزيع ناتج دالة الaggregate طبقاً للحقل الموضوع بعد كلمة by 
    على سبيل المثال إن كان لدينا البيانات التالية 
    { name:sharaf, age:21 } { name:ashraf, age: 49 } { name: mohamed, age:21 } { name:ahmed, age:25 } { name:saad, age:49 } إن قمت بتنفيذ الجملة 
    select * , count(*) over(partition by st_age ) from table_name سيقوم بإرجاع البيانات , وسيقوم بحساب عدد العناصر حسب العمر فسنجد ناتج الجملة كالتالي
    name age count sharaf 21 2 ashraf 49 1 mohamed 49 2 ahmed 25 1 saad 21 2 ستﻻحظ جلب البيانات وبجانبها الحقل count الذي يحدد كم عدد البيانات المنتمية لنفس الage, حيث أن في العادي إن إستخدمت الaggregate functions تقوم بتحويل عدد من الصفوف إلى صف واحد, ولكن صيغة ال over partition والتي يتم أيضاً تسميتها بالwindow functions تقوم بإرجاع مجموعة الصفوف إلى مجموعة صفوف أيضاً وليس صف واحد
  21. إجابة شرف الدين حفني سؤال في خطأ عند استخدام دالة map في جافاسكريبت كانت الإجابة المقبولة   
    البيانات تأتي لك في صورة كائن وليس مصفوفة, لديك أحد الحلين, إنا أن تقوم بإستقبال البيانات من خاصية #my-carousel .carousel-indicators في جافاسكريبت على النحو التالي
    data["#my-carousel .carousel-indicators"].map أو أن تقوم بتحويل الكائن كله إلى مصفوفة على هيئة مفتاح وقيمة (key & value)
    Object.keys(data).map((key, index) => ( console.log(data[key]) ))  
  22. إجابة شرف الدين حفني سؤال في ﻻ افهم فائدة ال for await بشكل جيد في الجافاسكريبت كانت الإجابة المقبولة   
    تُستخدم الfor await من أجل إتاحة صيغة الfor each ولكن للمُكررات(iterators) التي تقوم بإرجاع promise 
    فمثلاً في الطبيعي إن كان لدينا مُكرر كما بالشكل التالي
    function* colorIterator() { yield "blue"; yield "red"; } يمكننا بكل سهولة أن نقوم بالمرور عبره بإستخدام forEach بالشكل التالي
    const iterat = colorIterator(); for (const color of iterat) { console.log(color); } ولكن ماذا إن كان لدينا مُكرر يحتوي على promises ? في تلك الحالة لن تفيدنا كثيراً صيغة الfor each حيث أنها ستقوم بإرجاع promise وليس قيمة , أي أنها ستقوم بإرجاع كائن كما هو بهذا الشكل
     
    Promise {<pending>} [[Prototype]]: Promise [[PromiseState]]: "pending" [[PromiseResult]]: undefined وﻻ نستطيع إستخراج بيانات مفيدة من كائن بهذا الشكل, في الطبيعي كنا نقوم بإستخدام صيغة .then للتعامل مع الpromises كما بهذه الشفرة
    my_promise.then(response=>///code) ولكن ﻻ يمكننا تنفيذ صيغة كتلك في الforeach , الحل أن نقوم إذا بإستخدام صيغة الfor await , فإن كان لدينا مُكرر كالتالي
    const asyncIterable = { [Symbol.asyncIterator]() { return { i: 0, next() { if (this.i < 3) { return Promise.resolve({ value: this.i++, done: false }); } return Promise.resolve({ done: true }); } }; } والذي ببساطة يحتوي على مجموعة من الpromises تقوم بإرجاع 1, 2, 3
    فﻻ نستطيع إستخدام الfor each التقليدية لأننا لن نحصل إلى على promises لم تُعالج بعد, ففي تلك النقطة يجب إستخدام الfor await of كما في الشفرة البرمجية التالية
    (async function() { for await (let num of asyncGenerator()) { console.log(num); } وكما تﻻحظ عزيزي فإن الدالة التي تحتوي على الfor await هي من النوع async حيث ﻻ يمكننا إستخدام تلك الصيغة إلا على الدوال من النوع async 
  23. إجابة شرف الدين حفني سؤال في كيفية حذف جميع الأصفار المتتالية في نص في لغة c++ كانت الإجابة المقبولة   
    نقوم أولا بالتعبير عن نمط البحث بإستخدام التعبيرات الإعتيادية (regular expression) حيث أننا نريد حذف رقم صفر فنقوم بكتابة 0 داخل قوس في التعبير, وبما أننا نريد حذف الأصفار المتتالية نقوم بكتابة عﻻمة التتالي وهي رمز + إن كنا نريد أن نحذف الأصفار الموجودة في بداية النص نقوم بكتابة رمز ^ قبل التعبير إن كنا نريد حذف الأصفار الموجودة في نهاية النص نقوم بوضع عﻻمة ال$ في نهاية التعبير في النهاية يُصبح التعبير كما بالشكل التالي "[0]+" /// لمطابقة جميع الأصفار المتتالية سواء في بداية أو نهاية أو منتصف النص "^[0]+" ///لمطابقة الأصفار المتتالية في بداية النص "[0]+$" //لمطابقة الأصفار المتتالية في نهاية النص وبالنسبة لتطبيق ذلك في لغة c++ يجب أوﻻً أن نقوم بإنشاء متغير من نوع regex ليقوم بحفظ التعبير الذي قمنا بتصميمه 
    regex re("^[0]+") ومن ثم نقوم بإستخدام الدالة regex_replace التي تأخذ في أول مُعطى النص الذي نريد تنفيذ التعبير عليه, وفي ثاني معطى التعبير الذي قمنا بإنشاؤه , وفي ثالث مُعطى رقم التعبير إن كنا نمتلك مجموعة مختلفة من التعبيرات
    regex re("^[0]+"); string s="000sharaf"; cout<<regex_replace(s,re,"");////sharaf  
  24. إجابة شرف الدين حفني سؤال في هل يوجد خوارزمية فعالة للتأكد إن كان العدد أولي كانت الإجابة المقبولة   
    ﻻ يوجد قانون لحساب العدد الاولي ولكن يوجد طرق أكثر فاعلية من المرور من الرقم 2 حتى الرقم س , ولكن دعنا نضع الإثبات الرياضي التالي أولاً حتى نستوعب الطريقة بشكلٍ أفضل
    دعنا نرمز للرقم المُراد معرفة إن كان أولي بالرمز س دعنا نفترض عددين أ, و ب إن كان أ>جذر س و ب > جذر س إذاً أ*ب > س مما سبق نستنتج أن ﻻ يمكن أن يكون أ و ب أكبر من س الإستنتاج السابق يُبت لنا أن ﻻ يمكن أن يكون للعدد أعداد يقبل القسمة عليها أكبر من جذرهِ التربيعي
    بالتالي يمكننا تحسين الخوارزمية بدلاً من المرور بدءاً من الرقم 2 حتى العدد س , أن نقوم بالمرور بدءاً من العدد 2 حتى الجذر التربيعي للعدد س
    وبالتالي يتم تقليل التعقيد الوقتي(time complexity) للخوارزمية لتتحول من O(n) إلى O(sqrt(n)) 
    ويمكنك معرفة المقصود بالتعقيد الوقتي بشكل أكبر من خﻻل المقالة المرفقة
     
  25. إجابة شرف الدين حفني سؤال في لماذا تقوم قواعد البيانات باستخدام الb+ tree بدلاً من hashtable كانت الإجابة المقبولة   
    الhash table (جدول التشفير) يعمل بالشكل التالي
    يتم عمل عملية hashing للمفتاح يتم تخزين قيمة المفتاح في الذاكرة في العنوان الذي حصلنا عليه من عملية الhashing عندما نريد الحصول على القيمة المُخزنة في قاعدة البيانات نقوم بكُل بساطة بعملية hashing للمفتاح الذي نريد الحصول على قيمته ومن ثم نذهب للذاكرة في العنوان الذي حصلنا عليه من عملية الhashing ونأتي بالقيمة عملية بسيطة والتعقيد الوقتي لها (Time complexity) أقل نوع وهو الثابت O(1)  
    بالنسبة للأشجار(trees) فيتم فيها تخزين العناصر بشكل مرتب وعندما نريد الحصول على عنصر معين نقوم بالنظر في منتصف العناصر, إن كان العنصر المحصول عليه أكبر من المُراد نبحث في الجزأ الأيسر من العناصر( على فرض أن العناصر في الشجرة مرتبة من اليسار لليمين بشكلٍ تصاعدي) , إن كان العنصر أصغر نبحث في الجزأ الأيمن.
    تلك العملية في المتوسط تأخذ وقت O(logn) 
    حسنا لماذا إذا نقوم بإستخدام الأشجار بدلاً من الجداول؟ ببساطة لأن بسبب أن الجداول تتعامل بعنوان الذاكرة وليس ترتيب معين للعناصر يوجد بعض العمليات التي تكون غير عملية بإستخدام الجداول, مثلاً ﻻ نستطيع أن نعثر على جميع العناصر الأقل من قيمة معينة أو أكبر من قيمة معينة, ﻻ نستطيع العثور عﻻ جميع العناصر بين قيمتين 
    select * where id >5000 select * where id between(1000, 2000) select all where id <1000 كل تلك العمليات تكون غير عملية بالمرة بالنسبة للجدول , بالإضافة لعمليات الترتيب التي تكون مجهدة
    بالنسبة للأشجار لأنها تتعامل مع العناصر مرتبة وتخزن العناصر على هيئة قائمة وليس على اساس عنوان في الذاكرة فيكون تلك العمليات سهلة , فنضحي بشئٍ من السرعة مقابل الكثير من المرونة .
×
×
  • أضف...