#include <iostream.h>

// Lab 3 - CIS 280 - Jonathan LaZor

/*
Fraction A:
Enter price for stock (x-y-z): 2-1-3
Stock price: 2 1/3
Fraction B:
1 2/3
Fraction C:
Enter price for stock: 3-1-2
3 1/2
C as float: 3
Fraction D:
Enter price for stock as float: 1.3
1 19/64

A + B = 5 1/1
C + D = 4 51/64
A - B = -1 1/-3
C - D = 2 13/64
A * C = 0 49/6
B / D = 0 704/249
B + 2 = 3 2/3
2 + B = 3 2/3
B += 2 = 3 2/3
Comparison: A > B
Comparison: C > D
Press any key to continue
*/

class FracPri {
	int whole; //the whole number
	int numer; //the numerator of the fractional part
	int denom; //the denominator of the fractional part
	void reduce();
public:
	FracPri();
	FracPri(int w, int n, int d);
	void getFraction();
	void showFraction();
	FracPri addFracts(FracPri& f);
	FracPri operator+(FracPri& f);
	FracPri operator-(FracPri& f);
	FracPri operator*(FracPri& f);
	FracPri operator/(FracPri f);
	FracPri operator+(int i);
	friend FracPri operator+(int i, FracPri& f);
	bool operator<(FracPri& f);
	FracPri operator+=(FracPri& f);
	friend ostream& operator<<(ostream& out, FracPri& f);
	friend istream& operator>>(istream& in, FracPri& f);
	operator float();
	FracPri(float f);
};

FracPri::FracPri() {whole = numer = 0; denom = 1;}

FracPri::FracPri(int w, int n, int d) {
	if(d==0) {cout << "Denominator must not be 0, using 1\n"; d = 1;}
	whole = w; numer = n; denom = d;
	reduce();
}

void FracPri::reduce() {
	int a, b, q, r;
	if(numer < denom) {a = denom; b = numer;}
	else {a = numer; b = denom;}

	while (b) {
		q = a/b;
		r = a%b;
		a = b;
		b = r;
	}
	numer /= a;
	denom /= a;
}

void FracPri::getFraction() {
	char ch;
	cout << "Enter price for stock (x-y-z): ";
	cin >> whole >> ch >> numer >> ch >> denom;
	// cout << whole << ch << numer << ch << denom;
}

void FracPri::showFraction() {cout << "Stock price: " << *this;}

FracPri FracPri::addFracts(FracPri& f) {
	int cd = denom * f.denom;
	return FracPri(whole + f.whole, numer * f.denom + f.numer * denom, cd);
}

FracPri FracPri::operator+(FracPri& f) {
	int cd = denom * f.denom;
	return FracPri(whole + f.whole, numer * f.denom + f.numer * denom, cd);
}

FracPri FracPri::operator-(FracPri& f) {
	int cd = denom * f.denom;
	return FracPri(whole - f.whole, numer * f.denom - f.numer * denom, cd);
}

FracPri FracPri::operator*(FracPri& f) {
	int n1 = denom * whole + numer;
	int n2 = f.denom * f.whole + f.numer;
	return FracPri(0, n1 * n2, denom * f.denom);
}

FracPri FracPri::operator/(FracPri f) {
	int i = f.denom * f.whole + f.numer;
	f.whole = 0;
	f.numer = f.denom;
	f.denom = i;
	return *this * f;
}

FracPri FracPri::operator+(int i) {
	return FracPri(whole+=i, numer, denom);
}

FracPri operator+(int i, FracPri& f) {
	return FracPri(f.whole + i, f.numer, f.denom);
}

bool FracPri::operator<(FracPri& f) {
	if(whole != f.whole) return whole < f.whole;
	else return (numer * f.denom) < (f.numer * denom);
}

FracPri FracPri::operator+=(FracPri& f) {
	whole += f.whole;
	numer = numer * f.denom + f.numer * denom;
	denom = denom * f.denom;
	return *this;
}

ostream& operator<<(ostream& out, FracPri& f) {
	out << f.whole << " " << f.numer << "/" << f.denom; return out;
}

istream& operator>>(istream& in, FracPri& f) {
	char ch;
	in >> f.whole >> ch >> f.numer >> ch >> f.denom; return in;
}

FracPri::operator float() {
	float f;
	f = ((float) whole) + ((float) (numer / denom));
	return f;
}

FracPri::FracPri(float f) {
	f += 0.0078125;
	whole = (int) f;
	float flofrac = f - (float) whole;
	numer = flofrac * 64;
	denom = 64;
	reduce();
}

//FracPri (*functionpointer)(int i, FracPri& f) = operator+;

int main() {
	FracPri a, b(1, 2, 3), c, d;
	int i;
	float f;

	cout << "Fraction A:\n";
	a.getFraction();
	a.showFraction();
	cout << "\nFraction B:\n";
	cout << b;
	cout << "\nFraction C:\n";
	cout << "Enter price for stock: ";
	cin >> c;
	cout << c;
	cout << "\nC as float: " << (float) c;
	cout << "\nFraction D:\n";
	cout << "Enter price for stock as float: ";
	cin >> f;
	d = (FracPri) f;
	cout << d;

	cout << "\n\nA + B = " << (a + b) << endl
		<< "C + D = " << (c.addFracts(d)) << endl
		<< "A - B = " << (a - b) << endl
		<< "C - D = " << (c - d) << endl
		<< "A * C = " << (a * c) << endl
		<< "B / D = " << (b / d) << endl
		<< "B + 2 = " << (b + 2) << endl
		<< "2 + B = " << (2 + b) << endl
		<< "B += 2 = " << b << endl
		<< "Comparison: "
		<< (a < b ? "A < B" : (b < a ? "A > B" : "A = B")) << endl
		<< "Comparison: "
		<< (c < d ? "C < D" : (d < c ? "C > D" : "C = D")) << endl;

	return 1;
}