It is very common task to write some sort of testing application. It can be both an educational task and a commectial product. And the use of the composite pattern can dramatically simplify this task (of course if you are not making one-level tests). Composition pattern allows you to work with case studie as with any other kind of questions. You can read about this pattern here.
Here is my simple example of this pattern:
Classes for questions:
And I would add singleton pattern for test (and this class would calculate current points, watch for current question etc.). If you are interested I can show more complex example.
Here is my simple example of this pattern:
Classes for questions:
public abstract class TestTask { public TestTask(string text) { answers = new List<TaskAnswer>(); TaskText = text; } //abstract methods, common for every existing task public abstract void AddSubElement(TestTask element); public abstract void RemoveSubElement(TestTask element); public abstract bool CheckTask(); //methods and properties for answers private List<TaskAnswer> answers; public string TaskText { get; set; } public void AddAnswer(params KeyValuePair<string, bool>[] newAnswers) { foreach (var answer in newAnswers) { answers.Add(new TaskAnswer(answer.Key, answer.Value)); } } public void RemoveAnswer(int number) { answers.RemoveAt(number); } } public class SingleChoiseTask: TestTask { public SingleChoiseTask(string text) : base(text) {} //property for selected answer public TaskAnswer SelectedAnswer { get; set; } public override bool CheckTask() { //for single choise question just check if selected answer is correct return SelectedAnswer != null && SelectedAnswer.IsCorrect; } //single choise question cannot have any children public override void AddSubElement(TestTask element) { throw new NotImplementedException(); } public override void RemoveSubElement(TestTask element) { throw new NotImplementedException(); } } public class MultipleChoiseTask : TestTask { public MultipleChoiseTask(string text): base(text) { SelectedAnswers = new List<TaskAnswer>(); } //List for selected answers public List<TaskAnswer> SelectedAnswers; public override bool CheckTask() { //for multiple choise question we have to check that every selected answer is correct return SelectedAnswers.Count > 0 && SelectedAnswers.TrueForAll(answer => answer.IsCorrect); } // multiple choise question cannot have any children public override void AddSubElement(TestTask element) { throw new NotImplementedException(); } public override void RemoveSubElement(TestTask element) { throw new NotImplementedException(); } } public class CaseStudieTask: TestTask { public CaseStudieTask(string text): base(text) { SubTasks = new List<TestTask>(); } //List of childrens private List<TestTask> SubTasks; public override void AddSubElement(TestTask element) { SubTasks.Add(element); } public override void RemoveSubElement(TestTask element) { SubTasks.Remove(element); } public override bool CheckTask() { // for case studie we have to check that every sub question is correct return SubTasks.TrueForAll(el => el.CheckTask()); } }Class for answers:
public class TaskAnswer { public string AnswerText { get; set; } public bool IsCorrect { get; set; } public TaskAnswer(string text, bool isCorrect) { AnswerText = text; IsCorrect = isCorrect; } }And example of usage:
public void InitializeTest() { //Create container TestTask test = new CaseStudieTask("First test"); //Initialise sample questions var firstQuestion = new SingleChoiseTask("First question"); firstQuestion.AddAnswer(new KeyValuePair<string, bool>("correct answer", true), new KeyValuePair<string, bool>("incorrect answer", false)); var secondQuestion = new MultipleChoiseTask("Second question"); secondQuestion.AddAnswer(new KeyValuePair<string, bool>("correct answer 1", true), new KeyValuePair<string, bool>("correct answer 2", true)); var thirdQuestion = new CaseStudieTask("Case studie"); var firstSubQuestion = new SingleChoiseTask("First question in case studie"); firstSubQuestion.AddAnswer(new KeyValuePair<string, bool>("correct answer", true), new KeyValuePair<string, bool>("incorrect answer", false)); var secondSubQuestion = new SingleChoiseTask("Second question in case studie"); secondSubQuestion.AddAnswer(new KeyValuePair<string, bool>("correct answer", true), new KeyValuePair<string, bool>("incorrect answer", false)); thirdQuestion.AddSubElement(firstSubQuestion); thirdQuestion.AddSubElement(secondSubQuestion); // And populate test test.AddSubElement(firstQuestion); test.AddSubElement(secondQuestion); test.AddSubElement(thirdQuestion); }Of course this example is not full. There is no way to navigate throught test, no binding for the answers and no scores (user can pass the test only if he scores 100%).
And I would add singleton pattern for test (and this class would calculate current points, watch for current question etc.). If you are interested I can show more complex example.
No comments:
Post a Comment