لوحة المتصدرين
المحتوى الأكثر حصولًا على سمعة جيدة
المحتوى الأعلى تقييمًا في 04/22/21 في كل الموقع
-
الإصدار 1.2.0
21048 تنزيل
انتشر مصطلح العمل الحر في الآونة الأخير انتشار النار في الهشيم، وسبب ذلك جائحة كوفيد-19 التي ضربت العالم فقلبت الموازين، فالآن وبعد إلزام الدول للشعوب بالبقاء في المنازل وفرض قيود على نمط الحياة وحتى أسلوب العمل من أجل الحد من انتشار الوباء، تعرّف أغلب الناس طوعًا أو كرهًا إلى أسلوب العمل المستقل والعمل عن بعد من المنزل، واضطر كثير منهم إلى دخول سوق الإنترنت ليقدموا خدماتهم بشكل مستقل بعد إنهاء عقودهم مع شركاتهم بسبب تقليل الشركات لنفقاتها، وحتى الذي استمروا في عملهم ووظيفتهم اضطروا إلى تبني أسلوب العمل من المنزل إذ رأينا الكثير من الشركات التي أغلقت مقراتها ونقلها إلى أسلوب العمل عن بعد وهنا وجد الموظفون أنفسهم أمام نمط عمل غريب لم يعتادوه من قبل! وبات الكثير يسأل عن كيفية الدخول إلى هذا سوق العمل الحر وكيفية تبني أسلوب العمل من المنزل ويسألنا عن تجاربنا ومن أين يبدؤون وماذا يفعلون، لذا وجب علينا تقديم المساعدة والإجابات الوافية ومدُّ يَد العون لتوفر مرجع شامل يهدي الوافدين إلى ويرشد السالكين على طريق العمل الحر ونمط العمل عن بعد من المنزل، فكان هذا الكتاب! يبدأ الكتاب في أول فصل له بشرح مفهوم ثقافة العمل الحر والعمل عن بعد من المنزل واختلافهما عن العمل التقليدي كما يعرض واقع العالم العربي من العمل المستقل، ثم ينتقل في الفصل الثاني إلى التحدث عن سوق العمل الحر وعرض مجالاته وكيفية الدخول إليه. ينتقل الكتاب بعدها في الفصول التالية إلى شرح المهارات الواجب على كل عامل مستقل أن يمتلكها حتى يصبح عاملًا مميزًا له مكانته المرموقة في السوق ليتهافت أصحاب المشاريع على تسليمه العمل كلما برز اسمه بين العاملين في السوق، فيعرِّج على التسويق الذاتي ثم ينتقل إلى شرح كيفية إدارة المشروع من الناحية الفنية والمالية والتعامل مع العملاء أصحاب المشاريع وكيفية حل أي خلافات قد تطرأ. لم ننسَ أهمية صحة العامل المستقل والعامل عن بعد من منزله، فخصَّصنا فصلين نتحدث في أولهما عن المواضيع المتعلقة بالصحة النفسية والجسدية على حد سواء، بالإضافة إلى عرض أهم التحديات التي قد تواجه العامل من المنزل مثل الإجازات وإدارة الوقت وكيفية التعامل معها. عرجَّنا بعد ذلك في الفصل الذي يليه على الأمور المتعلقة ببيئة العمل، تلك البيئة التي سيمضي العامل البعيد فيها جل وقته، فعرضنا كيفية بناء بيئة العمل المريحة المثلى وتنظيمها وكيفية فصل بيئة العمل عن بيئة المنزل والأهل الملاصقة لها. تحدثنا عن التعهيد الخارجي في فصل كامل وهو مفهوم قد يلزم العامل المستقل لاحقًا لتوسيع عمله أو إنجاز مهام خارج اختصاصه، ثم انتقلنا في الفصل الأخير إلى التحدث عن أهم منصات العمل الحر العربية بمختلف أنواعها وكيفية إنشاء حسابات عليها لتطبيق كل ما تعلمناه سابقًا في الكتاب ودخول السوق من أوسع مداخله. يمكنك قراءة فصول هذا الكتاب مباشرةً على شكل مقالات، الموسومة بوسم «دليل العامل المستقل»، وإليك العناوين: مدخل إلى ثقافة العمل الحر الدخول إلى سوق العمل الحر على الإنترنت كيفية التسويق الذاتي في العمل الحر الإدارة الفنية للمشروع للعامل المستقل فن التعامل مع العملاء في العمل المستقل العناية بالصحة الجسدية والنفسية للعامل المستقل العناية ببيئة عمل العامل المستقل الإدارة المالية في العمل الحر ما يلزم العامل المستقل معرفته عن التعهيد الخارجي تعرف على منصات العمل الحر والعمل عن بعد7 نقاط -
لماذا الjquery لا يعمل في الصفحة ولماذا الصفحة الاُخرى book1.html لا استطيع الدخول اليها من الرابط التشعبي company.zip2 نقاط
-
هل لابد من تعلم لغتي html و css لتعلم لغة javascript1 نقطة
-
1 نقطة
-
لا أعتقد أن هناك إمكانية لحذف عرض قمت بتقديمه على مشروع فبمجرد إضافة عرض لن تستطيع حذفه و سيتم إنقاص عدد العروض المتاحة لك ب 1 و سيتم رفع عدد العروض لك بعد قبول أحد العُروض المقدمة على المشروع او إغلاق ذلك المشروع على ما أعتقد أن مدة إغلاق مشروع ما هي 14 يوم إذا لم يتم قبول أي عرض. بإمكانك أيضاً التعديل على عرض قدمته خلال 15 دقيقة من إضافته، وأيضا إذا قام صاحب المشروع بالتواصل معك عبر الرسائل قبل توظيفك على ذلك المشروع. هناك عدة معلومات أخرى بإمكانك الإطلاع عليها من صفحة: الأسئلة الشائعة1 نقطة
-
انا مبرمج لارافل حديث. قمت بعمل route يدخللي على هذا الرابط news/edit/{id}/ حيث أن {id} هنا هو رقم id لخاص بكل خبر. فقمت بتجربة الid: 1 فقام بجلب لي معلومات الid 1 وهذا امر منطقي. لكن الغريب ان عندما اكتب 1 في خانة id متبعة بحروف غريبة مثل kudhd او hdkd او h او اي حرف وليس رقم فيقوم بجلب لي ايضا معلومات الid 1 فكيف؟ .. الصورة موضحة قصدي. اقصد كيف يتم عمل ignore للاحرف بعد رقم الid ويأخذ الرقم فقط. مع العلم انه عندما اكتب id غير موجود بالداتا بيز بيعمللي redirect زي المكتوب في كود الكنترولر المرفق عادي ف ليه مش بيعمللي redirect لما يلاقي رقم وجمبه حروف غريبة؟1 نقطة
-
بالاضافه إلي ما تفضل بشرحه @Adnane Kadri يمكن إيضا إضافة validation إذا ال id موجود في جدول ال news بإضافة ال exists:news,id لل validation علي ال id $validator = Validator::make($request->all() , ['id' => 'required|integer|exists:news,id']); يوجد if condition لفحص ما إذا ال news موجوده او لا وتعمل redirect بالايرور ولكن ال validation ستقوم بفحص أن ال id, required, integer, exists in news table or not وفي حالة وجود أخطاء ستقوم بعمل redirect من ال fail function كما تفصل اخي بشرحها في هذه الحالة يمكنك الاستغناء عن الشرط في أول دالة ال edit1 نقطة
-
بالفعل هي مثل ما قلت ، وقد تم تصليح الأخطاء الإملائية التي وردت بارك الله فيك و وفقك الله لما يحبه و يرضاه.1 نقطة
-
اشكرك شكراً جزيلا اخي بارك الله فيك وزاد من علمك. اشكرك على توضيح لي الفكرة والحمد لله اجابتك صحيحة 99% فأتمنى منك تعديل هذا الخطأ المطبعي الغير مقصود منك وهو اظن انها where كما قلت انت وليست with ثاني خطأهنا وهو ان هذا الregex هيعمل matching مع 1 وأيضا مع 1f1hfh4 يعني يجب أن يكون الregex كالشكل التالي ^[0-9]+$ انت من علمتني في سئالي السابق مبادئ الregex فشكرا لك اخي1 نقطة
-
يمكنك تخصيص نوع البيانات في البارمتر الممرر في الراوت عن طريق التابع where , الذي يقبل البارمترز على الترتيب : param : معبرة عن اسم البارمتر الذي تقوم بتمريره . regex : تعبر عن Regular Expression تخص المقبول في هذا البارمتر فقط . و يتم تعريف التابع where التابع للinstance الذي اسمه Route في مثالك عن طريق : <? Route::get('news/edit/{id}', 'YourController@your_method')->where('id', '$[0-9]+^'); غير أن هاته الطريقة لن تحقق الغرض و سيتم رمي Exception Not Found 404 في حالة ما كان البارمتر id لا يماثل العبارة [0-9]+ , أي أنه ليس integer . أما في حالة ما أردت عمل Redirect لصفحة تريدها من داخل الController فيمكنك عمل validation بسيط للـ ID الممرر بهذا الشكل : <?php use Illuminate\Support\Facades\Validator; // لا تنسى تضمين الواجهات الللازمة class MyController extends Controller{ public function myMethod(Request $request){ $validator = Validator::make($request->all() , ['id' => 'integer']); if($validator->fails()){ // قم باعادة التوجيه } } }1 نقطة
-
لدي الرابط التالي: http://localhost:5000/download-file عند الدخول إلى الرابط يتم تحميل ملف فيديو، ما أريد فعله هو تحميل الملف من خلال مكتبة Axios في مكون react ولكن بدون إعادة توجيه المستخدم أو فتح صفحة أخرى. أعلم أنه بإمكاني إستخدام العنصر a لتحميل الملف ولكن كما ذكرت أريد أن يتم تحميل الملف من نفس الصفحة.1 نقطة
-
1 نقطة
-
- ( الخلاصة التي استفدتها أن الموضوع من قبل فلاتر يتم ب: responce.StatusCode عندما تكون قيمته تساوي ب 422 )، لكن لم تنجح معي للأسف في فلاتر علما أني أستخدم حزمة Dio ومع العلم أيضا أن VS code يظهر لي أن Status code الذي حصل 422 لكن لم يستطع أن يقرأ الرد مع العمل أيضا أن الرد شغال وقمت بتحربته باستخدام Postman كما يظهر في الصورة المرفقة. - أريد عندما يقوم المستخدم سواء بعملية ( login / register )، وكان رقم الجوال مسجل في قاعدة البيانات، أن يقوم بإظهر رسالة مناسبة له، ملاحظة / ال validation من جهة Laravel جاهز، ويقوم فعلا بإرجاع رسالة أن المستخدم مسجل بالفعل. - فما العمل؟1 نقطة
-
بملف index.js قم بتضمين الجيكويري على نحو صحيح : import '@laylazi/bootstrap-rtl/dist/css/bootstrap-rtl.min.css'; import '@laylazi/bootstrap-rtl/dist/js/bootstrap.min.js'; // import 'jquery/dist/jquery.min.js' عوضا عن هذا import $ from 'jquery'; // هذا import 'popper.js/dist/popper.min.js'; import '../sass/style.scss'; import '@fortawesome/fontawesome-free/js/all'; $(document).ready(function(){ console.log('جي كويري الان تعمل!'); }); أما عن المشكلة الثانية فلم أواجهها و تم الدخول عن طريق الرابط التشعبي بشكل عادي . و مثل ما أشار الأخ @سامح أشرف قد تكون لديك مشكلة في الملفات المؤقتة الخاصة بالمتصفح ،قم بتجربة متصفح آخر أو حذف الملفات المؤقتة.1 نقطة
-
لا يجب أن تستعمل jquery مع jquery.slim لأن الأخيرة هي نسخة مصغرة من jquery ولا تحتوي على كل الدوال، يجب فقط إستعمال jquery فقط. كما أن صفحة book1.html تعمل بشكل سليم بمجرد الدخول إلى الرابط الخاص بها (بالطبع بعد تشغيل المشروع). ربما لديك مشكلة في الملفات المؤقتة الخاصة بمتصفح الويب الخاص بك، لذلك عليك تجربة متصفح آخر أو حذف هذه الملفات المؤقتة.1 نقطة
-
كل الدورات التدريبية المقدمة من أكاديمية حسوب عبارة عن دروس مرئية مقسمة على مسارات و كل مسار يحتوي على عدة فصول و كل فصل به عدة دروس مثلا دورة تطوير التطبيقات باستخدام JavaScript تنقسم إلى هذه المسارات أساسيات لغة JavaScript أساسيات React.js أساسيات Node.js تطوير تطبيق جوال باستخدام React Native تطبيق دردشة يشبه WhatsApp و تكون الدروس عبارة عن مقاطع فيديو يُمكنك مُشاهدتها و التطبيق مع المُدرب و إذا واجهتك مشاكل أثناء تطبيقك للدروس توفر الأكاديمية فريق من المدربين يُساعدك في حل مشاكلك و تقديم الدعم لك طيلة تعلمك في الدورة.1 نقطة
-
يمكنك تجربة استعلام عن الريسبونس if (response.statusCode == 400) { if (apiResponse['message'] != null) { result['message'] = apiResponse['errors']['phone_number']; return result; } return result; } أو if (response.statusCode == 400) { if (apiResponse['message'] != null) { result['message'] = apiResponse['phone_number']; return result; } return result; } في الكود السابق الذي إرفقته في إجابتي الأولى.1 نقطة
-
هل api محلي أم على استضافة , وما هو الرابط؟ سواء استخدمت حزمة dio أو HTTP فالمنطق واحد , يمكنك إرجاع شكل response مثلا هكذا ( أنظر الصورة المرفقة) , يمكنك إنشاء Future من نوع Map واسمه register Future<Map> register(String name, String email, String password) async { final url = Config.url ; Map<String, String> body = { 'name': name, 'email': email, 'password': password, }; Map<String, dynamic> result = { "success": false, "message": 'Unknown error.' }; final response = await http.post( Uri.parse(url), body: body, ); if (response.statusCode == 200 || response.statusCode == 201) { _status = Status.Authenticated; result['success'] = true; result['message'] = 'Successfull Login'; notifyListeners(); return result; } Map apiResponse = json.decode(response.body); if (response.statusCode == 400) { if (apiResponse['message'] != null) { result['message'] = apiResponse['message']; return result; } return result; } return result; } ثم في واجهة التسجيل Future<void> submit() async { final form = _formKey.currentState; if (form.validate()) { response = await Provider.of<AuthProvider>(context, listen: false) .register(name, email, password); print(response); if (response['success'] == true) { //print(response['email']); await Provider.of<AuthProvider>(context, listen: false).login( email, password, ); Navigator.pushNamed(context, '/home'); } else { setState(() { message = response['message']; }); } } } أو يمكنك إرجاع alertDialog _showError() { showDialog( context: context, builder: (_) => new AlertDialog( title: new Text("ERROR"), content: new Text("ERROR"), actions: <Widget>[ TextButton( style: ButtonStyle( foregroundColor: MaterialStateProperty.all<Color>(Colors.blue), backgroundColor: MaterialStateProperty.all<Color>(Colors.blue), ), child: Text("Colse"), onPressed: () { Navigator.of(context).pop(); }, ), /*TextGradientButton( child: Text( S.of(context).close, style: TextStyle(color: Colors.white), ), gradient: LinearGradient( colors: <Color>[Colors.orange, Colors.red], ), onPressed: () { Navigator.of(context).pop(); }, ),*/ ], )); return Container(); } ويمكنك تغيير setState(() { message = response['message']; }); إلى _showError(); هذه مجرد فكرة للتوضيح, أو يمكنك تزويدي بملفات لارافل و مشروع flutter ويمكنني الإطلاع عليه.1 نقطة
-
لو لاحظت هنا Locale(value.locale), يمكنك جلب القيمة المخزنة في local storeage, ايضا لاحظ في Provider عند قمنا بتغيير اللغة قمنا بحفظها في Shared ثم تخزينها في local Storage _getLanguage() async { await _initialPreferences(); _locale = _preferences.getString('language') ?? 'en'; notifyListeners(); } وقمنا بوضع getter String _locale = 'en'; String get locale => _locale لو راجعت الكود جيدا, لكان سهل عليم الأمر كثير.1 نقطة
-
مرحبا محمد نعم فهي لغة من الأساس تستخدم في متصفحات الويب التي يتم انشاءها باستخدام html و css وذلك سبب كافي لتعلمهما, يتم استخدام جافاسكربت لإنشاء صفحات ويب أكثر تفاعلية مثل تحريك بعض العناصر واخفاء بعضها او اظهارها, ولفعل مثل تلك الأمور يجب أن تتعامل بشكل مباشر مع عناصر Html وأحيانا نريد أن نعطي عنصر html ما بعض تنسيقات css باستخدام جافاسكربت وهذا أيضا سبب آخر لتعملها, بالإضافة الى أنه من السهل تعلم html و css ولن تستغرق الكثير من الوقت لاتقانهما شكرا لك1 نقطة
-
طبعا العملية ستصبح سهلة مع التعود على مواجهة الأخطاء و حلها , لكن هذا لا يمنع من جعلها منهجية و منظمة لغرض إختصار الوقت و تنظيم العمل أكثر فحل مشكلة ما ,برأيي, يتطلب : مشكلة ! فبالطبع يجب أن تكون لديك مشكلة و من الواجب قراءتها و التأني في ذلك . إعادة إنتاج المشكلة و عزل كود مصدر المشكلة : أحب عادة حذف الأسطر التي تكون مسؤولة عن المشكلة , فإختفاء الخطأ يعني ثبوتها . ثم أقوم بإعادة انتاج المشكلة من جديد . هذا يجعلك تقوم بعزل كود المصدر المسؤول و وضع نظرتك على نطاق أضيق و أدق , فالتركيز في ثلاث أسطر أو أربع أفضل من التركيز في مشروع كامل أو ملف كامل. قم بوصف المشكلة : كأن تحاول الحصول على أكبر عدد من المعلومات عن هاته المشكلة . (مثال عن ذلك : الزر يشتغل و يستدعي دالة بالفعل لكن الـ console يقول أن هاته الدالة غير معرفة , و أرى أني قد عرفتها بالفعل في ملف index.js) بناءا على ذلك حاول الإجتهاد في حل المشكلة مما جمعت من وصف للمشكلة و تحديد لكود المصدر المسؤول , و لا بأس ببحث على الانترنت عن مشاكل إما مشابهة في الخطأ الظاهر أو في الوصف و الطرح أو السياق أو كود مصدر المشكلة . و ستصبح العملية سهلة و أبسط مع مرور الوقت و التعود على الأخطاء و على حلها . و قد يقودك إنتقال المشاكل من بسيطة , إلى معقدة إلى معقدة جدا , إلى تعلم الخوارزميات و الproblem solving التي ستنقل الأمر إلى مستوى اخر من التنظيم و المنهجية.1 نقطة
-
و عليكم السلام و رحمة الله . بالنسبة لسؤالك الأول : لا يزال عليك عمل التفاعلية المطلوبة بنفسك , بملف index.js قم بإضافة الأسطر التالية : $('.collapse') .on('show.bs.collapse', function () { $(this).prev().find('svg') .removeClass('fa-angle-down') .addClass('fa-angle-up') }) .on('hide.bs.collapse', function () { $(this).prev().find('svg') .removeClass('fa-angle-up') .addClass('fa-angle-down') }); . و بالطبع يجب عليك تعريف الحالة الإفتراضية للأسهم , إما فوق أو تحت : <i class="fa fa-angle-down" aria-hidden="true"></i> 2. السؤال الثاني : لم يعمل الفيديو بسبب أنك تقوم بتعريف الدالة بعد نسبها للـ Event Listener على هذا النحو : var myvideo=document.getElementById("video1"); myvideo.addEventListener("click", function playPause() { if(myvideo.paused) myvideo.play(); else myvideo.pause(); }, false); و : <section class="video"> <video id="video1"> <source src="./videos/video.mp4" type="video/mp4"> </video> <div class="overlay "> <button onclick="playPause()"> <i class="fa fa-video-camera" aria-hidden="true"></i> مشاهدة الفيديو </button> </div> </section> في حين أنك تستدعي دالة غير معرفة أصلا وإسم هاته الدالة داخل تعريف الـ Event Listener متجاهل أصلا . فحل المشكلة إما بتعريف الدالة خارجا على هذا النحو : myvideo.addEventListener("click", function(){ playPause(); } , false); function playPause() { if(myvideo.paused) myvideo.play(); else myvideo.pause(); } أو بربط الEvent Listener بالزر عوضا عن الفيديو نفسه فيكون : var myvideo=document.getElementById("video1"); var playVideoButton=document.getElementById("playVideoButton"); playVideoButton.addEventListener("click", function playPause() { if(myvideo.paused) myvideo.play(); else myvideo.pause(); }, false); و طبعا لا تنسى تعريف الزر بـ ID: <section class="video"> <video id="video1"> <source src="./videos/video.mp4" type="video/mp4"> </video> <div class="overlay "> <button id="playVideoButton"> <i class="fa fa-video-camera" aria-hidden="true"></i> مشاهدة الفيديو </button> </div> </section> و أفضل إستعمال الطريقة الثانية لأن العنصر بالايدي video غير ظاهر و لاحظ أن الoverlay فوقه فهو غير قابل للوصول أما عن الزر فهو غير ذلك . أما عن تنسيق زر تشغيل الفيديو فيمكنك إستبدال الأيقونة بغيرها : <div class="overlay "> <button id="playVideoButton"> <i class="fa fa-play" aria-hidden="true"></i> مشاهدة الفيديو </button> </div> و بالطبع لا تنسى أن تقوم بإعادة compile للملفات عن طريق : npm run build ملاحظات : لا أعلم إن كنت قد واجهت نفس الأخطاء بالنسبة للwebpack على هذا النحو : > product@1.0.0 build > webpack serve --mode development sh: 1: webpack: Permission denied بحيث تم حلها عن طريق تغيير الوضع : chmod 775 -R /product و لا ألزمك طبعا و لكن من اﻷفضل , و كشيء من الشائع بين الأوساط , تعريف السكربت watch عوضا عن build بملف package.json , كما يجب أيضا عمل سكربت للproduction : "scripts": { "watch": "webpack serve --mode development", "prod" : "webpack serve --mode production" }, فيتم الإستدعاء كالتالي : npm run watch npm run prod1 نقطة
-
أولا يجب تنزيل الحزم التالية من pub.dev intl: ^0.17.0 shared_preferences: ^0.5.12+4 provider: ^4.3.2+3 localstorage: ^3.0.6+9 intl_translation: git: url: https://github.com/nt4f04uNd/intl_translation ثم تنشأ واجهة لعرض اللغات مثل import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:provider/provider.dart'; import '../../common/constants.dart'; import '../../generated/l10n.dart'; import '../../models/init_model.dart'; class Languages extends StatefulWidget { @override _LanguagesState createState() => _LanguagesState(); } class _LanguagesState extends State<Languages> { @override Widget build(BuildContext context) { List<Widget> list = []; List<Map<String, dynamic>> languages = getAlllanguages(context); for (var i = 0; i < languages.length; i++) { list.add( Card( elevation: 0, margin: EdgeInsets.all(2), child: ListTile( leading: SvgPicture.asset( 'assets/flags/${languages[i]["image"]}.svg', fit: BoxFit.cover, width: 30, height: 20, ), title: Text(languages[i]["name"]), onTap: () async { print(languages[i]["code"]); await Provider.of<InitModel>(context, listen: false) .changeLanuguage(context, languages[i]["code"]); setState(() {}); }, ), ), ); } /*return Consumer<AuthProvider>(builder: (context, user, child) { });*/ return Scaffold( appBar: AppBar( elevation: 0, title: Text( S.of(context).language, ), backgroundColor: Theme.of(context).primaryColor, ), body: SingleChildScrollView( child: Column( children: [ ...list, ], ), ), ); } } ثم تنشأ قائمة اللغات و ممكن تخزنها في ملف اسمه constants.dart و تكون القائمة بهذا الشكل Function getAlllanguages = ([context]) { return [ { "id": 1, "name": "English", "image": "en", "code": "en", }, { "id": 2, "name": "Arabic", "image": "ar", "code": "ar", }, { "id": 2, "name": "Iran", "image": "ir", "code": "fa", } ]; }; ثم يمكنك إنشاء Provider ليتم تغيير اللغة بدون إيقافه و تشغيله مرة أخرى class InitModel with ChangeNotifier { Map<String, dynamic> appConfig; bool isLoading = true; String message; String _locale = 'en'; String get locale => _locale; final String key = "theme"; SharedPreferences _preferences; bool _darkMode = false; bool get darkMode => _darkMode; InitModel() { _darkMode = false; _locale = 'en'; _loadFromPreferences(); _getLanguage(); } _initialPreferences() async { if (_preferences == null) _preferences = await SharedPreferences.getInstance(); } _savePreferences() async { await _initialPreferences(); _preferences.setBool(key, _darkMode); } _loadFromPreferences() async { await _initialPreferences(); _darkMode = _preferences.getBool(key) ?? false; notifyListeners(); } toggleChangeTheme() { _darkMode = !_darkMode; _savePreferences(); notifyListeners(); } _getLanguage() async { await _initialPreferences(); _locale = _preferences.getString('language') ?? 'en'; notifyListeners(); } Future<void> changeLanuguage(BuildContext context, String countryCode) async { await _initialPreferences(); _locale = countryCode; _preferences.setString("language", _locale); /*try { SharedPreferences preferences = await SharedPreferences.getInstance(); //_locale = countryCode; await preferences.setString('language', countryCode); final LocalStorage storage = new LocalStorage('locale'); storage.setItem('locale', countryCode); _locale = preferences.getString('language'); _savePreferences(); return true; } catch (err) { return false; }*/ notifyListeners(); } void loadAppConfig() async { try { if (kAppConfig.indexOf('http') != -1) { final appJson = await http.get(Uri.encodeFull(kAppConfig), headers: {"Accept": "application/json"}); appConfig = convert.jsonDecode(appJson.body); } else { final appJson = await rootBundle.loadString(kAppConfig); appConfig = convert.jsonDecode(appJson); } isLoading = false; notifyListeners(); } catch (e) { isLoading = false; message = e.toString(); notifyListeners(); } } } class App { Map<String, dynamic> appConfig; App(this.appConfig); } ثم إضافة الكود التالي localizationsDelegates: [ RefreshLocalizations.delegate, S.delegate, GlobalWidgetsLocalizations.delegate, GlobalMaterialLocalizations.delegate, GlobalCupertinoLocalizations.delegate, DefaultCupertinoLocalizations.delegate, ], supportedLocales: S.delegate.supportedLocales, //locale: Locale('fa'), locale: Locale(value.locale), localeResolutionCallback: (Locale locale, Iterable<Locale> supportedLocales) { return locale; }, في MaterialApp, ثم تعريف final LocalStorage storage = new LocalStorage('locale'); في نفس الكلاس الذي يحتوي MaterialApp. في البداية قد تواجهك صعوبات في تنفيذ هذا الكود لأنه متقدم جداً, وربما تواجهك بعض الأخطاء ولكن يمكننا بعد قيامك خطوة بخطوة من تنفيذ الأكواد من فعل ما تريد. ملاحظة : جميع الأكواد مجربة ومستخدمة قبل ذلك.1 نقطة
-
كشيء جميل في اللارافل فإنه تم تم بناءه مع وضع الاختبارات في الاعتبار على عكس أطر عمل أخرى (مثال : الcodegniter) , فقد تم تضمين دعم الاختبارات باستخدام الphp Unit و يأتي كل Fresh Laravel Application مع ملف اعداد phpunit.xml و مجلد tests . بحيث يحتوي المجلد tests افتراضيًّا على مجلّدين : Feature (تعبر عن مجموعة اختبارات كل منها هو اختبار جزء من الشيفرة) و Unit (تعبر عن مجموعة اختبارات الوحدة). يتم تشغيل الاختبارات التي قمت بإنشاءها عن طريق طباعة الأمر في التارمنل : phpunit أو : vendor/bin/phpunit أي أن الاختبارات التي يتم عملها ببيئة عمل الphpunit في اللارافل هي أحد الخيارين : اختبار وحدة unit test : و يقصد بها اختبارات مكتوبة من منظور المبرمجين. وهي مصممة للتأكد من أن طريقة معينة (أو وحدة) للclass تؤدي مجموعة من المهام المحددة. اختبار ميزة feature test: و يقصد بها اختبار جزء أكبر من التعليمات البرمجية الخاصة بك ، بما في ذلك كيفية تفاعل العديد من الكائنات مع بعضها البعض أو حتى طلب HTTP إلى نقطة نهاية من الاي بي اي الخاص بك . أما عن الأشياء التي تحتاج إختبارها فلارافل توفر أغلب ذلك , خصوصا و قد تم تحسينها في النسخ الأخيرة . فكما ذكر @Sam Ahwيمكنك إختبار كل جانب من التطبيق : جانب الHTTP : بحيث يوفر اللارافل مجموعة من الmethods لمحاكاة طلب الى الخادم و التحقق من تفاصيله . مثال : <?php class TasksTest extends TestCase { /**@test */ // هكذا يتم تعريف الاختبار public function a_task_can_be_retrieved() { $response = $this->json('GET', '/api/v1/task/12'); // محاكاة الطلب $response->assertStatus(200); // التحقق من ان كود الحالة هو كما متوقع } /** * يمكن تعريفه هكذا ايضا * */ public function test_a_task_can_be_updated() { $response = $this->json('PATCH', '/api/v1/task/12' ,$some_data); // محاكاة الطلب $response->assertStatus(200); // التأكد من كود الحالة } /**@test */ public function a_task_name_is_required() { $response = $this->json('POST', '/api/v1/task' ,$some_data_that_has_not_a_name); // محاكاة الطلب $response->assertStatus(422); // التأكد من كود الحالة } } اختبارات المتصفح . Browser Tests أو كما هو شائع : Laravel Dusk . بحيث يمكنك إختبار كل ما يخص الواجهات . (التفاعل مع الواجهة , ضغط أزرار , نقر على روابط , التعامل مع القوائم المنسدلة , إرفاق الملفات عن طريق مدخلات الملفات .. و غيرها ) غير أن هاته الإختبارات تحتاج تسطيب حزمة laravel/dusk . و ستتلقى عنك عناء اختبار التطبيق بنفسك . مثال من ويكي حسوب : <?php namespace Tests\Browser; use App\User; use Tests\DuskTestCase; use Laravel\Dusk\Chrome; use Illuminate\Foundation\Testing\DatabaseMigrations; class ExampleTest extends DuskTestCase { use DatabaseMigrations; /** * مثال عن اختبار متصفح بسيط. * * @return void */ public function testBasicExample() { $user = factory(User::class)->create([ 'email' => 'taylor@laravel.com', ]); $this->browse(function ($browser) use ($user) { $browser->visit('/login') ->type('email', $user->email) ->type('password', 'secret') ->press('Login') ->assertPathIs('/home'); }); } } 3 . اختبارات قواعد البيانات : عن طريق الmodel factories و الdatabase seeders يمكنك ملئ قواعد البيانات الخاصة بك ببيانات مزيفة عن طريق مكتبة faker و من ثم اختبارها عن طريق مجموعة من التوكيدات . 4 . اختبارات تزييف الأحداث أو الـ Mocking : ويقصد بالأحداث أشياء مثل أحداث إرسال الايميلات App\Mails أو الأحداث داخل App\Events أو الإشعارات داخل App\Notifications أو تزييف الJobs داخل App\Jobs بل و حتى تزييف التخزين و التوكيد على عمله بشكل صحيح . فلارافل يمكنك من محاكاة ذلك و التوكيد على عمله دون عمله فعليا . إنشاء الاختبارات : يكون عن طريق الterminal : php artisan make:test UserTest 2. و من ثم التعديل على ملف الtest المنشئ بإضافة اختبارات بشكل methods معرفة بشكل صحيح (كما تم ذكر ذلك) . <?php class UserTest extends TestCase { /**@test*/ public function a_user_can_be_banned() { } } 3 . و من ثم محاكاة العملية التي تنوي إجراء الإختبار عليها : <?php class UserTest extends TestCase { /**@test*/ public function a_user_can_be_banned() { $response = $this->json('PATCH', '/users/34', ['is_banned' => true]); // } } 4 . و أخيرا استعمال التوكيد الصحيح : <?php class UserTest extends TestCase { /**@test*/ public function a_user_can_be_banned() { $response = $this->json('PATCH', '/users/34', ['is_banned' => true]); $response->assertStatus(200)->assertExactJson(['is_banned' => true,]); } } .. التوغل في كتابة الإختبارات و إختبار كل صغيرة و كبيرة بجوانب موقعك سيأخذ بك و تطبيقاتك إلى مستوى اخر من التطوير و يجعلك تمارس أحد مبادئ التطوير المتقدمة و هو الTDD أو الـ Test Driven Development و لن تضطر للعمل بطرق الإختبار التقليدية و ستكتفي بطباعة أمر واحد في التارمينل لإختبار تطبيقك ككل , في مرة واحدة.1 نقطة
-
بنية الشبكات العصبية الصنعية تتكون الشبكات العصبية الصنعية من عناصر أولية بسيطة من حيث طريقتها في معالجة البيانات تدعى العصبونات، ويمكن تمثيل أي من تلك العصبونات رياضيا -وفق مفاهيم البرمجة غرضية التوجه- على شكل كائن برمجي Object يتضمن كل نسخة (Instance) منه على مصفوفة من أوزان الدخل يساوي حجمها عدد إشارات الدخل الواردة لهذا العصبون والتي قد تتراوح ما بين العشرات والآلاف تبعا لبنية الشبكة العصبية وهيكليتها. إن معالجة العصبون الواحد للإشارات الواردة بسيطة من الناحية الرياضية، حيث يتم ضرب كل إشارة دخل بقيمة الوزن المقابل لها ومن ثم تجمع كافة النواتج لنحصل على مقدار كلي يمثل درجة استثارة العصبون أو شحنته الإجمالية، ومن ثم يرسل هذا الرقم إلى تابع التفعيل، وهو ببساطة علاقة رياضية تحاكي إلى حد ما سلوك العصبونات الحقيقية فيما يخص قانون الكل أو لاشيء مع بعض التصرف لاعتبارات تتعلق بخوارزميات التعليم المستخدمة (إمكانية حساب المشتق الرياضي كما في حالة تابع Sigmoid) أو لاعتبارات براغماتية عملية (سهولة البرمجة وسرعة التنفيذ كما في حالة التابع ReLU) أو حتى لاعتبارات تتعلق بطبيعة البيانات المعالجة (كشيوع استخدام التابع TanH عند التعامل مع بيانات الفئات والأصناف). في نهاية المطاف تستخدم قيمة الاستثارة الإجمالية للعصبون كدخل لتابع التفعيل x هذا، وبتطبيق العلاقة الرياضية الخاصة بتابع التفعيل المحدد للعصبون نحسب قيمة y المقابلة والتي تمثل الآن خرج هذا العصبون. تتألف الشبكات العصبية من بضع عشرات أو مئات أو حتى الآلاف من تلك الوحدات البنائية الأساسية والتي تنتظم في معمارية على شكل طبقات، حيث يحدد لكل طبقة عدد العصبونات التي تتضمنها، ونوع تابع التفعيل المستخدم لعصبونات تلك الطبقة (أي أن تابع التفعيل قد يختلف من طبقة إلى أخرى لكنه عادة ما يكون ذاته لجميع عصبونات الطبقة الواحدة)، وطريقة ارتباطها بالطبقة التي تسبقها والتي تليها (هل هو ربط كامل كأن تصل إشارة دخل واردة من كل عصبون موجود في الطبقة السابقة، أم هو جزئي يأخذ دخله من عصبونات الطبقة السابقة المجاورة لموضعه الحيزي كما هو حال الشبكات العصبية الصنعية التي تحاكي الباحات البصرية في الدماغ بغية التعرف على الأنماط في الصور). الفرق ما بين تدريب واستخدام الشبكات العصبية الصنعية إن تدريب الشبكات العصبية الصنعية يقصد به إيجاد القيم الأنسب لكافة أوزان الدخل لعصبونات الشبكة بحيث تكون قادرة على إعطاء الإجابات الصحيحة بأقل هامش خطأ في مخرجاتها وذلك للمدخلات المعروضة عليها، في حين يقع على عاتق المطور فن تحديد المعمارية الملائمة من حيث عدد الطبقات ونوع تابع تفعيل كل منها وعدد عصبوناته وطريقة ربطها مع بعضها البعض. قد تكون مهمة تدريب الشبكات العصبية الصنعية تحديا حسابيا هائلا تتطلب كما كبيرا من المعالجات الرياضية والتي قد تستغرق زمنا طويلا حتى لو أجريت على حواسيب فائقة، لكن بمجرد الوصول إلى الحل وإيجاد قيم الأوزان الملائمة التي تعطي نتائج مرضية عند معالجتها للبيانات، تصبح مسألة الاستخدام والتطبيق في منتهى البساطة، فكل ما عليك القيام به هو تمرير وحيد عبر طبقات الشبكة يتم خلاله إجراء بضع عمليات ضرب وجمع ومن ثم تطبيق تابع رياضي ما (تابع التفعيل)، وهكذا تمرر القيم من طبقة إلى أخرى وصولا إلى طبقة الخرج النهائية لتظهر من خلالها الإجابة. كيفية حفظ وتصدير الشبكات العصبية الصنعية بعد إتمام عملية تدريب الشبكة العصبية الصنعية والرضى عن نتائجها، كل ما نحتاج إليه هو حفظ بنيتها من حيث عدد الطبقات، وعدد العصبونات في كل طبقة، وطريقة ارتباط عصبونات الطبقات المختلفة بعضها ببعض، وكذلك تابع التفعيل المستخدم في كل طبقة، إضافة إلى قيم الأوزان لكل عصبون على حدة. هذا كل مافي الأمر! فإن حصلت على هذه الأرقام مجددا فأنت قادر على إعادة بناء واستخدام تلك الشبكة العصبية الصنعية بشكلها النهائي بعد أن اكتملت عملية تدريبها. عادة ما تقوم مكتبة TensorFlow بحفظ نموذج الشبكة العصبية الصنعية بكافة وسطائها وقيمها ضمن مجلد خاص بذلك خلال عملية التدريب والذي يمكن قراءته واستعادة بنية شبكته العصبية باستخدام لغة Python (ستجد ضمنه ملف بامتداد *.pb إضافة إلى مجلدين فرعيين هما variables وassets)، لكن هذه الصيغة من الحفظ ملائمة فقط لبيئة التطوير ولا تصلح للتطبيق العملي. عوضا عن ذلك أتاحت Google مجموعة من الصيغ المعيارية المناسبة للتطبيقات المختلفة من أهمها صيغة *.tfjs الموجهة للمبرمجين بلغة JavaScript ذائعة الصيت وواسعة الانتشار في عالم الويب سواء باستخدامها على طرف المستعرض أو حتى على طرف المخدم من خلال تقنية Node.js، كذلك لدينا صيغة *.tflite والمصممة أصلا لتعمل بموارد محدودة من سرعة معالجة ومساحة ذاكرة وذلك بهدف استخدامها على أجهزة الجوال أو إنترنت الأشياء. لا يقتصر الأمر على ذلك فحسب، لكن حزم الشبكات العصبية الصنعية وإعدادها للاستخدام العملي قد يتضمن بعضا من المقايضة بهدف تصغير حجمها وزيادة سرعة عملها ولو كان ذلك على حساب انخفاض طفيف ومقبول في دقة نتائجها، إحدى تلك الخوارزميات على سبيل المثال تقوم بإزالة الروابط التي تقترب قيم أوزانها من الصفر باعتبارها لا تساهم بشكل كبير في مقدار الاستثارة الكلية للعصبون المرتبطة به، في المقابل نكون قد خفضنا عدد الأوزان التي نحن بحاجة إلى حفظها وكذلك قللنا الزمن الكلي اللازم للحساب كون عدد المدخلات أصبح أقل. مكتبة Face-API كما هو واضح من المقدمة السابقة، فنحن لن نقوم هنا ببناء وتدريب شبكة عصبية صنعية من الصفر، لكننا في المقابل سوف نستعرض كيفية استخدام شبكة عصبية صنعية سبق وأن تم تدريبها وذلك ضمن تطبيقنا الخاص. لهذه الغاية أود تعريفكم بمكتبة face-api.js والتي تم بناؤها لأغراض التعرف على الوجوه وتمييزها ضمن بيئة المتصفح إنطلاقا من مكتبة TensorFlow.js، وهي بذلك تقدم مجموعة من نماذج الشبكات العصبية الصنعية المدربة والجاهزة لطيف متنوع من التطبيقات يمكنك الإطلاع عليها من خلال النقر على الرابط التالي لصفحة التوثيق الخاص بهذه المكتبة: https://justadudewhohacks.github.io/face-api.js/docs/ إن المثال الذي سوف نبنيه فيما يلي سيقوم باستخدام كاميرا حاسوبك أو جوالك من خلال صفحة ويب ستقوم ببرمجتها بنفسك لكي يأخذ صورة المستخدم ويقدّر منها عمره وجنسه. تخيل لو أننا نتحدث عن صفحة تسجيل مستخدم جديد في تطبيقك المستقبلي، سيكون من اللطيف والذكي في آن معا لو استطاع التطبيق تحديد القيم الافتراضية للعمر والجنس بناء على صورة المستخدم بحيث تكون قريبة إلى الواقع بطريقة تحسن من تجربة المستخدم. تم بناء نموذج التعرف على العمر والجنس باستخدام شبكة عصبية صنعية متعددة المهام توظف فيها طبقة استخلاص سمات الوجه لتقدير العمر وكذلك لتصنيف الجنس، يبلغ حجم حزمة النموذج بالإجمال قرابة 420kb، وقد تم تدريبها واختبارها باستخدام قواعد بيانات متعددة لصور الوجوه الموسومة بالعمر والجنس الحقيقيين (منها على سبيل المثال موسوعة Wikipedia وقاعدة IMDB للأفلام والممثلين)، وتبلغ دقتها 95% في تحديد الجنس، وهامش خطئها في تحديد العمر يقارب 4 سنوات ونصف. استخدام الشبكات العصبية في نافذة متصفحك لنقم بداية بإنشاء مجلد جديد وليكن اسمه face-api للمشروع الذي سنعمل عليه اليوم ضمن مخدم الويب المحلي الذي لديك لتجربة تطبيقات الويب التي تعمل عليها (أي ضمن المجلد C:\xampp\htdocs على سبيل المثال في حال كنت تستخدم مخدم XAMPP)، سنضيف داخل ذلك المجلد الرئيسي مجلدين فرعيين باسم js وكذلك models، ومن ثم نقوم بنسخ الملفات التي نحتاجها من مكتبة Face-API الأصلية على الشكل التالي: نُنزِّل الصيغة المصغرة/المضغوطة من المكتبة ذاتها (أي الملف "face-api.min.js") ونسخها إلى داخل المجلد الفرعي js في مشروعنا، يمكن الحصول على ذلك الملف من العنوان التالي: https://github.com/justadudewhohacks/face-api.js/tree/master/dist نُنَزِّل نماذج الشبكات العصبية الصنعية التي سنستخدمها، حيث يوجد ملفين لكل نموذج شبكة عصبية أحدهما ينتهي إسمه بكلمة "shard1" تحفظ فيه قيم أوزان الشبكة، أما الآخر فهو ملف بصيغة json يصف بنية الشبكة حتى يتم قراءة وتحميل قيم الأوزان السابقة بشكل سليم. في مثالنا الحالي سنحتاج إلى استخدام شبكتين عصبيتين هما "age_gender_model" و "tiny_face_detector_model"، أي أننا بحاجة إلى تنزيل أربع ملفات ومن ثم نسخها إلى داخل مجلد models في مشروعنا. يمكنك الحصول على تلك الملفات من العنوان التالي: https://github.com/justadudewhohacks/face-api.js/tree/master/weights بعد ذلك سنُنشِئ ملفين جديدين أحدهما سندعوه index.html سنضعه في المجلد الرئيسي للمشروع، أما الآخر فسندعوه main.js ونضعه ضمن المجلد الفرعي js المخصص لشيفرات لغة JavaScript البرمجية. سنقوم بداية بتنقيح محتوى صفحة HTML والتي سنجعلها بأبسط شكل ممكن بغرض التركيز على العناصر الأساسية التي نهتم بها: <html> <head> <title>Face-API Example</title> </head> <body> </body> </html> ضمن قسم body سنقوم بإضافة عنصر div فيه عنصر video لعرض الفيديو الذي تلتقطه كاميرا حاسوبك ندعوه webcam، ويتم ضبطها لتعمل تلقائيا ضمن النمط الصامت بمجرد تحميل الصفحة: <div class="container"> <video id="webcam" height="360" width="360" autoplay muted></video> </div> ثم نضيف حقل إدخال input مخصص للعمر ندعوه age: Age (years): <input id="age" size="3"><br /> بعد ذلك نضيف مجموعة أزرار اختيار من نوع radio ندعوها gender فيها اختيارين اثنين هما male وfemale: <input id="male" type="radio" name="gender" value="male">Male<br /> <input id="female" type="radio" name="gender" value="female">Female<br /> أخيرا وبعد اكتمال تحميل وعرض كافة عناصر الصفحة، نقوم بتضمين ملفات جافاسكريبت في نهاية محتويات الصفحة حتى نكون متأكدين من وصولها برمجيا لكافة العناصر ضمن تلك الصفحة: <script src="js/face-api.min.js"></script> <script src="js/main.js"></script> ملاحظة هامة: بسبب إعدادات الأمان فإن معظم متصفحات الويب تعرض رسالة للمستخدم تبيّن رغبة الصفحة في الوصول إلى الكاميرا وتطلب الإذن للسماح لها بذلك. هذا كل ما هو مطلوب فعليا ضمن صفحة HTML الخاصة بهذا المثال، أما الآن فعلينا الانتقال إلى لكتابة شيفرات لغة جافاسكريبت التي ستقوم بتحميل نموذج الشبكة العصبية الصنعية، وتمرير صور الكاميرا إليه، ومن ثم قراءة الخرج الناتج عن الشبكة العصبية الصنعية وعرضه ضمن عناصر الإدخال المقابلة في صفحة HTML السابقة. لذلك سنبدأ بكتابة محتوى الملف main.js من الشيفرات البرمجية مع شرح مختصر لكل قسم منها، فالسطر الأول يقوم بتعيين اسم الثابت video للإشارة إلى العنصر المدعوة webcam ضمن صفحة HTML السابقة: const video = document.getElementById("webcam"); بعد ذلك نقوم بتحميل نموذجي الشبكتين العصبيتين الخاصتين بالتعرف على الوجوه ضمن الصورة وتحديد الجنس وتقدير العمر من خلال سمات تلك الوجوه وذلك باستخدام آلية الوعود Promise.all، ومن بعد إتمام ذلك يتم استدعاء التابع startVideo الذي سنقوم بتعريفه لاحقا: Promise.all([ faceapi.nets.tinyFaceDetector.loadFromUri("models"), faceapi.nets.ageGenderNet.loadFromUri("models") ]).then(startVideo); يقوم هذا التابع بقراءة دفق إشارة الفيديو من الكاميرا وعرضها ضمن الكائن video، فإن حدث خطأ يتم كتابة رسالة الخطأ ضمن console.error في المستعرض: function startVideo() { navigator.getUserMedia( { video: {} }, stream => (video.srcObject = stream), err => console.error(err) ); } ومن ثم نضيف حدث يقوم بالإنصات لما يتم عرضه ضمن عنصر video بحيث يستدعي بشكل غير متزامن async (أي دون الحاجة لانتظار الإجابة حتى يتابع عرض الفيديو) وذلك كل ثانية (حيث تم ضبط الفترة الزمنية setInterval لتكون قيمتها 1000 ميلي ثانية). يقوم هذا الاستدعاء الدوري المتكرر بتعيين قيمة الكائن detection بواسطة مكتبة faceapi حيث تحدد جميع الوجوه الموجودة ضمن كائن video بالاستعانة بنموذج TinyFaceDetector مستخدمين الإعدادات الافتراضية، ومن ثم يمرر الناتج (أي الوجوه التي تم التعرف عليها في الصورة)، إلى الشبكة العصبية الأخرى التي تتعرف على العمر والجنس: video.addEventListener("playing", () => { setInterval(async () => { const detections = await faceapi .detectAllFaces(video, new faceapi.TinyFaceDetectorOptions()) .withAgeAndGender(); إن العبارة الشرطية التالية تتأكد إن كان الكائن detections موجودا أصلا (تذكر أن تعيين قيمة هذا الكائن تتم من خلال استدعاء غير متزامن وبالتالي يمكن أن تكون القيمة غير موجودة في البداية ريثما تصل إجابة ذلك الاستدعاء). ليس هذا فحسب، بل يجب أن يتضمن على الأقل وجه واحد على الأقل. فإن تحقق هذين الشرطين يتم قراءة الجنس المتوقع للوجه الأول detections[0].gender وتعيينه لعنصر الإدخال المقابل له، وكذلك قراءة العمر المتوقع لذات الوجه الأول detections[0].age وتقريبه إلى أقرب عدد صحيح باستخدام التابع Math.round ومن ثم إسناده كقيمة لعنصر الإدخال المدعو age ضمن صفحة HTML السابقة: if (detections && Object.keys(detections).length > 0) { document.getElementById(detections[0].gender).checked = true; document.getElementById("age").value = Math.round(detections[0].age); } }, 1000); }); هذا كل شيء! تستطيع الآن تجربة هذا التطبيق البسيط من خلال عرض الصفحة على نافذة المستعرض مستخدمين عنوانها على مخدم الويب المحلي وليكن على سبيل المثال: http://localhost/face-api نقاط تستحق التأمل من منا لا تغريه كم الإسقاطات التي تطرحها تقنية الشبكات العصبية الصنعية على مفهوم البرمجة ككل؟ إنها بذور جيل جديد مختلف جذريا عن كل ما سبق وأن اعتدنا عليه، فرغم أنها تعتمد على وحدات بسيطة في صميمها هي العصبونات، والتي قمنا بوصف آلية عملها بطريقة خوارزمية محددة تماما وواضحة، إلا أننا مع نمو شبكاتنا في الحجم والتعقيد استبدلنا الثقة بالأمل، والتحليل بالتجريب. لنأخذ على سبيل المثال نموذج اللغة العربية، فحتى نستطيع تشكيل أي جملة نستخدم علم النحو والإعراب الذي تعلمناه في مدارسنا، ومن خلال قواعده نحدد بناء الجملة وعناصرها كالفعل والفاعل أو المبتدأ والخبر وسواها من القواعد التي تساعدنا على ضبط أواخر الكلمات. هذه هي تماما الطريقة التي نبرمج بها حواسيبنا حاليا (منذ أيام تشارلز بابيج وحاسوبه الميكانيكي قبل مئتي عام)، فنحن نضع القواعد الصارمة لتدفق البيانات ونترجمها إلى عبارات شرطية وحلقات وسواها من بنى التحكم في عدد منتهي من الخطوات ندعوها بالخوارزمية. لكن لحظة، هل هذه هي الطريقة الصحيحة فعلا التي تجري بها الأمور؟ هل هذا ما نفعله حقيقة عندما يلتبس علينا تشكيل كلمة ما في نص نقرأه أو جملة نتحدثها؟ أغلب الظن ستكون إجابتك هي النفي! فمعظمنا لا يعرب الجملة في رأسه ليضبط أواخر الكلمات، بل نجرب الاحتمالات المختلفة ونرى أيها يملك الوقع الأكثر تجانسا وانسجاما في نفسنا (على سبيل المثال: هل أباك/أبوك/أبيك موجود؟). إنها ببساطة ما ندعوه بالسليقة اللغوية، وهي التي تفسر قدرة الطفل الصغير على التكلم بلغة صحيحة حتى قبل معرفته بوجود علم النحو والإعراب أصلا، فهو يتعلم مما يسمع وينسج على منواله، فكلما كانت الأمثلة كثيرة وصحيحة ازداد اتقانه للغة (ولهذا السبب كان العرب يرسلون أبنائهم إلى البادية لسلامة اللغة من اللحن الأعجمي هناك). إن التعلم من خلال الأمثلة هو ما تقوم به تماما الشبكات العصبية الصنعية التي نقوم بتطويرها، إنها تقوم ببناء خبرتها وسليقتها وفراستها الخاصة، في نهاية المطاف يمتلك كل من المبتدئ والخبير القواعد ذاتها، لكن عين الخبير رأت الكثير من الأمثلة التي صقلت بها خبرتها، حتى وصلت من التعقيد إلى درجة قد يصعب معها التفسير رغم قوة الإحساس ووضوحه في ذهنه. وهكذا ينتقل دور المبرمج رويدا رويدا من وضع القواعد وبنى التحكم لبرمجياته إلى ما بات يدعى اليوم بعلم البيانات وهندسة عملية استخلاص المزايا والخصائص المؤثرة في عملية التعلم من تلك البيانات، حيث أن دقة وجودة النموذج الناتج تعتمد بشكل حاسم على تكامل أمثلة التعليم وشمولها وصحتها، وأصبح امتلاك مثل هكذا مكانز رقمية موصّفة بشكل دقيق ومبنية بطريقة هيكلية سهلة الولوج والاستعلام يعادل قطع ما يتجاوز نصف الطريق إلى الوصول لعالم الذكاء الصنعي التطبيقي وقطف ثماره. دورة الذكاء الاصطناعي احترف برمجة الذكاء الاصطناعي AI وتحليل البيانات وتعلم كافة المعلومات التي تحتاجها لبناء نماذج ذكاء اصطناعي متخصصة. اشترك الآن مراجع للاستزادة مكتبة TensorFlow مكتبة face-api.js Model optimization اقرأ أيضًا المقال السابق: تصنيف الصور والتعرف على الوجه في مجال الذكاء الاصطناعي المفاهيم الأساسية لتعلم الآلة1 نقطة
-
السلام عليكم ورحمة الله بعد تحقيق الحد الادنى للدخل في ادسنس قام ادسنس بارسال رمز التحقق PIN وهو الان في الطريق إلي ، ولكن خلال عمل الموقع توقفت الاعلانات بشكل مفاجئ وبعد يومين ارسل ادسنس اشعار بأنه علي إدخال ads.txt إلى مدونتي للتحقق وقمت بتنفيذ الطلب ومع ذلك لم تظهر الاعلانات مرة أخرى. قمت بإنشاء وحدات اعلانية جديدة واستبدلت الشيفرات خاصتها بالشيفرات القديمة ويظهر في اعدادات ادسنس أنها نشطة ومع ذلك لم تظهر الاعلانات على الموقع. ملاحظة: قمنا بالعمل على المدونة لفترة من برنامج كاسر البروكسي وذلك لمقارنة أسعار النقرات بين بلدنا والبلدان الأخرى !! هل لهذا الأمر علاقة بالحظر ؟؟!! أدسنس لم يرسل لي أي بريد الكتروني ينبهني بالأمر أو ينوه إلى مخالفة قد ارتكبت !! أرجو من ذوي الخبرة أو التجارب السابقة إفادتي في هذا الموضوع وكيف استطيع إعادة الاعلانات إلى المدونة. جزيتم خيراً1 نقطة