// ==UserScript== // @name Inversion Test Trainer (Excel + Cost Control) // @namespace https://www.inversion-management.com/ // @version 1.1.0 // @description Bilingual training system for Excel and Cost Control, locked to inversion-management test page only. // @match https://www.inversion-management.com/test* // @run-at document-idle // @grant none // ==/UserScript== (function () { "use strict"; const ALLOWED_HOST = "www.inversion-management.com"; const ALLOWED_PATH = "/test"; if (location.hostname !== ALLOWED_HOST || location.pathname !== ALLOWED_PATH) { return; } const STORAGE_KEY = "inversion_test_trainer_progress_v2"; const LEVEL_SIZE = 10; const LEVELS = 10; const TOTAL_PER_TRACK = LEVEL_SIZE * LEVELS; const t = { ar: { appTitle: "منصة تدريب الاختبار - Excel و Cost Control", appSubTitle: "اختر المسار، تدرب على الأسئلة، وقيّم نفسك خطوة بخطوة", chooseTrack: "اختر المسار", excel: "اكسيل (Excel)", cost: "كوست كونترول (Cost Control)", resetProgress: "إعادة تعيين التقدم", totalScore: "إجمالي النقاط", level: "المستوى", question: "السؤال", yourAnswer: "إجابتك", showAnswer: "إظهار الإجابة", hideAnswer: "إخفاء الإجابة", myAnswerCorrect: "إجابتي صحيحة (+1)", myAnswerWrong: "إجابتي غير صحيحة", lesson: "الدرس التعليمي", scoreSaved: "تم حفظ النتيجة", selectTrackFirst: "اختر المسار أولاً", answerLabel: "الإجابة النموذجية", notesLabel: "ملاحظات", scoreByLevel: "نقاط المستوى", done: "تم", saveTypedAnswer: "حفظ الإجابة المكتوبة", }, en: { appTitle: "Test Training Platform - Excel & Cost Control", appSubTitle: "Choose a track, practice by level, and evaluate yourself step by step", chooseTrack: "Choose Track", excel: "Excel", cost: "Cost Control", resetProgress: "Reset Progress", totalScore: "Total Score", level: "Level", question: "Question", yourAnswer: "Your Answer", showAnswer: "Show Answer", hideAnswer: "Hide Answer", myAnswerCorrect: "My answer is correct (+1)", myAnswerWrong: "My answer is not correct", lesson: "Lesson", scoreSaved: "Score saved", selectTrackFirst: "Choose a track first", answerLabel: "Model Answer", notesLabel: "Notes", scoreByLevel: "Level Score", done: "Done", saveTypedAnswer: "Save typed answer", }, }; function pair(ar, en) { return { ar, en }; } function getExcelLesson(level) { const lessons = [ pair( "المستوى 1: أساسيات واجهة Excel، إدخال البيانات، التنسيق البسيط، والجمع اليدوي.", "Level 1: Excel interface basics, data entry, simple formatting, and manual summation." ), pair( "المستوى 2: الدوال الأساسية: SUM, AVERAGE, MAX, MIN, COUNT، مع مراجع الخلايا.", "Level 2: Core formulas: SUM, AVERAGE, MAX, MIN, COUNT with cell references." ), pair( "المستوى 3: الدوال المنطقية IF/AND/OR واستخدام الشروط المتعددة.", "Level 3: Logical formulas IF/AND/OR and multi-condition logic." ), pair( "المستوى 4: البحث والاسترجاع: VLOOKUP, XLOOKUP, INDEX-MATCH.", "Level 4: Lookup and retrieval: VLOOKUP, XLOOKUP, INDEX-MATCH." ), pair( "المستوى 5: تنظيف البيانات: TEXT, LEFT/RIGHT/MID, TRIM, SUBSTITUTE, DATE.", "Level 5: Data cleaning: TEXT, LEFT/RIGHT/MID, TRIM, SUBSTITUTE, DATE." ), pair( "المستوى 6: PivotTables وPivotCharts لتحليل البيانات بسرعة.", "Level 6: PivotTables and PivotCharts for fast analysis." ), pair( "المستوى 7: التحليل الشرطي: SUMIFS/COUNTIFS وConditional Formatting.", "Level 7: Conditional analysis: SUMIFS/COUNTIFS and Conditional Formatting." ), pair( "المستوى 8: أدوات What-If: Goal Seek, Scenario Manager, Data Tables.", "Level 8: What-If tools: Goal Seek, Scenario Manager, Data Tables." ), pair( "المستوى 9: Power Query ودمج وتحويل البيانات من مصادر متعددة.", "Level 9: Power Query for combining and transforming multi-source data." ), pair( "المستوى 10: نماذج احترافية، لوحات متابعة (Dashboards)، والتحقق من جودة النموذج.", "Level 10: Professional models, dashboards, and model quality checks." ), ]; return lessons[level - 1]; } function getCostLesson(level) { const lessons = [ pair( "المستوى 1: مفاهيم التكلفة الأساسية: مباشر/غير مباشر، ثابت/متغير.", "Level 1: Basic cost concepts: direct/indirect, fixed/variable." ), pair( "المستوى 2: عناصر التكلفة: مواد، عمالة، مصروفات صناعية وتبويبها.", "Level 2: Cost elements: materials, labor, and overhead classification." ), pair( "المستوى 3: مراكز التكلفة وتحميل التكاليف المباشرة وغير المباشرة.", "Level 3: Cost centers and direct/indirect cost allocation." ), pair( "المستوى 4: الموازنات التقديرية ومتابعة الانحرافات التشغيلية.", "Level 4: Budgeting and operational variance tracking." ), pair( "المستوى 5: تحليل الانحرافات المتقدم (سعر/كمية/كفاءة).", "Level 5: Advanced variance analysis (price/quantity/efficiency)." ), pair( "المستوى 6: تكاليف الأوامر والإنتاج المستمر والمقارنة بينهما.", "Level 6: Job order costing vs process costing." ), pair( "المستوى 7: تكلفة النشاط (ABC) ودوافع التكلفة.", "Level 7: Activity-Based Costing (ABC) and cost drivers." ), pair( "المستوى 8: CVP، نقطة التعادل، وهامش الأمان.", "Level 8: CVP, break-even analysis, and margin of safety." ), pair( "المستوى 9: قرارات التسعير والشراء/التصنيع والتحليل التفاضلي.", "Level 9: Pricing, make-or-buy, and differential analysis." ), pair( "المستوى 10: إدارة الأداء، KPIs، ومراجعة دقة نظام التكاليف.", "Level 10: Performance management, KPIs, and cost-system accuracy." ), ]; return lessons[level - 1]; } function excelQuestionTemplate(level, i) { const idx = (level - 1) * LEVEL_SIZE + i + 1; const slot = i + 1; const endRow = 5 + level + slot; const threshold = 45 + level * 3 + slot; const sales = 1200 + idx * 43; const cogs = 700 + idx * 29; const discount = 0.03 + level * 0.005; const scoreBand = 60 + level * 2; const monthCell = `D${slot + 1}`; const cityCell = `B${slot + 2}`; const categoryCell = `C${slot + 3}`; const levelCatalog = { 1: [ { q: pair(`اكتب معادلة جمع من A1 إلى A${endRow}.`, `Write a formula to sum A1:A${endRow}.`), a: pair(`=SUM(A1:A${endRow})`, `=SUM(A1:A${endRow})`) }, { q: pair(`احسب المتوسط في B1:B${endRow}.`, `Calculate average for B1:B${endRow}.`), a: pair(`=AVERAGE(B1:B${endRow})`, `=AVERAGE(B1:B${endRow})`) }, { q: pair(`اكتب معادلة لأكبر قيمة في C1:C${endRow}.`, `Write a formula for max value in C1:C${endRow}.`), a: pair(`=MAX(C1:C${endRow})`, `=MAX(C1:C${endRow})`) }, { q: pair(`اكتب معادلة لأقل قيمة في C1:C${endRow}.`, `Write a formula for min value in C1:C${endRow}.`), a: pair(`=MIN(C1:C${endRow})`, `=MIN(C1:C${endRow})`) }, { q: pair(`اكتب COUNT لعد الأرقام في D1:D${endRow}.`, `Write COUNT to count numbers in D1:D${endRow}.`), a: pair(`=COUNT(D1:D${endRow})`, `=COUNT(D1:D${endRow})`) }, { q: pair(`اكتب COUNTA لعد الخلايا غير الفارغة في E1:E${endRow}.`, `Write COUNTA to count non-empty cells in E1:E${endRow}.`), a: pair(`=COUNTA(E1:E${endRow})`, `=COUNTA(E1:E${endRow})`) }, { q: pair(`في F2 احسب B2*C2.`, `In F2 calculate B2*C2.`), a: pair(`=B2*C2`, `=B2*C2`) }, { q: pair(`في G2 احسب نسبة C2 من B2 كنسبة مئوية.`, `In G2 calculate C2 as a percentage of B2.`), a: pair(`=C2/B2`, `=C2/B2`) }, { q: pair(`اكتب صيغة طرح: صافي الربح = الإيراد - التكلفة في H2.`, `Write subtraction formula: Net profit = Revenue - Cost in H2.`), a: pair(`=B2-C2`, `=B2-C2`) }, { q: pair(`حوّل المرجع A1 إلى مرجع مطلق.`, `Convert reference A1 to absolute reference.`), a: pair(`$A$1`, `$A$1`) }, ], 2: [ { q: pair(`اكتب IF: إذا كانت E2 >= ${scoreBand} ارجع "Pass" وإلا "Fail".`, `Write IF: if E2 >= ${scoreBand}, return "Pass", else "Fail".`), a: pair(`=IF(E2>=${scoreBand},"Pass","Fail")`, `=IF(E2>=${scoreBand},"Pass","Fail")`) }, { q: pair(`اكتب IF مع شرطين AND: D2>=50 وE2>=50.`, `Write IF with AND: D2>=50 and E2>=50.`), a: pair(`=IF(AND(D2>=50,E2>=50),"Pass","Fail")`, `=IF(AND(D2>=50,E2>=50),"Pass","Fail")`) }, { q: pair(`اكتب IF مع OR: إذا B2="Cairo" أو B2="Alex".`, `Write IF with OR: if B2="Cairo" or B2="Alex".`), a: pair(`=IF(OR(B2="Cairo",B2="Alex"),"Main City","Other")`, `=IF(OR(B2="Cairo",B2="Alex"),"Main City","Other")`) }, { q: pair(`استخدم ROUND لتقريب F2 إلى منزلتين.`, `Use ROUND to round F2 to 2 decimals.`), a: pair(`=ROUND(F2,2)`, `=ROUND(F2,2)`) }, { q: pair(`استخدم ROUNDUP لتقريب G2 لأعلى لأقرب عدد صحيح.`, `Use ROUNDUP to round G2 up to nearest integer.`), a: pair(`=ROUNDUP(G2,0)`, `=ROUNDUP(G2,0)`) }, { q: pair(`استخدم ROUNDDOWN لتقريب G2 لأسفل لأقرب عدد صحيح.`, `Use ROUNDDOWN to round G2 down to nearest integer.`), a: pair(`=ROUNDDOWN(G2,0)`, `=ROUNDDOWN(G2,0)`) }, { q: pair(`اكتب INT لاستخراج الجزء الصحيح من H2.`, `Write INT to return integer part of H2.`), a: pair(`=INT(H2)`, `=INT(H2)`) }, { q: pair(`استخدم ABS لإزالة الإشارة السالبة من I2.`, `Use ABS to remove negative sign from I2.`), a: pair(`=ABS(I2)`, `=ABS(I2)`) }, { q: pair(`احسب متوسط شرطي بسيط: إذا C2 أكبر من ${threshold} اكتب "High" وإلا "Low".`, `Simple conditional label: if C2 > ${threshold}, write "High" else "Low".`), a: pair(`=IF(C2>${threshold},"High","Low")`, `=IF(C2>${threshold},"High","Low")`) }, { q: pair(`اكتب IFERROR لإرجاع 0 بدل الخطأ في J2/K2.`, `Write IFERROR to return 0 instead of error in J2/K2.`), a: pair(`=IFERROR(J2/K2,0)`, `=IFERROR(J2/K2,0)`) }, ], 3: [ { q: pair(`اربط الاسم الأول في A2 والاسم الأخير في B2 بمسافة.`, `Concatenate first name A2 and last name B2 with a space.`), a: pair(`=A2&" "&B2`, `=A2&" "&B2`) }, { q: pair(`استخرج أول 3 أحرف من C2.`, `Extract first 3 characters from C2.`), a: pair(`=LEFT(C2,3)`, `=LEFT(C2,3)`) }, { q: pair(`استخرج آخر 4 أحرف من D2.`, `Extract last 4 characters from D2.`), a: pair(`=RIGHT(D2,4)`, `=RIGHT(D2,4)`) }, { q: pair(`استخرج 5 أحرف من E2 بدءًا من الحرف الثاني.`, `Extract 5 characters from E2 starting at position 2.`), a: pair(`=MID(E2,2,5)`, `=MID(E2,2,5)`) }, { q: pair(`أزل المسافات الزائدة من F2.`, `Trim extra spaces from F2.`), a: pair(`=TRIM(F2)`, `=TRIM(F2)`) }, { q: pair(`بدّل "-" بـ "/" داخل G2.`, `Replace "-" with "/" inside G2.`), a: pair(`=SUBSTITUTE(G2,"-","/")`, `=SUBSTITUTE(G2,"-","/")`) }, { q: pair(`حوّل النص في H2 إلى أحرف كبيرة.`, `Convert text in H2 to uppercase.`), a: pair(`=UPPER(H2)`, `=UPPER(H2)`) }, { q: pair(`حوّل النص في I2 إلى أحرف صغيرة.`, `Convert text in I2 to lowercase.`), a: pair(`=LOWER(I2)`, `=LOWER(I2)`) }, { q: pair(`اجعل أول حرف كبيرًا في J2.`, `Capitalize first letter in J2.`), a: pair(`=PROPER(J2)`, `=PROPER(J2)`) }, { q: pair(`اكتب LEN لحساب عدد الأحرف في K2.`, `Use LEN to count characters in K2.`), a: pair(`=LEN(K2)`, `=LEN(K2)`) }, ], 4: [ { q: pair(`اكتب VLOOKUP لجلب السعر من الجدول A2:D200 حسب كود في G2 (العمود 4).`, `Write VLOOKUP to return price from A2:D200 by code in G2 (column 4).`), a: pair(`=VLOOKUP(G2,$A$2:$D$200,4,FALSE)`, `=VLOOKUP(G2,$A$2:$D$200,4,FALSE)`) }, { q: pair(`اكتب XLOOKUP لجلب اسم المنتج من ProductCodeRange/ProductNameRange.`, `Write XLOOKUP to return product name from ProductCodeRange/ProductNameRange.`), a: pair(`=XLOOKUP(G2,ProductCodeRange,ProductNameRange,"Not Found")`, `=XLOOKUP(G2,ProductCodeRange,ProductNameRange,"Not Found")`) }, { q: pair(`اكتب MATCH لموقع قيمة H2 داخل النطاق B2:B500.`, `Write MATCH to find position of H2 within B2:B500.`), a: pair(`=MATCH(H2,$B$2:$B$500,0)`, `=MATCH(H2,$B$2:$B$500,0)`) }, { q: pair(`استخدم INDEX+MATCH لجلب القيمة من D2:D500 حسب تطابق في B2:B500 مع H2.`, `Use INDEX+MATCH to return value from D2:D500 where B2:B500 matches H2.`), a: pair(`=INDEX($D$2:$D$500,MATCH(H2,$B$2:$B$500,0))`, `=INDEX($D$2:$D$500,MATCH(H2,$B$2:$B$500,0))`) }, { q: pair(`اكتب XMATCH لموقع ${cityCell} في CityRange.`, `Write XMATCH for position of ${cityCell} in CityRange.`), a: pair(`=XMATCH(${cityCell},CityRange,0)`, `=XMATCH(${cityCell},CityRange,0)`) }, { q: pair(`اكتب HLOOKUP لجلب صف ${slot + 1} من جدول A1:F6 باستخدام قيمة في A10.`, `Write HLOOKUP to return row ${slot + 1} from A1:F6 using lookup in A10.`), a: pair(`=HLOOKUP(A10,$A$1:$F$6,${slot + 1},FALSE)`, `=HLOOKUP(A10,$A$1:$F$6,${slot + 1},FALSE)`) }, { q: pair(`كيف تمنع خطأ #N/A في VLOOKUP؟`, `How do you prevent #N/A in VLOOKUP?`), a: pair(`لف الدالة داخل IFERROR مثل: =IFERROR(VLOOKUP(...),"Not Found")`, `Wrap with IFERROR, e.g. =IFERROR(VLOOKUP(...),"Not Found")`) }, { q: pair(`اكتب XLOOKUP يعيد "Missing" عند عدم العثور على الكود ${categoryCell}.`, `Write XLOOKUP returning "Missing" when code ${categoryCell} is not found.`), a: pair(`=XLOOKUP(${categoryCell},CodeRange,ResultRange,"Missing")`, `=XLOOKUP(${categoryCell},CodeRange,ResultRange,"Missing")`) }, { q: pair(`ما الميزة الرئيسية لـ INDEX-MATCH عن VLOOKUP؟`, `What is the main advantage of INDEX-MATCH over VLOOKUP?`), a: pair(`يسمح بالبحث يسارًا ومرونة أعلى عند تغيير ترتيب الأعمدة.`, `It supports left lookup and is more robust when column order changes.`) }, { q: pair(`اكتب FILTER لاستخراج الصفوف التي Amount>1000 من الجدول Table1.`, `Write FILTER to return rows where Amount>1000 from Table1.`), a: pair(`=FILTER(Table1,Table1[Amount]>1000)`, `=FILTER(Table1,Table1[Amount]>1000)`) }, ], 5: [ { q: pair(`اكتب TEXT لتحويل تاريخ A2 إلى "dd-mmm-yyyy".`, `Write TEXT to format date A2 as "dd-mmm-yyyy".`), a: pair(`=TEXT(A2,"dd-mmm-yyyy")`, `=TEXT(A2,"dd-mmm-yyyy")`) }, { q: pair(`اكتب DATE لإنشاء تاريخ من سنة B2 وشهر C2 ويوم D2.`, `Write DATE to build a date from year B2, month C2, day D2.`), a: pair(`=DATE(B2,C2,D2)`, `=DATE(B2,C2,D2)`) }, { q: pair(`اكتب TODAY للحصول على تاريخ اليوم.`, `Write TODAY to get current date.`), a: pair(`=TODAY()`, `=TODAY()`) }, { q: pair(`اكتب NOW للحصول على التاريخ والوقت الحاليين.`, `Write NOW for current date/time.`), a: pair(`=NOW()`, `=NOW()`) }, { q: pair(`استخرج رقم الشهر من E2.`, `Extract month number from E2.`), a: pair(`=MONTH(E2)`, `=MONTH(E2)`) }, { q: pair(`استخرج اسم اليوم كنص من F2.`, `Extract weekday name text from F2.`), a: pair(`=TEXT(F2,"dddd")`, `=TEXT(F2,"dddd")`) }, { q: pair(`احسب الفرق بالأيام بين G2 وH2.`, `Calculate day difference between G2 and H2.`), a: pair(`=G2-H2`, `=G2-H2`) }, { q: pair(`احسب عدد أيام العمل بين I2 وJ2.`, `Calculate working days between I2 and J2.`), a: pair(`=NETWORKDAYS(I2,J2)`, `=NETWORKDAYS(I2,J2)`) }, { q: pair(`أضف ${slot} أشهر إلى التاريخ في K2.`, `Add ${slot} months to date in K2.`), a: pair(`=EDATE(K2,${slot})`, `=EDATE(K2,${slot})`) }, { q: pair(`احسب نهاية الشهر لتاريخ L2.`, `Return end-of-month for date L2.`), a: pair(`=EOMONTH(L2,0)`, `=EOMONTH(L2,0)`) }, ], 6: [ { q: pair(`ما أول خطوة صحيحة قبل PivotTable؟`, `What is the first correct step before a PivotTable?`), a: pair(`تحويل البيانات إلى Table منظّم بعناوين واضحة وصفوف بلا فراغات.`, `Convert data to a clean structured Table with clear headers and no blank rows.`) }, { q: pair(`كيف تحسب إجمالي المبيعات لكل مدينة داخل PivotTable؟`, `How to calculate total sales by city in a PivotTable?`), a: pair(`ضع City في Rows وSales في Values (Sum).`, `Put City in Rows and Sales in Values as Sum.`) }, { q: pair(`كيف تعرض النسبة المئوية من الإجمالي داخل Pivot؟`, `How to show % of grand total in Pivot?`), a: pair(`Value Field Settings -> Show Values As -> % of Grand Total.`, `Value Field Settings -> Show Values As -> % of Grand Total.`) }, { q: pair(`كيف تجمع التواريخ شهريًا داخل Pivot؟`, `How to group dates monthly in Pivot?`), a: pair(`Right click date -> Group -> Months (and Years if needed).`, `Right click date -> Group -> Months (and Years if needed).`) }, { q: pair(`كيف تعمل فلترة سريعة داخل Pivot؟`, `How to do quick filtering in Pivot?`), a: pair(`استخدم Slicer أو Report Filter حسب الحقل المطلوب.`, `Use a Slicer or Report Filter for the required field.`) }, { q: pair(`كيف تضيف PivotChart مناسب للمقارنة بين الفئات؟`, `How to add a suitable PivotChart for category comparison?`), a: pair(`Insert PivotChart واختر Clustered Column للمقارنات.`, `Insert PivotChart and choose Clustered Column for comparisons.`) }, { q: pair(`كيف تحدّث Pivot بعد إضافة بيانات جديدة؟`, `How to refresh Pivot after adding new records?`), a: pair(`Refresh أو Data -> Refresh All، ويفضل أن المصدر Table تلقائي التوسع.`, `Use Refresh or Data -> Refresh All; source should be a dynamic Table.`) }, { q: pair(`كيف تمنع إظهار قيم 0 داخل Pivot؟`, `How to avoid displaying 0 values in Pivot?`), a: pair(`Value Filters أو Number Format مخصص لإخفاء الأصفار.`, `Use Value Filters or custom number format to hide zeros.`) }, { q: pair(`ما الأفضل عند وجود ملايين الصفوف: Pivot عادي أم Data Model؟`, `For millions of rows, Pivot only or Data Model?`), a: pair(`Data Model/Power Pivot أفضل للأداء والعلاقات.`, `Data Model/Power Pivot is better for performance and relationships.`) }, { q: pair(`كيف تضيف حقل محسوب في Pivot؟`, `How to add a calculated field in Pivot?`), a: pair(`PivotTable Analyze -> Fields, Items & Sets -> Calculated Field.`, `PivotTable Analyze -> Fields, Items & Sets -> Calculated Field.`) }, ], 7: [ { q: pair(`اكتب SUMIFS للمبيعات عندما المدينة=${cityCell} والفئة=${categoryCell}.`, `Write SUMIFS for sales where city=${cityCell} and category=${categoryCell}.`), a: pair(`=SUMIFS(SalesRange,CityRange,${cityCell},CategoryRange,${categoryCell})`, `=SUMIFS(SalesRange,CityRange,${cityCell},CategoryRange,${categoryCell})`) }, { q: pair(`اكتب COUNTIFS للصفوف التي الشهر=${monthCell} والقيمة>${threshold}.`, `Write COUNTIFS for rows where month=${monthCell} and value>${threshold}.`), a: pair(`=COUNTIFS(MonthRange,${monthCell},ValueRange,">${threshold}")`, `=COUNTIFS(MonthRange,${monthCell},ValueRange,">${threshold}")`) }, { q: pair(`اكتب AVERAGEIFS لمتوسط الربح للقسم "Ops" والمنطقة "East".`, `Write AVERAGEIFS for average profit where department="Ops" and region="East".`), a: pair(`=AVERAGEIFS(ProfitRange,DeptRange,"Ops",RegionRange,"East")`, `=AVERAGEIFS(ProfitRange,DeptRange,"Ops",RegionRange,"East")`) }, { q: pair(`اكتب MINIFS لأقل تكلفة لفئة "Raw".`, `Write MINIFS for minimum cost in category "Raw".`), a: pair(`=MINIFS(CostRange,CategoryRange,"Raw")`, `=MINIFS(CostRange,CategoryRange,"Raw")`) }, { q: pair(`اكتب MAXIFS لأكبر مبيعات للمنتج "P-01".`, `Write MAXIFS for max sales where product="P-01".`), a: pair(`=MAXIFS(SalesRange,ProductRange,"P-01")`, `=MAXIFS(SalesRange,ProductRange,"P-01")`) }, { q: pair(`ما قاعدة Conditional Formatting المناسبة لإبراز أعلى 10%؟`, `Which Conditional Formatting rule highlights top 10%?`), a: pair(`Top/Bottom Rules -> Top 10%`, `Top/Bottom Rules -> Top 10%`) }, { q: pair(`كيف تلوّن القيم الأقل من 0 تلقائيًا بالأحمر؟`, `How to auto-highlight values below 0 in red?`), a: pair(`Conditional Formatting -> Highlight Cells Rules -> Less Than 0.`, `Conditional Formatting -> Highlight Cells Rules -> Less Than 0.`) }, { q: pair(`اكتب صيغة Rule مخصص لتلوين الصف إذا D2="Delayed".`, `Write custom rule formula to highlight row when D2="Delayed".`), a: pair(`=$D2="Delayed"`, `=$D2="Delayed"`) }, { q: pair(`كيف تمنع إدخال نسبة أكبر من 100% في C2:C200؟`, `How to prevent entering percentage >100% in C2:C200?`), a: pair(`Data Validation -> Decimal between 0 and 1.`, `Data Validation -> Decimal between 0 and 1.`) }, { q: pair(`اكتب Data Validation List من النطاق M2:M10 في الخلية B2.`, `Set Data Validation list from M2:M10 in B2.`), a: pair(`Allow: List, Source: =$M$2:$M$10`, `Allow: List, Source: =$M$2:$M$10`) }, ], 8: [ { q: pair(`ما أداة What-If المناسبة لإيجاد سعر يحقق ربح مستهدف؟`, `Which What-If tool finds price for a target profit?`), a: pair(`Goal Seek`, `Goal Seek`) }, { q: pair(`في Goal Seek: ما الخلايا الثلاث المطلوبة؟`, `In Goal Seek: what are the three required fields?`), a: pair(`Set cell, To value, By changing cell.`, `Set cell, To value, By changing cell.`) }, { q: pair(`متى تستخدم Scenario Manager بدل Goal Seek؟`, `When to use Scenario Manager instead of Goal Seek?`), a: pair(`عند مقارنة عدة افتراضات متعددة المتغيرات في نفس الوقت.`, `When comparing multiple multi-variable assumptions at once.`) }, { q: pair(`ما دور Data Table (One-variable)؟`, `What is the role of one-variable Data Table?`), a: pair(`قياس أثر تغيير متغير واحد على نتيجة معادلة عبر نطاق قيم.`, `Tests one input across a range to see impact on a formula result.`) }, { q: pair(`ما دور Data Table (Two-variable)؟`, `What is the role of two-variable Data Table?`), a: pair(`تحليل حساسية النتيجة لتغير متغيرين معًا.`, `Sensitivity analysis for two changing inputs together.`) }, { q: pair(`إذا أردت أفضل تركيبة ضمن قيود تكلفة وطاقة، أي أداة؟`, `If you need best mix under cost/capacity constraints, which tool?`), a: pair(`Solver`, `Solver`) }, { q: pair(`ما نوع القيود الشائع في Solver للتكاليف؟`, `What common Solver constraint type applies to costs?`), a: pair(`<= للميزانية، وحدود سفلية/عليا للمتغيرات، وقيود عددية صحيحة عند الحاجة.`, `<= budget constraints, upper/lower bounds, and integer constraints when needed.`) }, { q: pair(`كيف تعرض نتيجة الحساسية بشكل واضح للإدارة؟`, `How do you present sensitivity output clearly to management?`), a: pair(`جدول مدخلات/نتائج مع رسم بياني وخلاصة قرار عملي.`, `Input/output sensitivity table with a chart and concise decision note.`) }, { q: pair(`ما الفرق بين Goal Seek وSolver في جملة؟`, `Difference between Goal Seek and Solver in one sentence?`), a: pair(`Goal Seek يغير متغيرًا واحدًا لهدف واحد، Solver يحل مسائل تحسين متعددة المتغيرات والقيود.`, `Goal Seek changes one input for one target; Solver optimizes multiple variables under constraints.`) }, { q: pair(`أي خطأ شائع في التحليل What-If يجب تجنبه؟`, `What common What-If mistake should be avoided?`), a: pair(`الاعتماد على افتراضات غير موثقة أو غير واقعية بدون اختبار نطاقات حساسية.`, `Using undocumented/unrealistic assumptions without testing sensitivity ranges.`) }, ], 9: [ { q: pair(`اذكر أول 3 خطوات في Power Query قبل التحليل.`, `List first 3 Power Query steps before analysis.`), a: pair(`استيراد البيانات، تحديد نوع الأعمدة، تنظيف القيم الفارغة/المكررة.`, `Import data, set data types, clean blanks/duplicates.`) }, { q: pair(`كيف تدمج جدولين بناءً على ProductID؟`, `How do you merge two tables based on ProductID?`), a: pair(`Merge Queries على ProductID واختيار نوع الربط المناسب (Left/Inner).`, `Use Merge Queries on ProductID and choose correct join type (Left/Inner).`) }, { q: pair(`كيف تضم عدة ملفات شهرية بنفس البنية؟`, `How to append multiple monthly files with same schema?`), a: pair(`Get Data from Folder ثم Combine & Transform.`, `Get Data from Folder then Combine & Transform.`) }, { q: pair(`ما الفائدة من خطوة Remove Duplicates؟`, `Benefit of Remove Duplicates step?`), a: pair(`تحسين دقة النتائج ومنع تكرار العد أو التجميع.`, `Improves result accuracy and avoids duplicate counting/aggregation.`) }, { q: pair(`كيف تنشئ عمود مشتق Margin = Sales - Cost في Power Query؟`, `How to create derived column Margin = Sales - Cost in Power Query?`), a: pair(`Add Column -> Custom Column: [Sales]-[Cost]`, `Add Column -> Custom Column: [Sales]-[Cost]`) }, { q: pair(`ما أفضل وقت لاستخدام Unpivot Columns؟`, `When is Unpivot Columns most useful?`), a: pair(`عند تحويل أعمدة شهور/فترات إلى شكل صفي تحليلي.`, `When converting month/period columns to a row-based analytical format.`) }, { q: pair(`كيف تضمن إعادة التحديث بدون كسر الاستعلام؟`, `How to ensure refresh without breaking query?`), a: pair(`استخدم مسارات ثابتة/معلمات، وأسماء أعمدة مستقرة، واختبر الأخطاء.`, `Use stable paths/parameters, stable column names, and test for errors.`) }, { q: pair(`ما الفرق بين Close & Load وClose & Load To؟`, `Difference between Close & Load and Close & Load To?`), a: pair(`الأولى تحميل افتراضي، الثانية تحدد الوجهة (Table/Data Model/Connection).`, `First is default load; second lets you choose destination (Table/Data Model/Connection).`) }, { q: pair(`ما أهم ميزة عند تسجيل الخطوات في Applied Steps؟`, `Key advantage of Applied Steps history?`), a: pair(`توثيق التحويلات وإعادة التطبيق التلقائي عند كل Refresh.`, `Documented transformations that replay automatically on refresh.`) }, { q: pair(`كيف تتعامل مع صفوف فيها أخطاء تحويل نوع البيانات؟`, `How to handle rows with data-type conversion errors?`), a: pair(`Filter Errors أو Replace Errors ثم مراجعة مصدر البيانات.`, `Use Filter Errors or Replace Errors, then review data source.`) }, ], 10: [ { q: pair(`اذكر 4 مكونات أساسية لـ Dashboard احترافي في Excel.`, `List 4 core components of a professional Excel dashboard.`), a: pair(`KPIs رئيسية، فلاتر/Slicers، رسوم واضحة، وملاحظات تفسيرية للقرارات.`, `Core KPIs, slicers/filters, clear visuals, and decision-oriented commentary.`) }, { q: pair(`ما أفضل رسم لعرض اتجاه شهري للمبيعات؟`, `Best chart to display monthly sales trend?`), a: pair(`Line chart`, `Line chart`) }, { q: pair(`ما أفضل رسم للمقارنة بين الأقسام في فترة واحدة؟`, `Best chart for comparing departments in one period?`), a: pair(`Clustered Column/Bar chart`, `Clustered Column/Bar chart`) }, { q: pair(`كيف تربط جميع الرسوم بـ Slicer واحد؟`, `How to connect all charts to one slicer?`), a: pair(`Report Connections -> اختر جميع PivotTables المرتبطة.`, `Use Report Connections and select all related PivotTables.`) }, { q: pair(`اذكر قاعدة تصميم مهمة في dashboard للألوان.`, `Mention one key color rule for dashboard design.`), a: pair(`استخدم لوحة ألوان محدودة ومتسقة وتجنب التشبع الزائد.`, `Use a limited consistent color palette; avoid over-saturation.`) }, { q: pair(`كيف تفحص جودة النموذج قبل التسليم؟`, `How do you quality-check model before handover?`), a: pair(`اختبار المعادلات، مراجعة الروابط، فحص الحالات الحدية، وتوثيق الافتراضات.`, `Test formulas, audit links, check edge cases, and document assumptions.`) }, { q: pair(`ما هي طريقة توثيق الافتراضات داخل الملف؟`, `How to document assumptions inside the workbook?`), a: pair(`ورقة Assumptions مخصصة + تعليقات مختصرة بجوار المدخلات الحساسة.`, `Dedicated assumptions sheet + concise notes near sensitive inputs.`) }, { q: pair(`كيف تضمن سهولة الاستخدام للإدارة غير الفنية؟`, `How to ensure usability for non-technical management users?`), a: pair(`واجهة بسيطة، تسميات واضحة، وملخص تنفيذي في أعلى الصفحة.`, `Simple interface, clear labels, and executive summary at top.`) }, { q: pair(`ما أهم مؤشر لمراقبة هامش الربحية عبر المنتجات؟`, `Most important KPI for monitoring product profitability?`), a: pair(`Gross Margin % مع تحليل الاتجاه والانحراف عن الهدف.`, `Gross Margin % with trend and target variance analysis.`) }, { q: pair(`ما الخطأ الشائع في dashboards ويجب منعه؟`, `Common dashboard mistake that must be avoided?`), a: pair(`ازدحام المؤشرات دون قصة تحليلية أو ربط بالقرار.`, `Overcrowding visuals without analytical storyline or decision linkage.`) }, ], }; const base = levelCatalog[level][i]; return { id: `excel-${idx}`, level, q: base.q, answer: base.a, notes: pair( `سؤال ${idx} - مستوى ${level}: راجع الصياغة بدقة ثم اختبرها على بيانات حقيقية قبل اعتماد الإجابة.`, `Question ${idx} - Level ${level}: validate syntax and test it on realistic data before finalizing.` ), }; } function costQuestionTemplate(level, i) { const idx = (level - 1) * LEVEL_SIZE + i + 1; const fixed = 25000 + idx * 120; const price = 120 + (idx % 9) * 5; const variable = 70 + (idx % 5) * 4; const cm = price - variable; const beu = Math.ceil(fixed / cm); const catalog = [ { q: pair( `عرّف التكلفة المباشرة بمثال واحد.`, `Define direct cost with one example.` ), a: pair( `تكلفة يمكن تتبعها مباشرة للمنتج مثل خامة الحديد في تصنيع منتج معدني.`, `A cost directly traceable to a product, e.g., steel raw material for a metal item.` ), }, { q: pair( `ما الفرق بين التكلفة الثابتة والمتغيرة في سطرين؟`, `What is the difference between fixed and variable cost in two lines?` ), a: pair( `الثابتة لا تتغير بتغير حجم النشاط ضمن المدى الملائم، والمتغيرة تتغير طرديًا مع الإنتاج.`, `Fixed costs stay stable within the relevant range, while variable costs move with output volume.` ), }, { q: pair( `احسب هامش المساهمة إذا سعر البيع = ${price} والتكلفة المتغيرة = ${variable}.`, `Calculate contribution margin if selling price = ${price} and variable cost = ${variable}.` ), a: pair(`هامش المساهمة = ${cm}`, `Contribution margin = ${cm}`), }, { q: pair( `احسب نقطة التعادل بالوحدات إذا التكاليف الثابتة = ${fixed} وهامش المساهمة للوحدة = ${cm}.`, `Calculate break-even units if fixed costs = ${fixed} and CM/unit = ${cm}.` ), a: pair(`نقطة التعادل = ${beu} وحدة تقريبًا`, `Break-even = about ${beu} units`), }, { q: pair( `ما الهدف الأساسي من تحليل الانحرافات في الكوست كونترول؟`, `What is the primary goal of variance analysis in cost control?` ), a: pair( `تحديد أسباب الفروق بين الفعلي والمخطط لاتخاذ إجراءات تصحيحية وتحسين الأداء.`, `Identify actual-vs-budget gaps and their causes to drive corrective actions and improve performance.` ), }, { q: pair( `متى تفضّل استخدام ABC بدلاً من النظام التقليدي؟`, `When do you prefer ABC over traditional costing?` ), a: pair( `عند تنوع المنتجات وارتفاع التكاليف غير المباشرة واختلاف استهلاك الأنشطة بين المنتجات.`, `When products are diverse, overhead is high, and activity consumption differs across products.` ), }, { q: pair( `اذكر KPI مناسب لمتابعة كفاءة التكلفة في مشروع.`, `Mention one suitable KPI to track cost efficiency in a project.` ), a: pair(`Cost Variance % أو CPI (Cost Performance Index).`, `Cost Variance % or CPI (Cost Performance Index).`), }, { q: pair( `ما الفرق بين Budget وForecast في إدارة التكلفة؟`, `What is the difference between Budget and Forecast in cost management?` ), a: pair( `Budget خطة أساسية معتمدة، بينما Forecast تحديث توقعي دوري بناءً على الأداء الفعلي.`, `Budget is the approved baseline plan; Forecast is the periodic updated outlook based on actuals.` ), }, { q: pair( `في قرار شراء أو تصنيع، ما نوع التكاليف التي يجب التركيز عليها؟`, `In a make-or-buy decision, which costs should be emphasized?` ), a: pair( `التكاليف التفاضلية/القابلة للتجنب فقط، وتجاهل التكاليف الغارقة.`, `Focus on differential/avoidable costs and ignore sunk costs.` ), }, { q: pair( `لماذا يعتبر هامش الأمان مهمًا بعد حساب نقطة التعادل؟`, `Why is margin of safety important after break-even analysis?` ), a: pair( `لأنه يقيس مدى تحمّل انخفاض المبيعات قبل الدخول في الخسارة.`, `It shows how much sales can drop before the business starts losing money.` ), }, ]; const base = catalog[(idx - 1) % catalog.length]; return { id: `cost-${idx}`, level, q: base.q, answer: base.a, notes: pair( `سؤال ${idx} - مستوى ${level}: ركّز على المفهوم والقرار الإداري، وليس الحساب فقط.`, `Question ${idx} - Level ${level}: focus on management decision impact, not only calculation.` ), }; } function buildTrackQuestions(builder) { const out = []; for (let level = 1; level <= LEVELS; level++) { for (let i = 0; i < LEVEL_SIZE; i++) { out.push(builder(level, i)); } } return out; } const tracks = { excel: { title: pair("اكسيل", "Excel"), lessons: Array.from({ length: LEVELS }, (_, i) => getExcelLesson(i + 1)), questions: buildTrackQuestions(excelQuestionTemplate), }, cost: { title: pair("كوست كونترول", "Cost Control"), lessons: Array.from({ length: LEVELS }, (_, i) => getCostLesson(i + 1)), questions: buildTrackQuestions(costQuestionTemplate), }, }; function loadState() { try { const raw = localStorage.getItem(STORAGE_KEY); if (!raw) return { track: null, lang: "ar", scores: {}, answered: {}, typedAnswers: {} }; const parsed = JSON.parse(raw); return { track: parsed.track || null, lang: parsed.lang || "ar", scores: parsed.scores || {}, answered: parsed.answered || {}, typedAnswers: parsed.typedAnswers || {}, }; } catch { return { track: null, lang: "ar", scores: {}, answered: {}, typedAnswers: {} }; } } function saveState(state) { localStorage.setItem(STORAGE_KEY, JSON.stringify(state)); } const state = loadState(); function txt(key) { return t[state.lang][key]; } function val(obj) { return obj[state.lang]; } function totalScore() { return Object.values(state.scores).reduce((a, b) => a + (Number(b) || 0), 0); } function levelScore(track, level) { return Array.from({ length: LEVEL_SIZE }, (_, i) => { const id = `${track}-${(level - 1) * LEVEL_SIZE + i + 1}`; return Number(state.scores[id] || 0); }).reduce((a, b) => a + b, 0); } const root = document.createElement("div"); root.id = "inversion-trainer-root"; root.innerHTML = `
${txt("selectTrackFirst")}
`; return; } const track = tracks[state.track]; let html = ""; for (let level = 1; level <= LEVELS; level++) { const questions = track.questions.slice((level - 1) * LEVEL_SIZE, level * LEVEL_SIZE); html += `${txt("question")} ${idx + 1}: ${val(q.q)}
Exam duration is 60 minutes. The timer starts when you click “Start exam”.
Choose the plan that fits your goals and get structured learning, job access, and direct support.
Prices are displayed in your country's currency
Fill in your details accurately so the concerned team can review your request and proceed with the booking process.