diff --git a/JS/helpers/calculator.js b/JS/helpers/calculator.js new file mode 100644 index 0000000..f984584 --- /dev/null +++ b/JS/helpers/calculator.js @@ -0,0 +1,43 @@ +/*global console, Rent */ + +function Calculator(home) { + 'use strict'; + this.home = home; + this.calculateRents(); + + console.log(this.home.rooms); +} + +Calculator.prototype.calculateRents = function () { + 'use strict'; + var room_id; + for (room_id in this.home.rooms) { + if (this.home.rooms.hasOwnProperty(room_id)) { + this.calculateRent(room_id); + } + } +}; + +Calculator.prototype.calculateRent = function (room_id) { + 'use strict'; + var room = this.home.rooms[room_id], + occupants = room.occupiedBy.length, + baseCost = this.home.commonShareCost * occupants, + roomCost = room.sqft * this.home.privateCostPerSqft * room.percentUsable, + price = baseCost + roomCost; + + room.rent = new Rent(price, room_id, this.home); + + this.applyFeesAndDiscounts(room); + if (this.home.roundDollar) { + room.rent.price += parseInt(room.rent.price, 10); + } +}; + +Calculator.prototype.applyFeesAndDiscounts = function (room) { + 'use strict'; + room.rent = ( + room.hasWindow ? + parseFloat(this.home.goodLightingFee) : parseFloat(this.home.badLightingDeduction) + ); +}; \ No newline at end of file diff --git a/JS/helpers/defaultRooms.js b/JS/helpers/defaultRooms.js new file mode 100644 index 0000000..82c22fe --- /dev/null +++ b/JS/helpers/defaultRooms.js @@ -0,0 +1,62 @@ +var defaultRooms = { + "B-R1": { + "sqft": 169, + "hasWindow": true, + "percentUsable": 100, + "occupiedBy": ["Conrad"] + }, + "B-R2": { + "sqft": 165, + "hasWindow": false, + "percentUsable": 100, + "occupiedBy": ["A. Kern", "Potluck"] + }, + "B-R3": { + "sqft": 151, + "hasWindow": false, + "percentUsable": 80, + "occupiedBy": ["Renee"] + }, + "B-R4": { + "sqft": 146, + "hasWindow": true, + "percentUsable": 100, + "occupiedBy": ["Hallie"] + }, + "B-R5": { + "sqft": 146, + "hasWindow": true, + "percentUsable": 100, + "occupiedBy": ["Jack"] + }, + "C-R1": { + "sqft": 191, + "hasWindow": true, + "percentUsable": 100, + "occupiedBy": ["Marco", "Alex C."] + }, + "C-R2": { + "sqft": 191, + "hasWindow": true, + "percentUsable": 100, + "occupiedBy": ["Ashley", "Robin"] + }, + "C-R3": { + "sqft": 178, + "hasWindow": false, + "percentUsable": 100, + "occupiedBy": ["Ari"] + }, + "C-R4": { + "sqft": 166, + "hasWindow": true, + "percentUsable": 100, + "occupiedBy": ["Nick"] + }, + "C-R5": { + "sqft": 167, + "hasWindow": true, + "percentUsable": 100, + "occupiedBy": ["Fouad"] + } +}; \ No newline at end of file diff --git a/JS/helpers/home.js b/JS/helpers/home.js index f1a6dbb..338ed26 100644 --- a/JS/helpers/home.js +++ b/JS/helpers/home.js @@ -1,4 +1,4 @@ -/*global rooms, console, moneyRound */ +/*global rooms, console, defaultRooms, dataType, getPropertyName, getDisplayName, moneyRound, convertItem */ var defaults = { attributeTableId: 'house-attribute-table', @@ -16,9 +16,15 @@ var defaults = { commonWeight: 0.60, houseSize: 6200, rentSum: 18000, + rooms: defaultRooms, roundDollar: true }; +var EDITABLE_FIELDS = [ + 'calculateAsSingles', 'cheapestRoomMustBeSingle', 'commonWeight', + 'rentSum', 'roundDollar' +]; + function Home(options) { 'use strict'; this.rooms = {}; @@ -31,6 +37,7 @@ function Home(options) { this.commonWeight = options.commonWeight || defaults.commonWeight; this.houseSize = options.houseSize || defaults.houseSize; this.rentSum = options.rentSum || defaults.rentSum; + this.rooms = options.rooms || defaults.rooms; this.roundDollar = options.roundDollar || defaults.roundDollar; this.feesAndDeducts = options.feesAndDeducts || defaults.feesAndDeducts; @@ -51,10 +58,8 @@ function Home(options) { } } - this.populateAttributeTable(this.attributeTableId, this); - this.populateAttributeTable('fees-attribute-table', this.feesAndDeducts); - - console.log(this); + this.populateAttributeTable(this); + this.populateAttributeTable(this.feesAndDeducts); } Home.prototype.setCheapestRoom = function (room) { @@ -146,8 +151,8 @@ Home.prototype.setOpposingFeeOrDeduction = function (name, feeDuct) { Home.prototype.fillHouse = function () { 'use strict'; /* TODO: check/grab rooms from structured screen before falling back on defaults */ - if (rooms !== undefined) { - this.rooms = rooms; + if (this.rooms !== undefined) { + this.rooms = defaultRooms; } }; @@ -174,33 +179,77 @@ Home.prototype.calculateRoomSqftCosts = function () { this.privateCostPerSqft = moneyRound(this.privateCostPerSqft); }; -Home.prototype.populateAttributeTable = function (tableId, attributes) { +Home.prototype.populateAttributeTable = function (attributes) { 'use strict'; - var attributeTable = document.getElementById(tableId), + var attributeTable = document.getElementById(this.attributeTableId), + dontPrint = ['attributeTableId'], row, cell, attribute, subAttribute, rowIndex = attributeTable.rows.length, cellIndex; - function insertCell(row, index, item) { - cell = row.insertCell(index); - cell.innerHTML = item; + function createValInput(item) { + var input = document.createElement('INPUT'); + input.setAttribute('type', 'text'); + input.setAttribute('value', item); + return input; } - function insertRow(table, index, cells) { - row = table.insertRow(index); - for (cellIndex = 0; cellIndex < cells.length; cellIndex += 1) { - insertCell(row, cellIndex, cells[cellIndex]); + function createValCheckbox(item) { + var input = document.createElement('INPUT'); + input.setAttribute('type', 'checkbox'); + input.checked = (item === 'true'); + return input; + } + function createValCell(row, attrName, attrValue) { + var propertyName = attrName; + attrName = getDisplayName(attrName); + cell = row.insertCell(0); + cell.innerHTML = attrName; + cell = row.insertCell(1); + + attrValue = convertItem(propertyName, attrValue); + if (EDITABLE_FIELDS.includes(propertyName)) { + if (dataType[propertyName].type === 'bool') { + attrValue = createValCheckbox(attrValue); + } else { + attrValue = createValInput(attrValue); + } + cell.appendChild(attrValue); + } else { + cell.innerHTML = attrValue; } } - console.log(tableId); + function insertRow(table, index, attrName, attrValue) { + row = table.insertRow(index); + createValCell(row, attrName, attrValue); + } + for (attribute in attributes) { if (attributes.hasOwnProperty(attribute)) { - if (typeof attributes[attribute] !== 'object') { - console.log(attributeTable, tableId, attribute); - insertRow(attributeTable, rowIndex, [attribute, attributes[attribute]]); + if (!dontPrint.includes(attribute) && (typeof attributes[attribute] !== 'object')) { + insertRow(attributeTable, rowIndex, attribute, attributes[attribute]); rowIndex += 1; } } } -}; \ No newline at end of file +}; + +Home.prototype.getAttributesFromTable = function () { + 'use strict'; + var attributeTable = document.getElementById(this.attributeTableId), + table, + tr, + tdName, + tdContent; + console.log(attributeTable); + for (tr = 1; tr < attributeTable.rows.length; tr += 1) { + if (attributeTable.rows.hasOwnProperty(tr)) { + tdName = getPropertyName(attributeTable.rows[tr].children[0].textContent); + tdContent = getText(attributeTable.rows[tr].children[1]); + tdContent = parseItem(tdName, tdContent); + this[tdName] = tdContent; + } + } + console.log(this); +}; diff --git a/JS/helpers/rent.js b/JS/helpers/rent.js new file mode 100644 index 0000000..6ba8e2e --- /dev/null +++ b/JS/helpers/rent.js @@ -0,0 +1,11 @@ +function Rent(price, room_id, home) { + 'use strict'; + this.price = price; + this.room_id = room_id; + this.home = home; +} + +Rent.prototype.getRoomDeets = function () { + 'use strict'; + return this.home.rooms[this.room_id]; +}; \ No newline at end of file diff --git a/JS/helpers/rooms.js b/JS/helpers/rooms.js index c80d9c3..cbbc2c8 100644 --- a/JS/helpers/rooms.js +++ b/JS/helpers/rooms.js @@ -1,62 +1,32 @@ -var rooms = { - "B-R1": { - "sqft": 169, - "hasWindow": true, - "percentUsable": 1, - "occupiedBy": ["Conrad"] - }, - "B-R2": { - "sqft": 165, - "hasWindow": false, - "percentUsable": 1, - "occupiedBy": ["A. Kern", "Potluck"] - }, - "B-R3": { - "sqft": 151, - "hasWindow": false, - "percentUsable": 0.8, - "occupiedBy": ["Renee"] - }, - "B-R4": { - "sqft": 146, - "hasWindow": true, - "percentUsable": 1, - "occupiedBy": ["Hallie"] - }, - "B-R5": { - "sqft": 146, - "hasWindow": true, - "percentUsable": 1, - "occupiedBy": ["Jack"] - }, - "C-R1": { - "sqft": 191, - "hasWindow": true, - "percentUsable": 1, - "occupiedBy": ["Marco", "Alex C."] - }, - "C-R2": { - "sqft": 191, - "hasWindow": true, - "percentUsable": 1, - "occupiedBy": ["Ashley", "Robin"] - }, - "C-R3": { - "sqft": 178, - "hasWindow": false, - "percentUsable": 1, - "occupiedBy": ["Ari"] - }, - "C-R4": { - "sqft": 166, - "hasWindow": true, - "percentUsable": 1, - "occupiedBy": ["Nick"] - }, - "C-R5": { - "sqft": 167, - "hasWindow": true, - "percentUsable": 1, - "occupiedBy": ["Fouad"] +/*global console, getPropertyName, getText, parseItem */ + +function createRoomsFromDefaults() { + 'use strict'; +} + +function getRoomsFromTables() { + 'use strict'; + var tables = document.getElementsByClassName('room'), + table, + tr, + tdName, + tdContent, + rooms = {}, + roomId; + for (table in tables) { + if (tables.hasOwnProperty(table)) { + roomId = tables[table].rows[0].textContent; + rooms[roomId] = {}; + for (tr = 1; tr < tables[table].rows.length; tr += 1) { + if (tables[table].rows.hasOwnProperty(tr)) { + tdName = getPropertyName(tables[table].rows[tr].children[0].textContent); + tdContent = getText(tables[table].rows[tr].children[1]); + tdContent = parseItem(tdName, tdContent); + rooms[roomId][tdName] = tdContent; + } + } + } } -}; \ No newline at end of file + console.log(rooms); + return rooms; +} \ No newline at end of file diff --git a/JS/helpers/utils.js b/JS/helpers/utils.js index 90a2a74..c441070 100644 --- a/JS/helpers/utils.js +++ b/JS/helpers/utils.js @@ -1,4 +1,219 @@ function moneyRound(number) { 'use strict'; - return parseFloat(number.toFixed(2)); -} \ No newline at end of file + return parseFloat(number).toFixed(2); +} + +function stripNumber(numString) { + 'use strict'; + return numString.replace(/[^0-9\.]+/g, ""); +} + +function invertDict(dict) { + 'use strict'; + var newDict = {}, + newKey, + newVal; + for (newVal in dict) { + if (dict.hasOwnProperty(newVal)) { + newKey = dict[newVal]; + newDict[newKey] = newVal; + } + } + return newDict; +} + +var displayNames = { + // House Attributes + calculateAsSingles: 'Calculated as Singles', + cheapestRoomMustBeSingle: 'Cheapest Room is Single', + commonWeight: 'Common Weight', + houseSize: 'House Size', + rentSum: 'Rent Sum', + roundDollar: 'Rounded to Dollar', + peepsCount: '# Housemates', + commonSpace: 'Common Area', + commonCostPerSqft: 'Common Cost per SqFt', + commonShareCost: 'Base share cost', + privateCostPerSqft: 'Room Cost per SqFt', + // Room attributes + sqft: 'Area', + hasWindow: 'Has Window', + percentUsable: 'Usable Space', + occupiedBy: 'Occupied By' +}; + +var propertyNames = invertDict(displayNames); +propertyNames.feeOrDeduct = 'feeOrDeduct'; + +var dataType = { + // House attributes + calculateAsSingles: { + type: 'bool', + displayName: displayNames.calculateAsSingles + }, + cheapestRoomMustBeSingle: { + type: 'bool', + displayName: displayNames.cheapestRoomMustBeSingle + }, + commonWeight: { + type: 'percent', + displayName: displayNames.commonWeight + }, + houseSize: { + type: 'sqft', + displayName: displayNames.houseSize + }, + rentSum: { + type: 'dollar', + displayName: displayNames.rentSum + }, + roundDollar: { + type: 'bool', + displayName: displayNames.roundDollar + }, + peepsCount: { + type: 'number', + displayName: displayNames.peepsCount + }, + commonSpace: { + type: 'sqft', + displayName: displayNames.commonSpace + }, + commonCostPerSqft: { + type: 'dollar', + displayName: displayNames.commonCostPerSqft + }, + commonShareCost: { + type: 'dollar', + displayName: displayNames.commonShareCost + }, + privateCostPerSqft: { + type: 'dollar', + displayName: displayNames.privateCostPerSqft + }, + feeOrDeduct: { + type: 'dollar' + }, + // Room attributes + sqft: { + type: 'sqft', + displayName: displayNames.sqft + }, + hasWindow: { + type: 'bool', + displayName: displayNames.hasWindow + }, + percentUsable: { + type: 'percent', + displayName: displayNames.percentUsable + }, + occupiedBy: { + type: 'list', + displayName: displayNames.occupiedBy + } +}; + +var toDataType = { + bool: function (item) { + 'use strict'; + return item.toString(); + }, + percent: function (item) { + 'use strict'; + return (item * 100).toString() + '%'; + }, + sqft: function (item) { + 'use strict'; + return item.toLocaleString(); + }, + dollar: function (item) { + 'use strict'; + return '$' + moneyRound(item).toLocaleString(); + }, + number: function (item) { + 'use strict'; + return item.toLocaleString(); + }, + list: function (item) { + 'use strict'; + return item.join(','); + } +}; + +var fromDataType = { + bool: function (item) { + 'use strict'; + return (item === 'true'); + }, + percent: function (item) { + 'use strict'; + return parseFloat(stripNumber(item)) / 100; + }, + sqft: function (item) { + 'use strict'; + return parseInt(stripNumber(item), 10); + }, + dollar: function (item) { + 'use strict'; + return moneyRound(stripNumber(item)); + }, + number: function (item) { + 'use strict'; + return parseInt(stripNumber(item), 10); + }, + list: function (item) { + 'use strict'; + return item.split(','); + } +}; + +function isFeeOrDeduct(name) { + 'use strict'; + return (name.includes('Deduction') || name.includes('Fee')); +} + +function parseItem(name, item) { + 'use strict'; + name = isFeeOrDeduct(name) ? propertyNames.feeOrDeduct : name; + var type = dataType[name].type; + return fromDataType[type](item); +} + +function convertItem(name, item) { + 'use strict'; + name = isFeeOrDeduct(name) ? propertyNames.feeOrDeduct : name; + var type = dataType[name].type; + return toDataType[type](item); +} + +function getText(item) { + 'use strict'; + if (item.firstChild.localName === 'input') { + if (item.firstChild.type === 'checkbox') { + return item.firstChild.checked.toString(); + } + return item.firstChild.value; + } + return item.textContent; +} + +function getDisplayName(name) { + 'use strict'; + if (displayNames.hasOwnProperty(name)) { + return displayNames[name]; + } + name = name.split(/(?=[A-Z])/).join(' '); + name = name.charAt(0).toUpperCase() + name.slice(1); + return name; +} + +function getPropertyName(name) { + 'use strict'; + if (propertyNames.hasOwnProperty(name)) { + return propertyNames[name]; + } + name = name.split(' ').join(''); + name = name.charAt(0).toLowerCase() + name.slice(1); + return name; +} + diff --git a/JS/index.html b/JS/index.html index 4c5f521..b39b710 100644 --- a/JS/index.html +++ b/JS/index.html @@ -1,18 +1,126 @@ - + + + - - -
House Attributes
- - -
Fees and Deduction
+
+ + +
House Attributes
+
+ + +
+ + + + + + + + + +
B-R1
Area169
Has WindowTrue
Usable Space100%
Occupied By
+ + + + + + + + + +
B-R2
Area165
Has WindowFalse
Usable Space100%
Occupied By
+ + + + + + + + + +
B-R3
Area151
Has WindowFalse
Usable Space80%
Occupied By
+ + + + + + + + + +
B-R4
Area146
Has WindowTrue
Usable Space100%
Occupied By
+ + + + + + + + + +
B-R5
Area146
Has WindowTrue
Usable Space100%
Occupied By
+ + + + + + + + + +
C-R1
Area191
Has WindowTrue
Usable Space100%
Occupied By
+ + + + + + + + + +
C-R2
Area191
Has WindowTrue
Usable Space100
Occupied By
+ + + + + + + + + +
C-R3
Area178
Has WindowFalse
Usable Space100%
Occupied By
+ + + + + + + + + +
C-R4
Area166
Has WindowTrue
Usable Space100%
Occupied By
+ + + + + + + + + +
C-R5
Area167
Has WindowTrue
Usable Space100%
Occupied By
+
+ + + diff --git a/JS/main.css b/JS/main.css new file mode 100644 index 0000000..78ca4e9 --- /dev/null +++ b/JS/main.css @@ -0,0 +1,38 @@ +html, body { + top: 0; + left: 0; + height: 100%; + width: 100%; +} + +table { + float: left; + border: 1px solid black; +} + +td { + border: 1px solid black; + width: 200px; +} + +input { + width: 100%; +} + +#attributes { + display: inline-block; +} + +#rooms { + display: inline-block; +} + +.room {} + +.room td { + width: 110px; +} + +#house-attribute-table {} + +#fees-attribute-table {} \ No newline at end of file diff --git a/JS/main.js b/JS/main.js index 3440580..84452bb 100644 --- a/JS/main.js +++ b/JS/main.js @@ -1,3 +1,13 @@ -/*global Home */ +/*global Calculator, Home, getRoomsFromTables */ -var homes = new Home(); \ No newline at end of file +function buildHome() { + 'use strict'; + var rooms = getRoomsFromTables(), + home = new Home({ + rooms: rooms + }); + //calculator = new Calculator(homes); + home.getAttributesFromTable(); +} + +document.addEventListener('DOMContentLoaded', buildHome, false); \ No newline at end of file