Permalink
Browse files

Proof of concept charting working again, with balances displayed on t…

…he left
  • Loading branch information...
1 parent 6a7b256 commit aac9f146b8cbd3fd51ddd37c1e9dfc292f39409c @konklone konklone committed Feb 28, 2010
Showing with 132 additions and 14 deletions.
  1. +6 −10 Rakefile
  2. +78 −0 charting.rb
  3. +2 −2 fixtures/accounts.yml
  4. +8 −1 models.rb
  5. +9 −1 ohnomymoney.rb
  6. +29 −0 views/index.erb
View
@@ -4,6 +4,9 @@ task :migrate => :environment do
ActiveRecord::Migrator.migrate 'migrations', (ENV['version'] ? ENV['version'].to_i : nil)
end
+def all_models
+ [User, Account, Day]
+end
namespace :fixtures do
@@ -26,18 +29,11 @@ task :environment do
require 'ohnomymoney'
end
-def all_models
- [User, Account, Day]
-end
-
-def fixture_dir
- "fixtures"
-end
def restore_fixture(model)
model.delete_all
- YAML::load_file("#{fixture_dir}/#{model.table_name}.yml").each do |row|
+ YAML::load_file("fixtures/#{model.table_name}.yml").each do |row|
record = model.new
row.keys.each do |field|
record[field] = row[field] if row[field]
@@ -57,8 +53,8 @@ def dump_fixture(model)
records << element
end
- FileUtils.mkdir_p fixture_dir
- File.open("#{fixture_dir}/#{model.table_name}.yml", "w") do |file|
+ FileUtils.mkdir_p "fixtures"
+ File.open("fixtures/#{model.table_name}.yml", "w") do |file|
YAML.dump data, file
end
View
@@ -0,0 +1,78 @@
+require 'google_chart'
+
+helpers do
+
+ def chart_for(days)
+ oldest = days.first
+ newest = days[days.size-1]
+ balances = days.map {|day| day.balance}
+
+ min = balances.min
+ max = balances.max
+ disparity = max - min
+ y = (disparity * 1.66).to_i
+ buffer = (y - disparity) / 2
+
+ y_min = round(min - buffer)
+ y_max = round(max + buffer)
+ y = y_max - y_min
+ y_step = round(y / 10.0, 2)
+
+ x_step = days.size / 7
+ x_step = 1 if x_step < 1
+ x_days = []
+ days.each_with_index {|b, i| x_days << b if i % x_step == 0}
+ x_days[0] = days[0]
+ x_days[-1] = days[-1]
+
+ y_labels = (0..10).map {|i| format_balance(y_min + (y_step * i))}
+ x_labels = x_days.map {|day| format_date day.date_of}
+
+ label = newest.balance > 0 ? 'Money' : 'Debt'
+ data = balances.map {|balance| (balance - y_min).to_f}
+ color = newest.balance > 0 ? '008800' : 'cc0000'
+
+ chart = GoogleChart::LineChart.new '857x350'
+ chart.data_encoding = :text
+ chart.max_value y
+ chart.data label, data, color
+ chart.axis :x, :labels => x_labels
+ chart.axis :y, :labels => y_labels
+ chart.axis :right, :labels => y_labels
+
+ p chart.to_url(:chdlp => 'b')
+ chart.to_url :chdlp => 'b'
+ end
+
+ def round(n, level = 3)
+ (n - (n % (10**level))).to_i
+ end
+
+ def double_encode(text)
+ text.gsub("&", "&amp;")
+ end
+
+ def format_balance(balance)
+ number = balance.to_f / 100
+ parts = ("%01.2f" % number).split('.')
+ answer = '$' + number_with_delimiter(parts[0]) + '.' + parts[1].to_s
+ if number > 0
+ answer = '+' + answer
+ elsif number < 0
+ answer = '-' + answer
+ end
+ answer
+ end
+
+ def number_with_delimiter(number)
+ number = number.to_i.abs
+ parts = number.to_s.split('.')
+ parts[0].gsub! /(\d)(?=(\d\d\d)+(?!\d))/, "\\1,"
+ parts.join '.'
+ end
+
+ def format_date(date)
+ date.strftime("%B ") + date.strftime("%d").gsub(/^0/, "")
+ end
+
+end
View
@@ -20,12 +20,12 @@
- name: Credit Card
created_at: 2010-02-15 01:55:20 -05:00
updated_at: 2010-02-15 02:23:49 -05:00
- account_type: debt
+ account_type: debts
id: 4
user_id: 1
- name: Student Loans
created_at: 2010-02-15 01:57:24 -05:00
updated_at: 2010-02-15 02:23:55 -05:00
- account_type: debt
+ account_type: debts
id: 5
user_id: 1
View
@@ -6,7 +6,7 @@ class Day < ActiveRecord::Base
end
class Account < ActiveRecord::Base
- TYPES = %w( worth assets debt )
+ TYPES = %w( worth assets debts )
belongs_to :user
has_many :days
@@ -15,10 +15,17 @@ class Account < ActiveRecord::Base
validates_presence_of :user_id
validates_inclusion_of :account_type, :in => TYPES
+ named_scope :worth, :conditions => {:account_type => 'worth'}
+ named_scope :assets, :conditions => {:account_type => 'assets'}
+ named_scope :debts, :conditions => {:account_type => 'debts'}
def needs_name
account_type != 'worth'
end
+
+ def balance
+ days.count > 0 ? days.first(:order => "created_at DESC").balance : 0
+ end
end
class User < ActiveRecord::Base
View
@@ -4,6 +4,9 @@
require 'sinatra'
require 'environment'
+require 'erb'
+require 'charting'
+
# For now, have the root URL act as if we visited the userpage of the first user
before do
request.path_info = "/#{User.first.handle}" if request.path_info == '/'
@@ -12,5 +15,10 @@
get "/:handle" do
halt 404 unless user = User.find_by_handle(params[:handle])
- user.accounts.all.map(&:name).join("<br/>\n")
+ erb :index, :locals => {
+ :user => user,
+ :worth => user.accounts.worth.first,
+ :assets => user.accounts.assets.all,
+ :debts => user.accounts.debts.all
+ }
end
View
@@ -0,0 +1,29 @@
+<!doctype html>
+<html>
+<head>
+ <title><%= user.name %>'s Money</title>
+</head>
+<body>
+
+ <h1><%= user.name %>'s Money</h1>
+
+ <div class="sidebar">
+ <div class="account worth">
+ <h2>Net Worth</h2>
+ <span><%= worth.balance %></span>
+ </div>
+
+ <% (assets + debts).each do |account| %>
+ <div class="account <%= account.account_type %>">
+ <h2><%= account.name %></h2>
+ <span><%= account.balance %></span>
+ </div>
+ <% end %>
+ </div>
+
+ <div class="main">
+ <img src="<%= double_encode chart_for(worth.days.all(:limit => 10)) %>" />
+ </div>
+
+</body>
+</html>

0 comments on commit aac9f14

Please sign in to comment.