المشكلة
يحجز شخصان القاعة نفسها في الساعة نفسها، ولا أحد يعرف أي القاعات تستخدم فعلا.
متاح للتجربةجدولة بيئة العملقراءة في دقيقة
حجز قاعات الاجتماعات بقواعد واحدة للإتاحة والموافقات وتسجيل الحضور.

01
يحجز شخصان القاعة نفسها في الساعة نفسها، ولا أحد يعرف أي القاعات تستخدم فعلا.
02
نظام حجز ثنائي اللغة يسأل ثلاثة أسئلة (متى، وكم شخصا، وما الذي تحتاجه القاعة) ثم يعرض قائمة قصيرة بالقاعات المناسبة مع سبب كل اقتراح. وخلفه تقويم يومي وأسبوعي وجدول أعمال، وموافقات، وتسجيل حضور برمز QR، وتقارير استخدام لمن يديرون المساحات.
03
تصميم المنتج والتنفيذ الكامل: القرارات والواجهة والمحتوى بالعربية والإنجليزية والتطوير والاختبارات والخادم والنشر.
ترفض قاعدة البيانات نفسها الحجز المزدوج، وتعود القاعة التي لم يسجل أحد حضوره فيها إلى قائمة الانتظار.
تم التحقق منه بمجموعة اختبارات تشمل محاولات حجز متزامنة دون أي حجز مزدوج. هو نسخة تجريبية ضمن الأعمال، لذلك لا توجد أرقام استخدام.



RoomFlow نظام ثنائي اللغة لحجز غرف الاجتماعات. من يحتاج قاعة يجيب عن ثلاثة أسئلة — متى، وكم عدد الأشخاص، وما الذي يحتاجه في القاعة — فيحصل على قائمة قصيرة بالقاعات المناسبة فعلا، مع سبب اقتراح كل واحدة. وخلف هذه الواجهة البسيطة يقع تقويم يومي وأسبوعي وجدولي، والموافقات، وتسجيل الحضور برمز QR، وتحرير القاعة عند عدم الحضور، وقائمة الانتظار، وفترات الصيانة، وتقارير الاستخدام لمن يديرون المكان.
يعمل كنسخة تجريبية عامة ببيانات وهمية. كل حساب وقاعة واجتماع وسجل تدقيق تراه فيه أنشئ خصيصا لهذه النسخة.
كل شيء: قرارات المنتج، وبنية المعلومات، وتصميم الواجهة والتفاعل، والمحتوى العربي والإنجليزي، والتنفيذ بـ PHP و MySQL، ومجموعة الاختبارات الآلية، وإعداد الخادم، والنشر.
الإصدار الأول كان مكتملا وصعب الاستخدام. كل ما قد يحتاجه مدير القاعات كان على الشاشات نفسها التي يحتاج فيها الموظف العادي شيئا واحدا. هذه هي القرارات التي عالجت ذلك.
خمس خطوات، كل واحدة تسأل عما تحتاجه فقط.

على الجوال كان زر القائمة موجودا، بالمقاس الصحيح والتسمية الصحيحة — ويعرض كصندوق فارغ. عيبان منفصلان، وكل منهما وحده كان كافيا لإخفاء القائمة.
.nav-ic المربع المصمت الذي كان ينوب عن الأيقونة. وظل زر القائمة يستخدم الترميز القديم — عنصر <span> — and no #ic-menu فارغ — ولم يكن هناك رمز أصلا. زر بمقاس ٤٤×٤٤ بحد من بكسل واحد ولا شيء بداخله.html[dir="rtl"] .sidebar يسجل ٠،٢،١ في أولوية CSS؛ بينما .sidebar.is-open يسجل ٠،٢،٠. فتفوقت حالة الإغلاق على حالة الفتح، وبالعربية — وهي اللغة الافتراضية — بقيت اللوحة خارج الحافة اليمنى حتى حين أعلن الزر أنها مفتوحة.كلاهما معالج، وأعيد بناء الدرج كحوار حقيقي: ينزلق من الحافة التي يقع عليها الزر، ويحصر التركيز أثناء فتحه، ويغلق بمفتاح Escape وبالنقر على الخلفية وبزر الإغلاق، ويعيد التركيز إلى زر القائمة في كل مرة، ويوقف تمرير الخلفية، ويخرج من ترتيب التنقل بالكامل عند إغلاقه.

لوحة التوفر تجيب عن السؤال دون بحث. القاعات المتاحة ترتب أولا، وكل قاعة تذكر حالتها بالكلمات إلى جانب أيقونة — لا باللون وحده، فاللون وحده غير مقروء لمن لديه عمى ألوان ولمن ينظر إلى شاشته في الشمس.
تفصيلة واحدة كلفتنا خللا: عبارة «متاحة حتى ٠٩:٠٠» كانت تشير إلى صباح الغد. صار كل استعلام عن «الحجز التالي» محصورا باليوم نفسه، فأي وقت يعرض للقارئ ينتمي إلى اليوم الذي ينظر إليه.

التوفر يجيب عن سؤال «هل يوجد شيء متاح الآن». أما التقويم فيجيب عن السؤال الآخر: كيف يبدو اليوم فعلا، وأين الفجوات. ثلاثة عروض، اختيرت لأنها مهام مختلفة حقا لا تخطيطا واحدا بثلاثة عروض.
توضع الكتل حسب أوقات بدايتها ونهايتها الحقيقية، محسوبة على الخادم، فتكون الشبكة صحيحة قبل تشغيل أي JavaScript. والحجوزات المتداخلة تنقسم إلى مسارات متجاورة — وعدد المسارات محصور بكل مجموعة تداخل، فالحجز الذي لا يتعارض مع شيء يحتفظ بالعمود كاملا بدل أن ينكمش لأن حجزين آخرين تعارضا في ذلك الصباح.
كل حالة يمكن تمييزها دون الاعتماد على اللون: المؤكد، وبانتظار الموافقة، والمنتهي، وعدم الحضور، والملغى، والصيانة — لكل معالجته الخاصة، ومفتاح ألوان، وكلمات في الاسم المتاح للقارئ الآلي. وخط أحمر يحدد الوقت الحالي، ولا يظهر إلا على اليوم الحالي.

الإشغال مشترك؛ والمحتوى ليس كذلك. يستطيع الموظف أن يرى أن قاعة محجوزة من ١٣:٠٠ إلى ١٤:٠٠ — وإلا لما أمكن للتقويم مساعدته في إيجاد فجوة — لكن اجتماع شخص آخر يظهر بوصفه Busyفقط، دون عنوان ولا منظم ولا رابط. أما المنسق فيرى التفاصيل التي يقتضيها دوره. والقاعدة مفروضة على الخادم، في الموضع نفسه الذي يحكم فتح الحجز مباشرة.


كل كتلة رابط حقيقي باسم متاح للقارئ الآلي يحمل العنوان والقاعة والحالة والوقتين — لأن شريطا ملونا في موضع ما لا يعني شيئا لقارئ الشاشة. والكتل التي لا يحق للمستخدم فتحها ليست روابط أصلا.
تتبع القاعات نظام تسمية واحدا يتيح للقارئ تخمين الغرض من القاعة قبل فتحها: تسمية بالغرض في الطرفين الصغير والكبير، وأسماء محايدة في الوسط. وتحمل كل قاعة نوعا صريحا إلى جانب رمزها.
| القاعة | العربية | النوع | السعة |
|---|---|---|---|
| Focus Room | قاعة التركيز | Focus room | 2 |
| Jasmine Room | قاعة الياسمين | Meeting room | 4 |
| Cedar Room | قاعة الأرز | Meeting room | 6 |
| Collaboration Room | قاعة التعاون | Collaboration room | 6 |
| Olive Room | قاعة الزيتون | Meeting room | 8 |
| Horizon Room | قاعة الأفق | Collaboration room | 12 |
| Executive Boardroom | قاعة الاجتماعات التنفيذية | Boardroom | 20 |
تعرض بطاقة النتيجة الاسم والرمز والنوع والسعة والجناح والطابق والمدخل بلا عوائق ومدة بقاء القاعة متاحة وتجهيزاتها. وما عدا ذلك يقع في صفحة القاعة بدل ازدحام البطاقة. وجميع القاعات السبع وهمية.
هذا هو الجزء الذي يجب أن يكون صحيحا. شخصان يضغطان «تأكيد» في اللحظة نفسها لا يجوز أن يحصل كلاهما على القاعة، ولا يمكن لأي تحقق في المتصفح أن يضمن ذلك.
ينشأ كل حجز داخل معاملة في قاعدة البيانات. وتقفل الصفوف المرشحة بـ SELECT … FOR UPDATE قبل تنفيذ اختبار التداخل، فيصطف الطلب الثاني خلف الأول بدل قراءة إجابة قديمة. واختبار التداخل نفسه يراعي المهلة الفاصلة: قاعة بمهلة ١٥ دقيقة ترفض حجزا يبدأ بعد ١٠ دقائق من انتهاء سابقه.
newStart < existingEnd + buffer newEnd > existingStart - buffer جرى التحقق منه بسباق اثنتي عشرة عملية تشغيل حقيقية على الموعد نفسه، خمس مرات. يفوز واحد فقط في كل جولة وتنتهي قاعدة البيانات بصف واحد بالضبط — ٦٠ محاولة متزامنة، دون أي حجز مزدوج. ولإثبات أن الاختبار ليس شكليا، وجهت المنظومة نفسها إلى تنفيذ ساذج يفحص ثم يدرج دون قفل: فأنتج اثني عشر حجزا متداخلا من اثني عشر.
لا يوجد هنا تعلم آلي ولا ادعاء به. الترتيب درجة صغيرة وحتمية يستطيع الإنسان قراءتها وتوقعها:
الأسباب المعروضة على كل بطاقة هي القيم نفسها التي حسبت منها الدرجة، فلا يمكن أن ينفصل التفسير عن الترتيب. والأسباب والتحفظات مفصولة عمدا: اشتراط الموافقة كلفة، وإدراجه تحت عنوان «لماذا هذه القاعة» يبيع عيبا على أنه ميزة.
وحين لا تناسب أي قاعة، ينتج المنطق نفسه بدائل — أقرب موعد متاح في كل قاعة مناسبة — بدل نتيجة فارغة.
ثلاثة أدوار، لكل منها شاشة أولى مختلفة. ويفحص كل مسار وكل إجراء في المتحكم وكل رابط مباشر على الخادم؛ فإخفاء الرابط عرض، لا حماية.
البحث عن قاعة وحجزها ورؤية حجوزاته وإلغاؤها وتسجيل الحضور برمز QR. ولا يستطيع فتح حجز أي شخص آخر، لا برابط ولا بغيره.
كل ما يفعله الموظف، إضافة إلى جدول اليوم في كل القاعات، وتسجيلات الحضور المستحقة، وحالات عدم الحضور، والموافقات، وفترات الصيانة.
كل ما يفعله المنسق، إضافة إلى المستخدمين والأدوار، وتقارير الاستخدام، وسجل التدقيق.
الموافقة على الحجز مهمة المنسق، لا صلاحية إدارة مستخدمين. وكان هذا التمييز خاطئا في إصدار سابق — إذ كان المنسق يدير الصيانة ولا يوافق على شيء، وهو الأمر الوحيد الذي يوجد الدور من أجله — وصارت اختبارات الأدوار الآلية تتحقق منه.
يحمل كل حجز رمز حضور عشوائيا بطول ١٢٨ بت، يولد بمعزل عن معرف الحجز فلا يمكن تخمينه أو تتبعه. ويرسم رمز QR بمرمز Reed–Solomon كتب لهذا المشروع بدل خدمة خارجية، فلا تغادر أي بيانات حجز الخادم لرسم رمز.
النسخة التجريبية مثيل حقيقي وتفاعلي بالكامل. يستطيع أي شخص الدخول وحجز قاعة. والضوابط غرضها حماية البيانات المشتركة، لا تعطيل المنتج.
demo_blocked.العربية هي اللغة الافتراضية ولغة من الدرجة الأولى، لا طبقة ترجمة. وتنعكس الواجهة بخصائص CSS المنطقية، فينقلب الدرج والتنقل وتخطيطات البطاقات وشبكات النماذج دون ورقة أنماط ثانية.


:focus-visible حتى لا تترك نقرة الفأرة حلقة خلفها.aria-current على عنصر التنقل النشط، وعناصر نماذج معنونة في كل مكان.prefers-reduced-motion محترمة — فيتوقف الدرج وأعمدة الرسم البياني وانتقالات الأزرار.HttpOnly, Secure and SameSite=Lax.X-Powered-By.PHP 8.3 و MySQL 8 دون إطار عمل. متحكم أمامي بجدول مسارات بتعابير نمطية، وتحميل تلقائي بنمط PSR، ومتحكمات نحيفة، وقواعد الحجز في مكان واحد بدل تشتتها في العروض.
NOW() and PHP's date() — وهو صنف الأخطاء الذي يكسر نوافذ التعارض وانتهاء القفل بصمت.open_basedir confining it.ست مجموعات اختبار تعمل على التطبيق المنشور، لا على محاكاة له.
| المجموعة | ما تغطيه | عدد الاختبارات |
|---|---|---|
| Unit and integration | منطق التداخل والمهل، والتحقق من السياسات، والموافقات، والصيانة، والتكرار، والترتيب، والبدائل، و ICS، و QR، والتغطية ثنائية اللغة وصيغ الجمع، وتوافق المنطقة الزمنية، ومهام الصيانة | 143 |
| Concurrency | ١٢ عملية حقيقية تتسابق على موعد واحد، ٥ جولات | ٦٠ محاولة، ٠ حجز مزدوج |
| HTTP مباشر | المصادقة، وفرض الأدوار، و CSRF، والوصول المباشر للكائنات، وترويسات الأمان، والنقل، وضوابط النسخة التجريبية، وعقد التنقل، وصياغة التوفر | 124 |
| Calendar | ثلاثة عروض، ووضع الكتل، ومسارات التداخل، والمرشحات، والحالات، ومؤشر الوقت الحالي، والحالات الفارغة، والأسماء للقارئ الآلي، والخصوصية حسب الدور، والتهريب، وثنائية اللغة | 56 |
| End-to-end journey | الدخول، والبحث، والاختيار، والتأكيد، والعرض، والتعارض، والتصدير، وتسجيل الحضور بـ QR، والإلغاء | 23 |
| Login throttling | القفل، وانتهاؤه، والعزل بين الحسابات | 5 |
اثنان من هذه الاختبارات موجودان لأنهما أمسكا بي. فحصت منظومة التزامن أمام تنفيذ غير مقفل عمدا لإثبات قدرتها على كشف العطل الذي تدعي منعه. وكان اختبار يتحقق من أن كل إجراء يغير حالة محمي في النسخة التجريبية ينجح شكليا — إذ كان يقسم الدوال على public function بينما تعلن المتحكمات public static function، فلم يحلل دالة واحدة قط. وبعد إعادة كتابته اعتمادا على جدول المسارات، كشف ثغرة حقيقية فورا.
هذه أرقام من البناء نفسه. لا توجد هنا أعداد مستخدمين ولا معدلات تبن ولا ادعاءات توفير، لأن RoomFlow نسخة عرض لمعرض أعمال وليست لديه أي منها.