Sci Fi Demo Project [Unity & WebGL]

Sci Fi Demo Project >>> PLAY NOW <<<

sci-fi-demo-project-thumbnail

This is the Sci Fi Demo Project by Jonathan Weinberger on Udemy.
Use the “E” button to pick up the coin from the vending machine and buy a weapon from the Shark also with “E” once you picked up the coin.
There is a destructible crate on the opposite side, in front of the fruit vendor.

In case you want to test play the game, here you go!

This is the project for you to download: Sci Fi Project

Galaxy Shooter [Unity & WebGL]

My first from idea to deployment Unity game project! >>> PLAY NOW <<<

galaxy-shooter-thumbnail

Hi guys, I have been playing around and following some tutorials with Unity which truly is great fun and a fantastic way of learning to code in a playful way. Of course the game I have been developing following the Udemy tutorial by Jonathan Weinberger is very simple, but it was critical to see how the whole process could look like, from the idea of the game, asset management, programming the game, post-processing and building the game with WebGL and finally hosting it on GitHub (which I added, because I wanted to share the game with friends). So now I know how to go through this steps and am ready to look into adding complexity along the way.

In case you want to test play the game, here you go! I know its not perfect, and there is room for improvement, but the excitement holds up for at least 30 seconds (yay!).

This is the project for you to download: Galaxy Shooter

Machine Learning A-Z [WIP]

Machine Learning A-Z™: Hands-On Python & R In Data Science
by Kirill Eremenko and Hadelin de Ponteves on Udemy

Actually a couple of new jobs and task at work and obviously major curiosity have led me to have a dive into Machine Learning. Guess what, I absolutely love it. It’s fantastic to get your head around the theory, but also try out some simple examples of applied ML – even if it is just to understand when people talk about it. Actually applying it to own real world problems is of course a different story, but this is a first step for me. It all boils down to ask the right question and to understand what the data might be able to tell you, rather then using Machine Learning for the sake of it.
I highly recommend the course, join me if you’d like!

This is the table of content as described on Udemy:

Part 1 – Data Preprocessing
Part 2 – Regression:

  • Simple Linear Regression
  • Multiple Linear Regression
  • Polynomial Regression
  • SVR
  • Decision Tree Regression
  • Random Forest Regression

Part 3 – Classification:

  • Logistic Regression
  • K-NN
  • SVM
  • Kernel SVM
  • Naive Bayes
  • Decision Tree Classification
  • Random Forest Classification

Part 4 – Clustering:

  • K-Means
  • Hierarchical Clustering

Part 5 – Association Rule Learning:

  • Apriori
  • Eclat

Part 6 – Reinforcement Learning:

  • Upper Confidence Bound
  • Thompson Sampling

Part 7 – Natural Language Processing: Bag-of-words model and algorithms for NLP
Part 8 – Deep Learning:

  • Artificial Neural Networks
  • Convolutional Neural Networks

Part 9 – Dimensionality Reduction:

  • PCA
  • LDA
  • Kernel PCA

Part 10 – Model Selection & Boosting:

  • k-fold Cross Validation
  • Parameter Tuning
  • Grid Search
  • XGBoost

visual graphing program [fltk]

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 16 Exercise 10
Using GUI library called FLTK (Fast Light Tool Kit, “full tick”).

Output:

//	Philipp Siedler
//	Bjarne Stroustrup's PP
//	Chapter 16 Exercise 10

#define _USE_MATH_DEFINES
#include "Simple_window.h"
#include "Graph.h"
#include <cmath>
#include "GUI.h"
#include "std_lib_facilities.h"
#include <functional>

// layout
constexpr int xmax = 600;
constexpr int ymax = 600;

constexpr int x_orig = xmax / 2;
constexpr int y_orig = ymax / 2;
Point orig(x_orig, y_orig);

constexpr int r_min = -10;
constexpr int r_max = 10;

constexpr int n_points = 40;

constexpr int x_scale = 20;
constexpr int y_scale = 20;

// layout
constexpr int xoffset = 100;
constexpr int yoffset = 100;

constexpr int xspace = 100;
constexpr int yspace = 100;

constexpr int xlength = xmax - xoffset - xspace;
constexpr int ylength = ymax - yoffset - yspace;

typedef double Fcti(double);

double mysin(double x) { return sin(x); }
double mycos(double x) { return cos(x); }

template <class T> class myFct : public Shape {
public:
	myFct(Fcti* f, double r1, double r2, Point orig, int count = 100, double xscale = 25, double yscale = 25, T precision = 1.0);
	~myFct() {}

	void set_f(Fcti* p) { f = p; }
	void set_r1(double r) { r1 = r; }
	void set_r2(double r) { r2 = r; }
	void set_orig(Point o) { orig = o; }
	void set_count(int c) { count = c; }
	void set_xscale(double x) { xscale = x; }
	void set_yscale(double y) { yscale = y; }
	void set_precision(T p) { precision = p; }

	double get_r1() { return r1; }
	double get_r2() { return r2; }
	Point get_orig() { return orig; }
	int get_count() { return count; }
	double get_xscale() { return xscale; }
	double get_yscale() { return yscale; }
	T get_precision() { return precision; }

	void calc();
	void reset(Fcti* f, double r1, double r2, Point orig, int count = 100, double xscale = 25, double yscale = 25, T precision = 1.0);

private:
	Fcti* f;
	double r1;
	double r2;
	Point orig;
	int count;
	double xscale;
	double yscale;
	T precision;
};

template <class T> myFct<T>::myFct(Fcti* f, double r1, double r2, Point orig, int count, double xscale, double yscale, T precision)
	:f(f), r1(r1), r2(r2), orig(orig), count(count), xscale(xscale), yscale(yscale), precision(precision)
{
	calc();
}

template <class T> void myFct<T>::calc()
{
	if (r2 - r1 <= 0) error("bad graphing range");
	if (count <= 0) error("non-positive graphing count");
	double dist = (r2 - r1) / count;
	double r = r1;

	// had to add void clear_points() { points.clear(); }
	// to the protected section of the Shape class - annoying
	clear_points();	

	for (int i = 0; i < count; ++i) {
		int x = orig.x + int(int(r * xscale) / precision) * precision;
		int y = orig.y - int(int(f(r) * yscale) / precision) * precision;
		add(Point(x, y));
		r += dist;
	}
}

template <class T> void myFct<T>::reset(Fcti* f, double r1, double r2, Point orig, int count, double xscale, double yscale, T precision)
{
	set_f(f);
	set_r1(r1);
	set_r2(r2);
	set_orig(orig);
	set_count(count);
	set_xscale(xscale);
	set_yscale(yscale);
	set_precision(precision);

	calc();
}

// ------------------------------ GRAPHING END-------------------------

struct application_window : Window {
	enum graph_enum
	{
		sin_g, cos_g
	};

	application_window(Point xy, int w, int h, const string& title);

	void draw_graph();

private:

	//------------- LAYOUT

	// quit button
	Button quit_button;

	// convert button
	Button graph_button;

	// graph type button;
	Button graph_type;
	Menu graph_type_menu;

	// in
	In_box x_parameter;
	Out_box base_equation;
	Out_box equation;

	//
	graph_enum g_type;

	// axis
	Axis x_axis;
	Axis y_axis;

	// function
	myFct<double> funct;

	//double x_manipulation(double x, int m) { return x * m; }
	double my_sin(double x) { return sin(x); }
	double my_cos(double x) { return cos(x); }

	// actions invoked by callbacks
	void quit() { hide(); }

	void graph_type_menu_pressed() { graph_type.hide(); graph_type_menu.show(); }

	void sin_graph();
	void cos_graph();	

	// callback functions
	static void cb_quit(Address, Address pw) { reference_to<application_window>(pw).quit(); }
	static void cb_calculate(Address, Address pw) { reference_to<application_window>(pw).draw_graph(); }

	static void cb_graph_type_menu_pressed(Address, Address pw) { reference_to<application_window>(pw).graph_type_menu_pressed(); }

	static void cb_sin_graph(Address, Address pw) { reference_to<application_window>(pw).sin_graph(); }
	static void cb_cos_graph(Address, Address pw) { reference_to<application_window>(pw).cos_graph(); }

	//------------- LAYOUT END
};

application_window::application_window(Point xy, int w, int h, const string& title)
	: Window(xy, w, h, title)
	, quit_button(Point(x_max() - 70, 0), 70, 20, "Quit", cb_quit)
	, graph_button(Point(x_max() - 70, 20), 70, 20, "Graph", cb_calculate)
	, graph_type(Point(20, 0), 100, 20, "Graph Type", cb_graph_type_menu_pressed)
	, graph_type_menu(Point(20, 0), 100, 20, Menu::vertical, "Graph Type")
	, base_equation(Point(x_max() / 2, 0), 90, 20, "equation")
	, x_parameter(Point(100, 40), 20, 20, "t-paramter")
	, equation(Point(x_max() / 2, 40), 90, 20, "equation")
	, x_axis(Axis::x, Point(orig.x - 200, orig.y), 400, 20, "1 == 20")
	, y_axis(Axis::y, Point(orig.x, orig.y + 200), 400, 20, "1 == 20")
	, funct(mysin, r_min, r_max, orig, n_points, x_scale, y_scale)
{
	attach(quit_button);
	attach(graph_button);
	attach(graph_type);
	attach(base_equation);
	attach(x_parameter);
	attach(equation);

	graph_type_menu.attach(new Button(Point(0, 0), 0, 0, "sin", cb_sin_graph));
	graph_type_menu.attach(new Button(Point(0, 0), 0, 0, "cos", cb_cos_graph));

	attach(graph_type_menu);

	x_axis.set_color(Color::black);
	y_axis.set_color(Color::black);
	attach(x_axis);
	attach(y_axis);

	funct.set_color(FL_BLACK);
	attach(funct);
	funct.set_color(Color::invisible);

	graph_type_menu.hide();
}

void application_window::sin_graph()
{
	graph_type_menu.hide();
	graph_type.show();

	base_equation.put("y = sin(x) * t");
	g_type = sin_g;
}

void application_window::cos_graph()
{
	graph_type_menu.hide();
	graph_type.show();

	base_equation.put("y = cos(x) * t");
	g_type = cos_g;
}

void application_window::draw_graph()
{	
	// GRAPHS
	if(g_type == sin_g)
	{		
		equation.put("y = sin(x) * " + x_parameter.get_string());

		// most painful lambda to function pointer work-around ever.
		// saved the day:
		// https://deviorel.wordpress.com/2015/01/27/obtaining-function-pointers-from-lambdas-in-c/

		int t = x_parameter.get_int();
		auto la = [=](double x) { return sin(x) * t; };

		static function< double(double) > static_variable;
		static_variable = la;
		double(*ptr)(double) = [](double x) { return static_variable(x); };

		funct.reset(
			[](double x) { return static_variable(x); }
			, r_min
			, r_max
			, orig
			, n_points
			, x_scale
			, y_scale
		);

	}
	if(g_type == cos_g)
	{
		equation.put("y = cos(x) * " + x_parameter.get_string());

		int t = x_parameter.get_int();
		auto la = [=](double x) { return cos(x) * t; };

		static function< double(double) > static_variable;
		static_variable = la;
		double(*ptr)(double) = [](double x) { return static_variable(x); };

		funct.reset(
			[](double x) { return static_variable(x); }
			, r_min
			, r_max
			, orig
			, n_points
			, x_scale
			, y_scale
		);
	}

	funct.set_color(Color::visible);
	redraw();
}

// ------------------------------ INTERFACE END-------------------------

int main()
try {
	application_window win(Point(100, 100), xmax, ymax + 20, "currency converter");

	return gui_main();
}
catch (exception& e) {
	cerr << "exception: " << e.what() << endl;
	char c;
	while (cin >> c&& c != ';');
	return 1;
}
catch (...) {
	cerr << "exception\n";
	char c;
	while (cin >> c && c != ';');
	return 2;
}

visual calculator [fltk]

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 16 Exercise 9
Using GUI library called FLTK (Fast Light Tool Kit, “full tick”).

Output:

//	Philipp Siedler
//	Bjarne Stroustrup's PP
//	Chapter 16 Exercise 9

#define _USE_MATH_DEFINES
#include "Simple_window.h"
#include "Graph.h"
#include <cmath>
#include "GUI.h"
#include "std_lib_facilities.h"

// ------------------------------ CALCULATOR ---------------------------

const char let = '#';
const char quitProg = 'Q';
const char print = ';';
const char number = '8';
const char name = 'a';
const char sqroot = 'S';
const char power = 'P';
const char constant = 'C';
const char reset = 'R';
const char help = 'H';

struct Token {
	char kind;
	double value;
	string name;
	Token(char ch) :kind(ch), value(0) { }
	Token(char ch, double val) :kind(ch), value(val) { }
	Token(char ch, string val) :kind(ch), name(val) { }
};

class Token_stream {
	bool full;
	Token buffer;
	;
public:
	Token_stream() :full(0), buffer(0) { }
	Token get(stringstream& ist);
	void unget(Token t) { buffer = t; full = true; }
	void ignore(char);
};

Token Token_stream::get(stringstream& ist)
{
	/*
	if (full) {
	full = false;
	return buffer;
	}

	char ch;
	ist >> ch;
	*/

	if (full) {
		full = false; return buffer;
	}
	char ch;
	ist.get(ch);

	while (isspace(ch)) {
		if (ch == '\n') return Token(print); // if newline detected, return print Token
		ist.get(ch);
	}

	switch (ch) {
	case '(':
	case ')':
	case '+':
	case '-':
	case '*':
	case '/':
	case '%':
	case ';':
	case '=':
	case 'k':
	case ',':
	{
		return Token(ch);
	}
	case '#':
	{
		return Token(let);
	}
	case '.':
	case '0':
	case '1':
	case '2':
	case '3':
	case '4':
	case '5':
	case '6':
	case '7':
	case '8':
	case '9':
	{
		ist.unget();
		double val;
		ist >> val;
		return Token(number, val);
	}
	default:
	{
		if (isalpha(ch) || ch == '_') { //is ch a letter?
			string s;
			s += ch;
			while (ist.get(ch) && (isalpha(ch) || isdigit(ch) || ch == '_')) { //reads chars, strings or digits
				s += ch;
			}
			ist.unget(); //puts the most recently read character back into the stream
			if (s == "quit") return Token(quitProg);
			if (s == "sqrt") return Token(sqroot);
			if (s == "pow") return Token(power);
			if (s == "const") return Token(constant);
			if (s == "reset") return Token(reset);
			if (s == "help" || s == "Help") return Token(help);
			return Token(name, s);
		}
		error("Bad token");
		return Token(' ');
	}
	}
}

void Token_stream::ignore(char c)
{
	if (full && c == buffer.kind) {
		full = false;
		return;
	}
	full = false;
	char ch;
	while (cin >> ch) {
		if (ch == c) return;
	}
}

struct Variable {
	string name;
	double value;
	bool immutable;
	Variable(string n, double v, bool i) :name(n), value(v), immutable(i) { }
};

class Symbol_table {
public:
	vector<Variable> var_table;
	double get(string);
	void set(string, double);
	bool is_declared(string);
	double declare(char, stringstream& ist);
	bool is_immutable(string);
};

Token_stream ts;
double expression(stringstream& ist);
double primary(stringstream& ist);

double Symbol_table::get(string s)
{
	for (int i = 0; i < var_table.size(); ++i) {
		if (var_table[i].name == s) {
			return var_table[i].value;
		}
	}
	error("get: undefined name ", s);
	return 0.0;
}

void Symbol_table::set(string s, double d)
{
	for (int i = 0; i <= var_table.size(); ++i) {
		if (var_table[i].name == s) {
			var_table[i].value = d;
			return;
		}
	}
	error("set: undefined name ", s);
}

bool Symbol_table::is_declared(string s)
{
	for (int i = 0; i < var_table.size(); ++i) {
		if (var_table[i].name == s) return true;
	}
	return false;
}

double Symbol_table::declare(char kind, stringstream& ist)
{
	Token t = ts.get(ist);
	if (t.kind != name) {
		error("name expected in declaration");
	}

	string name = t.name;
	if (kind == let || kind == constant) {
		if (is_declared(name)) error(name, " declared twice");
	}
	else if (kind == reset) {
		if (!is_declared(name))
			error(name, " has not been declared");
		if (is_immutable(name))
			error(name, " is a constant");
	}
	else {
		error("unknown statement");
	}

	Token t2 = ts.get(ist);
	if (t2.kind != '=') error("= missing in declaration of ", name);
	double d = expression(ist);
	if (is_declared(name))
		set(name, d);
	else
		var_table.push_back(Variable(name, d, (kind == constant)));
	return d;
}

bool Symbol_table::is_immutable(string s)
{
	for (int i = 0; i<int(var_table.size()); ++i)
		if (var_table[i].name == s && var_table[i].immutable) return true;
	return false;
}

double pow_function(Token _t, stringstream& ist) {
	_t = ts.get(ist);
	if (_t.kind != '(') {
		error("'(' expected");
	}

	double x = expression(ist);

	_t = ts.get(ist);
	if (_t.kind != ',') {
		error("',' expected");
	}

	double n = expression(ist);
	_t = ts.get(ist);
	if (_t.kind == ')') {
		return pow(x, n);
	}
	else {
		error("Expected ')'");
	}
}

double sqrt_function(Token _t, stringstream& ist) {
	_t = ts.get(ist);
	if (_t.kind != '(') {
		error("'(' expected");
	}
	ts.unget(_t);
	double d = primary(ist);
	if (d < 0.0) {
		error("negative square root");
	}
	return sqrt(d);
}


Symbol_table st;

double primary(stringstream& ist)
{
	Token t = ts.get(ist);
	switch (t.kind) {
	case '(':
	{
		double d = expression(ist);
		t = ts.get(ist);
		if (t.kind != ')') error("')' expected");
		return d;
	}
	case '-':
	{
		return -primary(ist);
	}
	case '+':
	{
		return primary(ist);
	}
	case number:
	{
		return t.value;
	}
	case sqroot:
	{
		return sqrt_function(t, ist);
	}
	case power:
	{
		return pow_function(t, ist);
	}
	case name:
	{
		return st.get(t.name);
	}
	default:
	{
		error("primary expected");
		return 0.0;
	}
	}
}

double term(stringstream& ist)
{
	double left = primary(ist);
	while (true) {
		Token t = ts.get(ist);
		switch (t.kind) {
		case 'k':
		{
			left *= 1000;
			break;
		}
		case '*':
		{
			left *= primary(ist);
			break;
		}
		case '/':
		{
			double d = primary(ist);
			if (d == 0) error("divide by zero");
			left /= d;
			break;
		}
		case '%':
		{
			int i1 = narrow_cast<int>(left);
			int i2 = narrow_cast<int>(primary(ist));
			if (i2 == 0) error("%: divide by zero");
			left = i1%i2;
			break;
		}

		default: {
			ts.unget(t);
			return left;
		}
		}
	}
}

double expression(stringstream& ist)
{
	double left = term(ist);
	while (true) {
		Token t = ts.get(ist);
		switch (t.kind) {
		case '+':
		{
			left += term(ist);
			break;
		}
		case '-':
		{
			left -= term(ist);
			break;
		}
		default:
		{
			ts.unget(t);
			return left;
		}
		}
	}
}

double statement(stringstream& ist)
{
	Token t = ts.get(ist);
	double d;
	if (t.kind == let || t.kind == reset || t.kind == constant) {
		d = st.declare(t.kind, ist);
	}
	else {
		ts.unget(t);
		d = expression(ist);
	}
	t = ts.get(ist);
	if (t.kind != print) {
		error("Missing terminator");
	}

	return d;
}

void clean_up_mess()
{
	ts.ignore(print);
}

static void calculate(stringstream& ist, ostringstream& ost)
{
	while (ist) try {
		Token t = ts.get(ist);
		ts.unget(t);
		ost << statement(ist);
		break;
	}
	catch (runtime_error& e) {
		ost << e.what() << endl;
		clean_up_mess();
	}
}

// ------------------------------ CALCULATOR END------------------------

// ------------------------------ INTERFACE ----------------------------

// layout
constexpr int xmax = 400;
constexpr int ymax = 400;

struct application_window : Window {
	application_window(Point xy, int w, int h, const string& title);

private:

	//------------- LAYOUT

	// quit button
	Button quit_button;

	// convert button
	Button calculate_button;

	// in
	In_box value_in;
	Out_box value_out;

	// actions invoked by callbacks
	void quit() { hide(); }
	void cal();

	// callback functions
	static void cb_quit(Address, Address pw) { reference_to<application_window>(pw).quit(); }
	static void cb_calculate(Address, Address pw) { reference_to<application_window>(pw).cal(); }

	//------------- LAYOUT END
};

application_window::application_window(Point xy, int w, int h, const string& title)
	: Window(xy, w, h, title)
	, quit_button(Point(x_max() - 70, 0), 70, 20, "Quit", cb_quit)
	, calculate_button(Point(x_max() - 70, 20), 70, 20, "Calculate", cb_calculate)
	, value_in(Point(70, 60), 70, 20, "equation")
	, value_out(Point(x_max() / 2, 60), 70, 20, "solution")
{
	attach(quit_button);
	attach(calculate_button);
	attach(value_in);
	attach(value_out);
}

void application_window::cal()
{
	ostringstream os;
	stringstream ss;
	ss.str(value_in.get_string() + ";");
	
	calculate(ss, os);

	string s(os.str());
	value_out.put(s);
}

// ------------------------------ INTERFACE END-------------------------

int main()
try {
	application_window win(Point(100, 100), xmax, ymax + 20, "currency converter");
	return gui_main();
}
catch (exception& e) {
	cerr << "exception: " << e.what() << endl;
	char c;
	while (cin >> c&& c != ';');
	return 1;
}
catch (...) {
	cerr << "exception\n";
	char c;
	while (cin >> c && c != ';');
	return 2;
}

visual currency converter [fltk]

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 16 Exercise 8
Using GUI library called FLTK (Fast Light Tool Kit, “full tick”).

Output:

//  Philipp Siedler
//  Bjarne Stroustrup's PP
//  Chapter 16 Exercise 8

#define _USE_MATH_DEFINES
#include "Simple_window.h"
#include "Graph.h"
#include <cmath>
#include "GUI.h"
#include <time.h>

// layout
constexpr int xmax = 400;
constexpr int ymax = 400;

enum currencies
{
	euro = 0, pound
};

struct application_window : Window {
	application_window(Point xy, int w, int h, const string& title, const string& conversion_rate_file_location);

private:

	//------------- DATA

	currencies from;
	currencies to;

	// data
	float conversion_rate;

	// methods
	float get_conversion(const string& crfl);

	//------------- DATA END


	//------------- LAYOUT

	// quit button
	Button quit_button;

	// convert button
	Button convert_button;

	// menu button
	Button from_menu_button;
	Button to_menu_button;

	// menu
	Menu from_menu;
	Menu to_menu;

	// in
	In_box value_in;
	Out_box value_out;
	Out_box value_in_currency;	
	Out_box value_out_currency;

	// actions invoked by callbacks
	void quit() { hide(); }

	void convert();

	void hide_from_menu() { from_menu.hide(); from_menu_button.show(); }
	void hide_to_menu() { to_menu.hide(); to_menu_button.show(); }

	void from_menu_pressed() { from_menu_button.hide(); from_menu.show(); }
	void to_menu_pressed() { to_menu_button.hide(); to_menu.show(); }

	void from_euro_pressed() { hide_from_menu(); value_in_currency.put("euro"); from = euro; }
	void from_pound_pressed() { hide_from_menu(); value_in_currency.put("pound"); from = pound; }

	void to_euro_pressed() { hide_to_menu(); value_out_currency.put("euro"); to = euro; }
	void to_pound_pressed() { hide_to_menu(); value_out_currency.put("pound"); to = pound; }
	
	// callback functions
	static void cb_quit(Address, Address pw) { reference_to<application_window>(pw).quit(); }

	static void cb_convert(Address, Address pw) { reference_to<application_window>(pw).convert(); }

	static void cb_from_menu(Address, Address pw) {	reference_to<application_window>(pw).from_menu_pressed(); }
	static void cb_from_euro(Address, Address pw) { reference_to<application_window>(pw).from_euro_pressed(); }
	static void cb_from_pound(Address, Address pw) { reference_to<application_window>(pw).from_pound_pressed(); }

	static void cb_to_menu(Address, Address pw) { reference_to<application_window>(pw).to_menu_pressed(); }
	static void cb_to_euro(Address, Address pw) { reference_to<application_window>(pw).to_euro_pressed(); }
	static void cb_to_pound(Address, Address pw) { reference_to<application_window>(pw).to_pound_pressed(); }

	//------------- LAYOUT END
};

application_window::application_window(Point xy, int w, int h, const string& title, const string& conversion_rate_file_location)
	: Window(xy, w, h, title)
	, quit_button(Point(x_max() - 70, 0), 70, 20, "Quit", cb_quit)
	, convert_button(Point(x_max() - 70, 20), 70, 20, "Convert", cb_convert)
	, from_menu_button(Point(0, 20), 70, 20, "From", cb_from_menu)
	, to_menu_button(Point(x_max() / 2, 20), 70, 20, "To", cb_to_menu)
	, from_menu(Point(0, 20), 70, 20, Menu::vertical, "From")
	, to_menu(Point(x_max() / 2, 20), 70, 20, Menu::vertical, "To")
	, value_in(Point(0, 60), 70, 20, "enter value")
	, value_out(Point(x_max() / 2, 60), 70, 20, "")
	, value_in_currency(Point(70, 60), 70, 20, "")
	, value_out_currency(Point(x_max() / 2 + 70, 60), 70, 20, "")
{
	conversion_rate = get_conversion(conversion_rate_file_location);

	from = euro;
	to = euro;

	attach(quit_button);
	attach(convert_button);
	attach(from_menu_button);
	attach(to_menu_button);

	attach(value_in);
	attach(value_out);

	attach(value_in_currency);
	attach(value_out_currency);

	value_in_currency.put("euro");
	value_out_currency.put("euro");

	from_menu.attach(new Button(Point(0, 0), 0, 0, "euro", cb_from_euro));
	from_menu.attach(new Button(Point(0, 0), 0, 0, "pound", cb_from_pound));

	to_menu.attach(new Button(Point(0, 0), 0, 0, "euro", cb_to_euro));
	to_menu.attach(new Button(Point(0, 0), 0, 0, "pound", cb_to_pound));

	attach(to_menu);
	attach(from_menu);

	to_menu.hide();
	from_menu.hide();
}

float application_window::get_conversion(const string& crfl)
{
	string iname = crfl;
	ifstream ist(iname);

	float rate;
	if (!ist) { error("File could not be read: ", iname); }
	else { ist >> rate; }

	return rate;
}

void application_window::convert()
{
	float input = strtof((value_in.get_string()).c_str(), 0);

	if (from == euro && to == pound)
	{
		input *= conversion_rate;

		ostringstream ss;
		ss << input;
		string s(ss.str());

		value_out.put(s);
	}
	else if (from == pound && to == euro)
	{
		input *= 1.0 + (1.0 - conversion_rate);

		ostringstream ss;
		ss << input;
		string s(ss.str());

		value_out.put(s);
	}
	else
	{
		ostringstream ss;
		ss << input;
		string s(ss.str());

		value_out.put(s);
	}
}

int main()
try
{
	application_window win(Point(100, 100), xmax, ymax + 20, "currency converter", "Data/conversion_rate.txt");
	return gui_main();
}
catch (exception& e) {
	cerr << "error: " << e.what() << '\n';
	keep_window_open();
	return 1;
}
catch (...) {
	cerr << "Unknown exception!\n";
	keep_window_open();
	return 2;
}
Input:
Text file: Data/conversion_rate.txt
0.87