"""
Fraction Class for SI@UCF
5/15/13
Sawyer Hood
"""
import time, random
class Fraction:


	#Initilizer for the Fraction class. Uses default values instead of overloading.
	def __init__(self, n = 1, d = 1):
		#Initializes instance variables and reduces the fraction.
		self.numerator = n
		self.denominator = d
		self.__reduce()

		#Avoid undefined values.
		if self.denominator == 0:
			self.denominator = 1

	#Factory method to make random fractions between 1 and max, inclusive.
	@classmethod
	def rand(cls, max=100):
		random.seed()
		num = random.randint(1,max)
		den = random.randint(1,max)
		return cls(num,den)

	#Reduces fraction to the lowest terms
	def __reduce(self):
		common = self.__class__.__gcd(self.numerator, self.denominator)
		self.numerator /= common
		self.denominator /= common

	#Static method that finds the greatest common denominator. Takes two numbers.
	@staticmethod
	def __gcd(a,b):
		i = 2
		answer = 1

		#Try out successively larger factors, and store one when found.
		while i <= a and i <= b:
			if a%i == 0 and b%i == 0:
				answer = i
			i+=1

		return answer

	#Adds a fraction object to the instance and returns another fraction object.
	def add(self,f):
		num = self.numerator * f.denominator + self.denominator * f.numerator
		den = self.denominator * f.denominator
		return Fraction(num,den)

	#Subtracts a fraction object from the instance fraction and returns a fraction.
	def subtract(self,f):
		num = self.numerator * f.denominator - self.denominator * f.numerator
		den = self.denominator * f.numerator
		
		return Fraction(num,den)

	#Multipy a fraction object by the instance and return a fraction.
	def multiply(self,f):
		num = self.numerator * f.numerator
		den = self.denominator * self.denominator
		
		return Fraction(num,den)

	#Divide fraction instance by another fraction. Returns a fraction.
	def divide(self,f):
		num = self.numerator * f.denominator
		den = self.denominator * f.numerator
		
		return Fraction(num,den)

	#Returns reciprocal of the fraction object.
	def reciprocal(self):
		return Fraction(self.denominator, self.denominator)

	#Raises a fraction by a power and returns the result.
	def power(self,exp):
		multiplier = self
		answer = self

		# Helps us deal with negative exponents. In this case, we
  		# will repeatedly multiply by the reciprocal of the current
  		# object.
		if exp < 0:
			multiplier = multiplier.reciprocal

		#Multiply the appropriate multiplier |exp| number of times.
		for i in range(1,exp):
			answer = answer.multiply(multiplier)
		return answer

	#Returns a String representation of the current object.
	def __str__(self):
		return "{0}/{1}".format(self.numerator,self.denominator)

	#Adds one to the current fraction object.
	def add_one(self):
		if self.denominator != 0:
			self.numerator += self.denominator

	#Copies the contents of f into the current object.
	def copy(self,f):
		self.denominator = f.denominator
		self.numerator = f.numerator

	#Oveerloads '==' operator
	def __eq__(self,other):
		if self.numerator == other.numerator and self.denominator == other.denominator:
			return True
		else:
	
			return False

#Fraction addition game!
def main():
	#Prints out greeting.
	print("Welcome to the Fraction Game.\nYou will be given 10 fraction addition problems.\nTo answer, simply type out the numerator, a / and then the denominator. i.e: 2/3")
	
	#Start the timer!
	start = time.time()

	correct = 0

	#Loop through 10 problems
	for i in range(0,10):

		#Generates random fractions.
		frac1 = Fraction.rand(5)
		frac2 = Fraction.rand(5)

		#Reads user input, splits input into seperate integers.
		inputVal = input("What is {0} + {1}: ".format(frac1,frac2))
		inputList = inputVal.split("/")
		usrInput = Fraction(int(inputList[0]), int(inputList[1]))

		#Calculate real answer.
		realAnswer = frac1.add(frac2)

		#Correct!
		if usrInput == realAnswer:
			print("Correct!")
			correct += 1
		#Incorrect, outputs real answer.
		else:
			print("Sorry, the correct answer was {0}.".format(realAnswer))

	#Stops timer.
	end = time.time()
	timeSpent = end-start

	#Prints results.
	print("You got {0} correct problems in {1} seconds.".format(correct,timeSpent))

main()














