تمارين المفاهيم


تمارين المفاهيم هي تمارين مصمّمة لتعليم مفاهيم (برمجية) محدّدة. وتشكّل المفاهيم التي تعلّمها تمارين المفاهيم منهجًا. لمزيد من المعلومات حول كيفية تصميم منهج، اطّلع على توثيق المنهج.

Note

يمكنك إنشاء هيكل تمرين مفهوم جديد بسرعة بتشغيل الأوامر التالية من الدليل الجذر للمسار:

bin/fetch-configlet
bin/configlet create --concept-exercise <slug>

لمزيد من المعلومات، اطّلع على توثيق configlet create

البيانات الوصفية

تُعرَّف البيانات الوصفية لتمرين المفهوم في المفتاح exercises.concept داخل ملف config.json. وتحدّد البيانات الوصفية معرّف UUID الخاص بالتمرين وقيمة slug والمزيد.

مثال

{
  "exercises": {
    "concept": [
      {
        "uuid": "93fbc7cf-3a7e-4450-ad22-e30129c36bb9",
        "slug": "cars-assemble",
        "name": "Cars, Assemble!",
        "concepts": ["if-statements", "numbers"],
        "prerequisites": ["basics"]
      }
    ]
  }
}

الملفات

لكل تمرين مفهوم دليل خاص به داخل دليل exercises/concept الخاص بالمسار. ويجب أن يطابق اسم دليل تمرين المفهوم خاصية slug الخاصة بتمرين المفهوم، كما هي معرّفة في ملف config.json.

ويتضمّن تمرين المفهوم أربعة أنواع من الملفات:

ملفات التوثيق

تُعرض هذه الملفات على الطالب للمساعدة في شرح التمرين.

  • .docs/introduction.md: يقدّم المفهوم أو المفاهيم التي يعلّمها التمرين للطالب (مطلوب)
  • .docs/instructions.md: يقدّم تعليمات التمرين (مطلوب)
  • .docs/hints.md: يقدّم تلميحات للطالب تساعده على تجاوز العقبات في التمرين (مطلوب)

ملفات البيانات الوصفية

لا تُعرض هذه الملفات على الطالب، بل تُستخدم لتعريف البيانات الوصفية للتمرين.

  • .meta/config.json: يحتوي على معلومات وصفية عن التمرين (مطلوب)
  • .meta/design.md: يصف تصميم التمرين (مطلوب)

ملفات الأساليب

تصف هذه الملفات الأساليب الخاصة بالتمرين.

  • .approaches/introduction.md: مقدمة عن أكثر الأساليب شيوعًا للتمرين (اختياري)
  • .approaches/config.json: البيانات الوصفية للأساليب (اختياري)
  • .approaches/<approach-slug>/content.md: وصف الأسلوب (اختياري)
  • .approaches/<approach-slug>/snippet.txt: مقتطف يعرض الأسلوب (اختياري)

ملفات المقالات

تصف هذه الملفات المقالات الخاصة بالتمرين.

  • .articles/config.json: البيانات الوصفية للمقالات (اختياري)
  • .articles/<article-slug>/content.md: وصف المقالة (اختياري)
  • .articles/<article-slug>/snippet.md: مقتطف يعرض المقالة (اختياري)

ملفات التمرين

الملفات الخاصة بلغة البرمجة، مثل ملفات التنفيذ والاختبار. وأسماء هذه الملفات خاصة بالمسار.

  • مجموعة الاختبارات: تتحقق من صحة الحل (مطلوب)
  • التنفيذ المبدئي: يوفّر نقطة انطلاق للطلاب (مطلوب)
  • التنفيذ النموذجي: يوفّر تنفيذًا متوافقًا مع أسلوب اللغة ويجتاز جميع الاختبارات (مطلوب)
  • ملفات إضافية: تضمن إمكانية تشغيل الاختبارات (اختياري)

مثال

exercises
└── concept
    └── cars-assemble
        ├── .approaches
        |   ├── for-loop
        |   |   ├── content.md
        |   |   └── snippet.txt
        |   ├── config.json
        |   └── introduction.md
        ├── .articles
        |   ├── performance
        |   |   ├── content.md
        |   |   └── snippet.md
        |   └── config.json
        ├── .docs
        |   ├── introduction.md
        |   ├── instructions.md
        |   └── hints.md
        ├── .meta
        |   ├── config.json        
        |   ├── design.md
        |   └── Exemplar.cs (التنفيذ النموذجي)
        ├── CarsAssemble.cs (التنفيذ المبدئي)
        └── CarsAssemblyTests.cs (الاختبارات)

الحد الأدنى من المواصفات الصالحة

نفضّل نهج «الدمج المتفائل» مع التمارين الجديدة، حيث يمكن للمسارات تطوير التمارين في حالة «قيد العمل». والحد الأدنى من الحالة الصالحة، التي ستجتاز configlet وتسمح لك بالدمج، هو:

  • مدخل صالح في config.json الخاص بالمسار، مع ضبط status على wip.
  • ملف .meta/config.json صالح
  • وجود الملفات التالية، وإن كان يُسمح بأن تكون فارغة:
    • .docs/introduction.md
    • .docs/instructions.md
    • .docs/hints.md
    • التنفيذ المبدئي
    • ملف الاختبار

ملف: .docs/introduction.md

الغرض: تقديم المفهوم أو المفاهيم التي يعلّمها التمرين للطالب.

التواجد: مطلوب

  • ينبغي أن تمنح المعلومات المقدّمة الطالب قدرًا كافيًا من السياق ليصل إلى الحل بنفسه.
  • ينبغي تقديم المعلومات اللازمة فقط لفهم أساسيات المفهوم وحلّ التمرين. أما المعلومات الإضافية فتُترك لمستند about.md الخاص بالمفهوم.
  • ينبغي استخدام الروابط باعتدال، إن استُخدمت أصلًا. فرغم أن رابطًا يشرح موضوعًا معقّدًا مثل الاستدعاء الذاتي قد يكون مفيدًا، فإن الروابط في معظم المفاهيم تقدّم معلومات أكثر من اللازم؛ لذا ينبغي أن يكون الهدف شرح الأمور بإيجاز في صلب النص.
  • ينبغي استخدام المصطلحات التقنية الصحيحة حتى يستطيع الطالب البحث بسهولة عن مزيد من المعلومات.
  • لا تُستخدم أمثلة الكود إلا لتقديم صياغة جديدة (إذ لا ينبغي أن يحتاج الطالب إلى البحث في الويب عن أمثلة للصياغة). وفي الحالات الأخرى، قدّم وصفًا أو روابط بدلًا من الكود.

على سبيل المثال، قد تصف مقدمة تمرين «السلاسل النصية» السلسلة النصية بأنها مجرد «تسلسل من محارف يونيكود» أو «سلسلة من البايتات»، وتخبر المستخدمين بكيفية إنشاء سلسلة نصية، وتوضّح أن للسلسلة النصية طُرقًا يمكن استخدامها لمعالجتها. وما لم يكن الطالب بحاجة إلى فهم تفاصيل أكثر دقة لحلّ التمرين، فإن هذا النوع من الشرح الموجز (إلى جانب مثال على صياغته) ينبغي أن يكون معلومات كافية ليحلّ الطالب التمرين.

مثال

# Introduction

There are two primary ways to assign objects to names in Ruby - using variables or constants. Variables are always written in snake case. A variable can reference different objects over its lifetime. For example, `my_first_variable` can be defined and redefined many times using the `=` operator:

```ruby
my_first_variable = 1
my_first_variable = "Some string"
my_first_variable = SomeComplexObject.new
```

ملف: .docs/introduction.md.tpl

الغرض: قالب يُولَّد منه ملف introduction.md.

التواجد: اختياري

يقدّم مستند introduction.md مفهوم التمرين أو مفاهيمه للطالب. ولكل مفهوم أيضًا مستند introduction.md الخاص به، ولا يُعرض خارج سياق تمرين.

إذا كان ينبغي تضمين مقدمة المفهوم حرفيًا في مقدمة التمرين، فيمكن استخدام ملف introduction.md.tpl. ويتيح هذا الملف الإشارة إلى مقدمات المفاهيم عبر العناصر النائبة: %{concept:<concept-slug>}.

يستطيع configlet توليد ملف introduction.md من ملف قالب. وسيكون في الملف المولَّد عناصر نائبة للمفاهيم استُبدلت بمحتويات introduction الخاصة بالمفهوم.

لا يعرف موقع Exercism إلا مستند introduction.md. وتقع على عاتق المسار مسؤولية توليد introduction.md عند استخدام ملف قالب.

يمكن للمسارات أن تقرّر لكل تمرين ما إذا كانت ستستخدم قالبًا أم لا. وفي بعض الحالات، قد لا يكون استخدام مقدمة المفهوم حرفيًا هو الأمثل. اختر دائمًا ما يوفّر أفضل تجربة تعلّم للطالب.

مثال

# Introduction

%{concept:variables}

ملف: .docs/instructions.md

الغرض: تقديم تعليمات التمرين.

التواجد: مطلوب

ينقسم هذا الملف إلى جزأين.

  1. يشرح الجزء الأول «قصة» التمرين أو «فكرته». وينبغي ألّا يحتوي عمومًا على أي أمثلة كود.
  2. ويقدّم الجزء الثاني تعليمات واضحة عمّا يحتاج الطالب إلى فعله، في صورة مهمة واحدة أو أكثر.

ويجب أن تتوافق كل مهمة مع المعيار التالي:

  • أن تبدأ بعنوان من المستوى الثاني يبدأ برقم (مثل ## 1. Do X، ## 2. Do Y).
  • ينبغي أن يصف العنوان ما يجب تنفيذه، لا كيفية تنفيذه (مثل ## 1. Check if an appointment has already passed).
  • صِف الدالة أو الطريقة التي يحتاج الطالب إلى تعريفها أو تنفيذها (مثل Implement method X(...) that takes an A and returns a Z)،
  • قدّم مثالًا على استخدام تلك الدالة في الكود. وينبغي أن تختلف هذه الأمثلة عن تلك الواردة في الاختبارات.

نولي أهمية كبيرة لجعل محتوى Exercism آمنًا للجميع، ولذلك كثيرًا ما نتحرّز في تقرير ما إذا كانت القصص مناسبة أم لا. ومع حرصنا على ما ندمجه، فإننا ندرك صعوبة إدراك ما قد يُنظر إليه على أنه إشكالي، لذا سنفترض دائمًا أنك تتصرف بحسن نية، وسنبذل قصارى جهدنا لالتقاط أي مشكلات في المراجعة بأسلوب غير مواجهاتي. وإذا أردت أن تراجع قصة معنا، فاذكر @exercism/leadership وسننظر فيها معًا. وإليك بعض النقاط الإرشادية:

  • حاول التأكد من أن القصة مُرحِّبة ويمكن للجميع فهمها. وإذا كانت القصة تحتوي على نكات داخلية أو عامية إقليمية، فحاول التفكير في عبارات بديلة.
  • حاول كتابة أمثلة شاملة للجميع. على سبيل المثال، فكّر في استخدام أسماء من ثقافات أخرى تشمل الجنسين.
  • اسأل نفسك إن كنت تعرف شخصيًا أي شخص قد يُستاء من القصة. وإذا كان الأمر كذلك، ففكّر في تغييرها لتجنّب ذلك.

مثال

# Instructions

In this exercise you're going to write some code to help you cook a brilliant lasagna from your favorite cooking book.

## 1. Calculate the remaining oven time in minutes

Define the `Lasagna#remaining_minutes_in_oven` method that takes the actual minutes the lasagna has been in the oven as a parameter and returns how many minutes the lasagna still has to remain in the oven, based on the expected oven time in minutes from the previous task.

```ruby
lasagna = Lasagna.new
lasagna.remaining_minutes_in_oven(30)
# => 10
```

ملف: .docs/hints.md

الغرض: تقديم تلميحات للطالب تساعده على تجاوز العقبات في التمرين.

التواجد: مطلوب

  • إذا واجه الطالب صعوبة، سنتيح له النقر على زر لطلب تلميح، يعرض الجزء ذا الصلة من الملف.
  • ينبغي أن تكون التلميحات في نقاط تحت العناوين.
  • ينبغي أن تكفي التلميحات لإزالة العقبة أمام أي طالب تقريبًا.
  • ينبغي ألّا تشرح التلميحات الحل بالتفصيل، بل تشير إلى مصدر يصف الحل (مثل الربط بتوثيق الدالة المطلوب استخدامها).
  • يجوز أن تستخدم التلميحات أمثلة كود لشرح المفاهيم، لكن ليس لتوضيح الحل. على سبيل المثال، قد تعرض في تمرين عن المصفوفات مقتطفًا يوضّح كيف تعمل دالة مصفوفة معيّنة، لكن دون أن يكون قابلاً للنسخ واللصق مباشرة في الحل.
  • يمكن أن تظهر التلميحات العامة حول التمرين كقائمة Markdown تحت عنوان ## General.
  • ينبغي أن تظهر التلميحات الخاصة بمهمة معيّنة كقائمة Markdown تحت عناوين تطابق عنوان مهمتها في instructions.md (مثل ## 2. Do Y).
  • إن لم توجد تلميحات عامة أو لم توجد تلميحات لمهمة معيّنة، فينبغي حذف العناوين. ويجب أن يتبع كل عنوان قائمة Markdown.
  • أعطِ الأولوية للتلميحات الخاصة بالمهام على التلميحات العامة، لأن التلميحات الخاصة بالمهام أكثر احتمالًا لإزالة العقبة أمام الطالب.
  • ينبغي أن تصف عناوين المهام ما تهدف إليه المهمة، لا كيفية تنفيذها.
  • ينبغي أن تتبع عناوين المهام النمط المعتاد في كتابة العناوين (مثل ## 2. Check if a book can be borrowed).
  • ينبغي أن تكون المهام صريحة بشأن الطريقة أو الدالة أو النوع المطلوب تنفيذه وقيمته المتوقعة (مثل Implement the 'canBorrowBook' function to check if a book can be borrowed. The function takes a book as its parameter and returns `true` if the book has not already been borrowed; otherwise, return `false`).

لن يكون عرض التلميحات مسارًا «موصى به»، وسنثني (بلطف) عن استخدامه ما لم يكن الطالب غير قادر على التقدّم بدونه. ومن ثمّ، يجدر الأخذ في الاعتبار أن الطالب الذي يقرؤها سيكون مرتبكًا بعض الشيء أو مشوشًا، وربما محبطًا.

مثال

# Hints

## General

- You need to define a [constant][constant] which should contain the [integer][integers] value specified in the recipe.

## 1. Calculate the remaining oven time in minutes

- You need to define a [method][methods] with a single parameter for the actual time so far.

[constants]: https://www.rubyguides.com/2017/07/ruby-constants/
[integers]: https://ruby-doc.org/core-2.7.0/Integer.html
[methods]: https://launchschool.com/books/ruby/read/methods

ملف: .meta/design.md

الغرض: وصف تصميم التمرين.

التواجد: مطلوب

يحتوي هذا الملف على معلومات حول تصميم التمرين، تشمل أشياء مثل هدفه، وأهدافه التعليمية، وما ينبغي عدم تدريسه، وغير ذلك. ويمكن استخراج هذه المعلومات من مشكلة GitHub المقابلة للتمرين.

وهو موجود لإطلاع المشرفين أو المساهمين المستقبليين على نطاق التمرين وحدوده، وتجنّب النزعة الطبيعية إلى جعل التمارين أكثر تعقيدًا مع الوقت.

مثال

# Design

## Goal

The goal of this exercise is to teach the student the basics of programming in Ruby.

## Learning objectives

- Know what a variable is.
- Know how to define a variable.
- Know how to update a variable.

## Out of scope

- Memory and performance characteristics.
- Method overloads.

## Concepts

The Concepts this exercise unlocks are:

- `basics`: know what a variable is; know how to define a variable; know how to update a variable.

## Prerequisites

There are no prerequisites.

ملف: .meta/config.json

الغرض: يحتوي على معلومات وصفية عن التمرين.

التواجد: مطلوب

يحتوي هذا الملف على معلومات وصفية عن التمرين:

  • authors: اسم المستخدم على GitHub لمؤلف التمرين أو مؤلفيه (مطلوب)
    • بما في ذلك المراجعين إذا غيّرت مراجعاتهم التمرين تغييرًا جوهريًا (إلى حدّ يبدو معه أن «الفضل مشترك»)
  • contributors: اسم المستخدم على GitHub لمساهم التمرين أو مساهميه (اختياري)
    • بما في ذلك المراجعين إذا كانت مراجعاتهم ذات دلالة أو قابلة للتنفيذ أو نُفّذت.
  • forked_from: التمرين أو التمارين التي استُنسخ منها (مطلوب إذا كان التمرين منسوخًا)
  • files: مواضع الملفات المستخدمة في هذا التمرين، نسبةً إلى دليل التمرين (مطلوب)
  • language_versions: متطلبات إصدار اللغة (اختياري)
  • blurb: وصف قصير لهذا التمرين. ويجب أن يكون طوله <= 350. لا يُدعم Markdown (مطلوب)
  • source: المصدر الذي يستند إليه هذا التمرين (اختياري)
  • source_url: رابط المصدر الذي يستند إليه هذا التمرين (اختياري)
  • representer: معلومات وصفية تتعلق بكيفية معالجة representer لهذا الملف (اختياري)
    • version: عدد صحيح لإصدار representer المستخدم للتمرين (مطلوب إذا وُجد المفتاح الأب)
  • icon: قيمة slug الخاصة بالأيقونة (انظر القائمة الكاملة للأيقونات). وإذا لم تُحدَّد، فستُستخدم قيمة slug الخاصة بالتمرين (اختياري)
  • custom: أي بيانات خاصة بالتمرين وغير قياسية. يمكن استخدامه لتخصيص سلوك أدوات المسار لكل تمرين (اختياري)

إذا كان شخص ما مؤلفًا _و_مساهمًا في الوقت نفسه، فاذكره كمؤلف فقط.

مثال مبسّط

{
  "authors": ["FSharpForever"],
  "files": {
    "solution": ["Lasagna.fs"],
    "test": ["LasagnaTests.fs"],
    "exemplar": [".meta/Exemplar.fs"]
  },
  "blurb": "Learn the basics of F# by cooking Lucian's Luscious Lasagna"
}

مثال كامل

افترض أن المستخدم FSharpForever كتب تمرينًا اسمه log-levels لمسار F#. ثمّ كيّف PythonProfessor التمرين لمسار Python. وبعد ذلك، حسّن المستخدم GladToHelp التمرين.

{
  "authors": ["PythonProfessor"],
  "contributors": ["GladToHelp"],
  "files": {
    "solution": ["log_levels.py"],
    "test": ["log_levels_test.py"],
    "exemplar": [".meta/exemplar.py"],
    "editor": ["test_helper.py"]
  },
  "forked_from": ["fsharp/log-levels"],
  "language_versions": ">=3.7",
  "blurb": "Learn how to work with strings by processing log lines.",
  "source": "Wikipedia",
  "source_url": "https://en.wikipedia.org/wiki/Log_file",
  "representer": {
    "version": 2
  },
  "icon": "logs",
  "custom": {
    "parallel": true
  }
}

لاحظ ما يلي:

  • ترتيب المؤلفين والمساهمين ليس مهمًا وليس له معنى.
  • إذا كنت تنسخ تمرينًا، فلا تشر إلى المؤلفين أو المساهمين الأصليين. احرص فقط على أن يكون forked_from صحيحًا.
  • ورغم أن ذلك ليس شائعًا، فإن نسخ تمرين من عدة تمارين ممكن.
  • language_versions سلسلة نصية حرة الصيغة، وللمسارات حرية استخدامها وتفسيرها كما تشاء.

ملف: .approaches/introduction.md

الغرض: مقدمة عن أكثر الأساليب شيوعًا للتمرين

التواجد: اختياري

يصف هذا الملف أكثر الأساليب شيوعًا للتمرين. اطّلع على التوثيق لمزيد من المعلومات حول ما ينبغي أن يحتويه هذا الملف.

مثال

# Introduction

The key to this exercise is to deal with C# strings being immutable, which means that a `string`'s value cannot be changed.
Therefore, to reverse a string you'll need to create a _new_ `string`.

## Using LINQ

```csharp
public static string Reverse(string input)
{
    return new string(input.Reverse().ToArray());
}
```

For more information, check the [LINQ approach][approach-linq].

## Which approach to use?

If readability is your primary concern (and it usually should be), the LINQ-based approach is hard to beat.

ملف: .approaches/config.json

الغرض: البيانات الوصفية للأساليب

التواجد: اختياري (مطلوب عند وجود مقدمة أسلوب أو أسلوب)

يحتوي هذا الملف على معلومات وصفية عن أساليب التمرين:

  • introduction: اسم المستخدم على GitHub لمؤلف أو مؤلفي مقدمة أسلوب التمرين (اختياري)

    • authors: اسم المستخدم على GitHub لمؤلف أو مؤلفي مقدمة أسلوب التمرين (مطلوب)
      • بما في ذلك المراجعين إذا غيّرت مراجعاتهم مقدمة أسلوب التمرين تغييرًا جوهريًا (إلى حدّ يبدو معه أن «الفضل مشترك»)
    • contributors: اسم المستخدم على GitHub لمساهم أو مساهمي مقدمة أسلوب التمرين (اختياري)
      • بما في ذلك المراجعين إذا كانت مراجعاتهم ذات دلالة أو قابلة للتنفيذ أو نُفّذت.
  • approaches: مصفوفة تسرد الأساليب المفصّلة (اختياري)

    • uuid: معرّف UUID من الإصدار V4 يميّز الأسلوب تمييزًا فريدًا. ويجب أن يكون المعرّف فريدًا داخل المسار وعلى مستوى جميع المسارات، وألّا يتغير أبدًا
    • slug: قيمة slug الخاصة بالأسلوب، وهي سلسلة بحروف صغيرة بصيغة kebab-case. ويجب أن تكون قيمة slug فريدة على مستوى جميع قيم slug للأساليب داخل المسار. ويجب أن يكون طولها <= 255.
    • title: عنوان الأسلوب. ويجب أن يكون طوله <= 255.
    • blurb: وصف قصير لهذا الأسلوب. ويجب أن يكون طوله <= 350. لا يُدعم Markdown (مطلوب)
    • authors: اسم المستخدم على GitHub لمؤلف أو مؤلفي أسلوب التمرين (مطلوب)
      • بما في ذلك المراجعين إذا غيّرت مراجعاتهم أسلوب التمرين تغييرًا جوهريًا (إلى حدّ يبدو معه أن «الفضل مشترك»)
    • contributors: اسم المستخدم على GitHub لمساهم أو مساهمي أسلوب التمرين (اختياري)
      • بما في ذلك المراجعين إذا كانت مراجعاتهم ذات دلالة أو قابلة للتنفيذ أو نُفّذت.
    • tags: تحديد شروط ربط الحل المُرسَل بأسلوب معيّن. (اختياري)
      • all: مصفوفة من الوسوم يجب أن تكون جميعها موجودة في الحل المُرسَل (اختياري، إلا إذا كانت any بلا عناصر)
      • any: مصفوفة من الوسوم يجب أن يكون واحد منها على الأقل موجودًا في الحل المُرسَل (اختياري، إلا إذا كانت all بلا عناصر)
      • not: يجب ألّا يكون أي من الوسوم موجودًا في الحل المُرسَل (اختياري)

مثال

{
  "introduction": {
    "authors": ["erikschierboom"]
  },
  "approaches": [
    {
      "uuid": "448fb2b4-18ab-4e55-aa54-ad4ed6d5f7f6",
      "slug": "span",
      "title": "Use Span<T>",
      "blurb": "Use Span<T> to efficiently reverse a string.",
      "authors": ["erikschierboom"]
    }
  ]
}

ملف: .approaches/<approach-slug>/content.md

الغرض: وصف مفصّل للأسلوب

التواجد: اختياري (مطلوب للأساليب)

يحتوي هذا الملف على وصف مفصّل للأسلوب. اطّلع على التوثيق لمزيد من المعلومات حول ما ينبغي أن يحتويه هذا الملف.

مثال

# Span

```csharp
Span<char> chars = stackalloc char[input.Length];
for (var i = 0; i < input.Length; i++)
{
    chars[input.Length - 1 - i] = input[i];
}
return new string(chars);
```

This `Span<T>` approach uses a `for` loop.

ملف: .approaches/<approach-slug>/snippet.txt

الغرض: مقتطف يعرض الأسلوب

التواجد: اختياري (مطلوب للأساليب)

يحتوي هذا الملف على مقتطف صغير يعرض الأسلوب. ويُعرض المقتطف في صفحة «التعمّق أكثر» الخاصة بالتمرين.

ويجب أن يكون عدد أسطره <= 8.

اطّلع على التوثيق لمزيد من المعلومات حول ما ينبغي أن يحتويه هذا الملف.

مثال

Span<char> chars = stackalloc char[input.Length];
for (var i = 0; i < input.Length; i++)
{
    chars[input.Length - 1 - i] = input[i];
}
return new string(chars);

ملف: .article/config.json

الغرض: البيانات الوصفية للمقالات

التواجد: اختياري (مطلوب عند وجود مقالة)

يحتوي هذا الملف على معلومات وصفية عن مقالات التمرين:

  • articles: مصفوفة تسرد المقالات المفصّلة (اختياري)
    • uuid: معرّف UUID من الإصدار V4 يميّز المقالة تمييزًا فريدًا. ويجب أن يكون المعرّف فريدًا داخل المسار وعلى مستوى جميع المسارات، وألّا يتغير أبدًا
    • slug: قيمة slug الخاصة بالمقالة، وهي سلسلة بحروف صغيرة بصيغة kebab-case. ويجب أن تكون قيمة slug فريدة على مستوى جميع قيم slug للمقالات داخل المسار. ويجب أن يكون طولها <= 255.
    • title: عنوان المقالة. ويجب أن يكون طوله <= 255.
    • blurb: وصف قصير لهذه المقالة. ويجب أن يكون طوله <= 350. لا يُدعم Markdown (مطلوب)
    • authors: اسم المستخدم على GitHub لمؤلف أو مؤلفي مقالة التمرين (مطلوب)
      • بما في ذلك المراجعين إذا غيّرت مراجعاتهم مقالة التمرين تغييرًا جوهريًا (إلى حدّ يبدو معه أن «الفضل مشترك»)
    • contributors: اسم المستخدم على GitHub لمساهم أو مساهمي مقالة التمرين (اختياري)
      • بما في ذلك المراجعين إذا كانت مراجعاتهم ذات دلالة أو قابلة للتنفيذ أو نُفّذت.

مثال

{
  "articles": [
    {
      "uuid": "6db71962-62d5-448b-a980-c20ae41013ed",
      "slug": "performance",
      "title": "Optimizing performance",
      "blurb": "Explore how to most efficiently reverse a string and what the trade-offs are.",
      "authors": ["erikschierboom"]
    }
  ]
}

ملف: .articles/<article-slug>/content.md

الغرض: وصف مفصّل للأسلوب

التواجد: اختياري (مطلوب للأساليب)

يحتوي هذا الملف على وصف مفصّل للأسلوب. اطّلع على التوثيق لمزيد من المعلومات حول ما ينبغي أن يحتويه هذا الملف.

مثال

# Performance

In this document, we'll find out which approach is the most performant one.

## Benchmark results

| Method |      Mean |     Error |    StdDev |    Median | Allocated |
| -----: | --------: | --------: | --------: | --------: | --------: |
|   Linq | 29.133 ns | 0.5865 ns | 0.5486 ns | 28.984 ns |      80 B |
|  Array |  4.806 ns | 0.4999 ns | 1.4739 ns |  3.967 ns |         - |

ملف: .articles/<article-slug>/snippet.txt

الغرض: مقتطف يعرض الأسلوب

التواجد: اختياري (مطلوب للمقالات)

يحتوي هذا الملف على مقتطف صغير يعرض المقالة. ويُعرض المقتطف في صفحة «التعمّق أكثر» الخاصة بالتمرين.

ويجب أن يكون عدد أسطره <= 8.

اطّلع على التوثيق لمزيد من المعلومات حول ما ينبغي أن يحتويه هذا الملف.

مثال

| Method |      Mean | Allocated |
| -----: | --------: | --------: |
|   Linq | 29.133 ns |      80 B |
|  Array |  4.806 ns |         - |

ملف: التنفيذ المبدئي

الغرض: توفير نقطة انطلاق للطلاب.

التواجد: مطلوب

  • صمّم التنفيذ المبدئي بحيث يعرف الطالب أين يضيف الكود.
  • عرّف هياكل مبدئية لكل صياغة لم تُقدَّم في التمرين. وفي معظم التمارين، يعني هذا تعريف دوال أو طُرق مبدئية.
  • في اللغات المترجَمة، فكّر في أن يكون الكود قابلًا للترجمة، لأن رسائل المترجم قد تصعب أحيانًا على الطلاب الجدد في اللغة.
  • ينبغي أن يكون الكود أبسط ما يمكن.
  • استخدم فقط ميزات اللغة التي يقدّمها التمرين أو متطلباته السابقة (ومتطلباتها السابقة، وهكذا).
  • يُعرض ملف التنفيذ المبدئي على الطالب عند البرمجة داخل المتصفح، ويُتنزَّل إلى نظام ملفات الطالب عند استخدام واجهة سطر الأوامر.
  • يجب تحديد المسارات النسبية إلى ملف أو ملفات التنفيذ المبدئي في المفتاح "files.solution" في ملف .meta/config.json.

مثال

class Lasagna
  def remaining_minutes_in_oven(actual_minutes_in_oven)
    raise NotImplementedError, 'Please implement the Lasagna#remaining_minutes_in_oven method'
  end

  def preparation_time_in_minutes(layers)
    raise NotImplementedError, 'Please implement the Lasagna#preparation_time_in_minutes method'
  end
end

ملف: الاختبارات

الغرض: التحقق من صحة الحل.

التواجد: مطلوب

  • ينبغي ألّا تستخدم الاختبارات الأمثلة الواردة في ملف instructions.md.
  • ينبغي أن يكون الكود أبسط ما يمكن.
  • استخدم فقط ميزات اللغة التي تقدّمها المتطلبات السابقة للتمرين (ومتطلباتها السابقة، وهكذا).
  • لا يُعرض ملف الاختبارات على الطالب عند البرمجة داخل المتصفح، لكنه يُتنزَّل إلى نظام ملفات الطالب عند استخدام واجهة سطر الأوامر.
  • يجب تحديد المسارات النسبية إلى ملف أو ملفات الاختبار في المفتاح "files.test" في ملف .meta/config.json.

مثال

require 'minitest/autorun'
require_relative 'lasagna'

class LasagnaTest < Minitest::Test
  def test_remaining_minutes_in_oven
    assert_equal 15, Lasagna.new.remaining_minutes_in_oven(25)
  end

  def test_preparation_time_in_minutes_with_one_layer
    assert_equal 2, Lasagna.new.preparation_time_in_minutes(1)
  end

  def test_preparation_time_in_minutes_with_multiple_layers
    assert_equal 8, Lasagna.new.preparation_time_in_minutes(4)
  end
end

ملف: التنفيذ النموذجي

الغرض: توفير التنفيذ المستهدف الذي ينبغي أن يسعى إليه الطالب.

التواجد: مطلوب

  • هذا التنفيذ هو الكود المستهدف الذي نريد أن يسعى إليه الطالب.
  • سيُعرض هذا الكود على الموجّهين باعتباره «الهدف» عند كتابة ملاحظاتهم
  • ينبغي ألّا يستخدم التنفيذ إلا ميزات اللغة التي يقدّمها التمرين أو متطلباته السابقة (ومتطلباتها السابقة، وهكذا).
  • لا يُعرض ملف التنفيذ النموذجي على الطالب عند البرمجة داخل المتصفح، ولا يُتنزَّل إلى نظام ملفات الطالب عند استخدام واجهة سطر الأوامر.
  • سيُعرض ملف التنفيذ النموذجي على الموجّهين عند التعليق على الحلول أو التمثيلات.
  • يجب تحديد المسارات النسبية إلى ملف أو ملفات التنفيذ النموذجي في المفتاح "files.exemplar" في ملف .meta/config.json.

مثال

class Lasagna
  EXPECTED_MINUTES_IN_OVEN = 40
  PREPARATION_MINUTES_PER_LAYER = 2

  def remaining_minutes_in_oven(actual_minutes_in_oven)
    EXPECTED_MINUTES_IN_OVEN - actual_minutes_in_oven
  end

  def preparation_time_in_minutes(layers)
    layers * PREPARATION_MINUTES_PER_LAYER
  end
end

ملف: ملفات إضافية

الغرض: ضمان إمكانية تشغيل الاختبارات.

التواجد: مطلوب إذا لم تكفِ الملفات الافتراضية لتشغيل الاختبارات

تحتاج بعض اللغات إلى ملفات إضافية لتشغيل الاختبارات. ومن أمثلة ذلك ملفات مشروع C# وملفات package.json في Node، التي بدونها لا يمكن تشغيل الاختبارات.

الملفات المشتركة

بعض الملفات ليست خاصة بتمرين بعينه، بل تنطبق على جميع التمارين. اطّلع على التوثيق لمزيد من المعلومات.

التسمية

ينبغي تسمية تمارين المفاهيم وفق قصتها أو فكرتها، لا وفق مفهومها أو مفاهيمها.

أمثلة جيدة على الأسماء:

  • Tim from Marketing
  • Lucian's Luscious Lasagna
  • Calculator Conundrum

أسماء غير مسموح بها:

  • Booleans: يستخدم اسم مفهوم، لا اسم قصة
  • Exercise #1: التمرين ليس قصة أو فكرة

عند نسخ تمرين دون تغييرات جوهرية، استخدم الاسم الأصلي إن أمكن.

قيم slug

لكل تمرين أيضًا قيمة slug، وهي نسخة معياريّة من اسم التمرين وفق القواعد التالية:

  1. استخدم الحروف الصغيرة.
  2. استخدم kebab-case.
  3. استخدم الأحرف اللاتينية الأبجدية الرقمية والشرطات (التعبير النمطي: [a-z0-9-]+)
  4. فضّل الأرقام المكتوبة بالحروف على الأرقام الرقمية، إلا إذا وُجد سبب محدّد لتفضيل الرقم (مثل two-fer بدلًا من 2-fer)

أمثلة جيدة على قيم slug:

  • tim-from-marketing
  • lucians-luscious-lasagna
  • calculator-conundrum

قيم slug غير مسموح بها:

  • TIM-FROM-MARKETING: لا يستخدم الحروف الصغيرة (أي tim-from-marketing)
  • TimFromMarketing: لا يستخدم kebab-case (أي tim-from-marketing)
  • floating-point-numbers: يستخدم اسم مفهوم، لا اسم قصة

العرض

هناك اختلاف في طريقة عرض توثيق التمرين للطالب عند استخدام المحرر داخل المتصفح مقابل استخدام واجهة سطر الأوامر. اطّلع على هذا المستند لمزيد من المعلومات.

الأيقونة

لكل تمرين أيقونة مصاحبة. وبشكل افتراضي، تكون الأيقونة المعروضة هي التي يطابق اسمها قيمة slug الخاصة بالتمرين. ويمكن تجاوز ذلك بتحديد خاصية icon في ملف .meta/config.json الخاص بالتمرين.

إذا كنت تنسخ تمرينًا موجودًا، فمن المحتمل أن تكون هناك أيقونة له بالفعل. وإن لم توجد، فيرجى فتح مشكلة في مستودع website-icons.