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

Rahaf Hammed

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

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

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

7 متابعين

آخر الزوار

لوحة آخر الزوار معطلة ولن تظهر للأعضاء

إنجازات Rahaf Hammed

عضو نشيط

عضو نشيط (3/3)

12

السمعة بالموقع

  1. توفر لغة HTML العديد من التعليمات التي تساعدك على تنسيق صفحات الويب وترتيب المحتوى داخلها. وهذا يلعب دورًا كبيرًا في تحسين ظهور محتوى الصفحات وتحسين تجربة المستخدم. في هذه المقالة ستتعلم كيفية ترتيب المحتوى في صفحات الويب وكيفية إنشاء صفحات جديدة وربطها مع الصفحة الرئيسية، وسنوضح أيضًا كيفية إضافة Twitter cards و Open Graph Social Metadata إلى صفحة الويب باستخدام HTML. كيفية توسيط أو محاذاة النص والصور على صفحة الويب الخاصة بك باستخدام تعليمات HTML تساعد محاذاة المحتوى إلى الوسط أو اليسار أو اليمين في ترتيب المحتوى على صفحتك. ويمكن استخدام تعليمات HTML لتغيير محاذاة النص أو الصور. لمحاذاة النص على صفحة الويب يجب استخدام السمة style وخاصية محاذاة النص text-align. على سبيل المثال استخدام التعليمات التالية ستؤدي إلى توسيط النص وإزاحته إلى منتصف الصفحة: <p style=" text-align:center;"> Sample text</p> لمحاذاة المحتوى إلى اليمين أو اليسار استبدل الخاصية center بالخاصية right أو left. سنعود الآن إلى ملف index.html الذي نعمل عليه في هذا المقال. وسنستخدم خاصية محاذاة النص لتوسيط الصور والنص في القسم العلوي من صفحة الويب. لتوسيط المحتوى سنضيف خاصية محاذاة النص text-align إلى العنصر <div> الذي يحتوي على صورة الخلفية وصورة الملف الشخصي والعنوان الرئيسي والعنوان الفرعي والارتباط في القسم العلوي من الصفحة الرئيسية. افتح ملف index.html وأضف التعليمات التالية: <!--First section--> <div style="background-image: url('https://html.sammy-codes.com/images/background.jpg'); background-size: cover; height:480px; padding-top: 80px; text-align: center;"> <img src="https://html.sammy-codes.com/images/small-profile.jpeg" style="height:150px; border-radius: 50%; border: 10px solid #FEDE00;"> <h1 style="font-size:100px; color:white; margin:10px;">Sammy the Shark</h1> <p style="font-size:30px; color: white;"><em>Senior Selachimorpha at DigitalOcean</em></p> <p style="font-size: 20px; color:#1F9AFE;"><a href="Webpage FilePath";>About this site</a></p> </div> لاحظ أننا أضفنا خاصية محاذاة النص فقط إلى الجزء العلوي من صفحة الويب. عند حفظ الملف وإعادة تحميله ستحصل على النتيجة التالية: من خلال استخدام خاصية محاذاة النص يمكنك التحكم بموضع المحتوى وترتيبه وفقًا للتصميم الأفضل لموقعك. في الفقرة التالية سنبدأ بإنشاء القسم الأوسط من موقع العرض التوضيحي. كيفية إنشاء جسم الصفحة الرئيسية باستخدام تعليمات HTML بعد أن انتهينا من إعداد وتصميم القسم العلوي من الصفحة الرئيسية لموقع العرض التوضيحي، سننتقل الآن إلى إنشاء جسم الصفحة أو القسم الأوسط من موقع الويب التوضيحي باستخدام العنصر <div> وخصائص السمة style. يحتوي القسم الأوسط من موقع العرض التوضيحي على صورة ملف تعريفي كبيرة وفقرة قصيرة من النص، وتتوضعان بجانب بعضهما البعض. يمكن تحقيق هذا التخطيط باستخدام حاويات <div> التي تعلمنا كيفية استخدامها في مقال" كيفية إعداد مشروع موقع ويب HTML وتنسيقه" من هذه السلسلة التعليمية. إذا واصلت تعلم مهارات الواجهة الأمامية مثل CSS، ستكتشف طرقًا محسنة لترتيب المحتوى على صفحة الويب، وتعتمد هذه الطرق على الأساليب التي نستخدمها في هذا المقال. كيفية إضافة صورة ملف تعريفي كبيرة إلى صفحة الويب أولاً، سنضيف صورة ملف تعريف كبيرة كالصورة التي تظهر في موقع العرض التوضيحي. ولكن قبل أن نبدأ تأكد من تحديد حجم صورة الملف التعريفي التي تريد استخدامها. سنعرض الصورة بمقاس 400 × 600 بكسل، لذا تحقق من أن حجم الصورة سيعمل مع هذه الأبعاد. وإذا لم يكن لديك صورة يمكنك تنزيل الصورة من موقعنا التجريبي. بعد تحديد الصورة احفظها في مجلد الصور في دليل مشروعك. بعد ذلك انسخ مقتطف الشفرة التالي والصقه بعد آخر رسم إغلاق للعنصر <div> وقبل وسم إغلاق العنصر <body> في ملف index.html. <!--Second section--> <img src="images/large-profile.jpg" style="height:600px; margin:100px; float: left;" alt="A pretend invisible person wearing a hat, glasses, and coat."> سنتوقف الآن لمراجعة التعليمات الواردة في المقتطف السابق: التعليمة <!--Second section-->: هي تعليق لا يقرأه المتصفح ويستخدم للمساعدة في تنظيم ملف html لتسهيل قراءته من قبل المطورين. العنصر <img>: يخبر المتصفح أننا ندرج صورة في صفحة الويب. السمة src="images/large-profile.jpg": تخبر المتصفح بمكان العثور على الصورة. السمة style: تتيح لنا تحديد خصائص الارتفاع والهامش وخاصية الطفو. تتيح لك خاصية الهامش margin تحديد حجم المساحة الفارغة المحيطة بعنصر HTML. وتتيح لك خاصية التعويم float تعويم الصورة إلى الجانب الأيمن والأيسر من الشاشة مع السماح بتدفق النص حول جانبها. السمة alt: تسمح لك بإضافة نص بديل إلى صورتك لتحسين إمكانية الوصول إلى الموقع للزوار الذين يستخدمون برامج قراءة الشاشة. (لا تنس تغيير النص البديل في مقتطف الشفرة إلى وصف يطابق صورتك). احفظ ملف index.html وأعد تحميله في المتصفح. سيظهر القسم الأوسط الموجود أسفل القسم العلوي من صفحة الويب كما يلي: إذا كانت لديك أي أخطاء فتأكد من أنك أضفت كل تعليمات HTML البرمجية في الموقع الصحيح من ملف index.html، وأن الصورة موجودة في مسار الملف الذي حددته باستخدام السمة src. كيفية إضافة قسم about me إلى صفحة الويب بعد إضافة الصورة سنضيف فقرة من النص إلى يمينها. لا تنس أنه يمكنك استبدال النص الوهمي في هذا المثال بنص من اختيارك. سنضيف النص داخل حاوية <div> جديدة لنتمكن من تنسيقه بالطريقة التي نريدها. في ملف index.html أضف مقتطف الشفرة التالي بعد وسم الصورة التي أضفتها في الخطوة السابقة، وقبل وسم إغلاق العنصر <body/>. <div style="height:600px; margin:100px;"> <h1>Hello </h1> <p style="line-height: 2.0; font-size:20px;">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Et magnis dis parturient montes nascetur ridiculus mus. Purus semper eget duis at tellus at urna condimentum mattis. Turpis in eu mi bibendum neque egestas. Rhoncus dolor purus non enim praesent elementum facilisis. Ipsum nunc alique bibendum enim facilisis gravida. Cursus turpis sa tincidunt dui ut ornare lectus. Enim nec dui nunc mattis enim ut. Sapien nec sagittis aliquam malesuada bibendum arcu vitae elementum curabitur. Tussa ultricies mi quis hendrerit dolor magna. Elit eget gravida cum sociis natoque penatibus et magnis dis. Enim tortor at auctor urna nunc id cursus metus.</p> <p style="line-height: 2.0; font-size:20px;">Email me at <a href="mailto:Sammy@SampleEmail.com">Sammy@SampleEmail.com </a></p> </div> سنتوقف مؤقتًا لدراسة كل جزء من الشيفرة: العنصر <div style="height:600px; margin:100px;">: ينشئ الحاوية <div> بارتفاع 600 بكسل وهامش 100 بكسل. العنصر <h1>: يضيف عنوانًا نصيًا إلى محتوى الصفحة. الوسمان <p style="line-height: 2.0; font-size:20px;"> و <p style="line-height: 2.0; font-size:20px;">: يضيفان فقرتين مع توسيع ارتفاع خطهما إلى 2.0 وبحجم خط 20 بكسل. العنصر <a href="mailto:Sammy@SampleEmail.com">Sammy@SampleEmail.com </a>: يضيف رابط بريد إلكتروني إلى عنوان البريد الإلكتروني. العنصر <div/>: هو وسم إغلاق الحاوية <div>. احفظ ملف index.html وأعد تحميله في المتصفح وسيظهر القسم الموجود أسفل القسم العلوي من صفحة الويب كما يلي: ستلاحظ أن الصفحة الآن تعرض الصورة والنص بالتنسيق الذي حددته. يمكنك ضبط خصائص النمط في أجزاء التعليمات البرمجية لتغيير الارتفاع أو الهوامش أو حجم الخط أو خصائص النمط الأخرى للمحتوى. ويمكنك ان تلاحظ أيضًا أنه في حل قلصت عرض المستعرض على نطاق واسع سيتدفق النص في النهاية إلى عناصر أخرى على صفحتك. لإنشاء تنسيقات تستجيب لمجموعة من الأجهزة المختلفة تحتاج إلى تعلم مهارات إضافية للواجهة الامامية مثل CSS. تعلمنا في هذه الفقرة كيفية ترتيب الصور والنص جنبًا إلى جنب باستخدام حاويات <div> والسمة style وخصائصها. وسننتقل إلى تعلم كيفية إنشاء تذييل لموقع الويب باستخدام العنصر <footer>. كيفية إضافة تذييل إلى صفحة الويب باستخدام HTML تذييل موقع الويب هو الجزء الأخير من المحتوى الموجود في الجزء السفلي من صفحة الويب. يمكن أن تحتوي التذييلات على أي نوع من أنواع محتوى HTML، بما في ذلك النصوص والصور والروابط. في الجزء الأخير من هذه السلسلة التعليمية سننشئ التذييل الأساسي التالي لصفحة الويب باستخدام العنصر <footer>. لإضافة تذييل إلى الصفحة الصق الشيفرة التالية بعد وسم الإغلاق <div/> وقبل وسم الإغلاق <body/>: <!--Footer--> <footer style="height:auto; background-color:#F7C201;"> <h1><Made with ? at DigitalOcean</h1> </footer> في التعليمات السابقة <!--Footer--> هو تعليق لا يقرأه المتصفح ويستخدم للمساعدة في تنظيم ملف html لسهولة قراءته من قبل المطورين. أسفل هذا التعليق أضفنا العنصر <footer> وحددنا لون خلفيته، واستخدمنا سمة النمط style لتحديد ارتفاعه وضبط المحتوى بداخله تلقائيًا. يعد عنصر <footer> عنصرًا دلاليًا يعطي المطورين فكرة عن الغرض من المحتوى. وفي الواقع هو مفيد للمطورين وكذلك زوار الموقع الذين يستخدمون برامج قراءة الشاشة. بخلاف ذلك يعمل عنصر <footer> تمامًا مثل عنصر <div>. أضفنا أيضًا محتوى نصي داخل عنصر <h1>، ويمكنك بالطبع تغيير هذا المحتوى النصي برسالة نصية مع إضافة رموز تعبيرية من اختيارك. احفظ الملف وأعد تحميله في المتصفح للتحقق من النتائج. يجب أن تحصل على هذه النتيجة: لاحظ أن محتوى التذييل مختلف قليلًا عن المحتوى الموجود في موقع العرض التوضيحي. حيث يحتوي محتوى التذييل على هامش سفلي أبيض والنص له تصميم مختلف. لإزالة الهامش السفلي وتغيير نمط النص، أضف السمات المميزة إلى عنصر <h1> كما يلي: <h1 style="color:white; padding:40px; margin:0; text-align:center;"Made with ? at DigitalOcean</h1> احفظ الملف وأعد تحميله في المتصفح. أصبح الآن تصميم تذييل الصفحة مطابق لتصميم الجزء صفحة الويب في موقعنا التجريبي. بعد أن تعلمت كيفية إنشاء وتصميم تذييل الصفحة، أصبح بإمكانك إضافة أنواع مختلفة من المحتوى والتصميم إلى تذييل صفحة الويب باستخدام عناصر HTML التي تعرفت عليها في هذه السلسلة التعليمية. كيفية إضافة Twitter cards و Open Graph Social Metadata إلى صفحة الويب باستخدام HTML عند مشاركة الروابط على منصات التواصل الاجتماعي، فإنها تقدم غالبًا بصور غنية وعنوان وملخص ورابط منسق بطريقة جيدة، بدلًا من نص عادي. على سبيل المثال إليك كيفية عرض تويتر هذا الرابط لسلسلة البرامج التعليمية: يمكنك إضافة روابط المشاركة على شكل وسائط متعددة تفاعلية إلى موقعك عن طريق تضمين الخاصية meta في العنصر <head> داخل ملف html. يوجد معيارين أساسيين لتحديد كيفية تنسيق هذه البيانات الوصفية هما: Twitter cards وOpen Graph protocol. في هذا المقال ستتعلم كيفية إضافة البيانات الوصفية لبطاقة Twitter وOpen Graph إلى صفحة الويب. إضافة بيانات تعريف Twitter cards إلى صفحة ويب تعد بطاقات Twitter أحد مواصفات البيانات الوصفية التي يستخدمها موقع تويتر لعرض النص المنسق والصور والفيديو عند مشاركة الروابط على الخدمة. تحتوي مواصفات ترميز بطاقة Twitter الكاملة على العديد من الخيارات، ولكن يمكنك البدء بالمعلومات الأساسية والتوسع من هناك. لإضافة البيانات الوصفية لبطاقة تويتر Twitter cards إلى موقعك أضف تعليمات <meta> التالية بين وسمي <head> و<head/>: <meta name="twitter:card" content="summary_large_image" /> <meta name="twitter:site" content="@digitalocean" /> <meta name="twitter:title" content="Sammy the Shark" /> <meta name="twitter:description" content="Senior Selachimorpha at DigitalOcean" /> <meta name="twitter:image" content="https://html.sammy-codes.com/images/large-profile.jpg" /> تأكد من تحديث الأجزاء المميزة بمعلوماتك الخاصة. وفيما يلي سنوضح معنى التعليمات التي أضفناها: twitter:card : تحدد هذه العلامة نوع بطاقة Twitter التي يجب عرضها. يعرض نوع summary_large_image ملخصًا قصيرًا مع معاينة كبيرة للصورة. twitter:site : اسمك كمستخدم Twitter، أو اسم مستخدم موقعك أو شركتك. twitter:title : العنوان الذي تريد استخدامه في البطاقة. يمكن أن يتطابق هذا مع ما وضعته في محتوى الوسم twitter:description : وصف موجز للصفحة التي ستعرض تحت العنوان. ويجب ألا يزيد هذا الوصف عن 200 حرف. twitter:image : صورة للعرض، معظم تنسيقات الصور القياسية PNG وJPG وGIF مقبولة ولكن يجب أن يكون حجمها أقل من 5 ميغابايت. قد تُقتص الصور تلقائيًا لعرضها في بطاقات ذات أحجام مختلفة. يجب أن ينتج عن هذه البيانات الوصفية بطاقة Twitter تشبه ما يلي: لمزيد من المعلومات حول ميزات وخيارات Twitter Card الأخرى، تفضل بزيارة وثائق Twitter Cards الرسمية. إضافة بيانات تعريف Open Graph إلى صفحة ويب بروتوكول Open Graph هو معيار مفتوح للبيانات الوصفية تستخدمه العديد من مواقع الويب لعرض معاينات الارتباط الغني لمستخدميها. تستخدم مواقع مثل فيسبوك ولينكد إن و Pinterest بروتوكول Open Graph لعرض الروابط. شيفرة Open Graph مشابهة لبطاقات تويتر Twitter cards، وهي مجموعة من الخصائص تضاف إلى الوسم <meta>. وهي موضحة بالمقتطف البرمجي التالي: <meta property="og:type" content="article" /> <meta property="og:title" content="Sammy the Shark" /> <meta property="og:description" content="Senior Selachimorpha at DigitalOcean" /> <meta property="og:url" content="https://html.sammy-codes.com/" /> <meta property="og:image"content="https://html.sammy-codes.com/images/large-profile.jpg" /> توضع هذه التعليمات في قسم <head> في مستند HTML ويمكنك تحديث الأحداث المميزة حسب الحاجة. إليك هذا الشرح لأهم الخصائص المستخدمة: og:type : نوع المحتوى الموصوف. يمكن أن يكون نوع المحتوى مقالة أو كتاب أو ملف شخصي. يمكنك الاطلاع على مستند the official og:type documentation للمزيد من المعلومات. og:title : عنوان الصفحة. يمكن استخدام نفس عنوان og:description : وصف موجز للصفحة، لا يوجد حد محدد للأحرف، ولكن حد Twitter البالغ 200 حرف لهذا الغرض يعد دليلًا جيدًا. og:url : عنوان URL الدائم (الأساسي) للصفحة. og:image : صورة تستخدم لربطها بالصفحة. يتوفر مزيد من المعلومات حول بروتوكول Open Graph على الموقع الإلكتروني الرسمي لبروتوكول Open Graph. اختبار البيانات الوصفية لصفحة الويب يتوفر عدد قليل من الأدوات التي يمكنك استخدامها لمعاينة كيفية عرض العلامات الوصفية على موقع الويب. مثلاً Open Graph Debugger هو محاكي غير رسمي يعرض معلومات Twitter card وOpen Graph، ولا يتطلب استخدامه إنشاء حساب. بالمقابل هناك أدوات يمكنك استخدامها لاختبار البيانات الوصفية تتطلب تسجيل الدخول ومنها: Twitter Card validator Facebook Sharing Debugger LinkedIn Post Inspector Pinterest Rich Pins Validator والعديد من المواقع الأخرى لديها أدوات مماثلة. إذا كان الموقع أو المجتمع مهمًا لك أو لشركتك، فابحث عن وثائق المطورين لمعرفة ما إذا كانوا يقدمون خدمة مماثلة للاختبار معها. مع نهاية هذا المقال أصبحت قادرًا على فهم كيفية إعداد الحد الأدنى من مجموعة البيانات الوصفية لتنسيق الرابط على مواقع اجتماعية مختلفة. ترجمة -وبتصرّف- للأجزاء من التاسع عشر وحتى اﻷخير من سلسلة المقالات How To Build a Website with HTML. اقرأ أيضًا HTML و CSS للمبتدئين: كيف تصمم أول صفحة ويب لك كيفية تصميم وتنسيق صفحة الويب الأساسية باستخدام تعليمات HTML كيف تنشر صفحة أو موقع ويب قمت بتصميمه على الإنترنت
  2. يلعب التصميم دورًا رئيسيًا في تحسين مظهر الصفحات وتنسيق المحتوى داخلها. في هذا المقال سنلقي الضوء على كيفية تصميم القسم العلوي من صفحة الويب وكيفية تصميم العنوان وإضافته، وكذلك كيفية إنشاء صفحة ويب إضافية. كيفية إضافة صورة خلفية إلى القسم العلوي من صفحة الويب الخاصة بك باستخدام HTML في هذه الفقرة سنوضح كيفية استخدام حاوية <div> لهيكلة القسم العلوي من صفحة الويب. سنستخدم سمة style لتحديد ارتفاع حاوية <div> ولإضافة صورة خلفية وتحديد أن صورة الخلفية يجب أن تغطي كامل مساحة حاوية <div>. في البداية سنحتاج إلى تحديد صورة خلفية، يمكنك اختيار أي صورة تريدها. كما يمكنك تنزيل صورة الخلفية لموقع العرض التوضيحي الذي ننشئه. (لتعلم كيفية إضافة الصور إلى صفحات الويب باستخدام تعليمات HTML انتقل إلى مقال "بعض العناصر والمفاهيم الهامة في لغة HTML"). بعد اختيار الصورة الخلفية احفظها في مجلد الصور باسم background-image.jpg. بعد ذلك انسخ الشفرات البرمجية التالية والصقها في ملف index.html أسفل وسم الفتح <body> وفوق وسم الإغلاق <body/>. <body> <!--First section--> <div style="background-image: url('Image_Location'); background-size: cover; height:480px; padding-top:80px;"> </div> </body> تأكد من استبدال النص الذي يشير إلى موقع الصورة "Image_Location" بمسار ملف صورتك، ولا تنس إضافة وسم الإغلاق <div/>. لاحظ أننا أضفنا التعليق للمساعدة في تنظيم شفرة HTML. التعليق هو جزء من التعليمات البرمجية يتجاهلها المتصفح، وتستخدم لمساعدة المطورين في شرح وتوضيح وتنظيم التعليمات البرمجية. يمكن إنشاؤها باستخدام علامة الفتح <! - وعلامة الإغلاق ->. في المثال السابق حددنا الارتفاع بـ 480 بكسل والحشو العلوي بـ 80 بكسل، مما سيخلق مساحة 80 بكسل بين الجزء العلوي من عنصر <div> وأي محتوى نضعه في الداخل. أما بالنسبة لقيمة الخاصية padding-top فلن تكون قادرًا على رؤية تأثيراتها حتى نضع المحتوى في الداخل في الخطوة التالية. عند حفظ الملف وإعادة تحميله في المتصفح ستظهر الصفحة التالية: يمكنك استخدام لون للخلفية بدلًا من صورة الخلفية. ولتنفيذ ذلك استبدل مقطف <div> الذي أنشأته في المثال التالي بالشيفرات البرمجية التالية: <body> <!--First section--> <div style="background-color: #f4bc01; height:480px; padding-top:80px;"> </div> </body> احفظ الملف وأعد تحميله للتحقق من النتائج. ستلاحظ استبدال صورة الخلفية بحاوية بنفس الحجم ولكن بلون أصفر. إذا وازنت حاوية <div> على موقعك مع نفس الحاوية <div> على موقع العرض التوضيحي، ستلاحظ أن حاوية <div> لصفحتك على الويب محاطة بهامش صغير من المساحة البيضاء. ويرجع هذا الهامش إلى حقيقة أن جميع صفحات HTML تُعين تلقائيًا بحيث يكون معها هامش صغير افتراضيًا. لإزالة هذا الهامش نحتاج إلى إضافة السمة style إلى وسم الفتح <body> وتعيين هامش العنصر <body> لصفحة HTML بـ 0 بكسل. لذلك أضف التعليمة التالية إلى الملف index.html: <body style=“margin:0;”> بعد ذلك احفظ الملف وأعد تحميله في متصفحك. يجب أن يزول الهامش الأبيض الذي كان محاطًا بالحاوية <div> العلوية. الآن يجب أن تكون قادرًا على فهم كيفية إضافة حاوية <div> مع صورة خلفية لهيكلة القسم العلوي من صفحة الويب. كيفية إضافة صورة ملف تعريفي إلى صفحة الويب باستخدام تعليمات HTML في هذا الجزء سنتعرف على خطوات إضافة وتصميم صورة الملف الشخصي الأعلى كما هو معروض في موقع الويب التوضيحي: قبل أن نبدأ عليك اختيار صور ملف شخصي لتضمينها في موقعك. وإذا لم يكن لديك صورة للملف الشخصي يمكنك استخدام أي صورة لأغراض توضيحية أو إنشاء صورة رمزية من خلال الاستعانة بأحد المواقع مثل Getavataaars. وإلا يمكنك استخدام صورة موقع العرض التوضيحي الذي ننشئه في هذه السلسة التعليمية. بعد تحديد الصورة احفظها باسم small-profile.jpg في مجلد الصور الموجود في مجلد المشروع. بعد ذلك أضف العنصر <img> بين وسم فتح العنصر <div> ووسم إغلاقه <div/>. كما توضح التعليمات التالية: <div style="background-image: url('ImageLocation');background-size: cover; height:480px; padding-top:80px;"> <img src="ImageFilePath" style="height:150px"> </div> تأكد من استبدال عنوان src بمسار ملف صورة ملفك الشخصي. ولاحظ أننا نستخدم السمة style لتحديد ارتفاع الصورة إلى 150 بكسل. ولاحظ أيضًا أن العنصر <img> لا يتطلب وسم إغلاق. احفظ الملف وأعد تحميل صفحة الويب في المتصفح للتحقق من النتائج. وستحصل على النتيجة التالية: ستظهر صورة ملفك الشخصي بطول 150 بكسل نظرًا للارتفاع الذي حددناه باستخدام السمة style. ويوجد 80 بكسل أسفل الجزء العلوي من حاوية <div>، بالنظر إلى خاصية الحشو العلوي التي حددناها في الحاوية. الآن سنضيف خصائص إلى السمة style، لتمنح الصورة شكلًا دائريًا أصفر اللون. كما أننا سنضيف نصًا بديلًا لتحسين إمكانية وصول زوار الموقع الذين يستخدمون برامج قراءة الشاشة. <img src="ImageFilePath" style="height:150px; border-radius: 50%; border: 10px solid #FEDE00;" alt="This is a small profile image of Digital Ocean’s mascot, a blue smiling shark."> تأكد من استخدام مسار الملف الصحيح لصورتك مدرجًا كعنوان src. ثم احفظ الملف وأعد تحميله في المتصفح. وستحصل على شيئًا كهذا: الآن سنتوقف قليلًا لدراسة تعديلات الشيفرة التي أضفناها. يؤدي تعيين نصف قطر الحد إلى 50% إلى منح الصورة شكلًا دائريًا. وضبط قيمة الحد على 10 بكسل سيعطي الصورة حدًا صلبًا بعرض 10 بكسل وله قيمة اللون السداسي العشري ‎#FEDE00. بعد أن تعرفنا على كيفية إضافة وتصميم صورة ملف تعريف إلى موقع الويب باستخدام تعليمات HTML. أصبحنا جاهزين لإضافة عنوان أساسي وعنوان فرعي إلى صفحة الويب في الفقرات التالية. كيفية تصميم العنوان وإضافته إلى صفحة الويب باستخدام تعليمات HTML تعد العناوين جزءًا أساسيًا من أي صفحة ويب. باستخدام تعليمات لغة HTML يمكننا إضافة العناوين الأساسية والعناوين الفرعية وهذه الفقرة مخصصة لتوضيح كيفية تنفيذ ذلك. في مثالنا التوضيحي سنستخدم اسم Sammy والمسمى الوظيفي لـ Sammy، ولكن يمكنك إضافة أي محتوى تريده. سنستخدم عنصر العنوان <h1> وعنصر الفقرة <p> وعنصر التركيز <em>. انسخ مقتطف الشفرات التالية بعد عنصر صورة ملفك الشخصي <img> وقبل وسم إغلاق العنصر <div>: <img src="https://html.sammy-codes.com/images/small-profile.jpeg" style="height:150px; border-radius: 50%; border: 10px solid #FEDE00; padding-top:80px;"> <h1>Sammy the Shark</h1> <p><em>Senior Selachimorpha at DigitalOcean</em></p> </div> عدل المحتوى النصي وفقًا لمعلوماتك الخاصة، واحفظ الملف وأعد تحميله في المتصفح وستحصل على النتيجة التالية: في المثال السابق استخدمنا بعض ميزات التصميم لتعديل شكل العنوان والعنوان الفرعي. ولكننا سنحتاج إلى إضافة قيم وخصائص إضافية إذا أردنا أن يتطابق نمط العنوان والعنوان الفرعي مع نمط موقع العرض التوضيحي. لإجراء هذه التعديلات سنضيف السمة style إلى هذه العناصر لتعيين خصائص إضافية. كما يلي: <h1 style="font-size:100px; color:white; margin:10px;">Sammy the Shark</h1> <p style="font-size:30px; color: white;"><em>Senior Selachimorpha at DigitalOcean</em></p> احفظ الملف وأعد تحميله في المتصفح وستحصل على الصفحة التالية: تعمل الخصائص المضافة إلى النمط style على ضبط حجم الخط إلى 30 بكسل وتغيير لون الخط إلى اللون الأبيض. كما أننا أضفنا هامشًا قدره 10 بكسل إلى العنصر <h1>. الآن أصبت قادرًا على فهم كيفية إضافة وتصميم العنوان الرئيسي والعنوان الفرعي إلى صفحة الويب باستخدام تعليمات HTML. وفي الفقرة التالية ستتعلم كيفية إنشاء صفحة ويب إضافية وربطها بموقعك الإلكتروني. كيفية إنشاء صفحات ويب إضافية على موقعك الإلكتروني باستخدام تعليمات HTML عند إنشاء موقع ويب ستحتاج غالبًا إلى إنشاء أكثر من صفحة ويب. إذا كنت ترغب بإنشاء صفحات إضافية وربطها فستحتاج أولًا إلى إنشاء ملف html جديد في دليل مشروع موقع الويب الذي تعمل على تطويره. يتضمن موقعنا الإلكتروني التوضيحي صفحة الويب "حول"، والتي تتضمن معلومات حول الموقع، وفيما يلي سنوضح كيفية إنشاء هذه الصفحة وربطها بموقعك الإلكتروني وسنوضح ما هي العناصر التي تتضمنها. لإضافة صفحة جديدة إلى موقعك الإلكتروني عليك أولًا إنشاء ملف جديد باسم about.html وحفظه في دليل المشروع html-Practice. (إذا لم تتابع سلسلة مقالاتنا التعليمية فيمكنك مراجعة إرشادات إعداد ملف html جديد في مقالنا "كيفية إعداد مشروع موقع ويب HTML وتنسيقه"). ملاحظة: إذا قررت اختيار اسمك كاسم للملف، فتأكد من تجنب استخدام مسافات الأحرف أو الأحرف الخاصة (مثل ! أو # أو % وغيرها من الرموز). وتجنب أيضًا استخدام الأحرف الكبيرة لأنها قد تسبب مشاكل لاحقًا. ولا تنس تضمين الامتداد ".html". بعد ذلك ستحتاج إلى تنسيق الملف عن طريق إضافة معلومات تساعد المتصفح في تفسير محتوى الملف. لتنسيق الملف أضف مقتطف الشيفرة التالية: <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>About</title> </head> </html> تأكد من تغيير النص المميز بالعنوان الذي تريده لصفحتك. قبل إضافة أي محتوى إلى هذه الصفحة سنوضح خطوات إضافة ارتباط إلى هذه الصفحة في الصفحة الرئيسية. ارجع إلى ملف index.html وأضف المقتطف التالي أسفل العنوان الفرعي لموقعك وفوق وسم إغلاق العنصر <div/>. <p style="font-size: 20px; color:#1F9AFE;"> <a href="Webpage_FilePath">About this site</a> </p> سنعدل مسار الملف المميز إلى المسار النسبي للملف about.html الذي أنشأناه منذ قليل. يشير المسار النسبي إلى موقع الملف بالنسبة إلى دليل العمل الحالي (على عكس المسار المطلق، والذي يشير إلى موقع الملف بالنسبة إلى الدليل الجذر). إذا كنت تستخدم محرر نصوص Visual Studio Code، فيمكنك نسخ مسار الملف النسبي عن طريق النقر بزر الفأرة الأيمن فوق رمز الملف وتحديد "Copy Relative Path" إذا كنت تستخدم نظام التشغيل ويندوز، أما إذا كنت تستخدم نظام التشغيل Mac فاضغط Ctrl مع زر الفأرة الأيسر. لاحظ أننا حددنا أيضًا حجم الخط واللون باستخدام السمة style. احفظ ملف index.html وأعد تحميله في المتصفح. الآن أضيف ارتباط يوجه المستخدم إلى صفحة الويب about.html وسيظهر في الصفحة كما يلي: إذا ظهر خطأ فتأكد أن الملف موجود في نفس دليل المشروع (نفس المجلد الذي يحتوي ملف index.html) وأنه لا توجد أخطاء في مسار المشروع. حتى الآن أصبحت قادرًا على إنشاء صفحة ويب جديدة وإضافة ارتباط لها على موقع الويب. ويمكنك استخدام نفس هذه الخطوات لإنشاء صفحات ويب إضافية. كما يمكنك إضافة محتوى إلى أي صفحة ويب جديدة بنفس الطريقة التي تعلمنا فيها إضافة المحتوى إلى الصفحة الرئيسية. ترجمة -وبتصرّف- للأجزاء من الخامس عشر وحتى الثامن عشر من سلسلة المقالات How To Build a Website with HTML. اقرأ أيضًا مكونات الويب: عناصر HTML المخصصة وقوالبها كيف تنشر صفحة أو موقع ويب قمت بتصميمه على الإنترنت HTML و CSS للمبتدئين: كيف تصمم أول صفحة ويب لك
  3. أول خطوة يجب القيام بها عند إنشاء مشروع موقع ويب جديد هي إنشاء دليل مشروع (أو مجلد) لتخزين جميع الملفات التي ستنشئها في عملية إعداد هذا المشروع. يقدم لك هذا المقال خطوات إعداد المجلدات والملفات اللازمة لبناء موقعك الإلكتروني باستخدام لغة HTML. بالنسبة لمشروع موقع الويب هذا يمكننا الاستمرار في استخدام دليل مشروع Practice وملف index.html الذي أنشأناه مسبقًا في هذه السلسلة من المقالات. إذا لم تتابع سلسلة المقال وتحتاج إلى إرشادات لإعداد دليل مشروع وملف index.html فيرجى الاطلاع على مقالنا "كيفية إنشاء موقع ويب باستخدام تعليمات HTML". ملاحظة: إذا قررت اختيار اسمك كاسم للدليل فتأكد من تجنب استخدام المسافات الفارغة والأحرف الخاصة (مثل ! أو # أو٪ أو غيرها) والأحرف الكبيرة، لأنها قد تسبب في مشاكل لاحقًا. سننسق ملف index.html ليكون بمثابة الصفحة الرئيسية لموقع الويب. وتتمثل الخطوة الأولى في تنسيق مستند الويب في إضافة إعلان <DOCTYPE html!> إلى السطر الأول. يخبر هذا الإعلان المتصفح بنوع إصدار HTML الذي تستخدمه ومن المهم الإعلان عنه نظرًا لوجود إصدارات متعددة من HTML. في هذا الإعلان يحدد html معيار الويب الحالي لـ HTML وهو HTML5. بعد ذلك سنضيف عنصر html من خلال إضافة وسوم الفتح والإغلاق <html>. يخبر العنصر <html> المتصفح أن كل المحتوى الذي يحتويه يهدف إلى قراءته بتنسيق HTML. وداخل هذا الوسم سنضيف السمة lang والتي تحدد لغة صفحة الويب. في المثال التالي سنحدد اللغة الإنجليزية كلغة للموقع باستخدام الخاصية en. <!DOCTYPE html> <html lang="en"> </html> ملاحظة: إذا أردت استخدام اللغة العربية في موقعك أضف الخاصية lang="ar". من الآن وصاعدًا سنكتب كل المحتوى الذي نريد إضافته إلى موقعنا الإلكتروني بين وسمي الفتح والإغلاق للعنصر <html>. كيفية إضافة الارتباطات التشعبية إلى صفحة الويب يمكن إضافة الارتباطات التشعبية Hyperlinks إلى النص أو الصور باستخدام العنصر <a>، والذي يتطلب استخدام السمة href لتحديد الارتباط. ويستخدم هذا العنصر على النحو التالي: <a href="www.DestinationLink.com">The text you want to link</a> ولتجربة ذلك عمليًا انتقل إلى ملف index.html وعدّل نموذج النص المميز برابط حقيقي مثل: https://academy.hsoub.com ثم انسخ التعليمة التالية: <a href="https://academy.hsoub.com/">The text you want to link</a> يجب أن تظهر النتيجة في صفحة الويب كما توضح لقطة الصورة التالية: يمكنك أيضًا إضافة ارتباط تشعبي إلى الصور بالطريقة التالية: <a href="https://www.digitalocean.com/community">The text you want to link <img src="https://html.sammy-codes.com/images/small-profile.jpeg"> </a> حاول اختبار نتيجة التعليمات السابقة وتأكد من نتيجتها في المتصفح. طريقة عمل عنصر تقسيم المحتوى div في لغة HTML يعمل عنصر تقسيم محتوى <div> في لغة HTML كحاوية لتنظيم صفحة الويب وتقسيمها إلى مكونات منفصلة لكل منها تصميم مخصص. عمومًا، إن لعنصر <div> تأثير ضئيل على تخطيط صفحة الويب، وعادةً ما يسند إليه سمات لضبط حجمها أو لونها أو موضعها. وفي الواقع يستخدم عنصر <div> كعنصر أساسي من عناصر CSS، ولكن في هذا المقال سنركز على كيفية عمل عناصر <div> من خلال تصميمها مباشرةً في مستند HTML. في المثال التالي صمم العنصر <div> مع السمة style، يمكنك أن تلاحظ أنه يمكن للعنصر <div> أم يحتوي على خصائص style متعددة. <div style="property: value; property: value;"></div> لاحظ أن العنصر <div> يحتوي على وسوم فتح وإغلاق ولكن لا يتطلب أي محتوى. ولفهم كيفية عمل عنصر <div> في مثال عملي. امسح محتويات ملف index.html واستبدله بالتعليمات البرمجية التالية: <div style="width:300px; height:200px; background-color:red;"> </div> احفظ الملف وأعد تحميله في المتصفح. يجب أن يظهر في صفحة الويب صندوق أحمر بعرض 300 بكسل وارتفاع 200، كما توضح لقطة الشاشة التالية: يمكنك إضافة محتوى نصي إلى العنصر <div> من خلال إضافة المحتوى بين وسوم الفتح والإغلاق. كما يوضح المثال التالي: <div style="width:300px; height:300px; background-color:red;"> This is text inside a div. </div> وعند حفظ الملف وإعادة تحميله في المتصفح ستحصل على النتيجة التالية: تسمح لك لغة HTML بوضع حاويات <div> داخل حاويات <div> أخرى. في المثال التالي سنضيف حاوية صفراء داخل الحاوية الحمراء التي أنشأناها في المثال السابق: <div style="width:300px; height:300px; background-color:red;"> <div style="width:100px; height:100px; background-color:yellow;"> </div> </div> وعند حفظ الملف وإعادة تحميله سنحصل على الصفحة التالية: لاحظ أن العنصر <div> هو عنصر من النوع Block-level، بالتالي تشغل كامل مساحة السطر وتدفع العناصر اللاحقة إلى السطر التالي. ولفهم هذه الفكرة سنضيف عنصر <div> آخر إلى الملف. انسخ التعليمات التالية والصقها في ملف المشروع: <div style="width:300px;height:300px;background-color:red;"> <div style="width:100px;height:100px; background-color:yellow;"> </div> </div> <div style="width:100px;height:100px; background-color:blue;"> </div> احفظ الملف وأعد تحميله في المتصفح وستحصل على النتيجة التالية: لاحظ كيفية دفع العنصر الجديد إلى السطر التالي على الرغم من وجود مساحة كافية تناسبه جوار العنصر السابق. يستخدم العنصر <div> كثيرًا عند بناء مواقع الويب، ويعد عنصرًا أساسيًا لأنه يساعد على تقسيم المحتوى وإضافة تصاميم مخصصة لكل جزء. كيفية تعديل الألوان في عناصر HTML يمكنك استخدام لغة HTML لتعديل ألوان العناصر وقطع محتوى صفحة الويب. على سبيل المثال يمكنك تغيير لون النص أو حدود الصورة أو عناصر <div>، وتختلف طريقة تغيير قيم الألوان لهذه الأجزاء من المحتوى من عنصر إلى آخر. فيما يلي سنوضح كيفية تغيير لون النص وحدود الصور وعناصر <div> باستخدام أسماء الألوان. يمكن تعديل لون عناصر النص مثل <h1> أو <p> باستخدام السمة style والخاصية color. وتضاف هذه الخصائص كما هو موضح في المثال التالي: <p style="color:blue;">This is blue text.</p> افتح ملف المشروع وأضف التعليمة السابقة واحفظ الملف، ثم أعد تحميله في المتصفح. ستلاحظ تغير لون النص إلى اللون الأزرق. بالنسبة للصور يمكن تعديل لون حدود الصورة باستخدام السمة style والخاصية border. مثال: <img src="https://html.sammy-codes.com/images/small-profile.jpeg" style="border: 10px solid green"/> في المثال السابق حددنا لون الحدود باللون الأخضر، وحددنا قياس الحدود 10 بكسل وأنها متينة. عند إضافة التعليمات السابقة إلى ملف المشروع وإعادة تحميله في المتصفح ستحصل على النتيجة التالية: يمكن تعديل لون الحاوية <div> باستخدام السمة style والخاصية background-color، كما يوضح المثال التالي: <div style="width:200px;height:200px;background-color:yellow;"></div> ستكون النتيجة على النحو الآتي: في الأمثلة السابقة عرفنا قيم الألوان بأسماء الألوان. تدرّب تغيير لون النص وحدود الصور وعناصر باستخدام أسماء الألوان التالية: black, white, gray, silver, purple, red, fuchsia, lime, olive, green, yellow, teal, navy, blue, maroon, aqua. يمكنك تحديد قيمة اللون من خلال القيم السداسية للون. يتكون اللون من 6 أرقام أبجدية رقمية يسبقها الرمز #. مثل: #0000FF أزرق، #40E0D0 فيروزي، #C0C0C0 فضي. في هذه السلسلة التعليمية سنستمر في استخدام أسماء الألوان. بعد نهاية مقالنا أصبحت الآن قادرًا على تنظيم وتنسيق صفحة الويب وتعديل الألوان وإضافة الروابط. وهذه المعلومات مهمة وسنستخدمها عندما نبدأ ببناء موقعنا الإلكتروني التجريبي. ترجمة -وبتصرّف- للأجزاء من السابع وحتى العاشر من سلسلة المقالات How To Build a Website with HTML. اقرأ أيضًا HTML و CSS للمبتدئين: كيف تصمم أول صفحة ويب لك HTML و CSS للمبتدئين: كيف تنشئ موقعا من عدة صفحات أساسيات لغة HTML
  4. تضم لغة HTML مجموعة كبيرة من العناصر التي تساعدنا على إضافة المحتوى إلى صفحة الويب وتنسيقه. ومن الضروري فهم طريقة عمل هذه العناصر وما هي الميزات والسمات التي يمكن استخدامها مع كل عنصر. في المقال التالي سنوضح الفرق بين عناصر Inline-level وعناصر Block-level، وكيفية ترتيب هذه العناصر في ملف المشروع، وكيفية إضافة السمات والخصائص الأساسية. كيفية استخدام عناصر Inline-level وعناصر Block-level في HTML عند ترتيب العناصر في ملف HTML، من المهم أن تدرك كيف تتوضع هذه العناصر في صفحة الويب، وما هي المساحة التي تشغلها. يمكن أن تشغل عناصر معينة مساحة على صفحة الويب أكبر من حجم المحتوى الذي تتضمنه. سيساعدك فهم سلوك أنواع العناصر المختلفة على توقع كيفية تأثيرها على موضع العناصر الأخرى على الصفحة. عمومًا يوجد نوعين مختلفين من عناصر HTML وهي عناصر Inline-level وعناصر Block-level. وكل نوع يشغل مساحة محددة من صفحة الويب. فيما يلي سنوضح كيف تحديد الإعدادات الافتراضية لهذه العناصر موضعها على صفحة الويب. عناصر Inline-level عناصر Inline-level هي العناصر التي يُحدد عرضها الأفقي وفقًا لعرض المحتوى الذي تتضمنه. على سبيل المثال العناصر <strong> و<em> التي تحدثنا عنها في الفقرات السابقة. يمكننا استخدام أداة مطوري الويب في المتصفح Firefox لفحص حجم عناصر HTML على صفحة الويب. وإذا كنت تستخدم المتصفح Chrome، فيمكنك استخدام أداة مطوري البرامج لنفس الغرض. ولكن هذا المقال سيقدم إرشادات حول أدوات مطوري الويب في المتصفح Firefox. سنجرب عرض هذه العناصر في متصفح الويب لتوضيح الفكرة. ولذلك انتقل إلى ملف index.html وافتحه في متصفح الويب. ثم انقر على زر خيارات في شريط القائمة العلوي وحدد "أدوات أكثر" لتظهر قائمة جديدة، حدد "أدوات مطوري الويب". وبالتالي ستظهر نافذة الفاحص التي تسمح لك بفحص عناصر HTML وCSS لصفحة الويب. بعد ذلك حرك المؤشر فوق عبارة وستلاحظ أن النص سيبرز باللون الأزرق الفاتح. يظهر هذا الظل المدى الكامل للمساحة التي يشغلها العنصر الذي يقف فوقه المؤشر. ويمكنك أن تلاحظ أن المساحة المشغولة للعنصر كافية لاحتواء محتواه النصي. على عكس عناصر Block-level لا تشغل عناصر Inline-level خط المساحة الأفقية الخاص بها. وبالتالي ستترتب عناصر Inline-level جنبًا إلى جنب على صفحة الويب إذا لم تضف عنصر HTML إضافي مثل عنصر فاصل السطر <br>. غالبًا ما يكون الحجم الافتراضي مناسبًا إذا كنت ترغب في تمييز كلمات مفردة في الفقرة، مثلًا يمكنك استخدام العنصر <em> لتمييز إحدى الكلمات في الفقرة بدون دفع النص التالي إلى سطر جديد. سنعود الآن إلى ملف index.html وسنضيف العنصر <br> بين سطري التعليمات. <strong>My strong text</strong> <br> <em>My emphasized text</em> لاحظ أن الوسم <br> لا يحتاج إلى وسم إغلاق. احفظ المستند وأعد تحميله في متصفحك للتحقق من النتائج. يجب أن تظهر الصفحة على النحو التالي: ستلاحظ فصل العبارتين في سطرين متتاليين بسبب استخدام عنصر فاصل السطر <br>. للتحقق من حجم العناصر استخدم أداة مطوري الويب في المتصفح Firefox، ستلاحظ أن عرض كل عنصر من عناصر النص لا يزال يتحدد من خلال عرض محتوى النص. إذا كنت تستخدم Firefox Web Developer Inspector للتحقق من حجم العناصر، فيمكنك تأكيد أن عرض كل عنصر من عناصر النص لا يزال يتحدد من خلال عرض محتوى النص: عناصر Block-level تختلف هذه العناصر عن عناصر Inline-level في أنها تشغل سطرًا كاملًا من المساحة الأفقية على صفحة الويب. هذا يعني أن هذه العناصر تبدأ تلقائيًا في سطر جديد وأنها تدفع العناصر اللاحقة إلى سطر جديد أيضًا. على سبيل المثال عناصر العنوان من <h1> إلى <h6> هي عناصر HTML من نوع Block-level، وهذه العناصر تضع محتواها تلقائيًا في سطر جديد وتدفع أي محتوى يتبعها إلى سطر جديد. يمثل كل عنصر من عناصر العناوين الستة حجم عنوان مختلف. سنوضح هذه الفكرة من خلال مثال عملي. انسخ التعليمات التالية والصقها في ملف index.html. <strong>My strong text</strong> <br> <em>My emphasized text</em> <h1>Heading 1</h1> <h2>Heading 2</h2> <h3>Heading 3</h3> <h4>Heading 4</h4> <h5>Heading 5</h5> <h6>Heading 6</h6> ثم احفظ الملف وأعد تحميله في المتصفح، وستظهر الصفحة التالية: الآن سنستخدم أداة الفاحص لدراسة كيفية توضع عناصر Block-level على الشاشة وما هو الاختلاف بينها وبين عناصر Inline-level. استخدم أداة مطوري الويب ومرر المؤشر فوق كل عنصر لفحص المساحة المشغولة والتي ستظهر مظللة باللون الأزرق. ستلاحظ أن المساحة الأفقية التي تشغلها عناصر Inline-level تقتصر على حجم المحتوى النصي، بينما تمتد المساحة الأفقية المشغولة لكل عنصر من عنصر Block-level على كامل السطر. تدفع عناصر Block-level عناصر Inline-level إلى السطر التالي، حتى لو كتبت عناصر HTML على نفس السطر في الملف. وللتأكد من ذلك سنكتب عنصر Block-level وعنصر Inline-level على نفس السطر. وفقًا لما يلي: <strong>My strong text</strong><h1>My heading</h1><em>My emphasized text</a> وستظهر النتيجة في صفحة الويب كما توضح لقطة الشاشة التالية: لاحظ أن عنصر العنوان <h1> بدأ في سطر جديد ودفع عنصر النص التالي إلى سطر جديد، على الرغم من كتابة جميع العناصر على نفس السطر. الآن أصبح لديك فهم لكيفية وضع عناصر Block-level وعناصر Inline-level وكيفية تأثيرها على موضع العناصر القريبة. كيفية دمج عناصر HTML متعددة قد نحتاج أحيانًا إلى تطبيق أكثر من عنصر من عناصر HTML على جزء محدد من المحتوى. ولذلك تتيح لغة HTML تداخل عناصر متعددة لإظهار النص بتصميم معين. يقصد بتداخل عناصر HTML أنه من الممكن وضع عنصر معين داخل عنصر آخر. يسمح لك هذا التداخل بتطبيق وسوم HTML متعددة على جزء واحد من المحتوى. وسنوضح هذه الفكرة في المثال التالي: انسخ هذا المقتطف والصقه داخل ملف index.html: <strong>My bold text and <em>my bold and emphasized text</em></strong> احفظ الملف وأعد تحميله في المتصفح، وستظهر الصفحة التالية: يوصى دائمًا بإغلاق الوسوم المتداخلة بالترتيب العكسي لوسوم الفتح. في المثال التالي أغلق الوسم <em> أولًا لأنه كان آخر وسم يُفتح. وأغلق الوسم <strong> أخيرًا لأنه كان أول وسم يُفتح. This sentence contains HTML elements that are <strong><em>nested according to best practices</em></strong> والمثال التالي يوضح كيفية عمل عناصر HTML غير المتداخلة، حيث أغلق الوسم <strong> قبل الوسم <em>: This sentence contains HTML elements that are <strong><em>not nested according to best practices</strong></em> كيفية استخدام سمات HTML تستخدم سمات HTML لتغيير ميزات عناصر HTML مثل اللون والحجم. على سبيل المثال يمكنك استخدام إحدى السمات لتغيير لون عنصر النص أو لتعديل عرض وارتفاع عنصر الصورة. فيما يلي سنتعرف على كيفية استخدام سمات HTML لتعيين قيم للحجم وخصائص الألوان لعناصر HTML. توضع السمات في وسم الفتح بالطريقة التالية: <element attribute="property:value;"> إحدى السمات الشائعة هي Style، والتي تسمح لك بإضافة خصائص النمط إلى عنصر HTML. من الشائع استخدام ورقة أنماط stylesheet منفصلة لتحديد تصميم مستند HTML. ولكننا سنستخدم السمة Style في هذا البرنامج التعليمي لتعديل تصميم العناصر. كيفية استخدام السمة Style يمكنك تغيير خصائص متعددة لعنصر <h1> باستخدام السمة style. امسح محتويات الملف index.html واستبدلها بالسطر البرمجي التالي: <h1 style="font-size:40px;color:green;">This text is 40 pixels and green.</h1> قبل تحميل الملف في المتصفح، سنشرح كل جزء من أجزاء عناصر HTML: الوسم h1 هو وسم HTML يحول النص إلى عنوان كبير الحجم. style: وهي سمة يمكن أن تأخذ مجموعة متنوعة من الخصائص المختلفة. font-size: هي الخاصية الأولى التي نحددها للسمة style. 40px: هي قيمة حجم الخط للخاصية font-size وهي تحول حجم محتوى نص العنصر إلى 40 بكسل. color: هو الخاصية الثانية التي نحددها للسمة style. green: هو قيمة الخاصية color وهي تحدد لون محتوى النص إلى اللون الأخضر. لاحظ أن الخصائص والقيم مضمنة بعلامات اقتباس، وأن كل خاصية تنتهي بفاصلة منقوطة. احفظ الملف وأعد تحميله في المصفح وستحصل على النص بالشكل التالي: كيفية استخدام HTML لإضافة الصور على موقع الويب تضاف الصور إلى مستند HTML باستخدام عنصر <img>، ويتطلب هذا العنصر السمة src التي تمكّنك من تحديد موقع الملف حيث تُخزّن الصورة. يكتب عنصر الصورة <img> على النحو التالي: <img src="Image_Location"> لاحظ أن العنصر <img> لا يستخدم علامة إغلاق <img/>. لتجربة مثال عملي حول إضافة الصور إلى صفحة موقع الويب. حمّل صورة Sammy the Shark، واحفظها في مجلد المشروع الذي نعمل عليه في هذه السلسلة html-Practice. ملاحظة: لتحميل صورة Sammy the Shark انقر على هذا الرابط ثم انقر بزر الفأرة الأيمن على الصورة إذا كنت تستخدم نظام ويندوز أو اضغط على CTRL+Left إذا كنت تستخدم نظام Mac، ثم حدد "حفظ باسم"، واحفظها باسم small-profile.jpeg في مجلد مشروعك. افتح الملف index.html في محرر النصوص وامسح المحتوى الموجود واستبدله بـ: <img src="Image_Location"> ثم انسخ مسار ملف الصورة واستبدل Image_Location في التعليمة السابقة بمسار موقع الصورة المحفوظة. ملاحظة: تأكد من نسخ المسار النسبي أو مسار ملف المشروع للصورة بدلًا من مسار الملف الكامل للصورة. حيث يشير المسار النسبي إلى موقع الملف بالنسبة إلى دليل العمل الحالي، بينما يشير المسار الكامل إلى موقع الملف بالنسبة إلى الدليل الجذر. ورغم أن كلا المسارين سيعمل في هذه الحالة، ولكن لن يعمل سوى المسار النسبي إذا قررنا نشر موقعنا على الإنترنت. نظرًا لأن هدفنا النهائي هو إنشاء موقع ويب قابل للنشر فإننا سنستخدم المسارات النسبية لإضافة عناصر <img> إلى الأمثلة. الخطوة الأخيرة هي حفظ ملف index.html وإعادة تحميه في المتصفح. وستظهر الصفحة التالية: تقنيًا يمكنك استخدام روابط للصور المستضافة على الإنترنت كمسار للملفات. ولفهم كيفية عمل ذلك، استبدل موقع الصورة في المثال السابق برابط صورة Sammy the Shark كما يلي: <img src="https://html.sammy-codes.com/images/small-profile.jpeg"> احفظ الملف بعد إضافة التعديلات السابقة وأعد تحميله في المتصفح. وستلاحظ أنك حصلت على نفس النتيجة ولكن في هذه المرة حصلت على الصورة من موقعها على الإنترنت بدلًا من دليل المشروع الحالي. يمكنك تجربة إضافة صور أخرى من الإنترنت باستخدام روابط الموقع كقيمة للسمة scr في الوسم <img>. ولكن عند إنشاء موقع ويب من الأفضل عدم استخدام صور من الإنترنت لضمان استدامة الموقع. لأنه إذا أزيلت الصور من قبل مضيفها أو تغير عنوانها فلن تعرض مرة أخرى على موقعك. إضافة نص بديل لتسهيل الوصول إلى الصورة عند إضافة صورة إلى صفحة الويب يجب تضمين نص بديل يصف محتواها باستخدام السمة alt. لا يعض هذا النص عادةً على صفحة الويب ولكنه يستخدم بواسطة برامج قراءة الشاشة لتوصيل المحتوى إلى زوار الموقع من ذوي المشاكل البصرية. مثال: <img src="https://html.sammy-codes.com/images/small-profile.jpeg" alt="Digital Ocean’s mascot, a blue smiling shark." > عند إضافة نص بديل، ضع في حسبانك ما يلي: بالنسبة للصور التي تحتوي على معلومات يجب أن يصف النص البديل موضوع الصورة بطريقة واضحة ودقيقة، وبدون الرجوع إلى الصورة نفسها. مثلًا لا تكتب "صورة قرش في المحيط" وإنما "قرش في المحيط". بالنسبة لصور الزخرفة يجب استخدام السمة alt ولكن بدون إضافة أي قيمة. أي بالطريقة التالية: <img src="images/decorative_image.jpeg" alt=""> وهذا يؤدي إلى تحسين تجربة قارئ الشاشة. خاتمة وضحنا في هذا المقال الفرق بين عناصر HTML وكيفية عمل كل منها، ثم شرحنا كيفية استخدام السمة style لتعديل النص، وكيفية إضافة الصور إلى صفحات الويب. وتعد هذه الأفكار ضرورية لإنشاء أي صفحة ويب. في المقال التالي سنبدأ بإعداد ملف المشروع وإنشاء الصفحة الرئيسية لموقعنا التجريبي. ترجمة -وبتصرّف- للأجزاء من الثالث وحتى السادس من سلسلة المقالات How To Build a Website with HTML. اقرأ أيضًا أساسيات لغة HTML مكونات الويب: عناصر HTML المخصصة وقوالبها الدلالات المضمنة لعناصر صفحة الويب ودورها في تعزيز سهولة الوصول هيكلة النصوص باستخدام لغة HTML
  5. تستخدم لغة الترميز HTML لإنشاء وتصميم مواقع الويب، وتساعد على وصف وتحديد محتويات صفحة الويب لبرامج التصفح. سنقدم لك في هذا الدليل سلسلة مقالات تعليمية لنساعدك على إنشاء موقع الويب وتخصيصه باستخدام لغة HTML وهي لغة الترميز القياسية المستخدمة لعرض المستندات في مستعرض الويب. لا يتطلب فهم هذه السلسة وجود أي خبرة سابقة في البرمجة، ولكننا نوصيك بالبدء من بداية السلسلة إذا كنت ترغب بإعادة إنشاء موقع الويب التوضيحي المنشأ في هذه السلسلة. في نهاية هذه السلسلة، ستحصل على موقع ويب جاهز للنشر على الإنترنت ومعرفة أساسية بلغة HTML. ويعد تعلم كيفية استخدام HTML أساسًا قويًا لتعلم مهارات تطوير الواجهة الأمامية للويب مثل CSS وJavaScript. كيفية إنشاء مشروع HTML جديد باستخدام محرر النصوص لإنشاء موقع جديد سنحتاج إلى استخدام محرر نصوص. المحرر الذي سنستخدمه هو برنامج Visual Studio Code، وهو محرر نصوص مجاني متاح للاستخدام على نظام التشغيل ويندوز ولينكس وماك، ويمكنك استخدام أي محرر نصوص تفضله. بعد فتح محرر النصوص الذي تفضله سننشئ مشروعًا جديدًا ونسميه "html-Practice". بالتالي سينشئ البرنامج مجلدًا جديدًا بهذا الاسم، وسنستخدم هذا المجلد لتخزين جميع الملفات والمجلدات التي ننشئها في سياق هذه السلسلة. لإنشاء مجلد مشروع جديد في برنامج Visual Studio Code انتقل إلى قائمة "File" في القائمة العلوية، ستظهر قائمة منسدلة حدد خيار "Add folder to Workspace". في النافذة الجديدة، انقر فوق زر "New Folder" وأنشئ مجلدًا جديدًا باسم html-Practice. بعد ذلك ستلاحظ ظهور قائمة على الجانب الأيسر، تضم جميع مجلدات أوراق العمل التي أنشئت في البرنامج. الخطوة التالية هي إنشاء ملف جديد وتسميته index.html داخل مجلد html-Practice. سنستخدم هذا الملف خلال هذه السلسلة. إذا كنت تستخدم برنامج Visual Studio Code، يمكنك إنشاء ملف جديد بالنقر على زر الفأرة الأيمن فوق اسم المجلد "html-Practice"، ثم تحديد خيار "new file". املأ الحقل الجديد باسم الملف مع إضافة اللاحقة "index.html"، وستلاحظ ظهور الملف الجديد تحت مجلد المشروع "html-Practice". سنستخدم هذا الملف في الدروس القادمة لكتابة تعليمات لغة html وتجربتها. التصحيح واستكشاف أخطاء CSS وHTML قبل أن نبدأ في دروس وتمارين HTML، سنقدم لك بعض الملاحظات الضرورية: الدقة مهمة جدًا عند كتابة تعليمات HTML، وأي تغيير بسيط في الأحرف أو حتى إضافة لمسافة فارغة سيؤدي إلى عرقلة عمل هذه التعليمات. إذا لاحظت وجود خلل في تنفيذ التعليمات في المستعرض، فتأكد من كتابة التعليمات ودقتها. لاكتشاف الأخطاء وإصلاحها تحقق من المسافات الزائدة أو المفقودة، ودقق طريقة كتابة الأحرف، وتحقق من الأخطاء الإملائية وعلامات الترقيم ومن الأحرف المفقودة أو الخاطئة. في كل مرة تضيف تعديلات على التعليمات، تأكد من حفظ الملف قبل إعادة تحميله في المتصفح. ملاحظة سريعة حول ميزات دعم HTML التلقائي توفر بعض برامج تحرير النصوص (مثل محرر Visual Studio Code الذي نستخدمه في هذه السلسلة) دعمًا تلقائيًا لكتابة تعليمات HTML البرمجية. بالنسبة إلى Visual Studio Code، يتضمن هذا الدعم الاقتراحات الذكية والإكمال التلقائي. وعلى الرغم من أهمية هذا الدعم، يجب أن تدرك أنه قد تحدث أخطاء كثيرة إذا لم تكن معتادًا على التعامل مع ميزات الدعم هذه. وفي حال وجدت أن هذه الميزات تشتت انتباهك فيمكنك إيقافها في تفضيلات محرر النصوص. كيفية عرض التعليمات البرمجية المصدرية لمستند HTML تستخدم تعليمات لغة HTML كإرشادات تُخبر المتصفح بكيفية عرض المحتوى في صفحة الويب. على سبيل المثال يمكن أن تخبر تعليمات HTML المتصفح عن محتوى النص الذي تريد عرضه على أنه عنوان، ومحتوى النص الذي تريد عرضه على أنه فقرة عادية. تستخدم تعليمات HTML لإضافة الصور إلى صفحة الويب وتعيين روابط للنصوص أو الصور. تكتب تعليمات لغة HTML باستخدام الوسوم <>، ومعظم التعليمات تكتب على النحو التالي: <tagname>. تستخدم العديد من التعليمات وسم الفتح ووسم الإغلاق للالتفاف حول المحتوى الذي تريد تعديله. للتعرف على كيفية استخدام هذه الوسوم، سندرس أولًا هذا المقتطف من تعليمات HTML: <h1>Sammy's Sample HTML</h1> <p>This code is an example of how HTML is written.</p> <p>It uses HTML tags to structure the text.</p> <p>It uses HTML to add a <a href="digitalocean.com/community">link</a>.</p> <p>And it also uses HTML to add an image:</p> <img src="https://html.sammy-codes.com/images/small-profile.jpeg"/> توضح تعليمات HTML في هذا المقتطف كيفية استخدام وسوم HTML لهيكلة النص وإضافة الصور والروابط. إذا لم تفهم الوسوم والتعليمات المذكورة فلا تقلق، لأننا سندرس هذه الوسوم في هذه السلسلة. بالذهاب إلى مجلد المشروع الذي أنشأناه ستلاحظ وجود ملف جديد باسم index.html، عند النقر عليه ستفتح صفحة ويب في المتصفح الذي تفضله، وستحتوي تنفيذًا للتعليمات التي أضفناها إلى الملف. الآن أصبح لديك نظرة عامة لكيفية عرض تعليمات HTML في مستعرض الويب. والآن سننتقل لتعلم كيفية عرض الشيفرات المصدرية لأي صفحة ويب باستخدام أداة المتصفح. كيفية عرض شيفرات المصدر لصفحة ويب تقريبًا كل صفحة ويب تصادفها تستخدم HTML لبناء صفحات HTML وعرضها. يمكنك فحص شيفرة المصدر لأي صفحة ويب باستخدام أي مستعرض ويب مثل فايرفوكس Firefox أو كروم Chrome. في Firefox انتقل إلى قائمة "أدوات" في القائمة العلوية ثم انقر على "أدوات مطوري الوب". أو يمكنك استخدام اختصار لوحة المفاتيح Ctrl+Shift+I لعرض الشيفرات المصدرية لصفحة الويب. في المتصفح Chrome العملية متشابهة جدًا. انقر على زر خيارات في الزاوية العلوية اليسرى. ستظهر قائمة منسدلة اختر "المزيد من الأدوات" ثم حدد "أدوات مطوري البرامج". أو يمكنك استخدام اختصار لوحة المفاتيح Ctrl+Shift+I. حاول فحص الشيفرات المصدرية لموقع الويب التجريبي الذي سننشئه في هذه السلسلة بالانتقال إلى هذه الصفحة. ستظهر لك صفحة تحتوي العديد من وسوم html. لا تقلق إذا وجدت التعليمات المذكورة غريبة، ففي نهاية هذه السلسلة سيصبح لديك فهم أفضل لكيفية تفسير تعليمات HTML وستصبح قادرًا على استخدام HTML لبناء مواقع الويب وتخصيصها. ملاحظة: يمكنك فحص شيفرة المصدر لأي صفحة ويب باستخدام أدوات متصفح الويب Firefox أو Chrome. حاول فحص شيفرات بعض مواقع الويب المفضلة لديك للتعرف على الشيفرات الأساسية التي تبني مستندات الويب. على الرغم من أن الشيفرات المصدرية لهذه المواقع قد تحتوي لغات أكثر من HTML. ولكن تعلم HTML في البداية سيساعد في إعدادك لتعلم لغات وأطر عمل إضافية لإنشاء مواقع الويب لاحقًا. يجب أن تكون قادرًا الآن على فهم كيفية تنسيق مستند HTML، ومعرفة كيفية فحص شيفرات HTML المصدرية باستخدام أداة المتصفح. كيفية فهم واستخدام عناصر HTML تتكون مستندات الويب من عناصر وتعليمات لغة HTML، وتحتوي معظم عناصر HTML على محتوى والذي يمثل نصوص أو صور إضافة إلى وسوم HTML التي تخبر المستعرض كيفية تفسير المحتوى (عنوان أو فقرة). يمكن استخدام عناصر HTML لإضافة بنية ودلالات وتنسيق إلى الأجزاء المختلفة من مستند HTML. تكتب معظم عناصر HTML داخل وسوم HTML، ويكتب المحتوى بين وسم البداية ووسم النهاية. فيما يلي رسم توضيحي يصف أجزاء عنصر HTML: سنحاول الآن اكتشاف HTML من خلال الممارسة العملية. انسخ السطر البرمجي التالي والصقه في ملف index.html الذي أنشأته عند إعداد مشروع HTML: <strong>My strong text</strong> في هذا المثال يضيف العنصر <strong> تنسيقًا ثخينًا عن طريق إرفاق النص بزوج من وسوم الفتح والإغلاق. لاحظ أن وسم الإغلاق يشار إليه بالعلامة /. ملاحظة: قد تلاحظ أن العنصر <strong> يضيف للنص النمط الثخين، ويمكن تحقيق نفس هذا التأثير باستخدام عنصر آخر وهو العنصر <B>. ولكن يضيف العنصر <strong> للنص نمطًا ثخينًا ومعنى دلاليًا أعمق بحيث يظهر النص بأنه أكثر أهمية موازنة من وسم <B>. وهناك العديد من العناصر المتشابهة الأخرى في لغة HTML التي تستخدم لتمييز النص. مثلًا يضيف عنصر التركيز <em> النمط المائل والمعنى الدلالي الذي يشير إلى التأكيد على النص. أما العنصر <i> يضيف فقط النمط المائل. لذلك إذا كنت تريد التأكيد على النص يفضل أن تستخدم العنصر <em>. للتحقق من النتائج يمكنك فتح ملف index.html في المتصفح كما ذكرنا سابقًا. وعلى الرغم أن ملفك ليس محفوظًا على الإنترنت إلا أن المتصفح يظل قادرًا على تفسير ملف HTML ولو كان مجرد مستند صفحة ويب. تأكد من حفظ التغييرات في ملف index.html قبل تحميله في المتصفح، لأنه سيعرض التحديثات المحفوظة فقط. كيفية عرض ملف HTML غير متصل في متصفحك يمكنك عرض ملف HTML دون اتصال في المتصفح بعدة طرق: سحب الملف وإسقاطه إلى متصفحك. النقر بزر الفأرة الأيمن على الملف (إذا كنت تستخدم نظام ويندوز)، أو نقر Ctrl+Left بعد تحديد الملف (إذا كنت تستخدم نظام Mac). نسخ المسار الكامل للملف ولصقه في شريط المتصفح. إذا كنت تستخدم محرر النصوص Visual Studio Code، فيمكنك نسخ مسار الملف index.html بالنقر عليه بزر الفأرة الأيمن وتحديد "نسخ". ثم لصق المسار في متصفح الويب. ملاحظة: لتحميل الملف في المتصفح من المهم نسخ المسار الكامل (الذي يشير إلى موقع الملف بالنسبة إلى الدليل الجذر) بدلًا من المسار النسبي (الذي يشير إلى ملف متعلق بدليل العمل الحالي). وفي المحرر Visual Studio Code يشير "مسار النسخ" إلى مسار الملف الكامل. ولكن تذكر أننا سنستخدم مسارات نسبية لبعض الملفات في أجزاء أخرى من هذا المقال. بعد تحميل الملف في المتصفح ستظهر الصفحة التالية: الآن سنجرب استخدام عناصر HTML أخرى. سننشئ ملفًا جديدًا باسم Practice.html ونستخدم العنصر <em> لزيادة تركيز النص. <strong>My strong text</strong> <em>My emphasized text</em> سنحفظ الملف ونعيد تحميله في المتصفح، وستظهر الصفحة التالية: نلاحظ أنه أضيف التنسيق الثخين للعبارة الأولى والعبارة الثانية ظهرت بتنسيق مائل، ووضعت العبارتين جنبًا إلى جنب. ربما كنت تتوقع أنه إذا أضفت العبارة الثانية <em>My emphasized text</em> إلى السطر الثاني من محرر النصوص، فإنها ستظهر أسفل العبارة الأولى في متصفح الويب. ولكن في الواقع تتطلب بعض عناصر HTML مثل <strong> و<em> تحديد فواصل أسطر باستخدام عناصر HTML خاصة. كيفية إضافة العنصر head إلى صفحة الويب يعد العنصر <head> أحد عناصر HTML المهمة، حيث يساعد على إنشاء قسم لتضمين معلومات حول مستند الويب يمكن قراءتها آليًا. وتستخدم هذه المعلومات من قبل المتصفحات ومحركات البحث لتفسير محتوى الصفحة. المحتوى الموجود داخل عنصر <head> لن يكون مرئيًا على صفحة الويب. ملاحظة: يعد عنصر <head> في HTML عنصرًا دلاليًا لأنه يخبر المتصفح والمبرمج ما هو الهدف من المحتوى. وتستخدم العناصر الدلالية لتسهيل القراءة البشرية للمستند HTML، ولكي تزود المتصفح بمزيد من المعلومات لتفسير المحتوى ولتحسين إمكانية الوصول إلى الموقع. ويمكن أن تساعد أيضًا في تحسين الموقع في محركات البحث SEO. لاستخدام العنصر head تحتاج إلى وسمي فتح وإغلاق، ويمكنك إضافة تعليمات HTML البرمجية بين هذين الوسمين، كما يوضح المثال التالي: <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Sammy’s First Website</title> </head> </html> لاحظ تداخل مجموعة متنوعة من عناصر HTML داخل بعضها البعض. يتداخل العنصران <title> و<meta> داخل العنصر <head>، ويتداخل العنصر <head> داخل العنصر <html>. وعند متابعة هذه السلسلة ستلاحظ استخدام تداخل العناصر بصورة متكررة. الآن سنتوقف لشرح التعليمات البرمجية في المثال السابق. في سطر الشيفرة بعد علامة فتح الوسم <head> أضفنا العنصر <meta charset="utf-8"> وهو يحدد مجموعة أحرف المستند من النوع UTF-8، وهو تنسيق يدعم غالبية الأحرف من مجموعة متنوعة من اللغات المختلفة. ويحدد السطر التالي من التعليمات البرمجية عنوان مستند HTML باستخدام العنصر <title>. ويعرض المحتوى الذي تضيفه في هذا العنصر في علامة تبويب المتصفح وكعنوان موقع الويب في نتائج البحث، ولكنه لا يظهر على صفحة الويب نفسها. عندما تنشئ موقعك الإلكتروني استبدل "Sammy’s First Website" باسمك أو اسم موقع الويب الذي تنشئه. يضيف المطورون غالبًا بعض المعلومات الإضافية في قسم <head>. ولكنّ المعلومات التي أضفناها كافية للإنشاء صفحة ويب أساسية، لذلك لن نغرقك في التفصيل أكثر. احفظ الملف قبل الانتقال إلى القسم التالي. وإذا حاولت تحميل الملف في متصفحك فستظهر صفحة فارغة ولا تحتوي أي إضافات، وستلاحظ ظهور العنوان الذي أضفته في شريط المتصفح. كيفية إضافة أيقونة المفضلة إلى موقعك الإلكتروني باستخدام تعليمات HTML تعد أيقونة المفضلة Favicon جزءًا أساسيًا من هوية موقع الويب. وهي صورة صغيرة تتواجد في علامة تبويب المتصفح بجانب عنوان صفحة الويب. يمكنك استخدام أي صورة تريدها كرمز لأيقونة المفضلة ولكن يفضل أن تكون الصورة بسيطة عالية التباين لتظهر بطريقة أفضل نظرًا لصغر حجم أيقونة المفضلة. ويمكنك إنشاء رمز لأيقونة المفضلة من خلال الاستعانة ببعض الموقع. فيما يلي سنشرح كيفية إضافة أيقونة المفضلة إلى صفحة موقع الويب باستخدام تعليمات HTML. توضح الصورة أدناه موقع الأيقونة المفضلة لموقع أكاديمية حسوب: لإضافة أيقونة المفضلة إلى موقعك أنشئ مجلدًا في دليل المشروع يسمى images واحفظ صورة أيقونة المفضلة في هذا المجلد. إذا لم يكن لديك صورة يمكنك تنزيل صورة Sammy the Shark هذه التي استضفناها على موقعنا التوضيحي على الويب. بعد ذلك أضف عنصر <link> إلى ملف index.html أسفل العنصر <title> مباشرةً. في النهاية يجب أن يضم ملفك التعليمات التالية: <title> Sammy’s First Website </title> <link rel="shortcut icon" type="image/jpg" href="Favicon_Image_Location"/> تأكد من استبدال FaviconImageLocation بمسار الملف النسبي لصورة أيقونة المفضلة التي تريد إضافتها. ثم احفظ ملف index.html وأعد تحميله في متصفح الويب. ستلاحظ ظهور صورة أيقونة المفضلة بجانب عنوان موقع الويب. كيفية تصميم عنصر في لغة HTML عنصر <body> هو عنصر دلالي يخبر المتصفح أن محتواه جزء من نص صفحة الويب ومخصص العرض. ويعد من العناصر المهمة والتي لا يمكن الاستغناء عنها. لذلك من المهم أن نتعلم كيفية إضافة العنصر <body> حيث يمكن إضافة المحتوى لاحقًا. لإضافة عنصر <body> إلى المستند، يجب إدراج وسوم الفتح والإغلاق للعنصر <body>، بعد وسم إغلاق العنصر </head> وقبل وسم إغلاق العنصر </html>. الآن أصبح مستند index.html يضم التعليمات التالية: <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Sammy’s First Website</title> <link rel="shortcut icon" type="image/jpg" href="Favicon_Image_Location"/> </head> <body> </body> </html> يجب أن تكون الآن قادرًا على فهم الغرض من استخدام كل العناصر المذكورة في الملف، وقادرًا على فهم كيفية إضافتها إلى مستند HTML. كيفية إنشاء القسم العلوي من صفحتك الرئيسية باستخدام HTML سنبدأ الآن بإضافة المحتوى عن طريق نسخ القسم العلوي من موقع الويب التوضيحي. يتكون هذا القسم العلوي من صورة خلفية كبيرة وصورة ملف تعريف صغير ورأس نصي ورأس فرعي للنص ورابط. صمم كل جزء من هذه الأجزاء من المحتوى ووضعه باستخدام تعليمات لغة HTML. في المقال التالي ستتعلم كيفية استخدام لغة HTML لإنشاء محتوى القسم العلوي في صفحة ويب جديدة. احصل على موقع إلكتروني مخصص لأعمالك أبهر زوارك بموقع احترافي ومميز بالاستعانة بأفضل خدمات تطوير وتحسين المواقع على خمسات أنشئ موقعك الآن ترجمة -وبتصرّف- للمقدمة والجزأين اﻷول والثاني من سلسلة المقالات How To Build a Website with HTML. اقرأ أيضًا HTML و CSS للمبتدئين: كيف تصمم أول صفحة ويب لك مكونات الويب: عناصر HTML المخصصة وقوالبها HTML و CSS للمبتدئين: كيف تنشئ موقعا من عدة صفحات.
  6. تُعَدّ وسائل التواصل الاجتماعي إحدى الأدوات التسويقية الأكثر شعبيةً، وتعتمد عليها اليوم معظم العلامات التجارية لتسويق منتجاتها وتعزيز علاقاتها مع العملاء. يركز التسويق الاجتماعي على الأسباب البيئية والنشاط الاجتماعي والحالة الاقتصادية للجمهور المستهدف، لذا تحاول معظم الشركات الترويج للحملات التسويقية عبر المنصات الاجتماعية مثل فيسبوك وإنستغرام ويوتيوب وتويتر، نظرًا لوجود أعداد كبيرة من المستخدمين على هذه المنصات. تساعد وحدة التسويق الاجتماعي في نظام أودو في إنجاز عمليات التخطيط والمراقبة وتعزيز دعم العملاء، وتقدم لك كل الأدوات التي تحتاجها لإدارة حساباتك على وسائل التواصل الاجتماعي وتنظيمها، كما أنها تساعد في الوصول إلى الجمهور بسرعة خلال وقت أقل. في هذه المقالة سنلقي الضوء على وحدة التسويق الاجتماعي في نظام أودو وكيفية استخدامها وأهم الميزات التي توفرها. ميزات وحدة التسويق الاجتماعي في نظام اودو تضم وحدة التسويق الاجتماعي في نظام أودو كل الأدوات التي تحتاجها لإدارة عمليات التسويق على منصات التواصل الاجتماعي، وتسمح لك بالتواصل مع العملاء وإدارة المحتوى وتحليل الحملات التسويقية المختلفة. وباستخدام وحدة Social marketing ستتمكن من الوصول إلى منصات التواصل الاجتماعي المشهورة، مثل فيسبوك وتويتر ولينكد عن ويوتيوب وإنستغرام. أهم الميزات التي توفرها وحدة التسويق الرقمي في نظام أودو: إمكانية نشر وجدولة منشورات منصات وسائل التواصل الاجتماعي، مثل فيسبوك وتويتر ولينكد إن. الحصول على قائمة دقيقة لزوار الموقع وإمكانية التواصل معهم عبر البريد الإلكتروني والرسائل النصية والإشعارات الفورية أو طلبات الدردشة المباشرة. إمكانية إرسال الإشعارات إلى مستخدمي موقعك الإلكتروني. إنشاء حملات تسويقية متكاملة والحصول على نظرة حول نتائج حملتك (عدد النقرات، الأرباح، المبيعات، العملاء الجدد). تتبع مسار رابط مضاف إلى أحد منشورات المنصات الاجتماعية والحصول على معلومات دقيقة حول مقدار الإيرادات التي حققها هذا الرابط وعدد العملاء الجدد. القوائم الأساسية في صفحة التسويق الاجتماعي تظهر الصورة التالية لوحة قيادة وحدة التسويق الاجتماعي في نظام أودو: يظهر في القائمة العلوية مجموعة من علامات التبويب وهي: Feed المشاركات الحملات الزائرين الإعدادات. لبدء استخدام التطبيق يجب عليك أولًا إضافة حسابك على أحد منصات التواصل الاجتماعي من خلال النقر على "ADD A STREAM". كما توضح الصورة التالية: وستظهر نافذة منبثقة تضم أهم منصات التواصل الاجتماعي الشهيرة: حدد منصة التواصل الاجتماعي التي تريد استخدامها للتسويق، واسمح بالأذونات المطلوبة لربط حسابات الوسائط الاجتماعية مع وحدة التسويق الاجتماعي في نظام أودو. الزر الثاني الموجود في الصفحة الرئيسية هو "New post" الذي يسمح لك بإضافة منشور فريد على وسائل التواصل الاجتماعي لنشر محتوى على حساباتك على وسائل التواصل الاجتماعي يمكنك إما النقر على زر "New post" كما توضح الصورة التالية: أو الانتقال إلى علامة التبويب مشاركات والنقر فوق زر "إنشاء". ستفتح صفحة تكوين المنشور الجديد، ومن خلالها يمكنك إنشاء منشور ونشره على منصات متعددة. تساعدك هذه الأداة على إدارة الحملات التسويقية وضبط الإشعارات وإنشاء المنشورات وتنسيقها ونشرها على موقعك الإلكتروني وحسابك على منصات التواصل الاجتماعي. في صفحة المنشورات، يوفر أودو عدة طرق لعرض المنشورات، وهي طريقة عرض كانبان والقائمة والتقويم والمحور. وباستخدام طريقة عرض التقويم يمكنك الحصول على نظرة عامة مفصلة على مشاركاتك التي نشرتها والتي جدولتها للنشر لاحقًا. هذه المفيدة مهمة إذا كان لديك عدد كبير من المنشورات على وسائل التواصل الاجتماعي، وتمكّنك من إدارة منشوراتك وعرضها وتصنيفها بسهولة. إرسال الإشعارات تمكّنك وحدة التسويق الاجتماعي "Social Marketing" من إرسال الإشعارات إلى العملاء، وبالتالي يمكنك إعلام العملاء بكل نشاطات شركتك مثل إصدار المنتجات والأخبار والتحديثات ومعلومات المنتج وغيرها الكثير. ولتمكين هذه الميزة، يجب أن تنتقل إلى علامة التبويب "إعداد" في وحدة الموقع الإلكتروني في نظام أودو، ثم قسم الإشعارات وتفعيل ميزة إرسال الإشعارات كما توضح الصورة التالية: بعد تحديد خيار تمكين الإشعارات ستظهر مجموعة من الحقول وهي العنوان والنص ووقت الانتظار، وبعد الانتهار من تفعيل ميزة إرسال الإشعارات في وحدة الموقع الإلكتروني، ستتمكن من استخدام هذه الميزة في وحدة التسويق الاجتماعي. الحملات التسويقية باستخدام وحدة Social marketing في نظام أودو، يمكنك إنشاء الحملات التسويقية وإدارتها. ولإنشاء حملة تسويقية جديدة، انتقل إلى علامة التبويب "الحملات" وانقر على زر إنشاء لتظهر الصفحة التالية: أدخل تفاصيل تكوين الحملة وعين الشخص المسؤول عنها، ثم استخدم الزر "إضافة" لحفظ الحملة. ستظهر عندهاالحملة الجديدة ضمن قائمة الحملات، ويمكنك النقر على اسم الحملة لعرض تفاصيلها. يوفر أودو العديد من الخيارات للترويج للحملات التسويقية، حيث يمكنك إرسال الحملة عبر منصات التواصل الاجتماعي أو الرسائل القصيرة أو الإشعارات الفورية. بعد الانتهاء من إضافة معلومات الحملة وإرسالها إلى العملاء، يمكنك الحصول على كل تفاصيل الحملة، بما في ذلك تفاصيل الإيرادات وعروض الأسعار والفرص وعدد النقرات. الزائرين Visitors يمكنك تتبع حساباتك على وسائل التواصل الاجتماعي بالانتقال إلى علامة التبويب الزوار، إذ تعرض هذه الصفحة معلومات حول عدد المشاهدات والزيارات وأسماء الزوار، كما تمكّنك من إرسال بريد إلكتروني أو رسالة نصية إلى شخص معين. ويمكن عرض المعلومات التفصيلية للزائر بالنقر على اسمه، حيث ستظهر التفاصيل الشخصية ورابط موقع الويب والحالة النشطة للزائرين. يمكنك تحديد الحساب الذي تريد استخدامه لنشر منشورك الجديد من القائمة المحددة. اكتب المحتوى الذي تريد إضافته في حقل "الرسالة"، واستخدم خيار "ATTACH IMAGES" لإرفاق الصور إلى منشورك. يمكنك تحديد وقت نشر المنشور باستخدام خيارات "Send now" لنشر المنشور فورًا أو "Schedule later" لجدولته ونشره لاحقًا. بعد إضافة جميع التفاصيل انقر على زر "حفظ"، حيث سيظهر المنشور في موجز وحدة Social marketing في نظام أودو. فوائد التسويق عبر وسائل التواصل الاجتماعي أصبح استخدام منصات التواصل الاجتماعي للتسويق ضروريًا لجميع الشركات التجارية، وفيما يلي سنذكر بعض الفوائد التي يمكن للشركات أن تحصل عليها عند دمج وسائل التواصل الاجتماعي في استراتيجيتها التسويقية: جذب انتباه الجمهور تُستخدم منصات التواصل الاجتماعي للترويج للمنتجات، وتحقيق المزيد من الأرباح من خلال تحسين الوصول إلى عدد أكبر من العملاء. ويمكن استخدامها للترويج للحملات التسويقية وتحليل سلوك العملاء وتحسين استراتيجيات الشركة. يساهم التسويق الاجتماعي في زيادة مبيعات الأعمال التجارية من خلال الترويج للمنتجات الفريدة والعروض المميزة التي تجذب اهتمام العملاء على وسائل التواصل الاجتماعي. خلق الوعي حول المنتج سواءً كنت تخطط لإطلاق منتج جديد أو التعريف بمجالات عمل شركتك الرائدة، يمكنك استخدام وسائل التواصل الاجتماعي لتسويق خدماتك وتقديم عرض تفصيلي حول منتجاتك. وهذا يساعد العملاء في التعرف على تفاصيل منتجاتك وميزاتها وأسعارها. تسهيل التفاعل مع الجمهور على عكس الإعلان التلفزيوني أو الإعلان الصحفي، يوفر التسويق الاجتماعي فرصةً للعملاء للتفاعل مع فريق المبيعات والتواصل معه بسهولة. وتساعد وسائل التواصل الاجتماعي على الحصول على آراء العملاء من خلال الرسائل المباشرة أو التعليقات، كما تساعد على الإجابة على الاستفسارات وحل المشاكل المتعلقة بكيفية استخدام المنتج. طريقة تسويق منخفضة التكلفة يُعَدّ التسويق الاجتماعي أحد طرق التسويق الفعال والمنخفض التكلفة. يمكن أن يكون لتغريدة تويتر أو منشور على فيسبوك تأثير أكبر من حملة تسويق الإعلانات الصحفية بفضل الأعداد الهائلة من المستخدمين المتواجدين على هذه المنصات. تتبع آراء العملاء تمكّنك منصات التواصل الاجتماعي من تتبع آراء العملاء بسهولة، من خلال مراجعة تقييمات العملاء ومتابعة تعليقاتهم، كما يمكن للشركات التعرف على المشاكل التي يعاني منها العملاء والتواصل معهم بطريقة سهلة ومرنة. التعرف على نمط الشراء تساعدك تحليلات منصات التواصل الاجتماعي على تتبع نمط الشراء وتحديد الجمهور المستهدف، والحصول على نظرة شاملة حول اهتمامات العميل وتفضيلاته. خاتمة باستخدام وحدة التسويق الاجتماعي Social marketing، يمكنك تسويق منتجاتك وخدماتك بسهولة على منصات التواصل الاجتماعي المختلفة، ومن خلال الميزات والأدوات المتقدمة المتوفرة في هذه الوحدة ستتمكن من تحسين استراتيجيتك التسويقية والحصول على أفضل النتائج. اقرأ أيضًا استخدام وحدة أودو للتسويق عبر البريد الإلكتروني نظرة تفصيلية على وحدة أتمتة التسويق في نظام أودو تطبيقات أودو وأهم استخداماتها
  7. يُعَد التسويق عنصرًا أساسيًا في مجال الأعمال، ولا يمكن للشركات الاستغناء عنه. وفي عالم التسويق التنافسي، لا يمكن للشركات أن تحقق أهدافها إلا بمساعدة نظام متطور لدعم التسويق، خاصةً بسبب صعوبة تحليل كفاءة الحملة إذا أجريت بالطريقة اليدوية وصعوبة إدارة الأنشطة التسويقية المختلفة. من هنا تأتي أهمية استخدام نظام أودو، فهو يضم أحدث أدوات التسويق التي تساعدك على إنجاز المهام التسويقية المختلفة وأتمتتها، ومن ضمن هذه الأدوات، وحدة أتمتة التسويق. ترتبط وحدة أتمتة التسويق في نظام أودو ارتباطًا وثيقًا بوحدات التسويق الأخرى في النظام، وتعمل جميع هذه الوحدات معًا لتشكيل أرضية عمل مشتركة لتحقيق أقصى قدر من الكفاءة في إدارة التسويق. سيمنحك هذا المقال نظرةً كاملةً عن وحدة أتمتة التسويق في نظام أودو وكيفية تكوينها واستخدامها وأهم الميزات التي تقدمها. تكوين وإعداد وحدة أتمتة التسويق في نظام أودو من السهل إعداد وتكوين وحدة إدارة التسويق، إذ تسمح لك هذه الوحدة بالحصول على بيئة عمل متقدمة لتتمكن من إدارة إجراءات ومهام التسويق المختلفة. تُعَد أتمتة التسويق ضروريةً لرعاية وتحفيز العملاء المحتملين ليصبحوا عملاء حقيقيين. تسمح لك الوحدة الذكية من أودو بإرسال معلومات البرامج الترويجية الصحيحة إلى الطرف المناسب في الوقت المناسب. التكوين والاستخدام قبل إنشاء برنامج الحملة الجديد، يجب أن تنتقل إلى تطبيق أودو لإدارة علاقات العملاء لعرض إجراءات العملاء وإلقاء نظرة على مهام فريق المبيعات لتتمكن من إرسال حملات فعالة إلى العملاء المناسبين. ولإنشاء حملة تسويقية جديدة، انتقل إلى وحدة أتمتة التسويق وانقر فوق زر "إنشاء" كما هو موضح في لقطة الشاشة التالية: بعد النقر فوق زر "إنشاء"، ستظهر صفحة إعداد الحملة التسويقية وفقًا للقطة الشاشة التالية: ابدأ بتسمية الحملة وتأكد أن الاسم مناسب وسيسمح لعملائك المحتملين بالحصول على فكرة حول الحملة وأهدافها. الخطوة التالية هي اختيار الهدف، وذلك من خلال خيارات القائمة المنسدلة. وتوضح الصورة التالية الخيارات المتاحة: نظرًا لتكامل وحدة أتمتة التسويق مع وحدة إدارة علاقات العملاء، فإن النظام الأساسي سيتعرف تلقائيًا على العملاء المحتملين ويرتبهم. وسترسل الحملة إلى العملاء المستهدفين بعد تهيئة خيار الأهداف. لاحظ وجود العديد من الخيارات ضمن قائمة تحديد الأهداف. يجب تحديد الأهداف المناسبة لحملتك، وبعد ذلك يمكنك إضافة عامل تصفية للعملاء المتوقعين من خلال النقر فوق خيار إضافة عامل التصفية من خيارات القائمة المنسدلة كما توضح الصورة التالية: بعد تحديد الفلتر اضغط على مفتاح "ADD NEW ACTIVITY" للمتابعة: ستظهر النافذة التالية التي تسمح لك بإضافة نشاط جديد وفقًا لاستراتيجيتك التسويقية وبناءً على البيانات التي جمعت من وحدة CRM حول العملاء المحتملين الجدد. أدخل اسم النشاط وحدد نوعه. هناك ثلاث أنواع من النشاطات تشمل البريد الإلكتروني وإجراء السيرفر والرسائل النصية القصيرة، حيث يتغير النموذج وفقًا لنوع النشاط الذي تختاره. فإذا اخترت البريد الإلكتروني، فسيظهر في الحقل التالي خيار لتحديد قالب البردي الإلكتروني، بينما إذا اخترت النوع رسائل SMS، فسيظهر في الحقل التالي خيار لاختيار قالب الرسائل النصية القصيرة "SMS Template" كما توضح الصورة التالية: إنشاء رسالة بريد إلكتروني باستخدام أودو بعد تحديد "البريد الإلكتروني" كنوع النشاط، سنبدأ بإعداد النشاط. انقر أولًا فوق خيار قالب "البريد"، بعدها انقر فوق خيار "إنشاء وتحرير" كما توضح الصورة التالية: تظهر في النافذة الجديدة مجموعة من القوالب الجاهزة التي يمكنك استخدامها للإنشاء وتصميم رسائل البريد الإلكتروني. حدد عنوان الرسالة ثم اختر أحد القوالب لتهيئته، وستظهر قسم جديد على الجانب الأيمن يحتوي خيارات لتعديل القالب كما توضح الصورة التالية: القسم مليء بخيارات التكوين المتقدمة لإنشاء قالب رسالة البريد الإلكتروني وتخصيصه، إذ يضم العديد من الكتل الجاهزة وهي إحدى الميزات التي يوفرها نظام أودو ويمكن استخدامها بسهولة من خلال خاصية السحب. تحتوي الكتل على وظائف وميزات متعددة تمكّنك من تكوين البريد بدءًا من إضافة الشعار وحتى المحتوى التسويقي وأزرار الوصول إلى شراء المنتجات. لإضافة أي كتلة إلى قالب الرسالة، اسحب الكتلة من "قسم الكتل" إلى القالب، ومن ثم ستحصل على ميزات تصميم متقدمة لتعديل الكتلة وإضافة النص أو تعديل الصور. يمكنك استخدام ميزة Style لتهيئة الكتلة المحددة، إذ تتوفر العديد من الخيارات والإعدادات ضمن هذه الميزة. يمكنك استخدام الخيارات في قسم Style لتخصيص الكتل كما تريد، مما سيساعدك على تصميم قالب البريد بما يتلاءم مع هوية علامتك التجارية، كما سيمكّنك من إضافة الوظائف التي تريدها. بعد الانتهاء من تصميم البريد، انتقل إلى علامة التبويب "خيارات" وستظهر النافذة التالية: من هنا يمكنك إرفاق الملفات التي تريد إرسالها مع رسالة البريد الإلكتروني، ويمكنك تحديد عنوان بريد الرد للمتابعين المستلمين أو البريد الإلكتروني المحدد. بالنسبة إلى خيار البريد الإلكتروني المحدد يجب إدخال عنوان بريد إلكتروني الذي تريد استخدامه لاستقبال الردود. عند الانتهاء انقر فوق زر "حفظ". كيفية إنشاء الحملات وإرسالها بعد الانتهاء من إعداد قالب رسالة البريد الإلكتروني، سنتابع عملية إعداد وتهيئة الحملة التسويقية. لاحظ أن قالب البريد الإلكتروني الذي أنشأناه سيكون متاحًا للإضافة في قسم قوالب البريد الإلكتروني. الخطوة التالية هي تحديد المفعل "Trigger"، حيث يسمح خيار المفعل بتعيين مشغل لحملة البريد الإلكتروني، ويمكنك تعيين الوقت الذي تريد تنشيط المفعل خلاله، إذ يوفر خيار المفعل عدة خيارات كما توضح الصورة التالية: بعد ذلك، يجب تحديد النطاق لتصفية العملاء بطريقة أكثر كفاءة، وهذا يتيح لك مراجعة عادات الشراء السابقة للعملاء أو طبيعة الاستهلاك، لإرسال رسائل البريد الإلكتروني للأشخاص المستهدفين فقط. عند الانتهاء من إعداد الحملة انقر فوق "زر حفظ". ميزات تطبيق أتمتة التسويق في نظام أودو يُعَدّ نظام أودو أحد أفضل حلول برامج إدارة الأعمال في السوق، ويتيح لك القدرة على التحكم الكامل بالأعمال. يقدم أودو وحدات مخصصة لتنفيذ العمليات التسويقية، وأهم هذه الوحدات هي وحدة أتمتة التسويق، إذ توفر جميع الوظائف والخيارات التي تحتاجها لتشغيل عمليات التسويق وإنشاء الحملات التسويقية وترويجها؛ أما أهم الميزات التي تقدمها وحدة أتمتة التسويق في نظام أودو فتتمثل في الأتي: وصف الحملة وإدارتها بطريقة فعالة باستخدام وحدة أتمتة التسويق في نظام أودو ستتمكن من إنشاء الحملة التسويقية وتشغيلها بفعالية. يمكنك تحديد عمليات التسويق التي تريد إضافتها إلى الحملة، كما يمكن أتمتة عمليات إرسال رسائل البريد الإلكتروني والرسائل القصيرة والدعوات، وتحديد العملاء المستهدفين بدقة. تسمح لك الوحدة أيضًا بتتبع الزائرين ومتابعة سلوك العملاء المحتملين. إمكانية تغيير الأداء بناءً على الجمهور المستهدف باستخدام وحدة أتمتة التسويق في نظام أودو، يمكن تحديد عمليات الترويج بناءً على الجمهور وطبيعة العملاء. ويمكن تحديد عمليات التسويق بناءً على منتجات وخدمات شركتك، كما يمكن تحديد قوالب البريد الإلكتروني وحفظها لإرسالها حسب المتطلبات. تحديد استراتيجيات التسويق المخصصة يمكنك تحديد استراتيجية التسويق وفقًا لمتطلبات التشغيل التجارية وأتمتة الحملات التسويقية وفقًا لها. توفر وحدة أتمتة التسويق في نظام أودو أدوات مخصصة لإدارة حملات تسويقية متعددة وإرسالها إلى العملاء المستهدفين. توفير الوقت تساعدك وحدة أتمتة التسويق على توفير وقت فريق التسويق، وذلك لأنها تمكّنه من إنشاء الحملات التسويقية وتعيين وقت لإرسالها وجدولتها. وتوفر هذه الوحدة ميزات عديدة تساعد على تنفيذ العمليات التسويقية بطريقة أسرع وأكثر تنظيمًا، ومنها إمكانية إنشاء حملات تسويقية متعددة وضمان التسليم السريع للرسائل القصيرة والبريد الإلكتروني. تحديد النماذج المستهدفة تمكّنك وحدة أتمتة التسويق من إرسال الرسائل الموجهة إلى العملاء المستهدفين من خلال توفير خيار لإدراج أنواع مختلفة من العملاء في قوائم بريدية مختلفة، وعندها سيتلقى كل عميل الرسالة الترويجية حول المنتجات التي يهتم بها، وهذا يساعد على تحسين العلاقة مع العملاء. خاتمة يُعَدّ تطبيق أتمتة التسويق مفيدًا لجميع أنواع المشاريع التجارية الصغيرة والكبيرة والمتوسطة، حيث يساعد في تخصيص تجربة التسويق وأتمتة عمليات إرسال الرسائل وإعداد الحملات التسويقية بدون بذل الكثير من الجهد. اقرأ أيضًا استخدام وحدة أودو للتسويق عبر البريد الإلكتروني جداول بيانات أودو Odoo وأهم ما يميزها كيفية إنشاء مسارات الفعاليات في نظام أودو
  8. وصلنا الآن إلى نهاية سلسلة مقالات NumPy، ونأمل أن تكون أدركت أهمية مكتبة NumPy وأنها مكتبة قوية ومتعددة الاستخدامات. وبنفس الوقت تذكر أن لغة بايثون هي لغة قوية جدًا، وقد تكون في بعض الحالات المحددة أقوى من NumPy. لنفكر على سبيل المثال، في تمرين مثير للاهتمام على النحو التالي: جُمعت إجابات مختلفة من المجتمع، وأسفرت الحلول المقترحة عن نتائج مفاجئة. لكن لنبدأ بكتابة التعليمات البرمجية بلغة بايثون لحل هذا التمرين: def solution_1(): # Brute force # 14641 (=11*11*11*11) iterations & tests Z = [] for i in range(11): for j in range(11): for k in range(11): for l in range(11): if i+j+k+l == 10: Z.append((i,j,k,l)) return Z هذا الحل هو الأبطأ لأنه يتطلب 4 حلقات، كما أنه يختبر جميع المجموعات المختلفة والبالغ عددها 11641 والمكونة من 4 أعداد صحيحة بين 0 و 10 للاحتفاظ فقط بالمجموعات التي يكون مجموعها مساوٍ إلى 10. يمكننا طبعًا التخلص من الحلقات باستخدام أداة itertools، لكن التعليمات تظل بطيئة: import itertools as it def solution_2(): # Itertools # 14641 (=11*11*11*11) iterations & tests return [(i,j,k,l) for i,j,k,l in it.product(range(11),repeat=4) if i+j+k+l == 10] كان أحد أفضل الحلول المقترحة يستفيد من إمكانية الحصول على حلقات مخبأة ذكية تتيح لنا بناء كل صف tuple مباشرةً، دون أي اختبار كما هو موضح أدناه: def solution_3(): return [(a, b, c, (10 - a - b - c)) for a in range(11) for b in range(11 - a) for c in range(11 - a - b)] يستخدم كاتب هذا التمرين أفضل حل بالاعتماد على NumPy استراتيجية مختلفة مع مجموعة مقيدة من الاختبارات: def solution_4(): X123 = np.indices((11,11,11)).reshape(3,11*11*11) X4 = 10 - X123.sum(axis=0) return np.vstack((X123, X4)).T[X4 > -1] إذا قيّمنا مدة تنفيذ هذه التوابع نحصل على: >>> timeit("solution_1()", globals()) 100 loops, best of 3: 1.9 msec per loop >>> timeit("solution_2()", globals()) 100 loops, best of 3: 1.67 msec per loop >>> timeit("solution_3()", globals()) 1000 loops, best of 3: 60.4 usec per loop >>> timeit("solution_4()", globals()) 1000 loops, best of 3: 54.4 usec per loop كما تلاحظ حل Numpy هو الأسرع ولكن الحل باستخدام بايثون قابل للمقارنة. سنحاول الآن إضافة تعديل صغير على حل بايثون: def solution_3_bis(): return ((a, b, c, (10 - a - b - c)) for a in range(11) for b in range(11 - a) for c in range(11 - a - b)) وسنحصل على النتيجة: >>> timeit("solution_3_bis()", globals()) 10000 loops, best of 3: 0.643 usec per loop اكتسبنا هنا عاملًا قدره 100 فقط عن طريق استبدال قوسين مربعين بأقواس عادية. كيف يعقل ذلك؟ يمكن العثور على التفسير من خلال النظر في نوع الكائن المُعاد: >>> print(type(solution_3())) <class 'list'> >>> print(type(solution_3_bis())) <class 'generator'> يعيد التابع ()solution_3_bis مولدًا generator يمكن استخدامه لإنشاء القائمة الكاملة أو للتكرار على جميع العناصر المختلفة. على أي حال، تأتي عملية التسريع الضخمة من عدم الاستقرار في القائمة الكاملة، وبالتالي من المهم أن نتساءل عما إذا كنت بحاجة إلى مثيل فعلي لنتيجتك أو إذا كان المولد البسيط ينفذ المهمة. مكتبة Numpy وأخواتها هناك العديد من حزم بايثون الأخرى إلى جانب Numpy، والتي تستحق النظر لأنها تتناول أصناف مشابهة ولكن مختلفة من المشكلات باستخدام التقنيات المختلفة (التجميع، الجهاز الافتراضي، وحدة معالجة الرسوميات GPU، الضغط، إلخ). قد تكون حزمة واحدة أفضل من الأخرى اعتمادًا على مشكلتك المحددة وأجهزتك الخاصة. دعونا نوضح استخدامهم من خلال مثال بسيط جدًا، إذ نريد حساب تعبير بناءً على متجهين عددين float: import numpy as np a = np.random.uniform(0, 1, 1000).astype(np.float32) b = np.random.uniform(0, 1, 1000).astype(np.float32) c = 2*a + 3*b حزمة NumExpr توفر حزمة numexpr إجراءات للتقييم السريع لتعبيرات المصفوفة من ناحية العناصر باستخدام جهاز افتراضي يعتمد على المتجهات vector-based، وهي مشابهة لحزمة SciPy، لكنها لا تتطلب خطوة ترجمة منفصلة لشيفرات C أو ++C. import numpy as np import numexpr as ne a = np.random.uniform(0, 1, 1000).astype(np.float32) b = np.random.uniform(0, 1, 1000).astype(np.float32) c = ne.evaluate("2*a + 3*b") مصرف Cython Cython هو مصرّف ثابت محسن لكل من لغة برمجة بايثون ولغة كايثون Cython الموسعة (استنادًا إلى Pyrex). يجعل مصرّف كايثون كتابة امتدادات C لبايثون سهلة مثل بايثون نفسها. import numpy as np def evaluate(np.ndarray a, np.ndarray b): cdef int i cdef np.ndarray c = np.zeros_like(a) for i in range(a.size): c[i] = 2*a[i] + 3*b[i] return c a = np.random.uniform(0, 1, 1000).astype(np.float32) b = np.random.uniform(0, 1, 1000).astype(np.float32) c = evaluate(a, b) مصرف Numba يمنحك مصرّف Numba القدرة على تسريع تطبيقاتك من خلال وظائف عالية الأداء مكتوبة مباشرةً بلغة بايثون. مع بعض التعليقات التوضيحية يمكن تجميع تعليمات بايثون array-oriented و math-heavy في الوقت المناسب لتعليمات الآلة الأصلية، على غرار C و ++C وفورتران Fortran، دون الحاجة إلى تبديل اللغات أو مترجم بايثون. from numba import jit import numpy as np @jit def evaluate(np.ndarray a, np.ndarray b): c = np.zeros_like(a) for i in range(a.size): c[i] = 2*a[i] + 3*b[i] return c a = np.random.uniform(0, 1, 1000).astype(np.float32) b = np.random.uniform(0, 1, 1000).astype(np.float32) c = evaluate(a, b) مكتبة Theano مكتبة Theano هي مكتبة بايثون تتيح لك تحديد التعبيرات الرياضية التي تتضمن مصفوفات متعددة الأبعاد وتحسينها وتقييمها بكفاءة. تتميز Theano بالتكامل الوثيق مع الاستخدام غير المستقر والشفاف لوحدة معالجة الرسوميات GPU ، والتمايز الرمزي symbolic differentiation الفعال، وتحسينات السرعة والثبات، وإنشاء شيفرة C الديناميكية، واختبار الوحدة الشامل والتحقق الذاتي. import numpy as np import theano.tensor as T x = T.fvector('x') y = T.fvector('y') z = 2*x + 3*y f = function([x, y], z) a = np.random.uniform(0, 1, 1000).astype(np.float32) b = np.random.uniform(0, 1, 1000).astype(np.float32) c = f(a, b) PyCUDA يتيح لك PyCUDA الوصول إلى واجهة برمجة تطبيقات الحساب المتوازي CUDA الخاصة بشركة Nvidia من بايثون. import numpy as np import pycuda.autoinit import pycuda.driver as drv from pycuda.compiler import SourceModule mod = SourceModule(""" __global__ void evaluate(float *c, float *a, float *b) { const int i = threadIdx.x; c[i] = 2*a[i] + 3*b[i]; } """) evaluate = mod.get_function("evaluate") a = np.random.uniform(0, 1, 1000).astype(np.float32) b = np.random.uniform(0, 1, 1000).astype(np.float32) c = np.zeros_like(a) evaluate(drv.Out(c), drv.In(a), drv.In(b), block=(400,1,1), grid=(1,1)) مكتبة PyOpenCL تتيح لك PyOpenCL الوصول إلى وحدات معالجة الرسومات وأجهزة الحوسبة المتوازية الأخرى من بايثون. import numpy as np import pyopencl as cl a = np.random.uniform(0, 1, 1000).astype(np.float32) b = np.random.uniform(0, 1, 1000).astype(np.float32) c = np.empty_like(a) ctx = cl.create_some_context() queue = cl.CommandQueue(ctx) mf = cl.mem_flags gpu_a = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=a) gpu_b = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=b) evaluate = cl.Program(ctx, """ __kernel void evaluate(__global const float *gpu_a; __global const float *gpu_b; __global float *gpu_c) { int gid = get_global_id(0); gpu_c[gid] = 2*gpu_a[gid] + 3*gpu_b[gid]; } """).build() gpu_c = cl.Buffer(ctx, mf.WRITE_ONLY, a.nbytes) evaluate.evaluate(queue, a.shape, None, gpu_a, gpu_b, gpu_c) cl.enqueue_copy(queue, c, gpu_c) Scipy وأخواتها إذا كان هناك عدة حزم إضافية لمكتبة Numpy، فهناك الملايين من الحزم الإضافية لـ scipy؛ إذ ربما يكون لكل مجال من مجالات العلوم مجموعته الخاصة، ومعظم الأمثلة التي كنا ندرسها حتى الآن كان من الممكن حلها في استدعائين أو ثلاثة استدعاءات باستخدام الحزمة ذات الصلة. لكن طبعًا لم يكن هذا هو الهدف. تعد برمجة الوظائف بنفسك عمومًا تمرينًا جيدًا إذا كان لديك بعض وقت الفراغ، وتتمثل أكبر صعوبة في هذه المرحلة في العثور على هذه الحزم ذات الصلة. فيما يلي قائمة قصيرة جدًا من الحزم التي جرى صيانتها واختبارها جيدًا والتي قد تبسط حياتك العلمية (اعتمادًا على مجالك). هناك طبعًا الكثير من الخيارات وذلك حسب احتياجاتك الخاصة، ومن المحتمل ألا تكون مضطرًا إلى برمجة كل شيء بنفسك. مكتبة scikit-learn scikit-learn هي مكتبة تعلم آلي مجانية للغة برمجة بايثون، وتتميز بخوارزميات تصنيف وانحدار وتجميع مختلفة بما في ذلك دعم خوارزمية أجهزة المتجهات vector machines، والغابات العشوائية random forests وتعزيز التدرج gradient boosting و k-means و DBSCAN، وهذه الحزمة مصممة للتفاعل مع مكتبات بايثون الرقمية والعلمية numpy و SciPy. مكتبة scikit-image scikit-image عبارة عن حزمة بايثون مخصصة لمعالجة الصور، واستخدام المصفوفات المتداخلة مثل كائنات صور. يصف هذا المقال كيفية استخدام scikit-image في مهام معالجة الصور المختلفة، ويركز على الارتباط بوحدات بايثون النمطية العلمية الأخرى مثل numpy و SciPy. مكتبة SymPy SymPy هي مكتبة بايثون للرياضيات الرمزية، وتهدف إلى أن تصبح كل ميزات النظام الحاسوبي جبرية -أو اختصارًا CAS- مع الحفاظ على الشيفرة بسيطة قدر الإمكان حتى تكون مفهومة وقابلةً للتوسّع بسهولة. كُتبت كامل مكتبة SymPy بلغة بايثون. حزمة Astropy مشروع Astropy هو جهد مجتمعي لتطوير حزمة أساسية واحدة لعلم الفلك astronomy في بايثون وتعزيز إمكانية التشغيل البيني بين حزم علم الفلك في بايثون. حزمة Cartopy Cartopy هي حزمة بايثون مصممة لتسهيل رسم الخرائط لتحليل البيانات والتصوير. تستفيد Cartopy من المكتبات القوية PROJ.4 والمكتوبة والمحددة الشكل ولها واجهة رسم بسيطة وبديهية لحزمة matplotlib لإنشاء خرائط جاهزة النشر. محاكي Brian Brian هو محاكي مجاني ومفتوح المصدر للشبكات العصبية، مكتوب بلغة البرمجة بايثون وهو متاح على جميع الأنظمة الأساسية تقريبًا. يساعد المحاكي في توفير وقت المعالجات إضافةً إلى توفير وقت الباحثين. صُمم محاكي Brian ليكون سهل التعلم والاستخدام ومرن جدًا وقابلًا للتوسيع بسهولة. مكتبة Glumpy Glumpy هي مكتبة تصور تفاعلي مبنية على OpenGL في بايثون، وهدفها هو تسهيل إنشاء تمثيلات مرئية سريعة وقابلة للتطوير وجميلة وتفاعلية وديناميكية. الخلاصة تُعد Numpy مكتبةً متعددة الاستخدامات، ولكن هذا لا يعني أنه ينبغي عليك استخدامها في كل الحالات. عرضنا في هذا الدليل بعض البدائل (بما في ذلك تعليمات بايثون العادية) وهي تستحق البحث والتعب، ولكن الاختيار عائدٌ لك، إذ عليك أن تفكر بالحل الأفضل بالنسبة لك من حيث وقت التطوير ووقت الحساب والجهد الذي ستحتاجه للتعديل. في حال قررت تصميم حلك الخاص فيجب عليك اختباره والمحافظة عليه، ولكن في المقابل ستكون حرًا في تصميمه بالطريقة التي تريدها. من ناحية أخرى: إذا قررت الاعتماد على حزمة طرف ثالث، فستوفر الكثير من وقت التطوير ولكن ستضطر إلى تكييف الحزمة مع احتياجاتك الخاصة. ترجمة -وبتصرّف- للفصل Beyond NumPy من كتاب From Python to Numpy لصاحبه Nicolas P. Rougier. اقرأ أيضًا المقال السابق: تخصيص أسلوب المتجهات Custom vectorization عبر استعمال مكتبة NumPy مفاهيم متقدمة حول مكتبة NumPy في بايثون أهم 8 مكتبات بلغة البايثون تستخدم في المشاريع الصغيرة
  9. تلعب الاستطلاعات دورًا كبيرًا في تحسين كفاءة إدارة الأعمال، وتعد الاستطلاعات بمثابة تقارير مباشرة من العملاء حول مدى جودة خدماتك وعملك. ومن خلال اتباع استراتيجيات ناجحة، يمكنك استغلال الاستبيانات للحصول على المزيد من المعلومات والبيانات لتطوير الشركة وتحسين الخدمات التي تركز على العملاء خصيصًا. في هذا المقال، سنلقي الضوء على كيفية إنشاء الاستطلاعات وإدارتها باستخدام وحدة الاستطلاعات في نظام أودو، وما أهمية استخدامها في شركتك. تنظر العديد من الشركات إلى إدارة الاستطلاعات على أنها أحد أصعب وظائف تشغيل أي عمل تجاري، لأنه من المهم الحصول على بيانات دقيقة لتتمكن الشركة من تحليلها والحصول على معلومات حقيقية. وتعد وحدة الاستطلاعات في نظام أودو أفضل حل لإدارة الاستطلاعات وجمع البيانات وتحليلها، وذلك بفضل الميزات والأدوات المتقدمة التي تتوفر في النظام. وحدة الاستطلاعات في نظام أودو عملية تكوين وحدة الاستطلاع ودمجها مع الوحدات النمطية هي عملية سهلة ومريحة. تعرض لوحة معلومات الاستطلاع جميع الاستطلاعات التي أجريتها. ويمكنك النقر على أي استطلاع لعرضه وإدارته، كما يمكنك استخدام هذه الوحدة لإدارة استطلاعات متعددة بطريقة سهلة، حيث يوفر لك أودو الأدوات التي تحتاجها لإنشاء الاستطلاعات وجمع البيانات وتحليلها وإنشاء تقارير مفصلة حولها. باستخدام زر "إنشاء"، يمكنك إنشاء استطلاع جديد، وستفتح صفحة جديدة لإضافة معلومات الاستطلاع كما توضح الصورة التالية: يجب إضافة عنوان الاستطلاع في البداية، وهذا يساعد على إدارة الاستطلاعات والتعرف عليها بسهولة.، بعدها يجب تحديد الشخص المسؤول عن الاستطلاع، وهنا يمكنك اختيار أي شخص من مؤسستك لإدارة الاستطلاعات. ضمن قسم الأسئلة، يجب إضافة أسئلة الاستطلاع. ولإضافة سؤال انقر فوق زر "إضافة سؤال"، وستفتح نافذة جديدة لكتابة السؤال كما توضح لقطة الشاشة التالية: يمكنك ملء السؤال في حقل السؤال واختيار نوع السؤال في الحقل التالي. يوجد العديد من أنواع الأسئلة التي يمكنك الاختيار من بينها، ويمثل كل نوع من أنواع الأسئلة موضوعات الأسئلة المختلفة للاستطلاعات. يمكنك المفاضلة بين الخيارات، وسينظم السؤال وفقًا لنوعك المفضل. ضمن قسم الوصف، يمكنك إضافة وصف للسؤال لإعطاء مزيد من المعلومات حوله. وبعد إضافة الوصف، انقر فوق علامة تبويب "خيارات" للحصول على المزيد من الخيارات المتقدمة كما توضح الصورة التالية: تشتمل الخيارات المتقدمة على إجابة إلزامية وعرض شرطي وعرض حقل التعليقات. يمكنك اختيار ما إذا كنت تريد تعيين السؤال على أنه إلزامي للإجابة أم لا، وذلك من خلال النقر فوق مربع الاختيار "إجابة إلزامية". وبعد تنشيط هذه الميزة، سيظهر سطر جديد لإضافة رسالة الخطأ التي ستظهر في كل مرة يتخطى فيها المستخدم الإجابة الإلزامية على السؤال. يسمح لك العرض الشرطي بإضافة سؤال جديد تلقائيًا ردًا على السؤال الرئيسي، ويشغّل هذا السؤال تلقائيًا عند الإجابة على السؤال الرئيسي. ولتنظيم الاستبيانات المباشرة، يتيح لك النظام تحديد حد زمني للأسئلة مما يساعدك على إجراء الاستطلاع بسرعة ودون إضاعة الوقت، حيث يمكنك تحديد المدة الزمنية التي تراها كافية. بعد الانتهاء من إضافة السؤال وإضافة كل التفاصيل المتعلقة به، انقر فوق زر "حفظ وإغلاق" للعودة إلى صفحة الاستطلاع، أو زر "حفظ وجديد" لفتح نافذ ةلإضافة سؤال جديد، أو زر "تجاهل"، بالتالي لن تُحفظ المعلومات التي أضفتها. بالعودة إلى نافذة إنشاء الاستطلاع، انقر على علامة التبويب "خيارات" للحصول على المزيد من الخيارات المتقدمة لتهيئة الاستطلاع، كما توضح لقطة الشاشة التالية: يمكنك تحديد كيفية ترتيب الأسئلة في الاستطلاع في قسم الصفحات، وهناك ثلاث خيارات أساسية: صفحة واحدة تحتوي جميع الأسئلة. صفحة واحدة لكل قسم صفحة واحدة لكل سؤال. يمكنك إدارة الاستطلاع ومن يمكنك الوصول إليه في قسم المرشحون "Participants". وافتراضيًا، يكون الخيار أي شخص لديه الرابط يمكنه فتح الاستطلاع، والخيار الآخر هو للأشخاص المدعوين فقط. في قسم "Time & Scoring" يمكنك تحديد مدة زمنية للاستطلاع، كما توضح الصورة التالية: عند تنشيط خيار الحد الزمني للاستطلاع سيغلق الاستطلاع تلقائيًا بعد انتهاء المدة المحددة. وفي قسم النقاط، هناك ثلاثة خيارات لتسجيل النقاط وهذه الخيارات هي: بدون نقاط عرض النقاط بدون الإجابات عند نهاية الاستطلاع عرض النقاط مع الإجابات عند نهاية الاستطلاع. كما يمكنك التحكم في جلسات الاستطلاع المباشرة من قسم "Live Session". ولتسهيل إدارة الاستطلاعاتK أضف رمز مخصص لكل جلسة. بعد الانتهاء من إعداد الاستطلاع وإضافة المعلومات الضرورية، انقر فوق زر "حفظ" لحفظ الاستطلاع، ويمكنك الوصول إليه من لوحة المعلومات الأساسية لوحدة الاستطلاعات. من المهم ملاحظة أن نظام أودو سيدير الاستطلاع بناءً على التكوينات. ونظرًا لأن العملية مؤتمتة للغاية وتتمحور حول البيانات، يمكنك الحصول على جميع البيانات الموجودة في الاستطلاع وتمثيلها بيانيًا أو بالطريقة التي تراها مناسبة. ما هي أهمية استخدام وحدة أودو للاستطلاعات؟ تُعَدّ الاستطلاعات مهمةً لجمع البيانات من مصادر مختلفة، فمن خلال الاستطلاعات، ستحصل على تعليقات وآراء العملاء والموظفين، مما يساعدك في اتخاذ القرارات الحاسمة. وتُعَدّ الاستطلاعات ضروريةً لتحسين الإنتاجية وزيادة المبيعات وخفض التكاليف وتطوير جودة الخدمات؛ أما في مجال التسويق، تساعدك الاستطلاعات على معرفة ما يريده المستهلكون بالضبط من خلال مجموعة من الأسئلة المنظمة. تُعد الاستطلاعات الطريقة الأكثر موثوقيةً للحصول على تعليقات صادقة من العملاء، وتساعدك على اكتشاف المكان الذي تستثمر فيه وقتك لتحقيق نتائج أفضل. لقد ساعدت وحدة اودو للاستطلاعات على جعل العملية أسهل، حيث ترشدك بطريقة فعالة لجمع معلومات حول رضا المستخدم وتوقعاته وانطباعه عن منتجاتك وخدماتك لتتمكن من تغيير استراتيجياتك التسويقية وفقًا لها. وفيما يلي أهم الميزات التي توفرها وحدة أودو للاستطلاعات: تساعدك على إنشاء استطلاع بسهولة باستخدام وحدة الاستطلاعات في نظام أودو، يمكنك إنشاء الاستطلاع وفقًا لمتطلباتك عن طريق طرح الأسئلة الصحيحة لجمع المعلومات من عملائك حول منتجاتك أو خدماتك. تُعَدّ هذه الوحدة مفيدةً لجمع التعليقات وتحليل آراء العملاء لمعرفة مدى رضاهم عن خدماتك وما هي العوامل التي تؤثر على ذلك، وتتميز وحدة الاستطلاعات بإمكانية حفظ البيانات وإدارتها وتحليلها. إضفاء الطابع الشخصي تسمح لك وحدة الاستطلاع بتخصيص كل سؤال للحصول على إجابات دقيقة من العملاء. وتمكّنك من إضافة وصف وشرح تفصيلي لأهمية الاستطلاع والغاية منه. من السهل تخصيص الاستبيان حسب حاجتك عن طريق اختيار تنسيق مناسب للسؤال. وتُعَدّ الطريقة التي تطرح فيها السؤال مهمة جدًا في الاستطلاع، ولذلك توفر وحدة الاستطلاعات في نظام أودو إمكانية تنسيق السؤال بالطريقة التي تراها مناسبة، كما توفر العديد من أنواع الأسئلة، بما في ذلك اختيار من متعدد، أو مربع نص متعدد الأسطر، أو مربع نص بسطر واحد، أو قيمة عددية، أو تاريخ، أو مصفوفة). وتوفر وحدة الاستطلاعات أيضًا خيارات متقدمة، حيث يمكن للمستخدم وضع بعض القواعد الإلزامية لكل سؤال. ومن خلال تمكين حقل إظهار التعليق، يمكنك جمع التعليقات من العملاء بسهولة، ويمكن أيضًا وضع حد زمني لكل استطلاع تنشئه. وتساعد ميزة إضافة الصور إلى الاستطلاع على جعله أكثر جاذبية. اختبار الاستطلاع قبل استخدام الاستطلاع لجمع البيانات، من المهم اختباره لتجنب الأخطاء المحتملة. يساعدك الاختبار على تحديد الأسئلة والأخطاء المربكة في الاستطلاع، والتي قد تنتج عنها أجوبة متحيزة وغير مفيدة؛ كما سيضمن دقة الاستطلاع من خلال اختبار صحة التعليمات الواردة. وبعد الانتهاء من إعداد الاستطلاع، يمكنك الضغط على زر "اختبار" لإجراء اختبار على الاستطلاع. تبادل الاستطلاعات بمجرد الانتهاء من اختبار الاستطلاع، هناك خيارات متعددة لمشاركة الاستطلاع، حيث يمكنك بسهولة إنشاء رابط ونشره على موقعك الإلكتروني. يحصل المستجيبون على تجربة أفضل من خلال إجراء الاستطلاع على موقع الويب بدلًا من فتح نوافذ متعددة. وسيساعدك تضمين الاستطلاعات على موقعك الإلكتروني على معرفة المزيد عن زوار موقعك وحفظ عنوان البريد الإلكتروني لاستخدامه لاحقًا. ومن خلال هذه الوحدة، يمكنك إرسال دعوات بالبريد الإلكتروني إلى الجمهور المستهدف باستخدام رابط الاستطلاع. تحليل البيانات تجمع وحدة الاستطلاع الردود تلقائيًا وتزامنها مع قاعدة البيانات، وتوفر خيارات متقدمة لتحليل الاستطلاع، مما يساعدك على معرفة الصورة العامة من الردود الفردية. يمكنك رؤية ردود الجمهور في قائمة الإجابات بناءً على معايير محددة يمكنك تصفية الردود، وعرضها على شكل مخططات أو أشرطة أو رسوم بيانية. تحسين الاستراتيجيات بعد تحليل البيانات التي جمعت في وحدة الاستطلاعات في نظام أودو، يمكن بسهولة دراسة الردود وتغيير السياسات الجارية لتحسين استراتيجيات العمل. ويمكنك مشاركة هذه البيانات مع أدوات أودو الأخرى وتحسين اتخاذ القرارات. تجدر الإشارة هنا إلى أن الاستطلاعات تساعد على تحسين عملية جمع الأفكار من الموظفين والمستهلكين والأسواق. خاتمة تسمح وحدة الاستطلاعات في نظام أودو للمستخدمين بتخصيص الاستطلاعات لمعرفة ما يفكر فيه المستهلكون، وجمع آرائهم حول المنتجات والخدمات التي تقدمها الشركة، كما تساعد في معرفة التحديثات التي يجب أن تتخذها الشركة لتطوير استراتيجياتها الحالية، ولذلك تُعَدّ هذه الوحدة ضرورة تنظيم وإدارة العمل في الشركات. اقرأ أيضًا تطبيقات أودو وأهم استخداماتها وحدة التعديلات في نظام أودو وميزاتها أهمية استخدام نظام أودو في الشركات الصغيرة وحدة المبيعات في نظام أودو Odoo وكيفية استخدامها الدليل الكامل لاستطلاعات تويتر
  10. تتمثل إحدى نقاط قوة مكتبة NumPy في إمكانية استخدامها لبناء كائنات جديدة أو لتصنيف كائن ndarray إلى صنف فرعي. هذه العملية السابقة مملة بعض الشيء ولكنها تستحق الجهد لأنها تسمح لك بتحسين كائن ndarray ليناسب مشكلتك. سندرس في هذا المقال حالتين من العالم الحقيقي (قائمة مقيدة بنوع typed list ومصفوفة مراعية للذاكرة memory-aware array) اللتان تُستخدمان على نطاق واسع في مشروع glumpy، بينما تُعد الحالة الثانية -وهي مصفوفة مضاعفة الدقة double precision array- شائعة في الدراسة الأكاديمية. القائمة المقيدة بنوع Typed list تسمى أيضًا المصفوفة غير المنتظمة، وهي قائمة بالعناصر التي تحتوي جميعها على نفس نوع البيانات (بمعنى NumPy). وتوفر كلًا من القائمة وواجهة برمجة تطبيقات ndarray. ولكن نظرًا لأن واجهات برمجة التطبيقات APIs المخصصة قد لا تكون متوافقة في بعض الحالات، علينا تحديد الخيارات. على سبيل المثال فيما يتعلق بالعامل "+" سنختار استخدام NumPy API، إذ تُضاف القيمة إلى كل عنصر على حدة بدلًا من توسيع القائمة عن طريق إلحاق عنصر جديد بها. >>> l = TypedList([[1,2], [3]]) >>> print(l) [1, 2], [3] >>> print(l+1) [2, 3], [4] نريد أن نوفر للكائن الجديد إمكانية إدراج العناصر وإنشائها وإزالتها بسلاسة من قائمة API، وهذا ما سنوضحه في الفقرات التالية. الإنشاء Creation نظرًا لأن الكائن ديناميكي بحكم التعريف، فمن المهم تقديم تابع إنشاء للأغراض العامة general-purpose قوي بما يكفي لتجنب الاضطرار إلى معالجات لاحقة، إذ تكلف معالجات مثل الإدراج، أو الحذف كثيرًا من العمليات ونحن نسعى إلى تجنبها. إليك اقتراح لإنشاء كائن TypedList: def __init__(self, data=None, sizes=None, dtype=float) """ Parameters ---------- data : array_like An array, any object exposing the array interface, an object whose __array__ method returns an array, or any (nested) sequence. sizes: int or 1-D array If `itemsize is an integer, N, the array will be divided into elements of size N. If such partition is not possible, an error is raised. If `itemsize` is 1-D array, the array will be divided into elements whose successive sizes will be picked from itemsize. If the sum of itemsize values is different from array size, an error is raised. dtype: np.dtype Any object that can be interpreted as a NumPy data type. """ تسمح واجهة برمجة التطبيقات API هذه بإنشاء قائمة فارغة أو إنشاء قائمة من بعض البيانات الخارجية. لاحظ أنه في الحالة الأخيرة نحتاج إلى تحديد كيفية تقسيم البيانات إلى عدة عناصر أو تقسيمها إلى عناصر بحجم 1، ويمكن أن يكون قسمًا عاديًا (أي أن كل عنصر بطول بيانات 2)، أو قسمًا مخصصًا (أي يجب تقسيم البيانات إلى عناصر بحجم 1 و2 و3 و4 عنصر). >>> L = TypedList([[0], [1,2], [3,4,5], [6,7,8,9]]) >>> print(L) [ [0] [1 2] [3 4 5] [6 7 8] ] >>> L = TypedList(np.arange(10), [1,2,3,4]) [ [0] [1 2] [3 4 5] [6 7 8] ] في هذه المرحلة السؤال هو ما إذا كان يجب إنشاء صنف فرعي مشتق من الصنف ndarray، أو استخدام مصفوفة ndarray داخلية لتخزين بياناتنا. في هذه الحالة، ليس من المنطقي استخدام صنف فرعي ndarray لأننا لا نريد تقديم واجهة ndarray. بدلًا من ذلك، سنستخدم مصفوفة ndarray لتخزين بيانات القائمة وسيوفر لنا اختيار هذا التصميم مزيدًا من المرونة. سنستخدم لتخزين حد limit لكل عنصر مصفوفة عناصر items، ستهتم بتخزين الموضع (البداية والنهاية) لكل عنصر. توجد حالتان منفصلتان لإنشاء قائمة، هما: لم تُقدم أية بيانات، أو قُدمت بعض البيانات. الحالة الأولى سهلة وتتطلب فقط إنشاء مصفوفتي data_ و items_. لاحظ أن حجم المصفوفتين غير فارغ لأن تغيير حجم المصفوفة سيكون مكلفًا جدًا في كل مرة ندخل عنصر جديد فيها. لذلك من الأفضل حجز بعض المساحة. الحالة الأولى: لم تُقدّم أية بيانات، فقط dtype. self._data = np.zeros(512, dtype=dtype) self._items = np.zeros((64,2), dtype=int) self._size = 0 self._count = 0 الحالة الثانية: قُدمت بعض البيانات بالإضافة إلى قائمة بأحجام العناصر. self._data = np.array(data, copy=False) self._size = data.size self._count = len(sizes) indices = sizes.cumsum() self._items = np.zeros((len(sizes),2),int) self._items[1:,0] += indices[:-1] self._items[0:,1] += indices الوصول Access بمجرد الانتهاء من عملية الإنشاء، لا بد من إجراء قليل من الحسابات في كل التوابع وتغيير مفتاح key مختلف عند الحصول على عنصر أو إدراجه أو ضبطه. إليك تعليمات تابع __getitem__، وهو تابع سهل ولكن هناك خطوة سلبية محتملة فيه: def __getitem__(self, key): if type(key) is int: if key < 0: key += len(self) if key < 0 or key >= len(self): raise IndexError("Tuple index out of range") dstart = self._items[key][0] dstop = self._items[key][1] return self._data[dstart:dstop] elif type(key) is slice: istart, istop, step = key.indices(len(self)) if istart > istop: istart,istop = istop,istart dstart = self._items[istart][0] if istart == istop: dstop = dstart else: dstop = self._items[istop-1][1] return self._data[dstart:dstop] elif isinstance(key,str): return self._data[key][:self._size] elif key is Ellipsis: return self.data else: raise TypeError("List indices must be integers") تمرين يُعد تعديل القائمة أكثر تعقيدًا، لأنه يتطلب إدارة الذاكرة بطريقة صحيحة، وبما أن ذلك لا يمثل صعوبة حقيقة، فقد تركنا هذا تمرينًا لك. في حال احتجت إلى مساعدة، يمكنك إلقاء نظرة على التعليمات البرمجية أدناه. كن حذرًا مع الخطوات السلبية ونطاق المفتاح وتوسع المصفوفة. عندما تحتاج المصفوفة الأساسية إلى التوسيع، فمن الأفضل توسيعها أكثر من اللازم لتجنب الحاجة إلى التوسع المستقبلي. ضبط عنصر Setitem يمكننا ضبط عنصر كما يلي: L = TypedList([[0,0], [1,1], [0,0]]) L[1] = 1,1,1 حذف عنصر Delitem يجري حذف عنصر على النحو التالي: L = TypedList([[0,0], [1,1], [0,0]]) del L[1] إدراج عنصر insert يمكننا إضافة عنصر كما يلي: L = TypedList([[0,0], [1,1], [0,0]]) L.insert(1, [3,3]) مصفوفة مراعية للذاكرة Memory aware array مكتبة Glumpy Glumpy هي مكتبة تمثيل مرئي تفاعلي مبنية على OpenGL في بايثون هدفها تسهيل إنشاء عروض مرئية سريعة وقابلة للتطوير وجميلة وتفاعلية وديناميكية. يوضح الشكل التالي محاكاة مجرة حلزونية باستخدام نظرية موجة الكثافة density wave theory: محاكاة مجرة حلزونية باستخدام نظرية موجة الكثافة. عرض لنمر باستخدام التجميعات واستدعائين GL. تعتمد Glumpy على تكامل محكم وسلس مع المصفوفات المعقدة، وهذا يعني أنه يمكنك معالجة بيانات وحدة معالجة الرسومات GPU كما تفعل مع مصفوفات numpy العادية، وستتولى مكتبة Glumpy بقية المهام، وأسرع طريقة لفهم ذلك هي بالمثال التالي: from glumpy import gloo dtype = [("position", np.float32, 2), # x,y ("color", np.float32, 3)] # r,g,b V = np.zeros((3,3),dtype).view(gloo.VertexBuffer) V["position"][0,0] = 0.0, 0.0 V["position"][1,1] = 0.0, 0.0 V هو VertexBuffer وهو يمثّل GPUData ومصفوفة numpy. عندما يُعدل V، تعتني Glumpy بحساب أصغر كتلة متجاورة من ذاكرة dirty حتى تحميلها على ذاكرة GPU. عندما يُستخدم هذا المخزن المؤقت على وحدة معالجة الرسومات GPU، تتولى Glumpy تحميل منطقة dirty في اللحظات الأخيرة، وهذا يعني أنه في حال عدم استخدامك V فلن يُحمّل أي شيء على وحدة معالجة الرسومات. في الحالة المذكورة أعلاه، تتكون آخر منطقة ذاكرة dirty محسوبة من 88 بايت بدءًا من الإزاحة 0 كما هو موضح أدناه: وبالتالي سينتهي الأمر بتحميل Glumpy 88 بايت بينما عُدّل 16 بايت فقط فعليًا. قد تتساءل عما إذا كان هذا هو الأمثل. في الواقع يكون الأمر كذلك في معظم الأوقات، لأن تحميل بعض البيانات إلى مخزن مؤقت يتطلب الكثير من العمليات على جانب GL ولكل استدعاء تكلفة ثابتة. صنف فرعي من Array كما هو موضح في توثيق Subclassing ndarray، فإن التصنيف الفرعي ndarray معقد بسبب حقيقة أن الحالات الجديدة لأصناف ndarray يمكن أن تظهر بثلاث طرق مختلفة: استدعاء صريح للباني. تحويل العرض view casting. قالب جديد. ومع ذلك فإن حالتنا أبسط لأننا مهتمون فقط بتحويل العرض، لذلك نحتاج فقط إلى تعريف التابع __new__ الذي سيُستدعى عند إنشاء كل نسخة. لذلك ستجهز صنف GPUData بخاصيتين: النطاقات extents: يمثل هذا النطاق الكامل للعرض نسبيًا بالنسبة للمصفوفة الأساسية، ويُخزّن مثل إزاحة بايت وحجم بايت. البيانات المنتظرة pending_data: يمثل هذا تجاور لمنطقة dirty ويُخزّن مثل (إزاحة البايت، حجم البايت) نسبيًا بالنسبة إلى خاصية extents. class GPUData(np.ndarray): def __new__(cls, *args, **kwargs): return np.ndarray.__new__(cls, *args, **kwargs) def __init__(self, *args, **kwargs): pass def __array_finalize__(self, obj): if not isinstance(obj, GPUData): self._extents = 0, self.size*self.itemsize self.__class__.__init__(self) self._pending_data = self._extents else: self._extents = obj._extents نطاقات الحوسبة نحتاج في كل مرة يُطلب فيها عرض جزئي للمصفوفة إلى حساب نطاقات هذا العرض الجزئي حتى نتمكن من الوصول إلى المصفوفة الأساسية. def __getitem__(self, key): Z = np.ndarray.__getitem__(self, key) if not hasattr(Z,'shape') or Z.shape == (): return Z Z._extents = self._compute_extents(Z) return Z def _compute_extents(self, Z): if self.base is not None: base = self.base.__array_interface__['data'][0] view = Z.__array_interface__['data'][0] offset = view - base shape = np.array(Z.shape) - 1 strides = np.array(Z.strides) size = (shape*strides).sum() + Z.itemsize return offset, offset+size else: return 0, self.size*self.itemsize تعقب البيانات المنتظرة pending data باستمرار تتمثل إحدى الصعوبات الإضافية في أننا لا نريد أن تتعقب جميع طرق العرض منطقة dirty المُستخدمة ولكن نريد تعقب فقط المصفوفة الأساسية. هذا هو سبب عدم إنشاء نسخة منself._pending_data في الحالة الثانية من تابع __array_finalize__. سنتعامل مع هذا عندما نحتاج إلى تحديث بعض البيانات أثناء استدعاء __setitem__ على سبيل المثال: def __setitem__(self, key, value): Z = np.ndarray.__getitem__(self, key) if Z.shape == (): key = np.mod(np.array(key)+self.shape, self.shape) offset = self._extents[0]+(key * self.strides).sum() size = Z.itemsize self._add_pending_data(offset, offset+size) key = tuple(key) else: Z._extents = self._compute_extents(Z) self._add_pending_data(Z._extents[0], Z._extents[1]) np.ndarray.__setitem__(self, key, value) def _add_pending_data(self, start, stop): base = self.base if isinstance(base, GPUData): base._add_pending_data(start, stop) else: if self._pending_data is None: self._pending_data = start, stop else: start = min(self._pending_data[0], start) stop = max(self._pending_data[1], stop) self._pending_data = start, stop الخلاصة كما هو موضح على موقع ويب NumPy، فإن مكتبة NumPy هي الحزمة الأساسية للحوسبة العلمية باستخدام بايثون، ولكن وكما هو موضح في هذا المقال يتجاوز استخدام نقاط قوة NumPy مجرد حاوية متعددة الأبعاد multi-dimensional container للبيانات العامة. يمكن استخدام ndarray مثل خاصية خاصة في حالة واحدة (أسلوب TypedList)، أو تصنيفًا فرعيًا مباشرًا لصنف ndarray (أسلوب GPUData) لتتبع الذاكرة في حالات أخرى، وقد وضحنا كيف يمكن أن تتوسع قدرات NumPy لتناسب احتياجات محددة للغاية. ترجمة -وبتصرّف- للفصل Custom vectorization من كتاب From Python to Numpy لصاحبه Nicolas P. Rougier. اقرأ أيضًا المقال السابق: الاعتماد على المتجهات في حل المشاكل باستعمال مكتبة NumPy في بايثون استخدام المتجهات vectorization في لغة بايثون مع مكتبة NumPy أهم 8 مكتبات بلغة البايثون تستخدم في المشاريع الصغيرة
  11. يعد الاعتماد على المتجهات في المشاكل أصعب بكثير من متجهات الشيفرات لأنه يعني أنه يتعين عليك إعادة التفكير في مشكلتك من أجل جعلها معتمدة على المتجهات vectorizable، وهذا يعني غالبًا أن عليك استخدام خوارزمية مختلفة لحل مشكلتك، أو حتى الأسوأ من ذلك، فقد تحتاج إلى ابتكار خوارزمية جديدة. وبالتالي تكمن الصعوبة في التفكير خارج الصندوق. لتوضيح ذلك دعنا نفكر في مشكلة بسيطة، ولنفرض لدينا متجهين X و Y، ونريد حساب مجموع [X * Y [j لجميع أزواج المؤشرات i و j. أحد الحلول البسيطة والواضحة هو كتابة: def compute_python(X, Y): result = 0 for i in range(len(X)): for j in range(len(Y)): result += X[i] * Y[j] return result ولكن تتضمن الشيفرات السابقة حلقتين وبالتالي فإن التنفيذ سيكون بطيئًا: >>> X = np.arange(1000) >>> timeit("compute_python(X,X)") 1 loops, best of 3: 0.274481 sec per loop كيف يمكن جعل المشكلة معتمدة على المتجهات إذًا؟ إذا كنت تتذكر مقرر الجبر الخطي، فربما تكون قد حددت التعبير [X * Y [j ليكون مشابهًا جدًا لتعبير المصفوفة، لذلك ربما يمكننا الاستفادة من سرعة NumPy. أحد الحلول الخاطئة هو بكتابة: def compute_numpy_wrong(X, Y): return (X*Y).sum() هذا الحل خاطئ لأن التعبير X * Y يحسب في الواقع متجهًا جديدًا Z وفقًا لما يلي: [Z = X * Y [i، وليس هذا ما نريده، لذلك سنجرب استغلال ميزة البث broadcasting لمكتبة NumPy وإعادة تشكيل المتجهين أولًا ثم ضربهما: def compute_numpy(X, Y): Z = X.reshape(len(X),1) * Y.reshape(1,len(Y)) return Z.sum() أصبح لدينا [Z[i,j] == X[i,0]*Y[0,j، وإذا حسبنا مجموع كل عناصر Z، سنحصل على النتيجة المتوقعة. سنتأكد الآن من مقدار التحسن في السرعة الذي اكتسبناه في هذه الطريقة: >>> X = np.arange(1000) >>> timeit("compute_numpy(X,X)") 10 loops, best of 3: 0.00157926 sec per loop هذا أفضل، فقد حصلنا على عامل سرعة أكبر بحوالي 150 مرة، ولكن لا يزال بإمكاننا تحسين هذا العامل. بالعودة إلى الطريقة الأولى، يمكنك أن تلاحظ أن الحلقة الداخلية تستخدم [X [i الذي لا يعتمد على المؤشر j، مما يعني أنه يمكن إزالته من الحلقة الداخلية. يمكن إعادة كتابة الشيفرة على النحو التالي: def compute_numpy_better_1(X, Y): result = 0 for i in range(len(X)): Ysum = 0 for j in range(len(Y)): Ysum += Y[j] result += X[i]*Ysum return result ونظرًا لأن الحلقة الداخلية لا تعتمد على المؤشر i، فيمكننا أن نحسبها مرةً واحدةً فقط: def compute_numpy_better_2(X, Y): result = 0 Ysum = 0 for j in range(len(Y)): Ysum += Y[j] for i in range(len(X)): result += X[i]*Ysum return result خفضنا التعقيد بفضل إزالة الحلقة الداخلية من "(O(n2" إلى "(O(n". وبنفس الطريقة يمكننا كتابة: def compute_numpy_better_3(x, y): Ysum = 0 for j in range(len(Y)): Ysum += Y[j] Xsum = 0 for i in range(len(X)): Xsum += X[i] return Xsum*Ysum أخيرًا، بعد أن أدركنا أننا نحتاج فقط إلى حاصل ضرب المجموع لكلٍ من X و Y على التوالي، يمكننا الاستفادة من دالة np.sum وكتابة: def compute_numpy_better(x, y): return np.sum(y) * np.sum(x) وبالتالي حصلنا على شيفرات برمجية أقصر وأرتب وأسرع: >>> X = np.arange(1000) >>> timeit("compute_numpy_better(X,X)") 1000 loops, best of 3: 3.97208e-06 sec per loop بهذه الطريقة نكون قد أعدنا صياغة المشكلة، مستغلين حقيقة أن: "‎∑ij XiYj = ∑iXi∑jYj". وتعلمنا الآن أن هناك نوعين من التحويل المعتمد على المتجهات، وهما: متجهات الشيفرات ومتجهات المشكلة. يُعد النوع الثاني من المتجهات هو الأصعب والأكثر أهمية لأنك من خلاله يمكنك توقع مكاسب هائلة في تحسين السرعة. اكتسبنا في هذا المثال البسيط عامل سرعة أكبر بمقدار 150 مرة عند استخدام متجهات الشيفرة، واكتسبنا عامل قدره 70000 باستخدام متجهات المشكلة، أي من خلال كتابة مشكلتنا بطريقة مختلفة فقط. إذا أعدنا كتابة الحل الأخير بطريقة بايثون فإن التحسين سيكون جيدًا ولكن ليس مثل استخدام numpy: def compute_python_better(x, y): return sum(x)*sum(y) هذا الإصدار الجديد من بايثون أسرع بكثير من إصدار بايثون السابق، لكنه لا يزال أبطأ 50 مرةً من الإصدار numpy: >>> X = np.arange(1000) >>> timeit("compute_python_better(X,X)") 1000 loops, best of 3: 0.000155677 sec per loop إيجاد المسار يتعلق اكتشاف المسار بإيجاد أقصر مسار في الرسم البياني. يمكن تقسيم هذا إلى مشكلتين مختلفتين: العثور على مسار بين كل عقدتين في الرسم البياني والعثور على أقصر مسار، وسنوضح ذلك من خلال اكتشاف المسار في متاهة، لذلك ستكون المهمة الأولى هي بناء المتاهة. متاهة سياج أخضر تحيط بمنزل Longleat الفخم في إنجلترا. صورة Prince Rurik، 2005. بناء متاهة توجد عدة خوارزميات لإنشاء متاهة، لكننا سنستخدم هنا خوارزمية معينة تعمل عن طريق إنشاء "n" (الكثافة) جزيرة بطول "p" (التعقيد). تنشأ الجزيرة من خلال اختيار نقطة بداية عشوائية بإحداثيات فردية، ثم نختار اتجاهًا عشوائيًا. إذا كانت الخلية التي تملك خطوتين في اتجاه معين حرة سيُضاف جدار في أول وثاني خطوة في هذا الاتجاه، وتُكرر العملية n خطوة لهذه الجزيرة، وبالتالي ننشيء p جزيرة. يكون كل من n و p أعداد عشرية float لتتكيف مع حجم المتاهة. تكون الجزر صغيرة جدًا مع هذا التعقيد المنخفض ويكون حل المتاهة سهلًا، وتحتوي المتاهة على مزيدٍ من "الغرف الفارغة الكبيرة" مع الكثافة المنخفضة. def build_maze(shape=(65, 65), complexity=0.75, density=0.50): # Only odd shapes shape = ((shape[0]//2)*2+1, (shape[1]//2)*2+1) # ضبط التعقيد والكثافة نسبةً إلى حجم المتاهة n_complexity = int(complexity*(shape[0]+shape[1])) n_density = int(density*(shape[0]*shape[1])) # بناء المتاهة الفعلية Z = np.zeros(shape, dtype=bool) # ملء الحدود Z[0, :] = Z[-1, :] = Z[:, 0] = Z[:, -1] = 1 # تبدأ الجزر بنقطة مع انحياز من طرف الحدود P = np.random.normal(0, 0.5, (n_density, 2)) P = 0.5 - np.maximum(-0.5, np.minimum(P, +0.5)) P = (P*[shape[1], shape[0]]).astype(int) P = 2*(P//2) # إنشاء الجزر for i in range(n_density): # Test for early stop: if all starting point are busy, this means we # won't be able to connect any island, so we stop. T = Z[2:-2:2, 2:-2:2] if T.sum() == T.size: break x, y = P[i] Z[y, x] = 1 for j in range(n_complexity): neighbours = [] if x > 1: neighbours.append([(y, x-1), (y, x-2)]) if x < shape[1]-2: neighbours.append([(y, x+1), (y, x+2)]) if y > 1: neighbours.append([(y-1, x), (y-2, x)]) if y < shape[0]-2: neighbours.append([(y+1, x), (y+2, x)]) if len(neighbours): choice = np.random.randint(len(neighbours)) next_1, next_2 = neighbours[choice] if Z[next_2] == 0: Z[next_1] = 1 Z[next_2] = 1 y, x = next_2 else: break return Z هنا رسم متحرك يوضح عملية التوليد. بناء متاهة متدرجة مع التحكم في التعقيد والكثافة. خوارزمية الاتساع أولا Breadth-first تعالج خوارزمية البحث ذات الاتساع أولًا Breadth-first (وكذلك خوارزمية العمق أولًا depth-first) مشكلة إيجاد مسار بين عقدتين من خلال فحص جميع الاحتمالات بدءًا من عقدة الجذر والتوقف بمجرد العثور على حل (الوصول إلى العقدة الوجهة). تعمل هذه الخوارزمية في الوقت الخطي بالتعقيد (|O(|V| + |E، إذ يمثل V عدد الرؤوس vertices و E هو عدد الحواف. كتابة مثل هذه الخوارزمية ليس صعبًا بشرط أن يكون لديك بنية البيانات الصحيحة. في حالتنا فإن تمثيل المتاهة على شكل مصفوفة ليس هو الحل الأنسب، ونحتاج إلى تحويله إلى رسم بياني حقيقي وفق اقتراح فالنتين بريوخانوف Valentin Bryukhanov. def build_graph(maze): height, width = maze.shape graph = {(i, j): [] for j in range(width) for i in range(height) if not maze[i][j]} for row, col in graph.keys(): if row < height - 1 and not maze[row + 1][col]: graph[(row, col)].append(("S", (row + 1, col))) graph[(row + 1, col)].append(("N", (row, col))) if col < width - 1 and not maze[row][col + 1]: graph[(row, col)].append(("E", (row, col + 1))) graph[(row, col + 1)].append(("W", (row, col))) return graph ملاحظة: إذا استخدمنا خوارزمية العمق أولاً فلا يوجد ضمان للعثور على أقصر مسار، ويمكننا فقط للعثور على مسار إذا كان موجودًا. بعد الانتهاء من ذلك، تكون كتابة خوارزمية الاتساع أولًا أمرًا سهلًا. نبدأ من عقدة البداية ونزور العقد في العمق الحالي ونكرر العملية حتى الوصول إلى العقدة النهائية إن أمكن. والسؤال هنا: هل نحصل بهذه الطريقة على أقصر طريق لاستكشاف الرسم البياني؟ في هذه الحالة المحددة "نعم"، لأننا لا نملك رسمًا بيانيًا مرجحًا للحافة، أي أن جميع الحواف لها نفس الوزن (أو التكلفة). def breadth_first(maze, start, goal): queue = deque([([start], start)]) visited = set() graph = build_graph(maze) while queue: path, current = queue.popleft() if current == goal: return np.array(path) if current in visited: continue visited.add(current) for direction, neighbour in graph[current]: p = list(path) p.append(neighbour) queue.append((p, neighbour)) return None طريقة بيلمان فورد Bellman-Ford خوارزمية بيلمان فورد Bellman-Ford قادرة على إيجاد المسار الأمثل في الرسم البياني باستخدام عملية الانتشار، إذ تعثر على المسار الأفضل عن طريق تصاعد التدرج الناتج. تعمل هذه الخوارزمية في الوقت التربيعي (|O(|V||E، إذ يمثّل V عدد الرؤوس و E عدد الحواف. في حالتنا البسيطة لن نواجه الكثير من المشاكل. الخوارزمية موضحة أدناه في الشكل (القراءة من اليسار إلى اليمين ومن أعلى إلى أسفل). بعد فهم الخوارزمية يمكننا صعود التدرج اللوني من عقدة البداية، ويمكنك التحقق من الشكل الذي يؤدي إلى أقصر طريق. قيم خوارزمية التكرار في متاهة بسيطة. بمجرد الوصول إلى المدخل، يكون من السهل العثور على أقصر طريق عن طريق صعود تدرج القيمة. نبدأ بتعيين عقدة الخروج على القيمة 1، بينما تُعيّن كل عقدة أخرى بالقيمة 0 باستثناء الجدران، ثم نكرر العملية بحيث تحسب القيمة الجديدة لكل خلية على أنها القيمة القصوى بين قيمة الخلية الحالية وقيم الخلايا الأربعة المُخفّضة المتجاورة (gamma=0.9 في الحالة أدناه). تبدأ العملية بمجرد أن تصبح قيمة عقدة البداية موجبة تمامًا. يُعد التنفيذ باستخدام NumPy أبسط إذا استفدنا من ميزات عامل الترشيح العام generic_filter (من scipy.ndimage) لعملية الانتشار: def diffuse(Z): # North, West, Center, East, South return max(gamma*Z[0], gamma*Z[1], Z[2], gamma*Z[3], gamma*Z[4]) # Build gradient array G = np.zeros(Z.shape) # Initialize gradient at the entrance with value 1 G[start] = 1 # Discount factor gamma = 0.99 # We iterate until value at exit is > 0. This requires the maze # to have a solution or it will be stuck in the loop. while G[goal] == 0.0: G = Z * generic_filter(G, diffuse, footprint=[[0, 1, 0], [1, 1, 1], [0, 1, 0]]) لكن في هذه الحالة بالتحديد يكون الأمر بطيئًا إلى حد ما، ومن الأفضل إعداد حلنا الخاص، وإعادة استخدام جزء من تشفير لعبة الحياة: # Build gradient array G = np.zeros(Z.shape) # Initialize gradient at the entrance with value 1 G[start] = 1 # Discount factor gamma = 0.99 # We iterate until value at exit is > 0. This requires the maze # to have a solution or it will be stuck in the loop. G_gamma = np.empty_like(G) while G[goal] == 0.0: np.multiply(G, gamma, out=G_gamma) N = G_gamma[0:-2,1:-1] W = G_gamma[1:-1,0:-2] C = G[1:-1,1:-1] E = G_gamma[1:-1,2:] S = G_gamma[2:,1:-1] G[1:-1,1:-1] = Z[1:-1,1:-1]*np.maximum(N,np.maximum(W, np.maximum(C,np.maximum(E,S)))) بمجرد الانتهاء من ذلك، يمكننا صعود التدرج للعثور على أقصر طريق كما هو موضح في الشكل أدناه: إيجاد المسار باستخدام خوارزمية بيلمان-فورد. تشير الألوان المتدرجة إلى القيم المنتشرة من نقطة نهاية المتاهة (أسفل اليمين). عُثر على المسار من خلال التدرج التصاعدي من الهدف. خوارزمية تدفقات السوائل Fluid Dynamics فيما يلي سنوضح طريقة عمل خوارزمية تدفقات السوائل، وكيفية تنفيذها برمجيًا. التدفق الهيدروديناميكي بمستويين مختلفين من التقريب، نهر نيكار، هايدلبرغ، ألمانيا. صورة Steven Mathey، 2012. طريقة لاغرانج Lagrangian مقابل أويلريان Eulerian في نظرية الحقل الكلاسيكية، فإن مواصفات لاغرانج للحقل هي طريقة للنظر إلى حركة السوائل، إذ يتبّع المراقب حركة السائل عبر المكان والزمان، ويعطينا رسم موقع كل جزء عبر الزمن مسار ذلك الجزء، ويمكن تخيل هذا على أنه الجلوس في قارب والانجراف في النهر. تعد مواصفات أويلريان لحقل التدفق طريقةً للنظر إلى حركة السوائل التي تركز على مواقع محددة في الفضاء الذي يتدفق من خلاله السائل مع مرور الوقت. يمكن تصور ذلك من خلال الجلوس على ضفة النهر ومشاهدة الماء يمر من الموقع الثابت. أي بعبارة أخرى، في حالة أويلريان يُقسم جزءٌ من الفضاء إلى خلايا وتحتوي كل خلية على متجه السرعة ومعلومات أخرى، مثل الكثافة ودرجة الحرارة. نحتاج في حالة لاغرانج إلى فيزياء تعتمد على الجسيمات مع تفاعلات ديناميكية وعمومًا نحتاج إلى عدد كبير من الجسيمات. لكلتا الطريقتين مزايا وعيوب ويعتمد الاختيار بين الطريقتين على طبيعة مشكلتك، ويمكنك أيضًا مزج الطريقتين في طريقة هجينة. مع ذلك، فإن أكبر مشكلة في المحاكاة القائمة على الجسيمات هي أن تفاعل الجسيمات يتطلب إيجاد الجسيمات المجاورة وهذا له تكلفة كما رأينا في حالة أسراب الطيور Boids في المقال السابق. إذا استهدفنا بايثونو NumPy فقط، فمن الأفضل اختيار طريقة أويلريان لأن الاعتماد على المتجهات سيكون عديم الأهمية تقريبًا مقارنةً بطريقة لاغرانج. كتابة الشيفرة باستخدام مكتبة NumPy لن نشرح كل النظرية الكامنة وراء ديناميك السوائل الحسابية لوجود العديد من الموارد عبر الإنترنت التي تشرح هذا بطريقة جيدة. لماذا نختار حسابات السائل إذًا؟ لأن النتائج تكون غالبًا جيدة ورائعة. سنعمل على تبسيط المشكلة أكثر من خلال تنفيذ طريقة من رسوميات الحاسوب بحيث يكون الهدف هو السلوك المقنع. سنعمل على تبسيط المشكلة أكثر من خلال تنفيذ طريقة من رسوميات الحاسوب، إذ لا يكون الهدف هو التصحيح ولكن السلوك المقنع. كتب جو ستام Jos Stam مقالًا لطيفًا جدًا لصالح SIGGRAPH عام 1999 يصف تقنية الحصول على سوائل مستقرة بمرور الوقت (أي لا يتباعد حلها على المدى الطويل). وكتب ألبيرتو سانتينيAlberto Santini تعليمات باستخدام لغة البرمجة بايثون (استخدم حينها numarray). الآن، علينا فقط تكييفها مع مكتبة NumPy الحديثة وتسريعها قليلًا باستخدام الحيل المعقدة. لن نشرح الشيفرات لأنها طويلة جدًا. محاكاة الدخان باستخدام خوارزمية السوائل المستقرة بواسطة جو ستام. تأتي معظم مقاطع الفيديو الصحيحة من حزمة Glumpy وتستخدم GPU (عمليات الإطارات الاحتياطية، أي عدم وجود OpenCL أو CUDA) لإجراء عمليات حسابية أسرع. أخذ عينات الضجيج الأزرق يشير الضجيج الأزرق blue noise إلى مجموعات العينات التي لها توزيعات عشوائية وموحدة مع عدم وجود أي انحياز طيفي. هذا الضجيج مفيد جدًا في مجموعة متنوعة من تطبيقات الرسوم، مثل التصيير rendering والتردد dithering وما إلى ذلك، وقد اقترحت عدة طرق لتحقيق مثل هذا الضجيج، ولكن الطريقة الأكثر بساطة هي بالتأكيد طريقة دارت DART. طريقة دارت DART تُعد طريقة دارت DART واحدةً من أقدم وأبسط الطرق، وهي تعمل عن طريق الرسم المتسلسل لنقاط عشوائية موحدة وقبول فقط تلك التي تقع على مسافة لا تقل عن كل عينة مقبولة سابقة، ولذلك فهي طريقة بطيئة جدًا لأن كل مرشح جديد يحتاج إلى اختباره مقابل المرشحين المقبولين السابقين؛ وكلما زادت النقاط التي تقبلها كانت الطريقة أبطأ. لنفكر في وحدة السطح والحد الأدنى لنصف القطر r لفرضه في كل نقطة. التعبئة الأكثر كثافة للدوائر في المستوى هي الشبكة السداسية لشكل خلية النحل، وتحسب الكثافة بالصيغة: بالنظر إلى الدوائر ذات نصف القطر r، يمكننا أن نكتب: نحن نعلم الحد الأعلى النظري لعدد الأقراص الممكن وضعها على السطح ولكن من المحتمل ألا نصل إلى هذا الحد الأقصى بسبب المواضع العشوائية. علاوةً على ذلك، نظرًا لرفض الكثير من النقاط بعد قبول القليل منها، سنحتاج إلى وضع حد لعدد المحاكمات الفاشلة المتتالية قبل أن نوقف العملية كاملةً. import math import random def DART_sampling(width=1.0, height=1.0, r = 0.025, k=100): def distance(p0, p1): dx, dy = p0[0]-p1[0], p0[1]-p1[1] return math.hypot(dx, dy) points = [] i = 0 last_success = 0 while True: x = random.uniform(0, width) y = random.uniform(0, height) accept = True for p in points: if distance(p, (x, y)) < r: accept = False break if accept is True: points.append((x, y)) if i-last_success > k: break last_success = i i += 1 return points تركنا لك تمرين إيجاد اتجاه توجيه لطريقة دارت DART. إذ تكمن الفكرة في إجراء حساب مسبق لعدد منتظم كافٍ من العينات العشوائية، إضافةً إلى المسافات المقترنة واختبار تضمينها التسلسلي. طريقة بريدسون Bridson إذا لم تسبب متجهات الطريقة السابقة أي صعوبة حقيقية، فإن تحسين السرعة ليس جيدًا وتظل الجودة منخفضة وتعتمد على المعامل k؛ فكلما كان هذا المعامل أعلى، كان ذلك أفضل لأنه يتحكم بصورةٍ أساسية في مدى صعوبة محاولة إدخال عينة جديدة، ولكن عندما يكون هناك عدد كبير فعلًا من العينات المقبولة، فإن فرصة واحد فقط ستسمح لنا بالعثور على موقع لإدخال عينة جديدة. يمكننا زيادة قيمة k ولكن هذا سيجعل الطريقة أبطأ دون أي ضمان في الجودة. حان الوقت للتفكير خارج الصندوق ولحسن الحظ، فعل روبرت بريدسون ذلك لنا واقترح طريقة بسيطة لكنها فعالة: الخطوة 0: تهيئة شبكة خلفية ذات n بُعد لتخزين العينات وتسريع البحث المكاني. نختار حجم الخلية المراد تقييدها من خلال بحيث تحتوي كل خلية شبكية على عينة واحدة على الأكثر، وبالتالي يمكن تنفيذ الشبكة مثل مصفوفة بسيطة من الأعداد الصحيحة ذات البعد n: يشير الرقم الافتراضي "1-" إلى عدم وجود عينة، بينما يعطي العدد الصحيح غير السالب مؤشر العينة الموجود في الخلية. الخطوة 1. حدد العينة الأولية x0، التي تُختار عشوائيًا من المجال، وأدخلها في شبكة الخلفية وهيّئ "القائمة النشطة" (مجموعة من مؤشرات العينة) باستخدام هذا المؤشر (صفر). الخطوة 2: عندما لا تكون القائمة النشطة فارغة، اختر منها مؤشرًا عشوائيًا وليكن i. عليك توليد ما يصل إلى "k" من النقاط المختارة بطريقة موحدة من الحلقة الكروية بين نصف القطر "r" و "2r" وحول xi. تحقق من أجل كل نقطة مما إذا كانت على مسافة "r" من العينات الموجودة (باستخدام شبكة الخلفية لاختبار العينات القريبة فقط). إذا كانت نقطة ما بعيدة بحد كافٍ عن العينات الموجودة فأرسلها على أنها عينة تالية وأضفها إلى القائمة النشطة. إذا لم يعثر على مثل هذه النقط بعد "k" محاولة، عليك إزالة i من القائمة النشطة. لا يطرح التنفيذ مشكلة حقيقية ويُترك بمثابة تمرين للقارئ. لاحظ أن هذه الطريقة ليست سريعة فحسب ولكنها تقدم أيضًا جودة أفضل (المزيد من العينات) من طريقة دارت DART ومع وجود عدد كبير من المحاولات. الخلاصة يعد المثال الأخير الذي كنا ندرسه هو مثال جيد، لأن متجهات المشكلة أكثر أهمية من متجهات الشيفرات، وقد كنا محظوظين في هذه الحالة المحددة بما يكفي لإنجاز العمل ولكن لن يكون الأمر كذلك دائمًا. نأمل أن تكون الآن مقتنعًا أنه من الجيد البحث عن حلول بديلة بمجرد العثور على حل. ستعمل دائمًا على تحسين السرعة من خلال متجهات الشيفرات والتعليمات البرمجية ولكن في هذه العملية فقد تفوتك تحسينات كبيرة. ترجمة -وبتصرّف- للفصل Problem vectorization من كتاب From Python to Numpy لصاحبه Nicolas P. Rougier. اقرأ أيضًا المقال السابق: استخدام المتجهات vectorization في لغة بايثون مع مكتبة NumPy مفاهيم متقدمة حول مكتبة NumPy في بايثون أهم 8 مكتبات بلغة البايثون تستخدم في المشاريع الصغيرة
  12. يُقصد باستخدام المتجهات vectorization في الشيفرة أن المشكلة التي تحاول حلها قابلةٌ للتحليل بطبيعتها ولا تتطلب سوى استخدام بعض الحيل لجعلها أسرع، وهذا لا يعني أن الأمر سهل أو مباشر، ولكنه على الأقل لا يستلزم إعادة التفكير في كامل مشكلتك. يتطلب الأمر بعض الخبرة لمعرفة أين يمكن استخدام المتجهات في الشيفرة. سنوضح ذلك من خلال مثال بسيط، إذ نريد تلخيص قائمتين من الأعداد الصحيحة. سنستخدم الدالة البسيطة التالية: def add_python(Z1,Z2): return [z1+z2 for (z1,z2) in zip(Z1,Z2)] إعادة كتابة الشيفرة السابقة عبر المتجهات من مكتبة NumPy بسهولة كبيرة بالشكل التالي: def add_numpy(Z1,Z2): return np.add(Z1,Z2) وكما هو متوقع تظهر المقارنة أن الطريقة الثانية هي الأسرع: >>> Z1 = random.sample(range(1000), 100) >>> Z2 = random.sample(range(1000), 100) >>> timeit("add_python(Z1, Z2)", globals()) 1000 loops, best of 3: 68 usec per loop >>> timeit("add_numpy(Z1, Z2)", globals()) 10000 loops, best of 3: 1.14 usec per loop كما أنها تتكيف أيضًا مع شكل Z1 و Z2، وهذا هو سبب عدم كتابة Z1 + Z2 لأن هذه الطريقة لن تعمل إذا كان كل من Z1 و Z2 قائمتين. تُفسّر عملية الجمع الداخلية في الطريقة الأولى المعتمدة على تابع لغة بايثون بطريقة مختلفة اعتمادًا على طبيعة الكائنين؛ وإذا أخذنا في الحسبان قائمتين متداخلتين، نحصل على المخرجات التالية: >>> Z1 = [[1, 2], [3, 4]] >>> Z2 = [[5, 6], [7, 8]] >>> Z1 + Z2 [[1, 2], [3, 4], [5, 6], [7, 8]] >>> add_python(Z1, Z2) [[1, 2, 5, 6], [3, 4, 7, 8]] >>> add_numpy(Z1, Z2) [[ 6 8] [10 12]] تربط الطريقة الأولى القائمتين معًا، بينما تربط الطريقة الثانية القوائم الداخلية معًا، وتحسب الطريقة الأخيرة ما هو متوقع. يمكنك إعادة كتابة تعليمات بايثون بحيث تضم قوائم متداخلة مختلفة الحجم. المتجه الموحد Uniform vectorization يُعد المتجه الموحد أبسط شكل من أشكال المتجهات، إذ تشترك جميع العناصر في نفس العملية الحسابية في كل خطوة زمنية مع عدم وجود معالجة محددة لأي عنصر. لعبة الحياة هي إحدى الحالات النمطية التي اخترعها جون كونواي John Conway وهي إحدى أقدم الأمثلة على المشغلات الآلية الخلوية cellular automata، التي تمثّل مجموعةً من الخلايا التي ترتبط معًا بمفهوم الجيران وتكون متجّهاتها بسيطة. سنحدّد بدايةً قواعد اللعبة ثم سندرس كيفية جعلها معتمدة على المتجهات: يظهر نسيج صدفة الحلزون نمط مشغل آلي خلوي على غلافها الخارجي. الصورة لريتشارد لينج 2005. لعبة الحياة يمكنك الحصول على فكرة حول لعبة الحياة في موقع ويكيبيديا؛ وهي لعبة معتمدة على المشغلات الآلية الخلوية، وابتكرها عالم الرياضيات البريطاني جون هورتون كونواي John Horton Conway في عام 1970. اللعبة هي لعبة بدون لاعب، مما يعني أن تطورها يُحدّد من خلال حالتها الأولية، ولا تحتاج اللعبة إلى مدخلات من اللاعبين، ويتفاعل المراقب مع لعبة الحياة من خلال إنشاء تكوين أولي ومراقبة كيفية تطور اللعبة. عالم لعبة الحياة هي شبكة متعامدة ثنائية الأبعاد لا نهائية من الخلايا المربعة، لكل منها حالتين محتملتين (حياة أو موت)، وترتبط حالة كل خلية بجاراتها الثمانية، وهي الخلايا المتجاورة أفقيًا، أو رأسيًا، أو قطريًا، وتحدث في كل خطوة في الوقت المناسب التحولات التالية: تموت أي خلية حية لها أقل من اثنين من الجيران الأحياء (كما لو كانت بسبب الاحتياجات الناجمة عن نقص السكان). تموت أي خلية لها أكثر من ثلاثة جيران أحياء (كما لو كان السبب هو الاكتظاظ). تعيش أي خلية حية لها اثنان أو ثلاثة من الجيران الأحياء للجيل القادم. تصبح أي خلية ميتة مع ثلاثة جيران أحياء بالضبط خليةً حية. يشكل النمط الأولي "أصل seed" النظام. يُنشأ الجيل الأول من خلال القواعد السابقة في وقت واحد على كل خلية (تحدث الولادات والوفيات في وقت واحد)، أي كل جيل هو نتيجة خالصة للجيل السابق، ويستمر تطبيق القواعد بطريقة مستمرة لخلق أجيال أخرى. كتابة شيفرة بلغة بايثون يمكننا كتابة شيفرة لعبة Game of Life في لغة بايثون باستخدام قائمة list تمثّل اللوحة، إذ من المفترض أن تتطور الخلايا. تُجهز هذه اللوحة بحدود صفرية "0" مما يسمح بتسريع الأمور قليلًا عن طريق تجنب إجراء اختبارات محددة للحدود عند حساب الجيران. Z = [[0,0,0,0,0,0], [0,0,0,1,0,0], [0,1,0,1,0,0], [0,0,1,1,0,0], [0,0,0,0,0,0], [0,0,0,0,0,0]] يكون عدد الجيران واضحًا عند أخذ الحدود بالحسبان: def compute_neighbours(Z): shape = len(Z), len(Z[0]) N = [[0,]*(shape[0]) for i in range(shape[1])] for x in range(1,shape[0]-1): for y in range(1,shape[1]-1): N[x][y] = Z[x-1][y-1]+Z[x][y-1]+Z[x+1][y-1] \ + Z[x-1][y] +Z[x+1][y] \ + Z[x-1][y+1]+Z[x][y+1]+Z[x+1][y+1] return N نكرر الخطوة في الوقت المناسب، ولذلك نحسب عدد الجيران لكل خلية داخلية ثم نحدث كامل اللوحة وفقًا للقواعد الأربعة المذكورة أعلاه: def iterate(Z): N = compute_neighbours(Z) for x in range(1,shape[0]-1): for y in range(1,shape[1]-1): if Z[x][y] == 1 and (N[x][y] < 2 or N[x][y] > 3): Z[x][y] = 0 elif Z[x][y] == 0 and N[x][y] == 3: Z[x][y] = 1 return Z يوضح الشكل أدناه أربعة تكرارات على منطقة 4×4، إذ أن الحالة الأولية هي طائرة شراعية glider، وهي بنية اكتُشفت عام 1970. من المعروف أن نمط الطائرة الشراعية يكرر نفسه خطوةً واحدةً قطريًا خلال أربعة تكرارات. كتابة شيفرة Numpy بناءً على التعليمات السابقة المكتوبة بلغة بايثون، نلاحظ أن شيفرة لعبة الحياة ينقسم إلى قسمين، أحدهما مسؤول عن حساب عدد الجيران والآخر مسؤول عن تطبيق القواعد. يُعد حساب عدد الجيران أمرًا سهلًا نسبيًا، لأننا حرصنا على إضافة حد فارغ حول النطاق arena. ومن خلال النظر في العروض الجزئية للنطاق يمكننا الوصول إلى الجيران بطريقة حدسية كما توضح هذه الحالة أحادية البعد: يتطلب الانتقال إلى الحالة ثنائية البعد حسابات إضافية للتأكد من مراعاة جميع الجيران الثمانية. N = np.zeros(Z.shape, dtype=int) N[1:-1,1:-1] += (Z[ :-2, :-2] + Z[ :-2,1:-1] + Z[ :-2,2:] + Z[1:-1, :-2] + Z[1:-1,2:] + Z[2: , :-2] + Z[2: ,1:-1] + Z[2: ,2:]) يمكننا لتطبيق القاعدة كتابة التعليمات البرمجية باستخدام تابع argwhere الذي سينتج عنه رقم المؤشر عندما يكون الشرط المحدد صحيحًا: # المصفوفات المسطحة N_ = N.ravel() Z_ = Z.ravel() # تطبيق القواعد R1 = np.argwhere( (Z_==1) & (N_ < 2) ) R2 = np.argwhere( (Z_==1) & (N_ > 3) ) R3 = np.argwhere( (Z_==1) & ((N_==2) | (N_==3)) ) R4 = np.argwhere( (Z_==0) & (N_==3) ) # ضبط قيم جديدة Z_[R1] = 0 Z_[R2] = 0 Z_[R3] = Z_[R3] Z_[R4] = 1 # كن متأكدًا من بقاء الحدود فارغة Z[0,:] = Z[-1,:] = Z[:,0] = Z[:,-1] = 0 رغم عدم استخدام الإصدار الأول للحلقات المتداخلة لكنه يبقى بعيدًا على أن يكون أمثليًا بسبب استخدام استدعاءات argwhere التي قد تكون بطيئة جدًا، ويمكننا بدلًا من ذلك تحليل القواعد إلى الخلايا التي ستبقى على قيد الحياة (أي التي ستبقى عند قيمة 1) والخلايا التي ستلد وذلك بالاستفادة من القدرة المنطقية لمكتبة Numpy: birth = (N==3)[1:-1,1:-1] & (Z[1:-1,1:-1]==0) survive = ((N==2) | (N==3))[1:-1,1:-1] & (Z[1:-1,1:-1]==1) Z[...] = 0 Z[1:-1,1:-1][birth | survive] = 1 إذا دققت في أول سطرين ستلاحظ أن المتغيرين birth و survive مصفوفتان يمكن استخدامهما لتعيين قسم المصفوفة Z إلى القيمة "1" بعد محوها. تمرين يمكن أن ينتج عن تفاعل الأصناف الكيميائية وانتشارها مجموعةً متنوعةً من الأنماط، تذكرنا غالبًا بتلك التي نراها في الطبيعة، ومن أمثلة هذا التفاعل نموذج معادلات جراي سكوت Gray-Scott، ولمزيد من المعلومات حول هذا النظام الكيميائي راجع مقالة الأنماط المعقدة في نظام بسيط. لنفكر في نوعين كيميائيين U و V، ولكل منهما تركيز u و v ومعدل انتشاء Du و Dv. يُحوّل V إلى P بمعدل تحويل k. يمثل f معدل العملية التي تشبع U وتجعل كل من U و V و P يتلاشى. ويمكن كتابة ذلك على النحو التالي: استنادًا إلى مثال لعبة الحياة سنجرب تنفيذ نظام نشر التفاعل. فيما يلي مجموعة من المعاملات التي سنحتاج إلى اختبارها: table { width: 100%; } thead { vertical-align: middle; text-align: center; } td, th { border: 1px solid #dddddd; text-align: right; padding: 8px; text-align: inherit; } tr:nth-child(even) { background-color: #dddddd; } الاسم Du Dv f k Bacteria 1 0.16 0.08 0.035 0.065 Bacteria 2 0.14 0.06 0.035 0.065 Coral 0.16 0.08 0.060 0.062 Fingerprint 0.19 0.05 0.060 0.062 Spirals 0.10 0.10 0.018 0.050 Spirals Dense 0.12 0.08 0.020 0.050 Spirals Fast 0.10 0.16 0.020 0.050 Unstable 0.16 0.08 0.020 0.055 Worms 1 0.16 0.08 0.050 0.065 Worms 2 0.16 0.08 0.054 0.063 Zebrafish 0.16 0.08 0.035 0.060 والنتائج هي كالآتي: والآتي: إضافةً إلى ما يلي: المتجهات الزمنية Temporal vectorization مجموعة Mandelbrot هي مجموعةٌ من الأعداد العقدية c التي لا تتباعد diverge فيها الدالة "fc(z) = z2 + c" عند تكرارها بدءًا من z = 0، أي من أجل التسلسل "… ,((fc(0), fc(fc(0" وتظل محدودة بالقيمة المطلقة. من السهل حسابها ولكنها قد تستغرق وقتًا طويلَا جدًا لأنك تحتاج إلى التأكد من أن رقمًا معينًا لا يتباعد، ويُنفّذ ذلك من خلال تكرار الحساب حتى أقصى عدد من التكرارات، وبعد ذلك إذا كان الرقم لا يزال ضمن الحدود يكون غير متباعد، وبالتأكيد كلما زاد عدد مرات التكرار زادت الدقة التي تحصل عليها. بروكلي رومانسكو، يُظهر شكلًا قريبًا من كسورية fractal طبيعية. صورة جون سوليفان، 2004. كتابة شيفرة بايثون تكتب التعليمات البرمجية على النحو التالي: def mandelbrot_python(xmin, xmax, ymin, ymax, xn, yn, maxiter, horizon=2.0): def mandelbrot(z, maxiter): c = z for n in range(maxiter): if abs(z) > horizon: return n z = z*z + c return maxiter r1 = [xmin+i*(xmax-xmin)/xn for i in range(xn)] r2 = [ymin+i*(ymax-ymin)/yn for i in range(yn)] return [mandelbrot(complex(r, i),maxiter) for r in r1 for i in r2] الجزء المثير للاهتمام والبطيء في الشيفرات السابقة هو دالة mandelbrot التي تحسب التسلسل "(((…fc(fc(fc". جعل هذه الشيفرات معتمدة على المتجهات ليس أمرًا واضحًا تمامًا بسبب تعليمة return الداخلية التي توحي بعملية فاضلية للعنصر. بمجرد أن يتباعد لا نحتاج إلى التكرار مرةً أخرى ويمكننا إرجاع عدد التكرارات في حال عدم التباعد، ولكن كيف يمكن أن تفعل Numpy الشيء نفسه؟ كتابة الشيفرة باستخدام مكتبة Numpy الحيلة هي البحث في كل قيم التكرار التي لم تتباعد بعد وتحديث المعلومات المتعلقة بهذه القيم فقط. نظرًا لأننا نبدأ من "Z = 0"، فإننا نعلم أن كل قيمة ستُحدث مرةً واحدةً على الأقل (عندما تكون مساويةً للصفر فإنها لم تتباعد بعد)، وستتوقف عن التحديث بمجرد تباعدها. ولفعل ذلك سنستخدم فهرسة fancy indexing مع الدالة (less(x1,x2 التي ترجع القيمة الحقيقية للعنصر المحقق (x1<x2). def mandelbrot_numpy(xmin, xmax, ymin, ymax, xn, yn, maxiter, horizon=2.0): X = np.linspace(xmin, xmax, xn, dtype=np.float32) Y = np.linspace(ymin, ymax, yn, dtype=np.float32) C = X + Y[:,None]*1j N = np.zeros(C.shape, dtype=int) Z = np.zeros(C.shape, np.complex64) for n in range(maxiter): I = np.less(abs(Z), horizon) N[I] = n Z[I] = Z[I]**2 + C[I] N[N == maxiter-1] = 0 return Z, N وإليك النتيجة: >>> xmin, xmax, xn = -2.25, +0.75, int(3000/3) >>> ymin, ymax, yn = -1.25, +1.25, int(2500/3) >>> maxiter = 200 >>> timeit("mandelbrot_python(xmin, xmax, ymin, ymax, xn, yn, maxiter)", globals()) 1 loops, best of 3: 6.1 sec per loop >>> timeit("mandelbrot_numpy(xmin, xmax, ymin, ymax, xn, yn, maxiter)", globals()) 1 loops, best of 3: 1.15 sec per loop كتابة الشيفرة الأسرع باستخدام Numpy سيكون الربح بزيادة السرعة خمسة أضعاف تقريبًا وليس بالقدر الذي نتوقعه، ومن أسباب هذه المشكلة هو أن الدالة np.less تشير إلى اختبارات xn × yn في كل تكرار، بينما نعلم أن بعض القيم قد تباعدت فعلًا، وحتى إذا أجريت هذه الاختبارات على المستوى C (من خلال numpy)، ستبقى التكلفة كبيرة. توجد طريقةٌ أخرى اقترحها دان جودمان Dan Goodman وذلك بالعمل على مصفوفة ديناميكية في كل تكرار بحيث تخزن فقط النقاط التي لم تتباعد بعد، وهذا يتطلب إضافة أسطر برمجية إضافية ولكن ستكون النتيجة أسرع وتؤدي إلى تحسين عامل السرعة عشر مرات مقارنةً بالطريقة الأولى. def mandelbrot_numpy_2(xmin, xmax, ymin, ymax, xn, yn, itermax, horizon=2.0): Xi, Yi = np.mgrid[0:xn, 0:yn] Xi, Yi = Xi.astype(np.uint32), Yi.astype(np.uint32) X = np.linspace(xmin, xmax, xn, dtype=np.float32)[Xi] Y = np.linspace(ymin, ymax, yn, dtype=np.float32)[Yi] C = X + Y*1j N_ = np.zeros(C.shape, dtype=np.uint32) Z_ = np.zeros(C.shape, dtype=np.complex64) Xi.shape = Yi.shape = C.shape = xn*yn Z = np.zeros(C.shape, np.complex64) for i in range(itermax): if not len(Z): break # Compute for relevant points only np.multiply(Z, Z, Z) np.add(Z, C, Z) # Failed convergence I = abs(Z) > horizon N_[Xi[I], Yi[I]] = i+1 Z_[Xi[I], Yi[I]] = Z[I] # Keep going with those who have not diverged yet np.negative(I,I) Z = Z[I] Xi, Yi = Xi[I], Yi[I] C = C[I] return Z_.T, N_.T وتصبح النتيجة كما يلي: >>> timeit("mandelbrot_numpy_2(xmin, xmax, ymin, ymax, xn, yn, maxiter)", globals()) 1 loops, best of 3: 510 msec per loop إظهار النتائج من أجل تصور نتائجنا يمكننا عرض المصفوفة N مباشرةً باستخدام الأمر imshow من مكتبة matplotlib ولكن هذا سينتج صورة مخططة banded وهي نتيجة معروفة لخوارزمية عد الهروب escape count المستخدمة. يمكن التخلص من هذا الربط من خلال حساب الهروب الجزئي وذلك عن طريق قياس مدى هبوط النقطة المتكررة خارج حدود قطع الهروب. فيما يلي صورة للنتيجة، إذ استخدمنا التسوية الطبيعية recount normalization، وأضفنا خريطة ألوان طبيعية (gamma=0.3) إضافةً إلى تظليل فاتح. تمرين نريد الآن قياس البعد الكسري لمجموعة ماندلبورت Mandelbrot باستخدام بُعد Minkowski–Bouligand dimension، ولفعل ذلك نحتاج إلى حسابات لمربع بأبعاد متناقص، كما هو موضح في لقطة الشاشة التالية، وكما تتوقع لا يمكننا استخدام تعليمات بايثون العادية لأنها ستكون بطيئة جدًا. الهدف من التمرين هو كتابة دالة باستخدام NumPy تأخذ مصفوفة عشرية ثنائية الأبعاد وتُرجع البعد. ينبغي توحيد القيم الموجودة في المصفوفة بين 0 و1. المتجهات المكانية تشير المتجهات المكانية إلى الحالة التي تشارك فيها العناصر نفس الحساب ولكنها تتفاعل مع مجموعة فرعية فقط من العناصر الأخرى، وكانت هذه الحالة موجودةٌ فعلًا في لعبة الحياة، ولكن في بعض المواقف هناك صعوبة إضافية لأن المجموعة الفرعية ديناميكية وتحتاج إلى التحديث في كل تكرار؛ فمثلًا في أنظمة الجسيمات تتفاعل الجسيمات غالبًا مع الجيران المحليين، وينطبق هذا أيضًا على حالة "boids" التي تحاكي سلوكيات السرب flocking. برنامج Boids الطيور المتدفقة هي مثال على التنظيم الذاتي في علم الأحياء. صورة Christoffer A Rasmussen، 2012. يُعد Boids برنامج حياة اصطناعية طُور بواسطة كريج رينولدز Craig Reynolds في عام 1986 وهو يحاكي سلوك سرب الطيور. اسم Boid هو اختصار إلى " bird-oid object" والذي يشير إلى كائن يمثل الطيور. كما هو الحال مع معظم برامج محاكاة الحياة الاصطناعية، فإن Boids هو مثال على السلوك الناشئ، أي أن تعقيد Boids ينشأ من تفاعل العوامل الفردية والالتزام بمجموعة من القواعد البسيطة. القواعد المطبقة في عالم Boids هي كما يلي: الانفصال separation: إرشاد لتجنب ازدحام رفاق السرب المحليين. المحاذاة alignment: إرشاد نحو متوسط اتجاه رفاق السرب المحليين. التماسك cohesion: الإرشاد للتحرك نحو متوسط الموضع (مركز الكتلة) للرفاق الحاليين. تنفيذ الشيفرة باستخدام تعليمات بايثون العادية نظرًا لأن كل boid هو كيان مستقل له العديد من الخاصيات، مثل الموضع والسرعة فمن الطبيعي أن نبدأ بكتابة الصنف Boid: import math import random from vec2 import vec2 class Boid: def __init__(self, x=0, y=0): self.position = vec2(x, y) angle = random.uniform(0, 2*math.pi) self.velocity = vec2(math.cos(angle), math.sin(angle)) self.acceleration = vec2(0, 0) الكائن vec2 هو صنف بسيط جدًا يتعامل مع جميع عمليات المتجه الشائعة بمكونين، وهذا سيوفر علينا بعض الكتابة في صنف Boid الرئيسي. يوجد بعض حزم المتجهات في فهرس حزمة Python، ولكن استخدامها سيكون مبالغة في مثل هذا المثال البسيط. يُعد السرب حالةً صعبة لبايثون العادية لأنه يتفاعل مع الجيران المحليين، ومع ذلك ونظرًا لأن أسراب الطيور تتحرك فإن العثور على مثل هؤلاء الجيران المحليين يتطلب حسابات في كل مرة تقطع المسافة إلى سرب طيور آخر لفرز تلك الطيور الموجودة في نصف قطر تفاعل معين، وبالتالي تكون الطريقة النموذجية لكتابة القواعد الثلاثة: def separation(self, boids): count = 0 for other in boids: d = (self.position - other.position).length() if 0 < d < desired_separation: count += 1 ... if count > 0: ... def alignment(self, boids): ... def cohesion(self, boids): … لإكمال الصورة، يمكننا أيضًا إنشاء كائن Flock: class Flock: def __init__(self, count=150): self.boids = [] for i in range(count): boid = Boid() self.boids.append(boid) def run(self): for boid in self.boids: boid.run(self.boids) يمكن أن نحصل باستخدام هذا النهج على ما يصل إلى 50 سربًا حتى يصبح وقت الحساب بطيئًا جدًا للحصول على رسم متحرك سلس. سنحصل بالاعتماد على مكتبة Numpy على أداء أفضل بكثير، ولكن قبل الانتقال إلى استخدام هذه المكتبة سنشير إلى المشكلة الرئيسية الموجودة في شيفرات بايثون السابقة؛ فكما تلاحظ يوجد في الشيفرات الكثير من التكرار، أي بتعبير أدق نحن لا نستغل حقيقة أن المسافة الإقليدية انعكاسية أي: |x − y| = |y − x|. والحقيقة أن كل دالة تحسب "n2" مسافة بينما حساب مسافة "n2/2" كافي، إذا خُزّنت تخزينًا مؤقتًا بطريقة صحيحة. وأيضًا تعيد كل قاعدة حساب كل مسافة دون تخزين نتيجة الدوال الأخرى تخزينًا مؤقتًا، وفي النهاية، نكون قد حسبنا "3n2" مسافة بدلًا من "n2/2". كتابة الشيفرة باستخدام مكتبة NumPy تتخذ كتابة الشيفرة باستخدام مكتبة Numpy نهجًا مختلفًا، سنجمع كل كائنات أسراب الطيور boids في مصفوفة الموضع ومصفوفة السرعة: n = 500 velocity = np.zeros((n, 2), dtype=np.float32) position = np.zeros((n, 2), dtype=np.float32) الخطوة الأولى هي حساب الجيران لكل كائنات boids، ولذلك نحتاج إلى حساب المسافات المزدوجة: dx = np.subtract.outer(position[:, 0], position[:, 0]) dy = np.subtract.outer(position[:, 1], position[:, 1]) distance = np.hypot(dx, dy) كان بإمكاننا استخدام دالة scipy cdist لكننا سنحتاج إلى المصفوفتين dx و dy لاحقًا، وبمجرد حسابها سيكون من الأسرع استخدام تابع hypot. لاحظ شكل المسافة (n,n) وكل خط يرتبط بكائن boid واحد، أي أن كل سطر يعطي المسافة إلى جميع كائنات boids الأخرى. يمكننا الآن حساب الجيران من هذه المسافات وفقًا للقواعد الثلاثة، مستفيدين من إمكانية دمجها معًا. يمكننا حساب قناع للمسافة والذي يكون موجبًا تمامًا (أي ليس له ارتباط ذاتي)، ثم جداء هذا القناع مع أقنعة المسافات الأخرى. mask_0 = (distance > 0) mask_1 = (distance < 25) mask_2 = (distance < 50) mask_1 *= mask_0 mask_2 *= mask_0 mask_3 = mask_2 ملاحظة: إذا افترضنا أن أسراب الطيور boids لا يمكن أن تحتل نفس الموضع، فكيف يمكن حساب mask_0 بفعالية أكثر؟ ثم نحسب عدد الجيران داخل نصف القطر المحدد ونتأكد من أنه 1 على الأقل لتجنب القسمة على الصفر. mask_1_count = np.maximum(mask_1.sum(axis=1), 1) mask_2_count = np.maximum(mask_2.sum(axis=1), 1) mask_3_count = mask_2_count الآن، سنكتب القواعد الثلاث: المحاذاة # حساب متوسط السرعة للجيران المحليين target = np.dot(mask, velocity)/count.reshape(n, 1) # توحيد النتيجة norm = np.sqrt((target*target).sum(axis=1)).reshape(n, 1) target *= np.divide(target, norm, out=target, where=norm != 0) # المحاذاة بسرعة ثابتة target *= max_velocity # الناتج steering حساب مسار الإرشاد alignment = target - velocity التماسك # حساب مركز الجاذبية للجيران المحليين center = np.dot(mask, position)/count.reshape(n, 1) # حساب الاتجاه إلى المركز target = center - position # توحيد النتيجة norm = np.sqrt((target*target).sum(axis=1)).reshape(n, 1) target *= np.divide(target, norm, out=target, where=norm != 0) # (max_velocity) التماسك بسرعة ثابتة target *= max_velocity # الناتج steering حساب مسار الإرشاد cohesion = target - velocity الانفصال # حساب قوة التنافر من الجيران المحليين repulsion = np.dstack((dx, dy)) # تتناسب القوة عكسيًا مع المسافة repulsion = np.divide(repulsion, distance.reshape(n, n, 1)**2, out=repulsion, where=distance.reshape(n, n, 1) != 0) # حساب الاتجاه بعيدًا عن الآخرين target = (repulsion*mask.reshape(n, n, 1)).sum(axis=1)/count.reshape(n, 1) # توحيد النتيجة norm = np.sqrt((target*target).sum(axis=1)).reshape(n, 1) target *= np.divide(target, norm, out=target, where=norm != 0) # (max_velocity) الانفصال بسرعة ثابتة target *= max_velocity # الناتج steering حساب مسار الإرشاد separation = target - velocity يجب أن تكون مسارات الإرشاد الثلاث الناتجة (الانفصال والمحاذاة والتماسك) محدودةً من حيث الحجم. وسنترك لك الدمج بين هذه القواعد. التحديث الناتج للسرعة والموضع: acceleration = 1.5 * separation + alignment + cohesion velocity += acceleration position += velocity أخيرًا نتخيل النتيجة باستخدام مخطط مبعثر scatter موجه مخصص. Boids هو برنامج حياة اصطناعية، طُوِّر بواسطة Craig Reynolds في عام 1986، والذي يحاكي سلوك الطيور المتدفقة. تمرين نحن الآن جاهزون لعرض أسراب الطيور boids، وأسهل طريقة لذلك هي استخدام دالة الرسوم المتحركة matplotlib ومخطط مبعثر. لسوء الحظ لا يمكننا توجيه التبعثر بطريقة فردية ونحتاج إلى صنع كائنات خاصة باستخدام توابع PathCollection العائد للدالة matplotlib. يمكن تعريف مسار المثلث البسيط كما يلي: v= np.array([(-0.25, -0.25), ( 0.00, 0.50), ( 0.25, -0.25), ( 0.00, 0.00)]) c = np.array([Path.MOVETO, Path.LINETO, Path.LINETO, Path.CLOSEPOLY]) يمكن تكرار هذا المسار عدة مرات داخل المصفوفة ويمكن جعل كل مثلث مستقلاً. n = 500 vertices = np.tile(v.reshape(-1), n).reshape(n, len(v), 2) codes = np.tile(c.reshape(-1), n) لدينا الآن مصفوفة (n, 4, 2) ومجموعة (n, 4) للشيفرات التي تمثل عدد n من boids. نحن مهتمون بمعالجة مصفوفة vertices لتعكس الترجمة والقياس والدوران لكل كائنات boids. كيف يمكن أن تكتب وظائف الترجمة والقياس والتدوير؟ الخلاصة درسنا من خلال هذه الأمثلة الثلاثة ثلاثة أشكال لاستخدام المتجهات في الشيفرات: المتجهات الموحدة، إذ تشترك العناصر في نفس الحساب دون قيد أو شرط وللمدة نفسها. المتجهات الزمانية، إذ تشترك العناصر في نفس الحساب ولكنها تتطلب عددًا مختلفًا من التكرارات. المتجهات المكانية، إذ تشترك العناصر في نفس الحساب ولكن على الوسطاء المكانية الديناميكية. ومن المحتمل أن يكون هناك العديد من أشكال متجهات الشيفرات. كما أوضحنا سابقًا يعد هذا النوع من المتجهات من أبسط الأنواع على الرغم من أننا رأينا أنه من الصعب حقًا تنفيذه ويتطلب بعض الخبرة أو بعض المساعدة أو كليهما. ترجمة -وبتصرف- للفصل Code vectorization من كتاب From Python to Numpy لصاحبه Nicolas P. Rougier. اقرأ أيضًا المقال السابق: مفاهيم متقدمة حول مكتبة NumPy في بايثون أهم 8 مكتبات بلغة البايثون تستخدم في المشاريع الصغيرة
  13. يلعب التسويق الرقمي دورًا مهمًا في جذب العملاء وتحسين المبيعات، لذلك من الضروري الحفاظ على وجودك على الإنترنت. يساعد التدوين التجاري الشركات على تقديم فكرة واضحة عن المنتج والخدمات التي تقدّم للعملاء، ويوفر إرشادات حول كيفية استخدام المنتجات والخدمات. تُعَدّ المدونات نوع من أنواع المواقع الإلكترونية، ويقدم لك نظام أودو أداةً مثاليةً لإنشاء المواقع الإلكترونية بمختلف أنواعها (مدونات، متاجر إلكترونية، مواقع ويب). ويمكّنك هذا النظام من إنشاء موقع ويب وإدارته بسهولة، إذ يقدم مجموعة أدوات مخصصة تسمح لك بتصميم الموقع وإدارته وصيانته وفقًا لمتطلباتك، دون أن يتطلب ذلك امتلاك أي خبرات برمجية أو تقنية. تسمح لك العناصر المتوفرة في أداة إنشاء مواقع الويب في نظام أودو بإضافة العديد من الوظائف والميزات إلى موقع الويب من خلال نقرات بسيطة، وكل ما عليك فعله هو اختيار كتل مناسبة لموقع الويب وتعديلها باستخدام خيارات النمط، ووفقًا لأهداف وطبيعة عملك يمكنك تصميم موقعك الإلكتروني الخاص. وتُعَد معظم وظائف الموقع مثبتةً مسبقًا في نظام أودو، بحيث يمكنك سحب الكتل المطلوبة وإضافتها. باستخدام نظام أودو، يمكنك إنشاء مدونات وظيفية وعامة، ومشاركتها بسهولة على منصات التواصل الاجتماعي المختلفة مثل تويتر وفيسبوك. وفي هذه المقالة سنوضح كيفية إنشاء مدونة باستخدام نظام أودو، وما هي الميزات التي يقدمها. وحدة المدونات في نظام أودو من خلال وحدة مواقع الويب في نظام أودو، سيحصل المستخدم على منصة لإدارة وإنشاء مدونات جديدة؛ بالتالي، ترتبط وحدة المدونات مع وحدة أداة بناء المواقع الإلكترونية، ولهذا يجب تثبيت وحدة المواقع الإلكترونية قبل تثبيت وحدة المدونات. في قائمة التطبيقات المثبتة في نظام أودو ستظهر فقط وحدة الموقع الإلكتروني. وعند فتحها ستظهر في القائمة العلوية علامة التبويب "ألمدونات"، كما توضح الصورة التالية: عند النقر على علامة التبويب "إعداد"، ستظهر قائمة منسدلة يمكنك من خلالها الوصول إلى إعداد الوسوم وفئات الوسم. تتضمن قائمة المدونات تفاصيل المقالات، مثل العنوان والمؤلف ونوع المدونة وعدد المشاهدات المساهم الأخير وتاريخ آخر تحديث، ومن الممكن تغيير طريقة عرض مقالات المدونة إلى طريقة عرض كانبان. كيفية إنشاء مدونات جديدة بالنقر على زر "إنشاء" ستنتقل إلى نافذة جديدة، حيث يمكنك إضافة المعلومات والتفاصيل الضرورية المتعلقة بالمدونة الجديدة. أكمل الآن كل الحقول الموجودة في نافذة إنشاء مدونة. في البداية، ستحتاج إلى تحديد نوع المدونة من القائمة المنسدلة، مع العلم أنه يمكنك إنشاء أنواع جديدة بالانتقال إلى إعدادات وحدة موقع الويب. يساعد تحديد نوع المدونة على تسهيل تصنيف مدوناتك على مواقع الويب. بعد ذلك أضف عنوان المدونة والعنوان الفرعي لها، واذكر الوسوم المناسبة للمدونة في حقل الوسوم. في حقل موقع الويب، يمكنك تحديد موقع الويب الذي تريد نشر هذه المدونة عليه. يمكنك أيضًا ترك هذا الحقل فارغًا، بالتالي ستنشر المدونة على جميع مواقع الويب التي أعدت في قاعدة بياناتك. في علامة التبويب "خيارات النشر"، أضف اسم مؤلف هذه المدونة وتاريخ النشر واسم المشارك الأخير وتاريخ آخر تحديث. لا تنسَ إضافة بعض المعلومات التي تساعد على تحسين ظهور مدونتك في نتائج بحث غوغل ضمن علامة التبويب "SEO"، مثل عنوان Meta ووصف Meta والكلمات المفتاحية. بعد الانتهاء من كل هذه الخطوات، يمكنك نشر مدونتك على مواقع الويب المحددة. نشر مدونات جديدة يمكنك استخدام زر Go To Website لنشر المدونة على موقعك الإلكتروني، إذ سينقلك نظام أودو إلى موقع الويب للاطلاع على النسخة غير المنشورة من مدونتك. يمكنك الآن إضافة محتوى إلى المدونة وتحسين العرض بمساعدة أدوات التحرير من الواجهة الأمامية. وكما توضح الصورة السابقة، يمكنك إضافة المحتوى الرئيسي للمدونة في المساحة المحددة بعد النقر فوق زر "Edit". باستخدام أدوات النمط Style، يمكنك ضبط حجم الخط ونوعه ومحاذاة النص، كما يمكنك إضافة أي روابط متعلقة بالمدونة بين المحتوى باستخدام أدوات التصميم. من أجل تصميم غلاف منشور المدونة، يمكنك النقر فوق عنوان المدونة وسيظهر خيار التصميم المقابل في لوحة التحرير كما هو موضح في الصورة أدناه. يمكنك تحديد لون مناسب أو إضافة صورة كخلفية للعنوان. يمكن عرض الصورة بملء الشاشة أو نصف شاشة أو ملاءمة النص حسب متطلباتك. يمكنك أيضًا ضبط كثافة الفلتر وإضافة علامات جديدة بمساعدة لوحة التحرير. وبعد اكتمال التحرير وإضافة المحتوى، انقر فوق زر "حفظ". والآن، انقر فوق زر غير منشور لتغيير الحالة إلى منشور. يمكن للقراء الاطلاع على قائمة المدونات المنشورة في قسم المدونة على موقع الويب، كما يمكن للمسؤول عن الموقع رؤية كل من المدونات المنشورة وغير المنشورة ضمن هذه القائمة. يقدم أودو العديد من الخيارات القابلة للتخصيص على هذا النظام الأساسي لجعل الصفحة أكثر جاذبية للعملاء. وباستخدام هذه الميزات، يمكنك إنشاء محتوى إبداعي ونشره على موقعك الإلكتروني. خيارات التخصيص تستخدم ميزات التخصيص المتاحة في نظام أودو لجعل المدونة أكثر تفاعليةً واستجابة، حيث تمكّنك من تنشيط الإعجابات والتعليقات، وتساعدك على خلق تفاعل بينك وبين الجمهور. تمكّنك خيارات التخصيص أيضًا من إضافة رموز خاصة لمشاركة المدونات على وسائل التواصل الاجتماعي. تساعدك الكتل الإنشائية الموجودة في أدوات التحرير على تصميم صفحات المدونة، حيث يمكنك إضافة العناصر التي تحتاجها وتنسيقها بالطريقة التي تريدها. ويمكنك تعديل مظهر غلاف المدونة والعنوان باستخدام ميزة "الغلاف العادي"، إذ تُعدّل هذه الميزة العنوان والعنوان الفرعي وكيفية ظهور اسم المؤلف والتعليقات وتاريخ النشر، بالإضافة إلى تخصيص صورة الغلاف. تتوفر العديد من الميزات التي تساعدك على تقديم معلومات إضافية عن كل مدونة ضمن قائمة التخصيص، مثل إضافة اسم المؤلف وإحصائيات التعليقات والمشاهدات والوسوم. ومن خلال الاستفادة من خيارات التخصيص المتقدمة في نظام أودو، يمكنك تحسين عرض صفحات موقعك واستكشافها بسهولة. ولتعديل طريقة عرض المدونة على موقعك الإلكتروني، يمكنك تحديد المدونة المطلوبة من موقع الويب واستخدام قائمة التخصيص. من خلال تمكين ميزة السماح بالتعليقات، يمكنك جمع الردود من القراء. ستمنح هذه الميزة فرصةً للقراء بإرسال تعليقاتهم وفرصةً للشركة لفهم مدى فعالية المدونة من خلال تحليل التعليقات. يساعدك زر زيادة قابلية القراءة "Increase Readability" على تحسين قابلية قراءة المدونة. يساعدك زر "Read Next article" على توفير زر للانتقال إلى المقالة التالية. وهذه استراتيجية رائعة لمساعدة الزوار على اكتشاف مواضيع مدونتك. تحسين المدونة في محركات البحث يقدم نظام أودو ميزات متخصصة لتحسين ظهور المدونة في نتائج بحث جوجل. وللوصول إلى هذه الميزات، انتقل إلى علامة التبويب "الدعاية" في وحدة موقع الويب. ومن القائمة المنسدلة، اختر "تحسين محركات البحث"، تمامًا كما تُظهِر الصورة التالية: ستظهر نافذة جديدة تضم كل الأدوات الأساسية والمعلومات التي يجب إضافتها لتحسين محركات البحث. أضف العنوان ووصف المدونة والكلمات الدلالية التي تساعد المستخدمين على الوصول إلى مدونتك بسهولة، وأضف صورةً للمدونة لمشاركتها على وسائل التواصل الاجتماعي. على الجانب الأيمن من النافذة، تظهر معاينة لطريقة ظهور المدونة ي نتائج البحث. يمكنك مشاركة منشورات المدونة بسهولة على منصات التواصل الاجتماعي المختلفة، بما في ذلك تويتر وفيسبوك وجول بلس، كما يمكنك إدارة المدونات ومنشورات المدونات باستخدام الواجهة الخلفية لنظام اودو، ويمكن تصميمها باستخدام محرر Odoo CMS. وتعتمد عملية التصميم على سحب وإفلات العناصر. خاتمة يقدم أودو نظامًا فريدًا لإنشاء مواقع الويب وتصميمها من الصفر، حيث تسمح لك الكتل الأساسية في أداة إنشاء مواقع الويب بإضافة العديد من الوظائف والميزات إلى موقعك الإلكتروني باستخدام بضع نقرات فقط، وكل ما عليك فعله هو اختيار كتل مناسبة لموقع الويب وفقًا لمتطلباتك وتعديلها باستخدام خيارات "Style". معظم وظائف الويب التي تحتاجها مثبتة مسبقًا في نظام أودو، بحيث يمكنك ببساطة سحب الكتل المطلوبة وإفلاتها وتخصيصها لتصبح جاهزةً للاستخدام في موقعك. اقرأ أيضًا تطبيقات أودو وأهم استخداماتها استخدام وحدة أودو للتسويق عبر البريد الإلكتروني كيفية تصميم موقع إلكتروني باستخدام نظام أودو Odoo إنشاء متجر إلكتروني باستخدام نظام أودو Odoo كيفية إنشاء مسارات الفعاليات في نظام أودو
  14. تُعد مكتبة NumPy إحدى مكتبات لغة بايثون Python وتُستخدم للتعامل مع المصفوفات، وتهدف إلى توفير كائن مصفوفة أسرع بما يصل إلى 50 مرة من قوائم بايثون التقليدية. يطلق على كائن المصفوفة في مكتبة NumPy اسم ndarray، ويوفر العديد من الوظائف الداعمة التي تجعل التعامل مع المصفوفات أمرًا سهلًا جدًا. تعتمد مكتبة NumPy على العمليات على المتجهات vectorization، فإذا كنت معتادًا على التعامل مع لغة بايثون، فهذه هي الصعوبة الرئيسية التي ستواجهها لأنك ستحتاج إلى تغيير طريقة تفكيرك، كما ستتغير نوع العناصر التي ستستخدمها. أكثر العناصر شيوعًا في مكتبة NumPy هي المتجهات vectors والمصفوفات arrays والعروض views والدوال العمومية ufuns. هذا المقال جزء من سلسلة متقدمة حول NumPy وإليك كامل روابط السلسلة: مفاهيم متقدمة حول مكتبة NumPy في بايثون استخدام المتجهات vectorization في لغة بايثون مع مكتبة NumPy الاعتماد على المتجهات في حل المشاكل باستعمال مكتبة NumPy في بايثون تخصيص أسلوب المتجهات Custom vectorization عبر استعمال مكتبة NumPy ما بعد مكتبة NumPy في بايثون مثال بسيط سنأخذ مثالًا بسيطًا وهو المشي العشوائي random walk، إذ يتوجب علينا في الطريقة التقليدية المعتمدة على البرمجة كائنية التوجه OOP تعريف صنف class يأخذ الاسم RandomWalker، ثم إنشاء التابع walk لإرجاع الموقع الحالي بعد كل خطوة عشوائية. يمكن تنفيذ هذا المثال باستخدام التعليمات البرمجية التالية: class RandomWalker: def __init__(self): self.position = 0 def walk(self, n): self.position = 0 for i in range(n): yield self.position self.position += 2*random.randint(0, 1) - 1 walker = RandomWalker() walk = [position for position in walker.walk(1000)] وتعطي تجربة قياس السرعة النتيجة التالية: >>> from tools import timeit >>> walker = RandomWalker() >>> timeit("[position for position in walker.walk(n=10000)]", globals()) 10 loops, best of 3: 15.7 msec per loop النهج الإجرائي Procedural approach يمكننا لحل مثل هذه المشكلة البسيطة حفظ تعريف الصنف والتركيز على دالة المشي walk التي تحسب المواقع المتتالية بعد كل خطوة عشوائية. def random_walk(n): position = 0 walk = [position] for i in range(n): position += 2*random.randint(0, 1)-1 walk.append(position) return walk walk = random_walk(1000) توفر هذه الطريقة من استهلاك وحدة المعالجة المركزية CPU ولكن ليس لحدٍ كبير لأنها تشبه الطريقة السابقة المعتمدة على البرمجة كائنية التوجه. >>> from tools import timeit >>> timeit("random_walk(n=10000)", globals()) 10 loops, best of 3: 15.6 msec per loop النهج المعتمد على المتجهات Vectorized approach يمكننا باستخدام وحدة itertools تحسين الأداء بطريقة أفضل، إذ تقدم هذه الوحدة مجموعةً من الدوال لإنشاء تكرارات لحلقات فعالة. نلاحظ أن مثال المشي العشوائي ما هو إلا تراكم خطوات، لذلك سنعيد كتابة الدالة بإنشاء جميع الخطوات أولًا، ثم تجميعها بدون استخدام أي حلقة، كما توضح التعليمات التالية: def random_walk_faster(n=1000): from itertools import accumulate # Only available from Python 3.6 steps = random.choices([-1,+1], k=n) return [0]+list(accumulate(steps)) walk = random_walk_faster(1000) اعتمدنا في هذا المثال على المتجهات في الدالة، فبدلًا من استخدام التكرار لاختيار الخطوات وإضافتها إلى الموضع الحالي، أنشأنا أولًا جميع الخطوات دفعةً واحدةً، ثم استخدمنا دالة التجميع accumulate لحساب جميع المواضع. تخلصنا من الحلقة وبالتالي أصبح تنفيذ التعليمات أسرع: >>> from tools import timeit >>> timeit("random_walk_faster(n=10000)", globals()) 10 loops, best of 3: 2.21 msec per loop لاحظ أننا وفرنا 85% من وقت الحساب مقارنةً بالإصدار السابق، لكن الإيجابية التي تميز الإصدار الجديد هي تبسيط العمليات المعقدة على المتجهات. سنحتاج إلى استبدال أدوات itertools بأدوات numpy: def random_walk_fastest(n=1000): # No 's' in numpy choice (Python offers choice & choices) steps = np.random.choice([-1,+1], n) return np.cumsum(steps) walk = random_walk_fastest(1000) هذه الطريقة سهلة وتوفر الكثير من الوقت كما توضح النتائج التالية: >>> from tools import timeit >>> timeit("random_walk_fastest(n=10000)", globals()) 1000 loops, best of 3: 14 usec per loop يركز هذا الدليل يركز على الاعتماد على المتجهات سواءٌ كان ذلك على مستوى المشكلة أو الشيفرات البرمجية، وسنوضح أهمية هذا الاختلاف قبل الانتقال إلى دراسة المتجهات المخصصة. سهولة القراءة مقابل السرعة قبل الانتقال إلى القسم التالي، سنلقي نظرةً على مشكلة محتملة قد تواجهها بعد أن تصبح على دراية بمكتبة NumPy؛ فمكتبة NumPy مكتبة قوية جدًا ويمكنك أن تصنع العجائب بها، ولكن هذا على حساب سهولة القراءة، لذلك إذا أهملت إضافة التعليقات أثناء كتابة التعليمات البرمجية، فلن تتمكن من معرفة وظيفة بعض التعليمات بعد بضع أسابيع أو ربما أيام. على سبيل المثال هل يمكنك معرفة ما هي نتيجة تنفيذ الدالتين التاليتين؟ ربما ستتمكن من فهم الدالة الأولى ولكن من غير المرجح أن تفهم الثانية: def function_1(seq, sub): return [i for i in range(len(seq) - len(sub)) if seq[i:i+len(sub)] == sub] def function_2(seq, sub): target = np.dot(sub, sub) candidates = np.where(np.correlate(seq, sub, mode='valid') == target)[0] check = candidates[:, np.newaxis] + np.arange(len(sub)) mask = np.all((np.take(seq, check) == sub), axis=-1) return candidates[mask] استخدمت الدالة الثانية مكتبة NumPy وهي أسرع بعشر مرات، ولكن المشكلة هي بصعوبة قراءة وفهم التعليمات البرمجية التي تستخدمها. تشريح المصفوفة كما أوضحنا سابقًا ينبغي أن تكون لديك خبرةً أساسيةً في التعامل مع مكتبة NumPy قبل المتابعة في هذا الدليل، وإذا لم يكن لديك هذه الخبرة فمن الأفضل أن تتعلم عنها قبل العودة إلى هنا، وبناءً على ذلك سنبدأ هذا الدليل بتذكير سريع على الهيكلية الأساسية للمصفوفات المعقدة، خاصةً بما يتعلق بتخطيط الذاكرة وعرضها ونسخ البيانات وتحديد نوعها، وهذه مفاهيم أساسية يجب أن تفهمها إذا كنت تريد أن تستفيد من فلسفة مكتبة numpy. لنفكر في مثال بسيط نريد من خلاله مسح جميع القيم في مصفوفة من النوع np.float32. كيف يمكن كتابة تعليمات تنفذ المثال السابق بسرعة؟ الصيغة أدناه واضحة إلى حد ما (على الأقل لأولئك الذين هم على دراية بمكتبة NumPy) ولكن السؤال أعلاه يطلب العثور على أسرع عملية. >>> Z = np.ones(4*1000000, np.float32) >>> Z[...] = 0 إذا دققت بنوع عناصر المصفوفة dtype وحجمها، يمكنك ملاحظة أنه يمكن تحويل هذه المصفوفة إلى العديد من أنواع البيانات "المتوافقة" الأخرى. نقصد هنا أنه يمكن تقسيم Z.size * Z.itemsize إلى أنواع عناصر dtype جديدة. >>> timeit("Z.view(np.float16)[...] = 0", globals()) 100 loops, best of 3: 2.72 msec per loop >>> timeit("Z.view(np.int16)[...] = 0", globals()) 100 loops, best of 3: 2.77 msec per loop >>> timeit("Z.view(np.int32)[...] = 0", globals()) 100 loops, best of 3: 1.29 msec per loop >>> timeit("Z.view(np.float32)[...] = 0", globals()) 100 loops, best of 3: 1.33 msec per loop >>> timeit("Z.view(np.int64)[...] = 0", globals()) 100 loops, best of 3: 874 usec per loop >>> timeit("Z.view(np.float64)[...] = 0", globals()) 100 loops, best of 3: 865 usec per loop >>> timeit("Z.view(np.complex128)[...] = 0", globals()) 100 loops, best of 3: 841 usec per loop >>> timeit("Z.view(np.int8)[...] = 0", globals()) 100 loops, best of 3: 630 usec per loop ولكن في الواقع فإن طريقة تصفية جميع القيم ليست هي الأسرع، فقد زاد معدل السرعة بنسبة 25% من خلال تحويل بعض عناصر المصفوفة إلى نوع البيانات np.float64، بينما زاد معدل السرعة بنسبة 50% من خلال عرض المصفوفة واستخدام نوع البيانات np.int8. تتعلق أسباب التسريع بهيكلية عمل مكتبة numpy. تخطيط الذاكرة Memory layout يُعرّف الصنف ndarray وفقًا لتوثيق Numpy كما يلي: المصفوفة هي كتلة مجاورة من الذاكرة يمكن الوصول إلى عناصرها باستخدام مخطط الفهرسة indexing scheme، الذي يحدد شكل ونوع البيانات، وهذا هو المطلوب لتعريف مصفوفة جديدة. Z = np.arange(9).reshape(3,3).astype(np.int16) حجم عناصر المصفوفة Z في التعليمة السابقة هو 2 بايت (int16)، وعدد أبعاد (len(Z.shape هو 2. >>> print(Z.itemsize) 2 >>> print(Z.shape) (3, 3) >>> print(Z.ndim) 2 نظرًا لأن Z ليست طريقة عرض، يمكننا استنتاج خطوات المصفوفة التي تحدد عدد البايتات التي يجب أن تخطوها لاجتياز كل بعد من أبعاد المصفوفة. >>> strides = Z.shape[1]*Z.itemsize, Z.itemsize >>> print(strides) (6, 2) >>> print(Z.strides) (6, 2) لنتمكن من الوصول إلى عنصر معين (مصمم بواسطة فهرس index tuple)، أي كيفية حساب إزاحة البداية والنهاية: offset_start = 0 for i in range(ndim): offset_start += strides[i]*index[i] offset_end = offset_start + Z.itemsize سنستخدم الآن طريقة التحويل tobytes للتأكد من المعلومة السابقة: >>> Z = np.arange(9).reshape(3,3).astype(np.int16) >>> index = 1,1 >>> print(Z[index].tobytes()) b'\x04\x00' >>> offset = 0 >>> for i in range(Z.ndim): ... offset + = Z.strides[i]*index[i] >>> print(Z.tobytes()[offset_start:offset_end] b'\x04\x00' يمكن تمثيل هذه المصفوفة بطرق (تخطيطات) مختلفة: تخطيط العنصر item layout تخطيط العنصر المسطّح Flattened item layout تخطيط الذاكرة Memory layout (C order, big endian)‎ إذا أخذنا الآن شريحة من Z، فإن النتيجة هي عرض المصفوفة الأساسية Z: V = Z[::2,::2] يُحدّد هذا العرض باستخدام نوع dtype وشكل وخطوات، إذ أصبح من غير الممكن استنتاج الخطوات strides من النوع والشكل فقط: تخطيط العنصر item layout تخطيط العنصر المسطّح Flattened item layout تخطيط الذاكرة Memory layout (C order, big endian)‎ العروض والنسخ تُعد العروض Views والنسخ copies مفاهيمًا مهمة لتحسين حساباتك الرقمية. بالرغم من تعاملنا مع هذه المفاهيم في الفقرات السابقة إلا أن الموضوع أكثر تعقيدًا. الوصول المباشر وغير المباشر أولًا علينا التمييز بين نوعي الفهرسة indexing و fancy indexing؛ إذ يعيد النوع الأول عرضًا view دائمًا، بينما يعيد النوع الثاني نسخةً copy. يؤدي تعديل العرض في الحالة الأولى إلى تعديل المصفوفة الأساسية، بينما لن يحدث ذلك في الحالة الثانية: >>> Z = np.zeros(9) >>> Z_view = Z[:3] >>> Z_view[...] = 1 >>> print(Z) [ 1. 1. 1. 0. 0. 0. 0. 0. 0.] >>> Z = np.zeros(9) >>> Z_copy = Z[[0,1,2]] >>> Z_copy[...] = 1 >>> print(Z) [ 0. 0. 0. 0. 0. 0. 0. 0. 0.] إذا كنت تريد استخدام نوع الفهرسة fancy indexing فمن الأفضل الاحتفاظ بنسخة الفهرس fancy index ثم التعامل معه: >>> Z = np.zeros(9) >>> index = [0,1,2] >>> Z[index] = 1 >>> print(Z) [ 1. 1. 1. 0. 0. 0. 0. 0. 0.] إذا لم تكن متأكدًا مما إذا كانت نتيجة الفهرسة هي عرض أو نسخة، فيمكنك التحقق باستخدام الأداة base؛ فإذا كانت النتيجة "None"، فسيكون النوع هو نسخة: >>> Z = np.random.uniform(0,1,(5,5)) >>> Z1 = Z[:3,:] >>> Z2 = Z[[0,1,2], :] >>> print(np.allclose(Z1,Z2)) True >>> print(Z1.base is Z) True >>> print(Z2.base is Z) False >>> print(Z2.base is None) True لاحظ أن بعض وظائف numpy تُعيد عرضًا view، مثل ravel عندما يكون ذلك ممكنًا، بينما يعيد البعض الآخر نسخةً copy، مثل flatten: >>> Z = np.zeros((5,5)) >>> Z.ravel().base is Z True >>> Z[::2,::2].ravel().base is Z False >>> Z.flatten().base is Z False نسخة مؤقتة Temporary copy يمكن إنشاء النسخ بطريقة صريحة كما في الأمثلة السابقة، ولكن الطريقة الأكثر استخدمًا هي الإنشاء الضمني للنسخ الوسيطة. يوضح المثال التالي إجراء العمليات الحسابية باستخدام المصفوفات: >>> X = np.ones(10, dtype=np.int) >>> Y = np.ones(10, dtype=np.int) >>> A = 2*X + 2*Y أنشأنا في هذا المثال ثلاث مصفوفات وسيطة: مصفوفة للاحتفاظ بنتيجة X*‏2 والثانية للاحتفاظ بنتيجة Y*‏2، والأخيرة لإيجاد نتيجة Y*‏2 + X*‏2، وتكون المصفوفات في هذه الحالة صغيرة الحجم ولا تحدث هذه الطريقة أي فرق واضح؛ ولكن في حال كانت المصفوفات كبيرة الحجم فعليك أن تكون حذرًا مع هذه التعبيرات وتفكر بطريقة مختلفة لإيجاد الحل، فعلى سبيل المثال إذا كانت النتيجة النهائية هي فقط المهمة ولم تكن بحاجة إلى X أو Y، فسيكون الحل البديل: >>> X = np.ones(10, dtype=np.int) >>> Y = np.ones(10, dtype=np.int) >>> np.multiply(X, 2, out=X) >>> np.multiply(Y, 2, out=Y) >>> np.add(X, Y, out=X) استغنينا باستخدام هذا الحل البديل عن فكرة إنشاء مصفوفات مؤقتة، لكن المشكلة أن هناك بعض الحالات التي تتطلب إنشاء هذه النسخ المؤقتة وهذا يؤثر على الأداء كما هو موضح في المثال التالي: >>> X = np.ones(1000000000, dtype=np.int) >>> Y = np.ones(1000000000, dtype=np.int) >>> timeit("X = X + 2.0*Y", globals()) 100 loops, best of 3: 3.61 ms per loop >>> timeit("X = X + 2*Y", globals()) 100 loops, best of 3: 3.47 ms per loop >>> timeit("X += 2*Y", globals()) 100 loops, best of 3: 2.79 ms per loop >>> timeit("np.add(X, Y, out=X); np.add(X, Y, out=X)", globals()) 1000 loops, best of 3: 1.57 ms per loop الخلاصة في الختام سندرس المثال التالي: لنفرض لدينا متجهين Z1 و Z2، ونرغب في معرفة ما إذا كان Z2 هو عرض view للمتجه Z1، وإذا كانت الإجابة نعم فما هو هذا العرض view؟ >>> Z1 = np.arange(10) >>> Z2 = Z1[1:-1:2] أولاً سنحدد نوع الفهرسة وهل Z1 هي أساس Z2: >>> print(Z2.base is Z1) True حتى الآن تأكدنا أن Z2 هي عرض view للمتغير Z1، مما يعني أنه يمكن التعبير عن Z2على النحو التالي: [Z1[start:stop:step. وتكمن الصعوبة في التعرف على البداية والتوقف والخطوة؛ إذ يمكننا بالنسبة للخطوة استخدام خاصية strides لأي مصفوفة تعطي عدد البايتات للانتقال من عنصر إلى آخر في كل بُعد. في حالتنا ولأن كلا المصفوفتين أحادي البعد، يمكننا مقارنة الخطوة الأولى فقط. >>> step = Z2.strides[0] // Z1.strides[0] >>> print(step) 2 الصعوبة التالية هي العثور على مؤشرات البداية والتوقف، إذ يمكننا فعل ذلك بالاستفادة من طريقة byte_bounds التي تُرجع مؤشرًا إلى نقاط نهاية المصفوفة. >>> offset_start = np.byte_bounds(Z2)[0] - np.byte_bounds(Z1)[0] >>> print(offset_start) # bytes 8 >>> offset_stop = np.byte_bounds(Z2)[-1] - np.byte_bounds(Z1)[-1] >>> print(offset_stop) # bytes -16 يعد تحويل هذه الإزاحات offset إلى مؤشرات أمرًا سهلاً باستخدام حجم العناصر مع الأخذ بالحسبان أن offset_stop سلبي (حد نهاية Z2 أصغر منطقيًا من حد النهاية لمصفوفة Z1)، لذلك نحتاج إلى إضافة حجم عناصر Z1 للحصول على فهرس النهاية الصحيحة: >>> start = offset_start // Z1.itemsize >>> stop = Z1.size + offset_stop // Z1.itemsize >>> print(start, stop, step) 1, 8, 2 وعند اختبار النتائج نحصل على ما يلي: >>> print(np.allclose(Z1[start:stop:step], Z2)) True يمكنك التمرين من خلال تحسين هذا التنفيذ الأول والبسيط جدًا من خلال مراعاة: خطوات سلبية. مصفوفة متعددة الأبعاد. ترجمة -وبتصرف- للفصلين Introduction و Anatomy of an array من كتاب From Python to Numpy لصاحبه Nicolas P. Rougier. اقرأ أيضًا المرجع الشامل إلى تعلم لغة بايثون أهم 8 مكتبات بلغة البايثون تستخدم في المشاريع الصغيرة
  15. في عالم الصناعة كل منتج له دورة حياة وتاريخ انتهاء صلاحية، ولضمان استمرار دورة حياة المنتج يجب استخدام تطبيق برنامج لإدارة المنتجات قابل للتكيف، بحيث يعاد تدوير المنتجات بعد انتهاء صلاحيتها وتطويرها بمواصفات جديدة ومناسبة للمستهلكين. على سبيل المثال، ترجع العناصر القابلة للتحلل المكونة من المواد الغذائية كأسمدة للأغراض الزراعية. والعناصر غير القابلة للتحلل تعاد إلى الشركة حيث يعاد تدويرها وإنتاجها بجودة مختلفة. من المهم أن تكون عمليات التصنيع في الشركة عمليةً محدّثةً وقادرةً على معالجة أي تغييرات وإضافة التعديلات اللازمة لتحسين جودة المنتجات والتغلب على الأخطاء، كما يجب أن تلتزم الشركات باتباع استراتيجية جرد المنتجات المخزنة في المستودع. وفي حال بقيت بعض المنتجات فترةً طويلةً في المستودع، فيفضل أن يعاد تدويرها أو تصنيعها مع إضافة خصائص مناسبة لها. وهنا تأتي وظيفة تطبيق إدارة دورة حياة المنتج PLM المتوفر في نظام أودو. يساعدك هذا التطبيق على إدارة الإنتاج وتعديل أسعار المنتجات ويسرع إدارة الوقت للحصول على الجودة القياسية والتغلب على المنافسين في السوق. يُعَدّ تطبيق PLM المقدم من نظام أودو أحد أفضل برامج إدارة الأعمال القادرة على إدارة عمليات الشركة بنهج معماري بدءًا من عمليات التصنيع والإنتاج والصيانة والجودة وحتى عمليات البيع. في هذه المقالة سنلقي نظرة على وحدة إدارة دورة حياة المنتج وأهم ميزاتها وكيفية استخدامها لتتبع دورة حياة المنتجات. ميزات وحدة PLM في نظام أودو كل المنتجات لها دورة حياة وتاريخ انتهاء صلاحية، وباستثناء المنتجات الاستهلاكية، يمكن إعادة استخدام هذه المنتجات أو إعادة تدويرها لتغييرها إلى منتج جديد. يجب أن تكون الشركات قادرةً على التكيف لإجراء تغييرات في منهجية الإنتاج لإعادة استخدام المنتجات التالفة أو المخزنة دون زيادة النفقات. ويمكن أن يساعدك استخدام تطبيق أودو لإدارة حياة المنتج على إنجاز العديد من المهام المتعلقة بإعادة تدوير المنتجات وإدارة تصنيعها. يُعَدّ التواصل هو العامل الرئيسي لتتمكن من إدارة التغييرات الهندسية بفعالية، لذا يعمل نظام إدارة دورة حياة المنتج من أودو على تسخير قوة الشبكة الاجتماعية للشركة لمساعدتك على التواصل بفاعلية أكبر عبر أقسام متعددة، حيث يتابع كل شخص ما يحتاجه فقط، وبإمكانك الحصول على الموافقات التي تحتاجها وإدارة التقارير والحصول على البيانات الحقيقية. ويقدم تطبيق PLM العديد من الميزات الإضافية أهمها: إدارة طلبات تصنيع المنتجات. إمكانية إضافة الباركود لكل نوع من أنواع المنتجات أثناء عمليات التصنيع لتسهيل عمليات طلب الصيانة. إدارة مشكلات إصلاح المنتجات المشمولة بالضمان أو في حال حدوث خطأ في التصنيع. وضع خطة لتصنيع المنتجات بعد الحصول على رؤية واضحة ودقيقة وإعادة جدولة تصنيع المنتجات. تتبع مدى توفر المنتجات في المتجر خلال إدارة فاتورة المواد، ومقارنة وقت الإنتاج ووقت انتهاء الصلاحية. تنظيم البيانات الرئيسية بطريقة مرنة ووفقًا لمعايير محددة. إمكانية التعرف على الإصدارات بسهولة من خلال تتبعها وتخصيصها بالإصدارات الجديدة. كيفية استخدام وحدة إدارة حياة المنتج في نظام أودو ستحتاج في البداية إلى تثبيت وحدة إدارة دورة حياة المنتج في نظام أودو. وبعد الانتهاء من التثبيت، ستظهر الوحدة من ضمن وحدات أودو. عند فتح وحدة PLM ستظهر صفحة نظرة عامة على دورة حياة المنتج كما توضح لقطة الشاشة التالية: من خلال نافذة "مقدمة منتج جديد"، تظهر عدد التغييرات الهندسية والتعديلات التي أنشئت في هذه الوحدة. وعند فتح صفحة "التغييرات الهندسية"، ستظهر جميع أوامر التصميم الهندسي التي أنشأت. يمكن عرض تفاصيل هذه الأوامر في عرض كانبان أو عرض القائمة أو التقويم أو العرض المحوري أو العرض الرسومي، كما يمكنك عرض تفاصيل المنتجات واستخدام عوامل الفلترة والتجميع حسب وعرض قائمة المفضلات. لإنشاء أوامر تصميم هندسي جديدة، انقر على زر "إنشاء" الذي يظهر أعلى قائمة تفاصيل المنتجات كما توضح لقطة الشاشة التالية. سينقلك زر "إنشاء" إلى نافذة جديدة لإدخال تفاصيل أمر التصميم كما توضح هذه الصورة: سنوضح فيما يلي كيفية إدخال المعلومات والتفاصيل المطلوبة لإنشاء أمر التصميم الجديد: الوصف "Description": يجب عليك في هذا القسم تقديم وصف موجز حول الهدف من أمر التصميم الجديد. النوع: هنا عليك أن تذكر نوع التغيير الذي تحتاجه. يمكنك الاختيار من القائمة المنسدلة. يطبق على: في هذا الحقل يمكنك اختيار إما قائمة المواد أو منتج فقط، ويطبق أمر التغيير على الخيار الذي تحدده فقط. المنتج: لتحديد المنتج الذي تريد إجراء تغييرات عليه، يمكنك اختيار أحد المنتجات من القائمة المنسدلة. قائمة المواد: هنا عليك أن تذكر قائمة المواد التي تريد تغيرها في المنتج. المسؤول: في هذا القسم تذكر الموظف المسؤول عن تغيير الإجراءات وتنفيذ كافة العمليات المرتبطة بذلك. الفعلي: هنا لديك خيارين (بأقرب وقت ممكن أو التاريخ)، ويسمح لك هذا بتحديد وقت وتاريخ اكتمال إجراء التغيير على المنتج. الوسوم: هنا يمكنك إدخال الوسوم المتعلقة بالتغييرات التي يمكن إضافتها. بعد الانتهاء من ملء جميع التفاصيل في الفراغ ستظهر علامتي تبويب وهما: الملاحظات. الموافقات. ضمن علامة تبويب "ملاحظة"، يمكنك ذكر الملاحظات الإضافية إذا كنت بحاجة إلى تغيير أي شيء إضافي للمنتج. وفي الموافقات يتعين عليك إضافة الدور للحصول على موافقة صاحب العمل. أخيرًا، عند إدخال جميع التفاصيل اضغط على زر "START REVISION". بعد ذلك ستلاحظ ظهور علامات جديدة توضح سير مراحل تنفيذ أمر التصميم الهندسي (قيد التنفيذ، تم الاعتماد، الفعلي). ويمكنك تتبع هذه المراحل حتى تصل إلى المرحلة النهائية. عند النقر على زر "حفظ" ستحفظ المعلومات التي أدخلتها في الوحدة ويمكنك الاطلاع عليها بالنقر فوق علامة التبويب "التغييرات". وفي طريقة عرض كانبان ستظهر تفاصيل أوامر التصميم الهندسي كما تظهر لقطة الشاشة التالية: إعداد وحدة PLM سننتقل الآن إلى علامة التبويب "إعداد" من شريط القائمة لوحدة PLM. وهنا يمكنك ضبط الإعدادات الرئيسية مثل مراحل أوامر التصميم الهندسي وأنواع أوامر التصميم الهندسي ووسومه. مراحل أوامر التصميم الهندسي ECO في هذه الصفحة يمكنك تكوين مراحل التصميم الهندسي للمنتج. وتوجد هنا عدة مراحل مختلفة كما يلي: المرحلة الأولى: هي "جديد" المرحلة الثانية: "قيد التنفيذ" المرحلة الثالثة: تسمى "تم الاعتماد" المرحلة الأخيرة: "الفعلي". عند الوصول إلى المرحلة الأخيرة، فهذا يعني أن المنتج قد عُدّل بالكامل وأجريت كل التغييرات اللازمة. من خلال النقر على زر "إنشاء"، يمكنك إنشاء مرحلة جديدة. وتوضح لقطة الشاشة التالية التفصيل التي يجب عليك إدخالها لإنشاء مرحلة تصميم هندسي جديدة: أنواع أوامر التصميم الهندسي ECO بالانتقال إلى أنواع أوامر التصميم الهندسي من القائمة المنسدلة في علامة التبويب "إعداد"، يمكنك تهيئة وإعداد أنواع جديدة لأوامر التصميم الهندسي وذلك بالنقر على زر "إنشاء". يجب عليك إدخال الحقول المتوفرة ثم النقر على زر حفظ. وسوم أوامر التصميم الهندسي ECO تستخدم وسوم أوامر التصميم الهندسي للتعرف على العناصر بسرعة. ويمكنك الاطلاع على وسوم أوامر التصميم الهندسي من خلال الانتقال إلى علامة التبويب "إعداد"، ثم اختيار "وسوم أوامر التصميم الهندسي". في هذه الصفحة، ستظهر قائمة بالوسوم التي أنشئت في هذه الوحدة. ويمكنك إنشاء وسوم جديدة بالنقر على زر "إنشاء". البيانات الرئيسية ضمن علامة التبويب البيانات الرئيسية يمكنك الاطلاع على قائمة المنتجات وقوائم المواد. ونظرًا لتكامل نظام أودو يمكنك إدارة المنتجات من وحدة إدارة دورة حياة المنتج، كما يمكنك الاطلاع على المواد الخام والمكونات المستخدمة في تصنيع المنتجات وإنشاء أوامر التصنيع والتحكم بدور حياة المنتج. لإنشاء منتج جديد، انقر على زر "إنشاء"، واملأ الحقول الموجودة. وستحفظ هذه المعلومات في قاعدة بيانات نظام أودو أي يمكن الوصول إليها من وحدة التصنيع والجرد ووحدة إدارة حياة المنتج. التقارير بالنقر على علامة التبويب التقارير يمكنك الحصول على نظرة شاملة على أوامر التصميم الهندسي، واستخدام خيارات التخصيص، مثل عوامل التصفية والتجميع حسب والمفضلات لتسهيل فهم البيانات، كما يمكنك تمثيل التقرير في العرض الرسومي أو المحوري. خاتمة تسمح أداة PLM للمستخدم النهائي بجدولة جميع عمليات تطوير المنتج والتحكم فيها، بالتالي فهي تساعد في الحد من مخاطر السوق وتساهم في تعزيز ثقة العملاء. وتُعَدّ إدارة دورة حياة المنتج "PLM" أحد أكثر الجوانب أهميةً في صناعة المنتجات التجارية، كما تُستخدم للتعامل مع جميع الأنشطة الهندسية للشركة، وإدارة مصادر المواد الخام ولها أهمية في إدارة أنشطة المبيعات وأنشطة الخدمة والإصلاح. اقرأ أيضًا كيفية استخدام تطبيقات أودو لإدارة المشاريع تطبيقات أودو وأهم استخداماتها استخدام وحدة أودو للتسويق عبر البريد الإلكتروني إدارة المستودعات والمخازن في نظام أودو إنشاء متجر إلكتروني باستخدام نظام أودو Odoo وحدة المبيعات في نظام أودو Odoo وكيفية استخدامها
×
×
  • أضف...