# Factory for mathematics Q&A

I'm having a hard time creating a design (due to my lack of experience). I need a little of help to create the Model.

It's a mathematics system. I've created an IProblem interface with a function IsCorrect, this function helps me to know if the result is correct or not (by parameter). It also has a function CreateAnswer() because some problems have 1, 2 or many answers.

public interface IProblem
{
}


IAnswer is an interface which contains the answer, it can be a string, integer, decimal, several, multiple choice, etc..

public interface IAnswer
{
}

{
public int Number { get; set; }
}

{
public string Number { get; set; }
}

{ ... }

{ ... }


Here is a concrete Problem:

public class BinaryProblem : IProblem,  IEquatable<BinaryProblem>
{
private int _number1;
private int _number2;

public int Number1
{
get { return _number1; }
set { _number1 = value; }
}

public int Number2
{
get { return _number2; }
set { _number2 = value; }
}

public BinaryProblem(int number1, int number2)
{
this.Number1 = number1;
this.Number2 = number2;
}

{
return integerAnswer.Number == _number1 + _number2;
}

{
}

public override string ToString()
{
return _number1 + " + " + _number2;
}

public override bool Equals(object obj)
{
if (obj is BinaryProblem)
return this.Equals(obj);
else
return false;
}

public bool Equals(BinaryProblem other)
{
return this.Number1 == other.Number1 &&
this.Number2 == other.Number2;
}
}


And to run this:

        // Binary problem test
BinaryProblem binary = new BinaryProblem(4, 5);


I realized it is necessary to store the correct answer. For example, if it's a problem where the stated question is: convert decimal to fraction. My limitation here is that I need to know the result at the moment the problem is created. I'm convinced that the Answer doesn't belong to the problem, but also, the class needs to know the correct answer when it is created. Because 0.111 it's confusing, it can be 1/9 or 111/1000, so I prefer to store the correct answer in some place.

So, where should I modify the model?

I created a factory where one can create problems, which contains values of necessary properties and the correct answer. I'd like to know if the performance or OOP rules are correct, or if there are things to do to improve the factory.

I've modified the answers by a generic class.

This is the interface for my factories:

public interface IFactory<T> where T : IProblem
{
T CreateProblem();
}


My base class factory:

public abstract class Factory<T> : IFactory<T> where T : IProblem
{
protected const int DEFAULT_SIZE = 20;
protected const int MAX_SIZE = 100;

protected static Random rnd;

public virtual int TotalProblemsPossible { get; set; }

protected Factory(Levels level)
{
Initialize();
ConfigureLevels(level);
FirstTime();
}

public virtual void FirstTime()
{
if (rnd == null) rnd = new Random(MAX_SIZE);
if (problems == null)
{
Generate(problems);
}

actualNode = problems.First;
}

public virtual T CreateProblem()
{
if (actualNode.Next == null)
{
Generate(problems);
}

actualNode = actualNode.Next;
return actualNode.Value;
}

{
for (int i = 0; i < DEFAULT_SIZE; i++)
{
T newProblem;
int bucles = 0;

do
{
if (bucles == 50) throw new InvalidOperationException();

newProblem = Generate();
bucles++;
} while (problems.Contains(newProblem));

}
}

protected virtual void Initialize()
{
}

protected abstract T Generate();
protected abstract void ConfigureLevels(Levels level);
}


And a particular factory. At this factory case, I create a class called Bound which contains limits for a number, and gets some numbers randomly to create the problem.

public class BinaryProblemFactory : Factory<BinaryProblem>
{
private Bound<int> Bound { get; set; }

public BinaryProblemFactory(Levels level)
: base(level)
{
}

protected override void Initialize()
{
Bound = new Bound<int>();
base.Initialize();
}

protected override void ConfigureLevels(Levels level)
{
switch (level)
{
case Levels.Easy:
this.Bound.Min = 10;
this.Bound.Max = 100;

break;
case Levels.Normal:
this.Bound.Min = 50;
this.Bound.Max = 200;

break;
case Levels.Hard:
this.Bound.Min = 100;
this.Bound.Max = 10000;

break;
}
}

protected override BinaryProblem Generate()
{
BinaryProblem problem;

int number1 = rnd.Next(Bound.Min, Bound.Max);
int number2 = rnd.Next(Bound.Min, Bound.Max);

problem = new BinaryProblem(number1, number2, correctValue);
return problem;
}
}


The idea is to do something similar with each problem type I want to add to the program. What do you think?

For testing:

        BinaryProblemFactory factory = new BinaryProblemFactory(Levels.Normal);
List<BinaryProblem> problemList = new List<BinaryProblem>();
for (int i = 0; i < 50; i++)
{
BinaryProblem binary2 = (BinaryProblem)factory.CreateProblem();
}

• Not a direct answer to your question, but you should override the bool Equals(object) method instead of (or in addition to) providing you own typed Equals method. Also, you should override the int GetHashCode() method. This will ensure that your object's instances are treated correctly when they are compared by things like the standard .NET collection classes. – Jonathan DeCarlo Jan 13 '12 at 20:11

Firstly, do you really need it to be that generic? You support arbitrary types and numbers of answers. But unnecessary genericness just make the design overly complicated. If you are only going to every have a single number answer, then just write code to do that.

Secondly, you store the answers on the Problem object. But the answers given are not a property of the problem. It makes more sense to have the problem take in the answers as a parameter to the IsCorrect() function.

Thirdly, your problem interfaces don't appear very useful. It seems that I get access and presumably modify the given answers, and then check if the answers are correct. But what about finding out what the problem is? There's not much point in an interface if you are just going to have to cast down to the actual class to do any work.

Fourthly, your provide getters/setters on the numbers and such for the problem. Do you really need them? Are you really changing the problems after they are created?

Fifthly, an obvious way to use OOP here would be to one class for each operator (multiple, divide, add, subtract, etc).

The way I'd approach this:

interface IProblem
{
String GetQuestion();
}

class BinaryOperatorProblem : IProblem
{
int number1, number2;
BinaryOperatorProblem(int number1, int number2);
}

{
String GetQuestion()
{
return "%d + %d" % (number1, number2);
}

{
return answer == number1 + number2;
}
}


Notes: I don't do C# so above syntax is mostly guesses. I also don't know much about your problem, so you mileage will vary.

• Well, I really need to store the values which the student wrote. Yes, I agree with that the generic interface is causing much trouble. So do you think is better to maintain another interface for the answers or results? – Darf Zon Jan 15 '12 at 5:26
• And some problems will need several answers – Darf Zon Jan 15 '12 at 5:55
• @DarfZon, if you need multiple answers I'd pass the answer as an array instead. Without a better idea what you are doing I'm not sure where I'd store the answers, but I wouldn't store them with the problem. – Winston Ewert Jan 15 '12 at 18:56
• okay, by the momment, I've uploaded the project in mediafile (check the post, below). The idea which I have, is to store the problem and answers in a single class, where I plan later to serialize. I'm not ready to do that yet, but that's the idea. – Darf Zon Jan 15 '12 at 19:15
• @DarfZon, but why do you want them in the same class? They are distinct concepts, don't necessarily have a one-to-one relationship, so it doesn't make any sense to me to put in them in one class. – Winston Ewert Jan 15 '12 at 20:40

Declaring the interfaces as below might proof useful:

public interface IProblem<T>
{
}

{
T Value { get; set; }
}

{
public T Value { get; set; }
}


This would allow for the following implementation:

public class BinaryProblem : IProblem<int>, IEquatable<BinaryProblem>
{
private int _number1;
private int _number2;

// .....

{
return answer.Value == _number1 + _number2;
}

{

And can save you a ton of descendants, reduce the amount of knowledge you need within an IProblem implementation, while still offering the possibility of creating very specialized IAnswer implementations.