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

لوحة المتصدرين

  1. Mustafa Suleiman

    Mustafa Suleiman

    الأعضاء


    • نقاط

      8

    • المساهمات

      15303


  2. محمد عاطف17

    محمد عاطف17

    الأعضاء


    • نقاط

      3

    • المساهمات

      5534


  3. ياسر مسكين

    ياسر مسكين

    الأعضاء


    • نقاط

      3

    • المساهمات

      1713


  4. عمر حسام أحمد عبدالغفار سلو

    • نقاط

      3

    • المساهمات

      27


المحتوى الأكثر حصولًا على سمعة جيدة

المحتوى الأعلى تقييمًا في 03/23/25 في كل الموقع

  1. هل سنتطرق في هذه الدورة لfrontend او backend مثل تطوير الويب بشكل كامل مثلا ؟
    3 نقاط
  2. السلام عليكم لدي ويندوز 11 كل شي باللغةالعربية كم هو موضح في عرض نظام العربية ليبيا لماذا بعض خيارات لاتظهر بالعربي
    1 نقطة
  3. بسم الله السلام عليكم ورحمة الله هناك مسافة لونها بنفسجي لما انا بعمل inspect للكود عندي مخربطه عليا الدنيا كلها انا معرفش هي جت ازاي ولا هي ايه انا عايز اعرف تفاصيل عنها
    1 نقطة
  4. اضغط على الثلاث نقاط مرة أخرى بجانب اللغة، وتأكد من تفعيل خيار Set as my Windows display language ثم حاول إعادة تشغيل النظام، من المفترض أن يتم تغيير اللغة طالما قمت بذلك، لو استمرت المشكلة، قم بتشغيل CMD كمسؤول ثم اكتب التالي لتحويل اللغة: DISM /Online /Set-DefaultUILanguage:ar-LY
    1 نقطة
  5. اضغط على الثلاث نقاط على يمين اللغة "العربية ليبيا" ثم اختر language option أو خيارات اللغة، في حال ظهر لك installed أو مثبتة فيعني أن ملفات اللغة تم تحميلها، في حال ظهر لك زر تثبيت اضغط عليه. بعد ذلك قم بالرجوع للخلف لإعدادات اللغة، ومن windows display language اختر الإنجليزية ثم اختر العربية مرة أخرى، في حال ظهر لك يجب تسجيل الخروج قم بالضغط على sign-out.
    1 نقطة
  6. قمت بإعادة التشغيل لزالت اللغة الانجليزية موجودة
    1 نقطة
  7. قم بإعادة تشغيل الحاسوب ليتم تعديل اللغة في كامل برامج الويندوز.
    1 نقطة
  8. كيف اتغلب على مشكلة الخروج من اللوميون أثناء عملية الرندر حيث يصل إلى حد معين ويخرج تلقائيا قبل اكتمال عملية الرندر
    1 نقطة
  9. ليس بشكل كامل بمعنى بناء مشاريع وشرح تقنيات الواجهة الأمامية مثل React والواجهة الخلفية مثل Express.js. لكن سيتم شرح أساسيات كلٌ منهم، ففي مسار قواعد البيانات ستتعلم أساسيات الواجهة الخلفية وكيفية التعامل مع قواعد البيانات المختلفة وتعلم اللغة الخاصة بها وهي SQL، وأيضًا تعلم أساسيات بيئة التشغيل Node.js الخاصة بالواجهة الخلفية وكيف يتم بناء سيرفر والتعامل مع قاعدة البيانات من خلاله. ثم في مسار إلى عالم الويب، ستتعلم أساسيات الويب وكيف يعمل الإنترنت وآلية الربط بين الواجهة الأمامية والخلفية، لكن لم يتم التطرق للغات الواجهة الأمامية وهم HTML, CSS فليس الغرض من الدورة بناء المواقع. وقبل كل في مسار أساسيات البرمجة ستتعلم لغة جافاسكريبت وهي اللغة الأساسية لبرمجة الواجهة الأمامية، وبعد ذلك أصبحت تستخدم في تطوير الواجهة الخلفية من خلال Node.js وأيضًا تطبيقات الهواتف وسطح المكتب.
    1 نقطة
  10. ما سيتم التطرق إليه في هذه الدورة هو هذه النقاط: أساسيات الحاسوب وعلومه والتفكير المنطقي وما هي الخوارزميات وكيف تفيد في البرمجة تطبيقات عملية على أساسيات التفكير المنطقي باستخدام بيئة سكراتش Scratch التفاعلية أساسيات لغة البرمجة JavaScript وتطبيق المفاهيم التي تم شرحها باستخدامها، والتوسع في شرح التطبيقات العملية للغات البرمجة أساسيات أنظمة التشغيل المختلفة وكيفية تثبيت البرمجيات اللازمة للبرمجة عليها أساسيات سطر الأوامر في نظام لينكس، وشرح الأسس التي بني عليها النظام مع تطبيقها عمليًا أنظمة قواعد البيانات المختلفة، مع شرح تفصيلي للغة SQL للتعامل معها مبادئ أساسية في أنظمة قواعد البيانات NoSQL المفاهيم الأساسية التي تبنى فيها صفحات الويب مفاهيم أساسية في الشبكات والخوادم، وكيف يتم استقبال الطلبيات إلى الخادم والرد عليها مبادئ الحماية والأمان في الويب يمكنك الاطلاع عليها من خلال التوجه إلى صفحة الدورة، من خلال تبوبية: دورات أو من هنا مباشرة: بالتوفيق إن شاء الله.
    1 نقطة
  11. نحتاج كثيرًا إلى استعمال جداول البيانات لتخزين بيانات دورية خلال يومنا لتجنب نسيانها فقد لا نكون دومًا خلف طاولة العمل حيث الدفاتر والحاسوب بل قد نكون في الشارع أو الحافلة ولا نملك سوى الهاتف في يدنا ولا نريد استعمال تطبيق الملاحظات الممتلئ بملاحظات مبعثرة هنا وهناك. على سبيل المثال إذا احتجنا لاستخدام جداول بيانات جوجل Google Sheets لتسهيل تسجيل بعض البيانات ومتابعتها دوريًا من مكان واحد سنواجه صعوبة في التعامل مع Google Sheets على الجوال لأن الشاشة صغيرة وغير مريحة بالعمل، لذا قد نضطر إلى تدوين الملاحظات سريعًا لإدخالها في جداول البيانات وتنظيمها لاحقًا عند توفر الحاسوب. سنوضح في مقال اليوم طريقة سهلة وعملية لإدارة إدخال البيانات في جداول بيانات جوجل من خلال إنشاء بوت تلغرام Telegram وظيفته إدخال البيانات وتنظيمها مباشرةً في جداول البيانات، فلا يكاد يخلو أي هاتف جوال من تطبيق تلغرام الشهير وبهذا ندخل البيانات بسهولة من خلاله دون الحاجة لفتح تطبيق جداول البيانات، كل ما نحتاجه هو إرسال رسالة بصيغة معينة للبوت ليأخذها ويرسلها لجداول بيانات جوجل ويخزنها هناك.أي تتألف العملية من ثلاثة خطوات، ارسال الرسالة التي تحوي البيانات إلى البوت، ثم نقل البيانات، ثم أخيرًا تخزينها في وجهتها. متطلبات مسبقة للعمل نحتاج قبل إكمال هذا المقال إلى ما يلي: حساب على تطبيق تلغرام حساب جوجل مع إمكانية الوصول إلى تطبيق جداول بيانات جوجل Google Sheets معرفة مسبقة باستعمال Google Sheets، ويمكن الرجوع إلى مقال مقدمة إلى جداول بيانات جوجل Google Sheets معرفة أساسية بلغة جافاسكريبت، ويمكن الرجوع إلى مقال تعلم لغة جافا سكريبت JavaScript التطبيق النموذجي لربط بوت تلغرام مع جداول بيانات جوجل سنعتمد على نموذج بيانات بسيط بغرض التعلم حيث سنتعلم من خلاله آلية ربط بوت تلغرام مع جداول بيانات جوجل، والنموذج الذي سنستخدمه هنا هو بيانات الإيرادات والنفقات اليومية كما توضح الصورة التالية: ملاحظة: استخدمنا هذا النموذج بغرض التعلم ونترك لكم تطبيق ما ستتعلمونه على نموذج البيانات المناسب لاحتياجاتكم. الخطوة الأولى: إنشاء بوت تلغرام Telegram Bot سنستعمل تطبيق تلغرام على الويب للسهولة، لذا سنفتح تطبيق تلغرام ويب ونسجل الدخول، ثم نبحث في حقل البحث عن BotFather وهو كبيرُ البوتات الذي سيساعدنا على إنشاء بوتات تلغرام وإدراتها. لنتبه إلى أن مُعرِّف كبير البوتات الرسمي هو ‎@botfather إذ ستظهر لنا عدة نتائج في حقل البحث: لنضغط بعدها على البدء Start وستظهر أمامنا رسالة فيها قائمة طويلة من الخيارات اللازمة لإنشاء بوتات تلغرام وإدارتها، بعدها سيسألنا كبيرُ البوتات عن اسم البوت الذي نريد إنشاءه فنجبه باسم البوت وسندخل هنا الاسم إيرادات ونفقات: سيطلب بعدها كبيرُ البوتات إدخال اسم مُعرِّف أو اسم المستخدم للبوت الجديد، وننتبه لأن هذا الاسم يجب أن ينتهي بالكلمة bot سواءً بالشكل usernameBot أو username_bot، وسنستخدم هنا الاسم MyIncomeAndExpensesBot: ملاحظة: قد لا يقبل البوت بعض اقتراحات اسم المستخدم مثلًا عندما جربنا إدخال اسم المستخدم IncomeExpensesBot وIncomeAndExpensesBot لم يقبلهما لكونهما محجوزان مسبقً، لذا قد نحتاج لتعديل الاسم حتى نجد اسمًا متاحًا. سينُشئ بعدها كبيرُ البوتات البوت الجديد ويرسل لنا رسالة يخبرنا فيها عن رابط الوصول للبوت ورمز الوصول إليه access token عبر طلبات HTTP: لنحفظ هذا الرمز لأننا سنستعمله لاحقًا في التواصل مع هذا البوت. تجربة التواصل مع بوت تلغرام الجديد سنلاحظ في آخر الرسالة الموضحة بالصورة السابقة أن كبير البوتات قد أشار إلى توثيق واجهة البوت البرمجية، سنحتاج دومًا لفتح هذا التوثيق ونرجع إليه دومًا في آلية ربط بوت تلغرام والتواصل معه، فقد تتغير الآلية وتتعدل الواجهة البرمجة مستقبلًا. لنتأكد أن البوت قد أُنشئ وأصبح جاهزًا للتواصل، وذلك بزيارة الرابط التالي في متصفح الويب بعد تبديل {access_token} برمز وصول البوت الذي حصلنا عليه مسبقًا: https://api.telegram.org/bot{access_token}/getMe إن سارت الأمور على ما يرام، فسنحصل على نتيجة مشابهة للنتيجة التالية تحوي تفاصيل البوت ورده علينا: { "ok": true, "result": { "id": 7666156735, "is_bot": true, "first_name": "إيرادات ونفقات", "username": "MyIncomeAndExpensesBot", "can_join_groups": true, "can_read_all_group_messages": false, "supports_inline_queries": false, "can_connect_to_business": false, "has_main_web_app": false } } نلاحظ أننا حصلنا من الرسالة السابقة على رقم البوت id، واسمه first_name، واسم المستخدم username، وبعض التفاصيل الأخرى التي لن تلزمنا في هذا المقال مثل إمكانية انضمام البوت للمجموعات وغيرها. ضبط بوت تلغرام قبل أن نكمل، نود أن نشير لإمكانية ضبط بوت تلغرام الجديد -وأي بوت آخر- عبر كبير البوتات BotFather مباشرةً، فمثلًا لنجرب كتابة / أو اضغط على زر قائمة Menu بجانب حقل الكتابة في المحادثة وستظهر لنا خيارات كثيرة كان كبير البوتات قد ذكر أهمها في أول رسالة أرسلها لنا بعد الضغط على زر البدء Start: سنذكر بعض هذه الأوامر: ‎/mybots لعرض بوتات تلغرام الخاصة بنا ‎/setname لتغيير اسم بوت تلغرام ‎/setdescription لضبط أو تغيير وصف البوت ‎/setuserpic لضبط أو تغيير صورة البوت يمكن تجربة هذه الأوامر مع بقية الأوامر لتتعلم أكثر عن ضبط وإدارة بوتات تلغرام. فهم آلية الربط والتواصل بين بوت تلغرام وجداول بيانات جوجل قبل أن ننتقل إلى الخطوة التالية من مقالنا، من الضروري فهم آلية ربط بوت تلغرام مع جداول بيانات جوجل -أو أي خدمة أخرى مثلًا- حتى نفهم كيف سنكمل عملية الضبط. لنتذكر أن هدف المقال إرسال رسالة بصيغة معينة إلى بوت تلغرام، ليقوم بدوره بتنفيذ أوامر محددة وظيفتها أخذ رسالتنا وإرسالها إلى جداول بيانات جوجل لتخزينها هناك، وبذلك يمكن تقسيم العملية إلى ثلاثة خطوات، الأولى إرسال الرسالة التي تحوي البيانات إلى البوت، و الثانية نقل البيانات، والثالثة تخزينها في وجهتها. يمكننا التواصل مع البوت عبر آليتين : الأولى هي التواصل عبر الواجهة البرمجية APIs مباشرةً وسؤاله عما نريد، مثلًا يمكن إرسال طلب للواجهة البرمجية ‎/getMe لطلب معلومات عن البوت، أو الواجهة البرمجية ‎/getUpdates لطلب كافة الرسائل المرسلة إلى البوت وغيرها، ويمكنك الرجوع إلى توثيق واجهات بوت تلغرام البرمجية للاطلاع على القائمة الكاملة. الآلية الثانية هي التواصل من خلال خطافات الويب Web Hooks أي أننا نطلب من البوت نفسه أن يتواصل معنا عند وقوع أحداث معينة، وسنجد في توثيق Update قائمة الأحداث المدعومة في بوت تلغرام، حيث نحدد ما هي الأحداث التي نحتاجها بالضبط. هذا يشبه آلية تواصلنا نحن البشر، تخيل لو كنا نريد -ونحن في العمل- معرفة إن وصلت طلبية طلبناها إلى منزلنا أم لا، عندها إما أن أتصل بالمنزل ونسأل الأهل إن وصلت الطلبية، أو أن نطلب من الأهل أن يتصلوا بنا متى ما وصلت الطلبية. سنعتمد في هذا المقال على آلية خطافات الويب web hooks وسنختار حدث استلام رسالة، فكلما استلم البوت رسالة سيقوم بأمر محدد وهو إرسالها إلى خادم جوجل ننشره على الإنترنت عبر عبر برمجة تطبيقات Google أو Apps Scripts والذي بدوره يستلم البيانات ويُخزِّنها في جدول بيانات جوجل وهذا ما سنعمل على ضبطه. ملاحظة: ذكرنا أننا سنعتمد على خادم ننشره عبر برمجة تطبيقات جوجل وبذلك لن نحتاج إلى إنشاء خادم خاص للتواصل، ولكن الأمر هنا يعود لما يناسب احتياجنا ومتطلباتنا، فيمكن إنشاء خادم خاص والتواصل مع البوت ومعالجة البيانات وتخزينها بأي لغة برمجة نريدها، وإظهارها بالشكل الذي نريد مما يفتح لنا أفاقًا واسعةً لبناء وتطوير بوتات تلغرام خدمية. الخطوة الثانية: إنشاء جدول بيانات جوجل والتحكم به برمجيًا لننشئ جدول بيانات جديد في درايف لتخزين البيانات الواردة من بوت التلغرام برمجيًا بشكل مؤتمت، وذلك عبر إضافة توفرها جوجل وهي لغة برمجة تطبيقات جوجل Apps Scripts . ما هي لغة Google Apps Scripts تعد Google Apps Scripts لغة برمجة هدفها إدارة جميع تطبيقات جوجل كبريد Gmail وتخزين Drive وجداول بيانات جوجل Sheets وغيرها، وهي مبنية على لغة جافاسكربت ولاحقتها ملفاتها البرمجية هي ‎.gs وتوفر جوجل بيئة تطوير على السحابة Google Workspace تساعدنا على تنفيذ الأكواد التي نكتبها بهذه اللغة، أي لن نحتاج لبيئة تطوير لمعالجة وتنفيذ الملفات المكتوبة بهذه اللغة محليًا. التحكم بجدول البيانات برمجيًا بعد إنشاء جدول بيانات جديد وتسميته باسم الإيرادات والنفقات، يمكننا ربطه والتحكم به برمجيًا بسهولة عبر Apps Scripts من خيار الإضافات Extensions ثم برمجة تطبيقات Google كما في الصورة التالية: سيُنشَأ ملف بلغة برمجة تطبيقات جوجل Apps Scripts ويُربط بملف جداول البيانات: هنا يمكننا فعل أي شيء بملف جدول البيانات برمجيًا، وحتى الوصول إلى بقية خدمات جوجل وتطبيقاتها مثل البريد Gmail ومستندات جوجل، ويمكننا أيضًا التواصل مع خدمات خارجية وهو ما نريد فعله بربط جدول البيانات مع بوت التلغرام الذي أنشأناه. نلاحظ في الجزء الأيمن في قسم الملفات وجود ملف باسم الرمز.gs، نلاحظ أيضًا أن هذه البيئة تشبه بيئة التطوير إذ توفر لنا مكانًا لكتابة الكود وتنفيذه من الخيارات في الشريط العلوي. ملاحظة: يمكن تغيير اسم المشروع من الأعلى إلى اسم مناسب وهنا سنضعه بنفس اسم البوت. لنجرب بدايةً عرض ناتج تنفيذ الواجهة البرمجية getMe في هذه البيئة، لذا نغيّر اسم الدالة myFunction إلى getMe مثلًا ونكتب محتواها البرمجي التالي: function getMe() { const response = UrlFetchApp.fetch('https://api.telegram.org/bot7666156735:AAFlJYPgOzT5cTf8CfRx_5vf0GNuVmcvAuk/getMe'); Logger.log(response.getContentText()); } استعملنا الدالة UrlFetchApp.fetch لجلب محتوى رابط أو واجهة برمجية، ومررنا لها رابط الواجهة البرمجية ‎/getMe كاملًا مع رمز الوصول access token، ثم استعملنا Logger.log لطباعة الناتج. نضغط على زر تنفيذ في الأعلى، وبما أننا ننفذ هذا السكربت لأول مرة فسيُطلَب منا إعطاءه صلاحيات محددة: نضغط على مراجعة الأذونات، ثم نحدد حسابنا ونضغط بعدها على السماح بعد مراجعة الأذونات المطلوبة، وسنجد بعدها ناتج تنفيذ الدالة getMe ضمن السكربت في قسم سجل التنفيذ في الأسفل: المعلومات هنا هي نفس المعلومات التي حصلنا عليها من فتح الرابط في المتصفح تمامًا، وبذلك نكون قد نجحنا في اختبار بيئة التطوير وجاهزيتها. ملاحظة: قد نضطر في كل تعديل إلى ضغط زر الحفظ وهو بجانب زر التنفيذ في الشريط العلوي أو ضغط الاختصار ctrl + s لحفظ المشروع. سنعيد تنظيم الشيفرة قليلًا ليسهل علينا استدعاء بقية الواجهات البرمجية بالشكل التالي: const token = '7666156735:AAFlJYPgOzT5cTf8CfRx_5vf0GNuVmcvAuk'; const url = 'https://api.telegram.org/bot' \+ token; function getMe() { const response = UrlFetchApp.fetch(url \+ '/getMe'); Logger.log(response.getContentText()); } يمكن الآن استدعاء ‎/getUpdates بسهولة بكتابة دالة جديدة باسم getUpdates بالشكل التالي: const token = '7666156735:AAFlJYPgOzT5cTf8CfRx_5vf0GNuVmcvAuk'; const url = 'https://api.telegram.org/bot' \+ token; function getMe() {` const response = UrlFetchApp.fetch(url \+ '/getMe'); Logger.log(response.getContentText()); } function getUpdates() { const response = UrlFetchApp.fetch(url \+ '/getUpdates'); Logger.log(response.getContentText()); } لتنفيذ الدالة، نختار من القائمة الموجودة في الشريط العلوي اسم الدالة، ثم نضغط على تنفيذ ونشاهد الناتج في قسم سجل التنفيذ. ملاحظة: قد تظهر لنا رسالة تحذير بأن التطبيق غير آمن ولم يتحقق جوجل منه ولا بأس بالإكمال كما توضح الصورة التالية لأننا نحن من نطور السكربت ولكن يجب الحذر إن كان السكريبت من مصدر غير موثوق لأن قد يصل إلى معلومات حساسة. نشر تطبيق ويب يصل بين بوت تلغرام وجداول بيانات جوجل فهمنا سابقًا آلية التواصل التي سنطبقها والتي تتم بتواصل بوت التلغرام عبر خطاف ويب web hook مع خادم ويب كلما استلم البوت رسالة جديدة بعدها سيعمل خادم الويب على تخزين البيانات الواردة بعد معالجتها في جدول البيانات كما هو موضح بالصورة التالية: السؤال هو كيف سنحصل على خادم ويب؟ يمكننا بناء خادم ويب بأي لغة نريد سواءً بلغة بايثون أو لغة جافاسكربت، أو يمكننا الاستفادة من بيئة تطوير تطبيقات جوجل Apps Script فهي تمكننا من نشر المشروع على أنه تطبيق ويب على الإنترنت مباشرة واستضافته على خوادم جوجل السحابية. لنشر المشروع، نضغط على زر النشر في الأعلى ثم نختار تطبيق ويب: نختار من القائمة التي تظهر من حقل المستخدم الذي لديه الإذن بالوصول إلى عملية النشر الخيار أي شخص لكي يعمل التطبيق ثم نضغط على زر نشر: نحصل بعد تمام عملية النشر على رابط URL للتطبيق ويب جاهز ومنشور على الإنترنت، ويمكننا نسخ رابطه ولصقه في المتصفح للتأكد من عمل التطبيق، وإن جربنا في حالتنا فسنحصل على الخطأ التالي: Script function not found: doGet توضح هذه الرسالة أن السكربت لا يحوي دالة باسم doGet لتنفيذها وهو طلب HTTP من النوع get لذا نضيف الدالة doGet إلى السكربت: function doGet(e) { return HtmlService.createHtmlOutput("Hello " \+ JSON.stringify(e)); } تعمل الدالة السابقة على إعادة صفحة HTML فيها كلمة مرحبًا Hello وكائن بالمعلومات المرسلة بالطلبية، ولنعد إلى نافذة المتصفح حيث فتحنا رابط التطبيق وحدِّثنا الصفحة ولكن وجدنا أن الرسالة لم تتغير. يحصل ذلك لأننا لم ننشر نسخة جديدة من التطبيق بعد إضافة الدالة الجديدة إليه. لنشر نسخة جديدة من التطبيق، نضغط على زر نشر في الأعلى ثم نختار إدارة عمليات النشر ثم نضغط على زر التعديل في قسم الإعداد ثم نختار من قائمة الإصدار خيار الإصدار الجديد لنشر إصدار جديد من التطبيق: إن حدثنا الصفحة فسنرى ناتج تنفيذ الدالة doGet التالي: Hello {"queryString":"","contentLength":-1,"contextPath":"","parameters":{},"parameter":{}} ملاحظة: قد يحتاج تطبيق الويب لبعض الوقت بعد نشره أو نشر إصدار جديد منه للعمل. أصبحنا الآن جاهزين للانتقال إلى الخطوة التالية وهي ربط خطاف ويب web hook بوت التلغرام وبين تطبيق الويب المنشور الذي أنشأناه للتو. الخطوة الثالثة: ضبط خطاف الويب بين تطبيق الويب وبوت التلغرام يمكن لتطبيق الويب الذي أنشأناه عبر لغة برمجة تطبيقات جوجل أن يستقبل ويعالج طلبات HTTP، وقد رأينا كيف أنه استقبل طلب GET ويمكنه أيضًا أن يستلم طلب POST أيضًا، فعبر ربط خطاف الويب بين تطبيق الويب وبوت التلغرام، سيرسل البوت طلب POST كلما استلم رسالة جديدة. ولضبط خطاف الويب في بوت التلغرام، سنستعين بالواجهة البرمجية setWebhook التي تأخذ معاملًا باسم url وهو رابط تطبيق أو خادم الويب الذي ستُرسل إليه التحديثات الواردة من بوت التلغرام. نُعرِّف في السكربت دالة جديدةًبالاسم setWebhook والتي سترسل طلبية إلى الواجهة البرمجية تلك مع رابط تطبيق الويب، ويمكن أن نحصل على رابط تطبيق الويب بالضغط على زر نشر في الأعلى ثم الضغط على خيار إدارة عمليات النشر ثم ننسخ عنوان URL للتطبيق ونضغه في السكريبت بالشكل التالي: … const webAppUrl = "https://script.google.com/macros/s/AKfycbwkoaVQ6aIWp6R0Pz5Q1EkiIydaKMusCKI7hEUYtPWXau7SLiznaagiAHDqkfiLzhhyXw/exec"; function setWebhook() { const response = UrlFetchApp.fetch(url \+ '/setWebhook?url=' \+ webAppUrl); Logger.log(response.getContentText()); } نحصل بعد تنفيذ الدالة setWebhook وحفظ السكربت على الناتج التالي: {"ok":true,"result":true,"description":"Webhook was set"} تخبرنا الرسالة بأنه تم ضبط خطاف الويب بنجاح، لكن إن جربنا الآن أن نرسل رسالة إلى بوت التلغرام فلن يحصل أي شيء، لماذا؟ لأننا لم نضبط بعد عملية معالجة طلبات POST التي يرسلها البوت عبر خطاف الويب بعد، فعندما يتلقى الخادم طلبًا من البوت عبر POST مثلاً، عند وصول رسالة جديدة، يجب على الخادم أن يعالج هذا الطلب. وللقيام بالمعالجة المطلوبة سنعرِّف دالة باسم doPost التي تعالج طلبيات POST المستقبلة، وسنجرب حاليًا إرسال بريد إلكتروني إلى حسابنا كلما استلمنا رسالة جديدة بالشكل التالي: function doPost(e) { GmailApp.sendEmail(Session.getEffectiveUser().getEmail(), "رسالة جديدة من بوت التلغرام", JSON.stringify(e, null, 4)); } لنحفظ السكريبت ثم ننشر إصدارًا جديدًا من التطبيق والذي سيطلب مرة أخرى قبول أذونات جديدة لأننا أضفنا تطبيقًا جديدًا إلى السكريبت وهو تطبيق البريد GmailApp، لنقبلها بالضغط على رز تفويض الوصول ولنجرب مرة أخرى إرسال رسالة إلى البوت. إن أرسلنا رسالة إلى البوت، فستصل رسالة إلى البريد تحوي معلومات الطلب كالتالي: أصبحت الآن البيانات بحوزتنا وتصلنا إلى تطبيق الويب مباشرة من البوت عند استلامه أي رسالة جديدة، وخطوتنا التالية هي معالجة هذه البيانات وإدخالها ضمن جدول البيانات. الخطوة الرابعة: إرسال رد على كل رسالة يرسلها بوت التلغرام قبل أن نحفظ البيانات في جدول بيانات جوجل، سنعمل على كتابة دالة وظيفتها إرسال رد أو تأكيد على بوت التلغرام ونستفيد منها في التواصل مع البوت والرد عليه كما أرسل لنا تحديثًا. كانت خطوة إرسال البريد خطوة تجريبية فقط لعرض المعلومات التي وصلتنا من البوت لنحاول استخلاص بعض المعلومات المهمة منها وهي بالشكل التالي: { "contextPath": "", "queryString": "", "contentLength": 295, "parameters": {}, "parameter": {}, "postData": { "contents": "{\"update_id\":412227169,\n\" message\":{\"message_id\":39,\"from\":{\"id\":957260622,\"is_bot\":false,\"first_name\":\"Jamil\",\"username\":\"jBailony\",\"language_code\":\"en\"},\"chat\":{\"id\":957260622,\"first_name\":\"Jamil\",\"username\":\"jBailony\",\"type\":\"private\"},\"date\":1735667656,\"text\":\"Hi, this is my first message\"}}", "length": 295, "name": "postData", "type": "application/json" } } ما يهمنا هنا موجود ضمن postData في خاصية اسمها contents ولكنها بصيغة JSON لنفككها إلى كائن بالشكل التالية: const contents = JSON.parse(e.postData.contents); والناتج هو كالتالي: { "update_id": 412227169, "message": { "message_id": 39, "from": { "id": 957260622, "is_bot": false, "first_name": "Jamil", "username": "jBailony", "language_code": "en" }, "chat": { "id": 957260622, "first_name": "Jamil", "username": "jBailony", "type": "private" }, "date": 1735667656, "text": "Hi, this is my first message" } } يلزمنا مُعرِّف المحادثة id والرسالة نفسها التي وصلتنا: const contents = JSON.parse(e.postData.contents); const id = contents.message.from.id; const name = contents.message.from.first_name; نحتاج إلى المُعرِّفلأننا سنعتمد على الواجهة البرمجية ‎/sendMessage التي تحتاج إلى المعامل chat_id الذي هو مُعرِّف المحادثة السابق id. لنكتب الدالة sendMessage التي تعتمد على تلك الواجهة البرمجية بالشكل التالي: function sendMessage(chatId, message) { const response = UrlFetchApp.fetch(${url}/sendMessage?chat_id=${chatId}\&text=${message}); Logger.log(response.getContentText()); } نلاحظ أن الواجهة البرمجية ‎/sendMessage تحتاج أيضًا إلى المعامل text الذي يمثِّل نص الرسالة المراد إرسالها. لنستعملها الآن ضمن الدالة doPost بإرسال رد على الرسالة: function doPost(e) { GmailApp.sendEmail(Session.getEffectiveUser().getEmail(), "رسالة جديدة من بوت التلغرام", JSON.stringify(e, null, 4)); const contents = JSON.parse(e.postData.contents); const id = contents.message.from.id; const name = contents.message.from.first_name; const text = contents.message.text; sendMessage(id, `وصلتنا رسالتك، شكرًا لك يا ` + name); } نحفظ المشروع وننشر إصدارًا جديدًا منه ثم نرسل رسالة إلى البوت وسنجد أنه يرد علينا كما توضح الصورة التالية: ممتاز، كل شيء يعمل على ما يرام، وخطوتنا التالية هي إدخال المعلومات المستلمة ضمن جدول البيانات. الخطوة الخامسة: حفظ البيانات المستلمة من بوت التلغرام في جدول البيانات أصبح لدينا محتوى الرسالة المستلمة من البوت، ونحتاج الآن إلى إدخالها ضمن جدول البيانات ولكن قبل ذلك، لنتعلم استعمال بعض الدوال التي ستلزمنا في التعامل مع جداول بيانات جوجل Google Sheets. التعامل مع جداول بيانات جوجل عبر لغة Apps Script سنعتمد على الواجهة SpreadsheetApp في التعامل مع جداول بيانات جوجل، ولنكتب بداية الدالة التالية التي وظيفتها إضافة سطر في جدول البيانات المرتبط بالشكل التالي: function appendRow() {` SpreadsheetApp.getActiveSheet().appendRow([1, 2, 3, 4]); } إن حفظنا السكريبت ثم نفذنا الدالة appendRow فسنحصل على الناتج التالي: ملاحظة: سيُطلب منا مرة أخرى قبول أذونات جديدة لأننا استعملنا واجهة تطبيق جديد في السكريبت، وهذا سيحصل كلما أضفنا واجهة جديدة لأحد تطبيقات جوجل. عملت الطريقة السابقة بشكل صحيح، ولكنها ليست الطريقة الأفضل، فمن الأفضل استعمال رابط ملف جدول البيانات مباشرة في تحديد الملف بالشكل التالي: const fileURL = 'https://docs.google.com/spreadsheets/d/1LZlRezLubnD_4mGZulQ7RUZ9-itRefmJNSsSizRh8iY/edit'; function appendRow() { SpreadsheetApp.openByUrl(fileURL).appendRow([1, 2, 3, 4]); } أو يمكننا الاعتماد على مُعرِّف الملف الذي نستخلصه من رابط ملف جدول البيانات السابق بالشكل التالي فهذه الطريقة أفضل وأقصر: const fileId = '1LZlRezLubnD_4mGZulQ7RUZ9-itRefmJNSsSizRh8iY'; function appendRow() { SpreadsheetApp.openById(fileId).appendRow([1, 2, 3, 4]); } نلاحظ أن هذا الأمر سيضيف سطرًا في أول جدول بيانات أو ورقة sheet في الملف، ولكن ماذا لو أردنا إضافة بيانات في ورقة محددة؟ يمكننا استعمال الطريقة التالية: const fileId = '1LZlRezLubnD_4mGZulQ7RUZ9-itRefmJNSsSizRh8iY'; const sheetName = "Sheet1"; function appendRow() { SpreadsheetApp.openById(fileId).getSheetByName("Sheet1").appendRow([1, 2, 3, 4]); } استعملنا getSheetByName مع تمرير اسم الورقة إليها من أجل تعديلها. سنتعلم أخيرًا كيفية جلب قيمة محددة من السطر الأخير وإعادة إضافتها في السطر التالي مع زيادتها بقيمة 1 مثلًا وذلك بالشكل التالي: const fileId = '1LZlRezLubnD_4mGZulQ7RUZ9-itRefmJNSsSizRh8iY'; const sheetName = "Sheet1"; function appendRow() { const sheet = SpreadsheetApp.openById(fileId).getSheetByName("incomes"); sheet.appendRow([5]); const lastValue = Number(sheet.getRange(sheet.getLastRow(), 1).getValue()); sheet.appendRow([lastValue + 1]); } تعمل هذه الدالة على إضافة قيمة في آخر سطر ثم جلب هذه القيمة باستعمال الدالة getRange التي تأخذ رقم السطر والعمود إذ رقم السطر هو رقم آخر سطر حصلنا عليه من الدالة getLastRow والعمود مررناه يدويًا، وبعد تنفيذ الدالة حصلنا على الناتج المتوقع: هذا يكفي لمقالنا الحالي، وسمكن استكشاف بقية الدوال والواجهات من التوثيق الرسمي. إضافة البيانات المستلمة من بوت التلغرام إلى جدول البيانات سنختار صيغة البيانات المرسلة من البوت إلينا حتى نعالجها ولتكن بالشكل التالي: تمثِّل @ وما بعدها اسم الورقة ثم يليها رقم ثم يليها الوصف مباشرةً، ولنعتمد أنه إذا لم نحدد اسم الورقة فلتكن افتراضيًا ورقة المصاريف، ونأخذ هذه المعلومات ونضيفها في الورقة المحددة، لذا سنُعدِّل الدالة doPost والدالة appendRow بالشكل التالي: function doPost(e) { GmailApp.sendEmail(Session.getEffectiveUser().getEmail(), "رسالة جديدة من بوت التلغرام", JSON.stringify(e, null, 4)); const contents = JSON.parse(e.postData.contents); const id = contents.message.from.id; const name = contents.message.from.first_name; const text = contents.message.text; let sheetName = "مصاريف"; let itemValue, itemName; if (/^@/.test(text)) { const textArray = text.slice(1).split(" "); sheetName = textArray[0]; itemValue = textArray[1]; itemName = textArray.splice(2).join(" "); } else { const textArray = text.split(" "); itemValue = textArray[0]; itemName = textArray.shift().join(" "); } appendRow(sheetName, [new Date().toLocaleString(), itemValue, itemName]); sendMessage(id, `سجلت المبلغ والقيمة في جدول ${sheetName}، شكرًا لك!`); } function appendRow(sheetName, data) { const spreadSheet = SpreadsheetApp.openById(fileId); const sheet = spreadSheet.insertSheet(sheetName); sheet.appendRow(data); } السكربت المكتوب بسيط وهو يتحقق إن كانت اسم الورقة مضافة ضمن الرسالة فيأخذها ويحلل الرسالة وفقًا لذلك أو إن لم تكن مضافة يحلل الرسالة مباشرة ويستخلص منها البيانات، ثم يدخل البيانات مع التاريخ ولاحظ أننا استعملنا الدالة insertSheet في الدالة appendRow وذلك لإضافة الورقة ضمن الملف. نحفظ السكربت ونعيد نشره ثم نرسل للبوت الرسالة التالية @نفقات 10 شراء فواكه ونجد أنه قد رد علينا بالرسالة سجلت المبلغ والقيمة في جدول النفقات، شكرًا لك! وقد أضاف ورقة جديدة بالاسم نفقات وأضاف فيها البيانات: تعمل عملية الربط بصورة صحيحة إلى الآن ولكن ماذا لو جربنا أن نرسل الرسالة مرة أخرى نفسها؟ الخطوة السادسة: التقاط الأخطاء ومعرفتها وحلها إن جربنا إرسال نفس الرسالة للبوت @نفقات 10 شراء فواكه، لن يحصل أي شيء ولن يرد علينا البوت بأي رد، وهذا دليل بأنه حصل خطأ ولكن كيف سنعرفه ونحله؟ سنلتقط الخطأ أولًا عبر كتلة try/catch ونرسل داخل catch رسالة إلى البوت بالخطأ الحاصل بالشكل التالي: const chatId = 957260622; function doPost(e) { try { GmailApp.sendEmail(Session.getEffectiveUser().getEmail(), "رسالة جديدة من بوت التلغرام", JSON.stringify(e, null, 4)); const contents = JSON.parse(e.postData.contents); const id = contents.message.from.id; const name = contents.message.from.first_name; const text = contents.message.text; let sheetName = "مصاريف"; let itemValue, itemName; if (/^@/.test(text)) { const textArray = text.slice(1).split(" "); sheetName = textArray[0]; itemValue = textArray[1]; itemName = textArray.splice(2).join(" "); } else { const textArray = text.split(" "); itemValue = textArray[0]; itemName = textArray.shift().join(" "); } appendRow(sheetName, [String(new Date().toLocaleString()), itemValue, itemName]); sendMessage(id, `سجلت المبلغ والقيمة في جدول ${sheetName}، شكرًا لك!`); } catch (e) { sendMessage(chatId, `حصل خطأ`); sendMessage(chatId, JSON.stringify(e?.message ?? e, null, 4)); } } أخذنا رقم المحادثة وحفظناه في المتغير chatId الذي حصلنا عليه من المعلومات المرسلة إلينا في البريد والسبب أن الخطأ قد يحصل في أي مكان، فربما يحصل في البداية ويضيع رقم المحادثة وبالتالي لن يصلنا البريد. نلاحظ أيضًا أننا استعملنا التعبير e?.message ?? e وذلك لاستخراج نص الرسالة مباشرة وسبب الخطأ فلا نريد أن تصلنا الكثير من البيانات في الرسالة. إن جربنا حفظ السكريبت وإعادة نشر التطبيق ثم إرسال نفس الرسالة للبوت وهي @نفقات 10 شراء فواكه، فسنلاحظ أنه لم يتغير شيء ولم تصلنا رسالة بالخطأ الحاصل، وبعد التحقق من السكربت نجد أن الخطأ في الدالة sendMessage إذ يجب ترميز نص الرسالة عبر encodeURIComponent قبل إرسالها في حال إرسال كائن أو شيفرة برمجية وبعد التعديل على الدالة تصبح بالشكل التالي: function sendMessage(chatId, message) { const response = UrlFetchApp.fetch(`${url}/sendMessage?chat_id=${chatId}&text=${encodeURIComponent(message)}`); Logger.log(response.getContentText()); } نعيد نشر التطبيق ثم إرسال نفس الرسالة وحينها نحصل على الرد التالي من البوت: تقول رسالة الخطأ بأن هنالك ورقة بنفس الاسم نفقات موجودة سابقًا ولا يمكن إنشاء ورقة جديدة بالاسم نفسه. عرفنا الآن سبب الخطأ ويمكننا حله بتعديل الدالة appendRow بالشكل التالي: function appendRow(sheetName, data) { const spreadSheet = SpreadsheetApp.openById(fileId); const sheet = spreadSheet.getSheetByName(sheetName) ? spreadSheet.getSheetByName(sheetName) : spreadSheet.insertSheet(sheetName); sheet.appendRow(data); } تحققنا أن الورقة موجودة، فإن كانت موجودة نستعملها عبر getSheetByName ونضيف فيها أو ننشئها من جديد عبر insertSheet وبذلك تُحل المشكلة إن أعدنا إرسال الرسالة من جديدة وطبعًا بعد نشر إصدار جديد من تطبيق الويب.ن الشيفرة الكاملة للبوت فيما يلي الشيفرة الكاملة للبوت بعد الانتهاء منه وتنفيذ كافة الخطوات const token = '7666156735:AAFlJYPgOzT5cTf8CfRx_5vf0GNuVmcvAuk'; const url = 'https://api.telegram.org/bot' + token; const webAppUrl = "https://script.google.com/macros/s/AKfycbwkoaVQ6aIWp6R0Pz5Q1EkiIydaKMusCKI7hEUYtPWXau7SLiznaagiAHDqkfiLzhhyXw/exec"; const fileId = '1LZlRezLubnD_4mGZulQ7RUZ9-itRefmJNSsSizRh8iY'; const chatId = 957260622; function getMe() { const response = UrlFetchApp.fetch(url + '/getMe'); Logger.log(response.getContentText()); } function getUpdates() { const response = UrlFetchApp.fetch(url + '/getUpdates'); Logger.log(response.getContentText()); } function doGet(e) { return HtmlService.createHtmlOutput("Hello " + JSON.stringify(e)); } function setWebhook() { const response = UrlFetchApp.fetch(url + '/setWebhook?url=' + webAppUrl); Logger.log(response.getContentText()); } function appendRow(sheetName, data) { const spreadSheet = SpreadsheetApp.openById(fileId); const sheet = spreadSheet.getSheetByName(sheetName) ? spreadSheet.getSheetByName(sheetName) : spreadSheet.insertSheet(sheetName); sheet.appendRow(data); } function sendMessage(chatId, message) { const response = UrlFetchApp.fetch(`${url}/sendMessage?chat_id=${chatId}&text=${encodeURIComponent(message)}`); Logger.log(response.getContentText()); } function doPost(e) { try { GmailApp.sendEmail(Session.getEffectiveUser().getEmail(), "رسالة جديدة من بوت التلغرام", JSON.stringify(e, null, 4)); const contents = JSON.parse(e.postData.contents); const id = contents.message.from.id; const name = contents.message.from.first_name; const text = contents.message.text; let sheetName = "مصاريف"; let itemValue, itemName; if (/^@/.test(text)) { const textArray = text.slice(1).split(" "); sheetName = textArray[0]; itemValue = textArray[1]; itemName = textArray.splice(2).join(" "); } else { const textArray = text.split(" "); itemValue = textArray[0]; itemName = textArray.shift().join(" "); } appendRow(sheetName, [String(new Date().toLocaleString()), itemValue, itemName]); sendMessage(id, `سجلت المبلغ والقيمة في جدول ${sheetName}، شكرًا لك!`); } catch (e) { sendMessage(chatId, `حصل خطأ`); sendMessage(chatId, JSON.stringify(e?.message ?? e, null, 4)); } } أفكار لتطوير البوت انتهينا من تطوير تطبيقنا وربطنا بوت تلغرام مع جداول البيانات بطريقة صحيحة ولكن هنالك الكثير من الأفكار والتطويرات التي يمكن إجراؤها على التطبيق وفيما يلي أبرز الأفكار التحسينية. تحليل الرسالة المستقبلة من البوت لم نعمل على تحليل الرسالة التي يستقبلها البوت، لذا يُفضَّل إضافة خطوة تحقق validation منها، فإن كانت لا تُطابق شروطًا معينة مثلًا لا تحوي على قيمة عددية تمثل المصروف أو النفقات سنرفض الرسالة ونعيد إرسال رسالة للبوت توضح أن هنالك شيء ناقص في الرسالة مع توضيح كيفية استعمال البوت وصيغة التواصل معه. إضافة قائمة أوامر للبوت بعد فترة قد ننسى كيفية استعمال البوت ولا نريد أن تفتح الشيفرة البرمجية لذا يمكن أن نضيف قائمة أوامر commands للبوت عبر ‎/setcommands فيها مثلًا كيفية الاستعمال ليرد علينا البوت بكيفية الاستعمال وغيرها من الأوامر السريعة التي توسِّع عمل البوت وتسهِّل استخدامه. تحسين تنسيق الرسالة المرسلة للبوت أرسلنا في تطبيقنا رسالة نصية عادية text ولكن يمكننا الاستفادة من المعامل parse_mode في الواجهة البرمجية ‎/sendMessage لإرسال الرسالة بتنسيق مارك داون أو بتنسيق HTML، وللمزيد انظر التنسيقات المدعومة في التوثيق. تحسين تنسيق جدول البيانات وتطويره يمكنك إضافة جداول أو أوراق sheets مسبقة وتعديل تنسيقها بصيغة معينة، فنحن لم نركز في هذا المقال على تنسيق الجداول لأنه خارج نطاقنا- كما يمكنك أيضًا إضافة أعمدة أو صفوف جامعة sum أو متوسط حسابي average بحيث نربطها مع أمر في البوت يجلب لنا مجموع المصروف أو النفقات الكلية أو لشهر محدد مثلً،ا وهكذا نطور تطبيق المصاريف والنفقات أو نتوسع وتُطوِّر من التطبيق أكثر ليصبح تطبيق محاسبي يفيد المستخدم. كما يمكننا إضافة أوامر تجلب لنا صورة عن مخططات شهرية مثلًا ثم إرسال هذه الصورة إلى البوت عبر الواجهة البرمجية ‎/sendPhoto وغيرها من الأفكار العديدة الأخرى. ربط البوت مع ChatGPT هذه فكرة مميزة جدًا إذ يمكننا تحليل البيانات ومعالجتها عبر ربط البوت مع أحد نماذج الذكاء الاصطناعي مثل التفاعل مع الواجهة البرمجية API لروبوت الدردشة الشهير ChatGPT ، وبهذا يمكن تمرير الرسائل التي يرسلها المستخدم للبوت، وتحويلها إلى ChatGPT للحصول على رد وإعادة الناتج إلى البوت من جديد وبذلك نطوِّر من قدرات البوت وإمكانياته. خاتمة تعلمنا في هذا المقال كيفية إنشاء تطبيق متكامل يربط بين بوت تلغرام وجداول بيانات جوجل، وبذلك أصبح لدينا بوت يحفظ البيانات المرسلة إليه ويرد علينا برسالة مخصصة تؤكد حفظ البيانات أو رسالة بملخص الخطأ إن حصل، ولا يكتفي بذلك بل أيضًا يرسل لنا رسالة إلى بريدنا كلما وصلته رسالة من المستخدم. وختمنا المقال بأفكار لتحسين التطبيق والبناء عليه لتطوير بوتات تلغرام أكثر احترافية، وإذا كانت لديكم أي أفكار أخرى تخص تطوير بوتات تلغرام نرحب بمشاركتها معنا في قسم التعليقات أسفل المقال. اقرأ أيضًا التعامل مع جداول البيانات والأوراق والنطاقات من خلال Apps Script أساسيات برمجة التطبيقات Apps Script باستخدام جداول بيانات جوجل بناء بوت Bot تلغرام باستخدام لارافيل وبوتمان BotMan برمجة الروبوت: الدليل الشامل
    1 نقطة
  12. وعليكم السلام ورحمة الله وبركاته. الحل صحيح في بعض الحالات ولكن في حالات أخرى خاطئ لهذا فإن هذا الحل لن يتم قبوله على الموقع . لاحظ أنك لا تقوم بالتأكد من الرقم هل هو موجب أم سالب . حيث إذا كان سالبا لا يجب وضعه في المجموع لديك . أيضا لاحظ أنك تقوم بتكرار الكود هو هو مرتين مرة في else ومرة بداخل if الإختلاف هو فقط في إذا كان تم حذف القيم الفريدة أم لا من خلال إستخدام set. لهذا يمكنك فقط وضع جزء واحد من الكود وتحويل set مباشرة . لهذا قم بتحويل المصفوفة إلى set مباشرة ومن ثم التكرار على عناصر set الجديدة وجمع الرقم إذا كان موجبا وعدم جمعه إذا كان سالبا.
    1 نقطة
  13. وعليكم السلام ورحمة الله، عند استخدام هذا السطر: for num in set(array): سيتم التكرار عبر العناصر بترتيب عشوائي على سبيل المثال، إذا كانت مصفوفة الأعداد هي: [2, -1, 3, -1] فإن ترتيب واحد مثل [2, -1, 3] قد يعطي مجموعا تراكميا 2 ،1 ، 4 بإجمالي 4 بينما ترتيب آخر مثل [2, 3, -1] قد يعطي 2 ، 5 ، 4 بإجمالي 5. وأيضا عندما توجد أعداد موجبة، الاستراتيجية المثلى هي استبعاد الأعداد السالبة لأن وجودها يقلل من المجموع الكلي في هذه المشكلة، إذا كان هناك عدد موجب واحد على الأقل، يمكنك دائما حذف الأعداد السالبة بحيث يكون المجموع الأمثل هو مجموع كل الأعداد الموجبة المميزة (الصفر لا يؤثر على المجموع) في حلّك قد تتم إضافة بعض الأعداد السالبة من المجموعة مما يقلل من المجموع. وبما أنه مسموح لك بحذف أي عناصر، يمكنك دائما تشكيل مصفوفة فرعية (Subarray) تحتوي على كل عدد مفيد (أي موجب) مرة واحدة فقط. الحل الأمثل هو: إذا كان هناك عدد موجب على الأقل: احسب مجموع جميع الأعداد الموجبة المميزة. إذا لم توجد أعداد موجبة: قم بإرجاع أكبر عنصر أي العدد "الأقل سلبية".
    1 نقطة
  14. الحل غير صحيح، المطلوب إيجاد أكبر مجموع لـ subarray متتالي أي عناصر متجاورة في المصفوفة الأصلية بحيث، جميع عناصر الـ subarray فريدة ويُسمح بحذف أي عدد من العناصر من المصفوفة الأصلية لكن يجب أن يبقى الsubarray متتاليًا بعد الحذف. لكل قيمة فريدة في المصفوفة، تتبع الحد الأقصى لتكرار تلك القيمة، وتستطيع ببساطة تخزين القيمة الفريدة نفسها وكأنها الحد الأقصى لتكرارها، وانتبه إلى أنّ تتبع الحد الأقصى للتكرار لا يعني عد مرات الظهور بالمعنى الحرفي، بل التعامل مع كل قيمة فريدة مرة واحدة فقط، واختيار القيمة نفسها كممثل لها. ثم جمع الحدود القصوى لتكرارات كل قيمة فريدة فقط إن كانت موجبة، ولو المصفوفة تحتوي فقط على قيم سالبة أو صفر، ستقوم بإرجاع العنصر الأكبر في المصفوفة الأصلية. كالتالي: class Solution: def maxSum(self, nums): max_sum = 0 current_sum = 0 unique_elements = set() left = 0 for right in range(len(nums)): while nums[right] in unique_elements: unique_elements.remove(nums[left]) current_sum -= nums[left] left += 1 unique_elements.add(nums[right]) current_sum += nums[right] if current_sum > max_sum: max_sum = current_sum return max_sum if max_sum != 0 else max(nums) وتلك نسخة أقصر من الكود: class Solution(object): def maxSum(self, nums): ans = 0 for num in set(nums): if num > 0: ans += num return ans if ans else max(nums)
    1 نقطة
  15. نستخدمها لمعالجة البيانات النصية وليس الصور، بالتالي لو مجموعة البيانات تحتوي على مسارات الصور images/cat1.jpg وتسمياتها "cat" في ملف CSV أو Excel، فاستخدم Pandas لقراءة القائمة. بعد ذلك، تمرر المسارات إلى tf.data أو DataLoader لتحميل الصور الفعلية ومعالجتها.
    1 نقطة
  16. Kadane's Algorithm هي خوارزمية خطية تستخدم لإيجاد أكبر مجموع لمصفوفة فرعية في مصفوفة معينة تعرف المصفوفة الفرعية بأنها مجموعة متصلة من العناصر داخل المصفوفة وتتعامل الخوارزمية بفاعلية مع الأرقام الموجبة والسالبة، مما يجعلها أداة متعددة الاستخدامات لحل العديد من المشكلات المتعلقة بالمصفوفات الفرعية. تعتمد الخوارزمية على منهج البرمجة الديناميكية من خلال حساب أكبر مجموع متصل ينتهي عند كل عنصر في المصفوفة والفكرة الأساسية هي مقارنة العنصر الحالي بأكبر مجموع متصل سابق، وتحديث القيم بناء على ذلك ولتنفيذها نقوم بالتالي أولا نقوم بتهيئة متغيرين: max_so_far: أكبر مجموع متصل تم العثور عليه حتى الآن. max_ending_here: المجموع المتصل الحالي. ثم نمرر على كل عنصر في المصفوفة من خلال إضافة العنصر الحالي إلى max_ending_here فإذا كان max_ending_here أقل من الصفر، نقوم بإعادة ضبطه إلى صفر، ونقوم بتحديث max_so_far إذا كان max_ending_here أكبر منه. وعند الانتهاء من المرور على المصفوفة، سيحتوي max_so_far على أكبر مجموع متصل على هذا النحو: public class KadaneAlgorithm { public static int maxSubarraySum(int[] arr) { int max_so_far = Integer.MIN_VALUE; int max_ending_here = 0; for (int i = 0; i < arr.length; i++) { max_ending_here += arr[i]; if (max_ending_here < 0) { max_ending_here = 0; } if (max_so_far < max_ending_here) { max_so_far = max_ending_here; } } return max_so_far; } public static void main(String[] args) { int[] arr = {-2, 1, -3, 4, -1, 2, 1, -5, 4}; int maxSum = maxSubarraySum(arr); System.out.println("أكبر مجموع متصل هو: " + maxSum); } } ثم الإخراج سيكون: أكبر مجموع متصل هو: 6 وهو ناتج جمع [4, -1, 2, 1]. أما بالنسبة للتعقيد الزمني لهذه الخوارزنية فهو O(n) حيث n هو عدد عناصر المصفوفة.
    1 نقطة
  17. تلك خوارزمية لحل مشكلة أقصى مجموع جزئي أو أكبر مجموع فرعي متجاور Maximum Subarray Problem، وذلك لإيجاد المجموع الأعظمي لتسلسل فرعي متجاور ضمن مصفوفة أحادية البعد تحتوي على أرقام قد تكون موجبة أو سالبة. تحتفظ الخوارزمية بمتغيرين max_so_far يمثل أقصى مجموع تم العثور عليه حتى الآن، و max_ending_here يمثل أقصى مجموع ينتهي عند العنصر الحالي. ثم تمر عبر عناصر المصفوفة: لكل عنصر، تضيف قيمته إلى max_ending_here. وإن أصبح max_ending_here سالبًا، تعيد تعيينه إلى الصفر لأن البدء من جديد أفضل من الاستمرار بمجموع سالب. ثم تحديث max_so_far في حال max_ending_here أكبر منه. بعد الإنتهاء تعيد max_so_far كنتيجة. وذلك مثال من خلال جافاسكريبت: let array = [-2, 1, -3, 4, -1, 2, 1, -5, 4] function maxSubArray(array) { let current_sum = array[0] let max_sum = array[0] for (let i = 1; i < array.length; i++) { current_sum = Math.max(array[i], current_sum + array[i]) if (current_sum > max_sum) { max_sum = current_sum } } return max_sum } console.log(maxSubArray(array))
    1 نقطة
  18. وعليكم السلام ورحمة الله وبركاته. بالتأكيد يجب أن تحول ملفات الصور إلى أرقام (مصفوفات رقمية) قبل تدريب شبكات CNN. فالشبكات العصبية التوافقية (CNNs) لا تستطيع التعامل مباشرة مع ملفات الصور كما هي، بل تحتاج إلى تمثيل رقمي للصور. ولكن لا تقوم بذلك يدوياً إنما عملية التحويل تتم عادة باستخدام مكتبات مثل TensorFlow أو PyTorch حيث توفر وظائف لتحميل ومعالجة الصور بشكل تلقائي، لكن التحويل من الصورة إلى تمثيل رقمي يحدث بالفعل.
    1 نقطة
  19. وعليكم السلام ورحمة الله وبركاته. لا تحتاج إلى تحويل الصور إلى أرقام يدويا قبل التدريب في CNNS.حيث هي مصممة بالفعل للتعامل مباشرة مع بيانات الصورة و تقوم تلقائيا بتحويل الصور إلى تمثيل رقمي (مصفوفات من الأرقام) كجزء من عملية المعالجة حيث المكتبات تقوم بهذه الخطوة تلقائيا. حيث الصورة يتم تمثيلها بشكل طبيعي كمصفوفة من الأرقام مصفوفة ثلاثية الأبعاد في حالة الصور الملونة (RGB) أو ثنائية الأبعاد في حالة الصور الرمادية حيث كل بكسل في الصورة له قيمة رقمية تمثل شدة اللون. وعند إدخال الصورة إلى الشبكة العصبية يتم تمرير هذه المصفوفة مباشرة كمدخل و لا تحتاج إلى تحويلها بنفسك إلى أرقام لأنها بالفعل في شكل رقمي.
    1 نقطة
  20. يجب أن تكون الصور في الأساس في صيغة بيانات رقمية قبل إدخالها إلى الشبكة، فالشبكة نفسها لا تقوم بتحويل الصور من شكلها الخام أي ملفات JPEG أو PNG إلى بيانات رقمية داخليًا من تلقاء نفسها، بل تعتمد على أن تكون البيانات جاهزة في شكل مناسب للمعالجة. وأنت لست بحاجة إلى القيام بذلك يدويًا، فالمكتبات المستخدمة لبناء وتدريب الشبكات العصبية وهي TensorFlow أو PyTorch تتولى تلك الخطوة تلقائيًا عند تحميل الصور. حيث أولاً تقوم بتحميل الصور باستخدام مكتبة pillow أو openCV ثم تحويلها إلى مصفوفات من خلال مكتبة numpy، بعد ذلك تهيئتها بواسطة tensorflow بضبط أبعاد الصورة لتتناسب مع مدخلات الشبكة والتهيئة Normalization بتحويل قيم البكسلات من النطاق [0, 255] إلى [0, 1] أو أي نطاق آخر، والتعامل مع القنوات للتأكد من ترتيب القنوات RGB حسب ما تتطلبه الشبكة. لكن في حال البيانات الكبيرة كآلاف الصور لن نقوم بذلك بالطريقة السابقة، فلديك مكتبة PyTorch والتي توفر أدوات لتحميل البيانات من خلال دفعات batches ومعالجتها تلقائيًا، أو من خلال tf.keras.utils.image_dataset_from_directory مع tf.data من مكتبة TensorFlow وهي الطريقة الأسهل لتحميل الصور من المجلدات وإنشاء مجموعات بيانات datasets.
    1 نقطة
  21. وعليكم السلام ورحمة الله وبركاته. لا بالطبع إن ال Convolutional Neural Networks (CNNs) لا تقتصر فقط على تطبيقات ال Computer Vision بالرغم بالفعل أنها مشهورة ومستخدمة بكثرة في هذا المجال.حيث أن CNNs فعالة في التعامل مع البيانات التي لها بنية شبكية مثل الصور ولكنها يمكن استخدامها أيضا في مجالات أخرى. معالجة اللغة الطبيعية (Natural Language Processing - NLP) مثل : تحليل المشاعر. التصنيف النصي. الترجمة الآلية. تحليل البيانات الزمنية (Time Series Analysis) مثل : التنبؤ بأسعار الأسهم تحليل البيانات الطبية مثل تخطيط القلب والبيانات التي لها تسلسل زمني. مراقبة حالة الآلات وأدائها. تحليل الأصوات (Audio Processing) مثل : التعرف على الكلام. وغيرها من المجالات الأخرى حيث CNNs فعالة في أي مهمة تتضمن بيانات ذات بنية شبكية أو متسلسلة.
    1 نقطة
×
×
  • أضف...