Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stef -- Carets #32

Open
wants to merge 20 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
62f9465
View files added.
SesameSeeds Dec 12, 2017
6701682
Can view quotes, with symbols and prices and all that good stuff that…
SesameSeeds Dec 12, 2017
3c91903
Fixed bug with adding and subtracting with buy and sell.
SesameSeeds Dec 15, 2017
3d71ed7
Can buy a quote.
SesameSeeds Dec 16, 2017
11a4a3b
Removed unnecessary code.
SesameSeeds Dec 16, 2017
5183778
Can sell quotes, both buying and selling meets requirements.
SesameSeeds Dec 16, 2017
4958383
Added files for orders in views and models.
SesameSeeds Dec 16, 2017
d0b1d9d
Addition of necessary import/export information.
SesameSeeds Dec 17, 2017
79fbbb4
Collections order_list added.
SesameSeeds Dec 17, 2017
249a504
Added orderList and orderListView to app.js, similar logic to quote.
SesameSeeds Dec 17, 2017
d6cfc70
Added basic necessities to build on logic, initially built off quotes.
SesameSeeds Dec 17, 2017
570d60f
Events added for buying/selling orders, working on buy order logic.
SesameSeeds Dec 17, 2017
95d7cc7
Buy logic WIP.
SesameSeeds Dec 17, 2017
ce83f10
Sell order logic added, working on getting it to work properly.
SesameSeeds Dec 17, 2017
4359396
Added destroy for cancel button.
SesameSeeds Dec 17, 2017
86caafb
Form working, can buy/sell with no price.
SesameSeeds Dec 18, 2017
c5ea3df
Mild clean-up, logic addition to get orders to render WIP, not buying…
SesameSeeds Dec 18, 2017
8445492
Added some basic order tests.
SesameSeeds Dec 18, 2017
03225f4
Removed unnecessary code from previous attempt at another thought pro…
SesameSeeds Dec 18, 2017
dbaba17
Testing something to see if I can get it to buy with a price, know wh…
SesameSeeds Dec 18, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions spec/models/order_spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import Order from 'models/order';

describe('Order spec', () => {

describe('Initialize', () => {
it('Can access all instance variables.', () => {
const order = new Order({
currentQuote: 'HELLO',
currentPrice: 100.00,
buy: true,
targetPrice: 101.00
});

expect(order.get('currentQuote')).toEqual('HELLO');
expect(order.get('currentPrice')).toEqual(100.00);
expect(order.get('buy')).toEqual(true);
expect(order.get('targetPrice')).toEqual(101.00);
});
});

describe('Creates a new Order.', () => {

it('Creates a valid instance of Order', () => {
const order = new Order({
currentQuote: 'HELLO',
currentPrice: 100.00,
buy: true,
targetPrice: 50.00,
});

expect(order.isValid()).toEqual(true);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Validation failing

});

it ('Rejects an empty price.', () => {
const order = new Order({
symbol: 'HELLO',
currentPrice: '',
action: true,
});

expect(order.isValid()).toEqual(false);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Validation failing

});

it('Can not create an order with target price greater than or equal to the current price when buying.', () => {
const order = new Order({
currentQuote: 'HELLO',
currentPrice: 100.00,
buy: true,
targetPrice: 101.00,
});

expect(order.isValid()).toEqual(false);
});

it('Can not create an order with target price less than or equal to the current price when selling.', () => {
const order = new Order({
currentQuote: 'HELLO',
currentPrice: 100.00,
buy: false,
targetPrice: 99.00,
});

expect(order.isValid()).toEqual(false);
});

});
});
36 changes: 36 additions & 0 deletions src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,18 @@ import 'foundation-sites/dist/foundation.css';
import 'css/app.css';

import $ from 'jquery';
import _ from 'underscore';

import Backbone from 'backbone';
import Simulator from 'models/simulator';

import Quote from 'models/quote';
import QuoteList from 'collections/quote_list';
import QuoteListView from './views/quote_list_view';

import Order from 'models/order';
import OrderList from 'collections/order_list';
import OrderListView from './views/order_list_view';

const quoteData = [
{
Expand All @@ -27,9 +36,36 @@ const quoteData = [

$(document).ready(function() {
const quotes = new QuoteList(quoteData);
const orders = new OrderList();
const simulator = new Simulator({
quotes: quotes,
});

const quoteListView = new QuoteListView({
model: quotes,
template: _.template($('#quote-template').html()),
el: '#quotes-container'

});
quoteListView.render();

const formDropDown = function formDropDown() {
const $formSelect = $('select[name=symbol]');

quotes.forEach((quote) => {
const quoteSymbol = quote.get('symbol');
$formSelect.append(`<option value=${quoteSymbol}>${quoteSymbol}</option>`);
});
};
formDropDown();

const orderListView = new OrderListView({
model: orders,
template: _.template($('#order-template').html()),
quoteList: quotes,
el: '#order-workspace'
});
orderListView.render();

simulator.start();
});
8 changes: 8 additions & 0 deletions src/collections/order_list.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import Backbone from 'backbone';
import Order from 'models/order';

const OrderList = Backbone.Collection.extend({
model: Order,
});

export default OrderList;
31 changes: 31 additions & 0 deletions src/models/order.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import Backbone from 'backbone';

const Order = Backbone.Model.extend({
initialize(params) {
this.buy = params.buy,
this.currentQuote = params.currentQuote,
this.currentPrice = params.currentPrice,
this.targetPrice = params.targetPrice
},

validate(attributes) {
const error = {};
if (this.buy && this.targetPrice >= this.currentPrice) {
error.targetPrice = ['Price is higher than market, aim lower!'];
}
else if (!this.buy && this.targetPrice <= this.currentPrice) {
error.targetPrice = ['Price is lower than market, aim higher!'];
}
else if (!attributes.targetPrice) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You also need (based on your tests) to check for numeric value for price, boolean value for buy and maybe check if (!attributes.targetPrice) first.

error.targetPrice = ['Price must not be blank!'];
}

if (Object.keys(error).length < 1) {
return error;
} else {
return false;
}
},
});

export default Order;
4 changes: 2 additions & 2 deletions src/models/quote.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ const Quote = Backbone.Model.extend({
},

buy() {
// Implement this function to increase the price by $1.00
this.set('price', this.get('price') + 1.00);
},

sell() {
// Implement this function to decrease the price by $1.00
this.set('price', this.get('price') - 1.00);
},
});

Expand Down
75 changes: 75 additions & 0 deletions src/views/order_list_view.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import _ from 'underscore';
import $ from 'jquery';

import Backbone from 'backbone';

import OrderView from '../views/order_view';
import Order from '../models/order'

const OrderListView = Backbone.View.extend({
initialize(params) {
this.template = params.template;
this.quoteList = params.quoteList;
this.listenTo(this.model, 'update', this.render);
},

render() {
this.$('#orders').empty();
this.model.each((order) => {
const orderView = new OrderView({
model: order,
template: this.template,
tagName: 'li',
className: 'order',
});
this.$('#orders').append(orderView.render().$el);
});
return this;
},

events: {
'click button.btn-buy': 'buyOrder',
'click button.btn-sell': 'sellOrder'
},

buyOrder: function(event) {
event.preventDefault();
const orderData = {
buy: true,
symbol: this.$('select[name=symbol]').val(),
targetPrice: parseFloat(this.$('input[name=price-target]').val()),
currentPrice: 0,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is the order to get the current quote price? Maybe this view needs to have an instance variable referring to the Quotelist.

currentQuote: 0
};

const newOrder = new Order(orderData);

if (newOrder.isValid()) {
this.model.add(newOrder);
} else {
console.log('Invalid Order!', newOrder.validationError);
}
},

sellOrder: function(event) {
event.preventDefault();

const orderData = {
buy: false,
symbol: this.$('select[name=symbol]').val(),
targetPrice: parseFloat(this.$('input[name=price-target]').val()),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No currentPrice

};

const newOrder = new Order(orderData);

if (newOrder.isValid()) {
this.model.add(newOrder);
} else {
console.log('Invalid Order!');
}
},


});

export default OrderListView;
30 changes: 30 additions & 0 deletions src/views/order_view.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import $ from 'jquery';
import _ from 'underscore';

import Backbone from 'backbone';

import Order from '../models/order';

const OrderView = Backbone.View.extend({
initialize(params) {
this.template = params.template;
this.orderTemplate = params.orderTemplate;
this.listenTo(this.model, "change", this.render);
},

render() {
const compiledTemplate = this.template(this.model.toJSON());
this.$el.html(compiledTemplate);
return this;
},

events: {
'click button.btn-cancel': 'cancelOrder',
},

cancelOrder(){
this.model.destroy();
},
});

export default OrderView;
28 changes: 28 additions & 0 deletions src/views/quote_list_view.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import _ from 'underscore';
import Backbone from 'backbone';

import QuoteView from '../views/quote_view';
import Quote from '../models/quote';

const QuoteListView = Backbone.View.extend({
initialize(params) {
this.template = params.template;
this.listenTo(this.model, 'update', this.render);
},

render() {
this.$('#quotes').empty();
this.model.each((quote) => {
const quoteView = new QuoteView({
model: quote,
template: this.template,
tagName: 'li',
className: 'quote',
});
this.$('#quotes').append(quoteView.render().$el);
});
return this;
},
});

export default QuoteListView;
41 changes: 41 additions & 0 deletions src/views/quote_view.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import $ from 'jquery';
import _ from 'underscore';

import Backbone from 'backbone';
import Quote from '../models/quote';

const QuoteView = Backbone.View.extend({
initialize(params) {
this.template = params.template;
this.listenTo(this.model, "change", this.render);
},

// This is the portion of the code, that needs to be listening to the buttons for click events, as it is rendering the buttons on the page.
render() {
const compiledTemplate = this.template(this.model.toJSON());
this.$el.html(compiledTemplate);

return this;
},

events: {
'click button.btn-buy': 'buyQuote',
'click button.btn-sell': 'sellQuote',
},

buyQuote: function() {
this.model.set('buy', true);
let tradeTemplate = _.template($('#trade-template').html());
$('#trades').prepend(tradeTemplate(this.model.attributes));
this.model.buy();
},

sellQuote: function() {
this.model.set('buy', false);
let tradeTemplate = _.template($('#trade-template').html());
$('#trades').prepend(tradeTemplate(this.model.attributes));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should not directly access jQuery in a view. Instead use this.$ to select things within the view. Since the trades section is not within the view you can can trigger an event and let the larger view handle the prepending.

this.model.sell();
},
});

export default QuoteView;