From c96f0a78593a43a06884519e2aa6ee5b41bb300a Mon Sep 17 00:00:00 2001 From: Seth Call Date: Wed, 20 May 2015 09:24:17 -0500 Subject: [PATCH 01/45] * VRFS-3260 - fraud check code and admin helpers complete --- admin/app/admin/fraud_alert.rb | 69 +++++++++++ admin/app/admin/machine_extra.rb | 8 ++ admin/app/admin/machine_fingerprint.rb | 22 ++++ admin/app/admin/music_sessions_comment.rb | 13 +++ admin/app/admin/session_info_comment.rb | 8 ++ db/manifest | 3 +- db/up/optimized_redemption_warn_mode.sql | 42 +++++++ ruby/lib/jam_ruby.rb | 3 + .../jam_ruby/models/fingerprint_whitelist.rb | 17 +++ ruby/lib/jam_ruby/models/fraud_alert.rb | 26 +++++ ruby/lib/jam_ruby/models/jam_track_right.rb | 91 +++++++++++---- ruby/lib/jam_ruby/models/machine_extra.rb | 35 ++++++ .../jam_ruby/models/machine_fingerprint.rb | 20 +++- .../jam_ruby/models/jam_track_right_spec.rb | 110 +++++++++++++----- ruby/spec/support/utilities.rb | 8 ++ web/app/assets/javascripts/jam_rest.js | 5 +- web/app/controllers/users_controller.rb | 8 +- web/config/application.rb | 4 +- .../api_jam_tracks_controller_spec.rb | 17 ++- web/spec/support/app_config.rb | 8 ++ web/spec/support/remote_ip_monkey_patch.rb | 17 +++ web/spec/support/utilities.rb | 2 +- 22 files changed, 471 insertions(+), 65 deletions(-) create mode 100644 admin/app/admin/fraud_alert.rb create mode 100644 admin/app/admin/machine_extra.rb create mode 100644 admin/app/admin/machine_fingerprint.rb create mode 100644 admin/app/admin/music_sessions_comment.rb create mode 100644 admin/app/admin/session_info_comment.rb create mode 100644 db/up/optimized_redemption_warn_mode.sql create mode 100644 ruby/lib/jam_ruby/models/fingerprint_whitelist.rb create mode 100644 ruby/lib/jam_ruby/models/fraud_alert.rb create mode 100644 ruby/lib/jam_ruby/models/machine_extra.rb create mode 100644 web/spec/support/remote_ip_monkey_patch.rb diff --git a/admin/app/admin/fraud_alert.rb b/admin/app/admin/fraud_alert.rb new file mode 100644 index 000000000..7c4754a83 --- /dev/null +++ b/admin/app/admin/fraud_alert.rb @@ -0,0 +1,69 @@ +ActiveAdmin.register JamRuby::FraudAlert, :as => 'Fraud Alerts' do + + menu :label => 'Fraud Alerts', :parent => 'JamTracks' + + config.sort_order = 'created_at desc' + config.batch_actions = false + + + scope("Not Whitelisted", default:true) { |scope| + scope.joins('INNER JOIN "machine_fingerprints" ON "machine_fingerprints"."id" = "fraud_alerts"."machine_fingerprint_id" LEFT OUTER JOIN "fingerprint_whitelists" ON "fingerprint_whitelists"."fingerprint" = "machine_fingerprints"."fingerprint"').where('fingerprint_whitelists IS NULL')} + + index do + default_actions + + column :machine_fingerprint + column :user + column :created_at + column :resolved + + column "" do |alert| + link_to 'Matching MAC', "fraud_alerts/#{alert.id}/same_fingerprints" + end + column "" do |alert| + link_to 'Matching MAC and IP Address', "fraud_alerts/#{alert.id}/same_fingerprints_and_ip" + end + column "" do |alert| + link_to 'Matching IP Address', "fraud_alerts/#{alert.id}/same_ip" + end + column "" do |alert| + link_to 'Resolve', "fraud_alerts/#{alert.id}/resolve" + end + column "" do |alert| + link_to 'Whitelist Similar', "fraud_alerts/#{alert.id}/whitelist" + end + end + + member_action :same_fingerprints, :method => :get do + alert = FraudAlert.find(params[:id]) + + redirect_to admin_machine_fingerprints_path("q[fingerprint_equals]" => alert.machine_fingerprint.fingerprint, commit: 'Filter', order: 'created_at_desc') + end + + member_action :same_fingerprints_and_ip, :method => :get do + alert = FraudAlert.find(params[:id]) + + redirect_to admin_machine_fingerprints_path("q[fingerprint_equals]" => alert.machine_fingerprint.fingerprint, "q[remote_ip_equals]" => alert.machine_fingerprint.remote_ip, commit: 'Filter', order: 'created_at_desc') + end + + + member_action :resolve, :method => :get do + alert = FraudAlert.find(params[:id]) + alert.resolved = true + alert.save! + + redirect_to admin_fraud_alerts_path, notice: "That fraud alert has been marked as resolved" + end + + member_action :whitelist, :method => :get do + alert = FraudAlert.find(params[:id]) + + wl = FingerprintWhitelist.new + wl.fingerprint = alert.machine_fingerprint.fingerprint + success = wl.save + + redirect_to admin_fraud_alerts_path, notice: success ? "Added #{alert.machine_fingerprint.fingerprint} to whitelist" : "Could not add #{alert.machine_fingerprint.fingerprint} to whiteliste" + end + + +end \ No newline at end of file diff --git a/admin/app/admin/machine_extra.rb b/admin/app/admin/machine_extra.rb new file mode 100644 index 000000000..c1c5b8738 --- /dev/null +++ b/admin/app/admin/machine_extra.rb @@ -0,0 +1,8 @@ +ActiveAdmin.register JamRuby::MachineExtra, :as => 'Machine Extra' do + + menu :label => 'Machine Extra', :parent => 'JamTracks' + + config.sort_order = 'created_at desc' + config.batch_actions = false + +end \ No newline at end of file diff --git a/admin/app/admin/machine_fingerprint.rb b/admin/app/admin/machine_fingerprint.rb new file mode 100644 index 000000000..4ea9c3c7a --- /dev/null +++ b/admin/app/admin/machine_fingerprint.rb @@ -0,0 +1,22 @@ +ActiveAdmin.register JamRuby::MachineFingerprint, :as => 'Machine Fingerprints' do + + menu :label => 'Machine Fingerprints', :parent => 'JamTracks' + + config.sort_order = 'created_at desc' + config.batch_actions = false + + index do + column :user + column 'Hash' do |fp| + fp.fingerprint + end + column :remote_ip + column 'Detail' do |fp| + detail = fp.detail + if detail + detail.to_s + end + end + column :created_at + end +end \ No newline at end of file diff --git a/admin/app/admin/music_sessions_comment.rb b/admin/app/admin/music_sessions_comment.rb new file mode 100644 index 000000000..5b651a11f --- /dev/null +++ b/admin/app/admin/music_sessions_comment.rb @@ -0,0 +1,13 @@ +ActiveAdmin.register JamRuby::MusicSessionComment, :as => 'Ratings' do + + config.per_page = 150 + config.clear_action_items! + config.sort_order = 'created_at_desc' + menu :parent => 'Sessions', :label => 'Ratings' + + index do + column :comment + column :user + column :created_at + end +end diff --git a/admin/app/admin/session_info_comment.rb b/admin/app/admin/session_info_comment.rb new file mode 100644 index 000000000..cf8fb3c0c --- /dev/null +++ b/admin/app/admin/session_info_comment.rb @@ -0,0 +1,8 @@ +ActiveAdmin.register JamRuby::SessionInfoComment, :as => 'Comments' do + + config.per_page = 50 + config.clear_action_items! + config.sort_order = 'created_at_desc' + menu :parent => 'Sessions', :label => 'Comments' + +end diff --git a/db/manifest b/db/manifest index 48ba477b9..f2cfbbc71 100755 --- a/db/manifest +++ b/db/manifest @@ -283,4 +283,5 @@ payment_history.sql jam_track_right_private_key.sql first_downloaded_jamtrack_at.sql signing.sql -optimized_redeemption.sql \ No newline at end of file +optimized_redeemption.sql +optimized_redemption_warn_mode.sql \ No newline at end of file diff --git a/db/up/optimized_redemption_warn_mode.sql b/db/up/optimized_redemption_warn_mode.sql new file mode 100644 index 000000000..faf2ad984 --- /dev/null +++ b/db/up/optimized_redemption_warn_mode.sql @@ -0,0 +1,42 @@ +DROP TABLE machine_fingerprints; + +CREATE TABLE machine_fingerprints ( + id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(), + user_id VARCHAR(64) NOT NULL REFERENCES users(id) ON DELETE CASCADE, + fingerprint VARCHAR(20000) NOT NULL, + when_taken VARCHAR NOT NULL, + print_type VARCHAR NOT NULL, + remote_ip VARCHAR(1000) NOT NULL, + jam_track_right_id BIGINT REFERENCES jam_track_rights(id) ON DELETE SET NULL, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP +); + +CREATE TABLE machine_extras ( + id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(), + machine_fingerprint_id VARCHAR(64) NOT NULL REFERENCES machine_fingerprints(id) ON DELETE CASCADE, + mac_address VARCHAR(100), + mac_name VARCHAR(255), + upstate BOOLEAN, + ipaddr_0 VARCHAR(200), + ipaddr_1 VARCHAR(200), + ipaddr_2 VARCHAR(200), + ipaddr_3 VARCHAR(200), + ipaddr_4 VARCHAR(200), + ipaddr_5 VARCHAR(200), + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP +); + +CREATE TABLE fraud_alerts ( + id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(), + machine_fingerprint_id VARCHAR(64) NOT NULL REFERENCES machine_fingerprints(id) ON DELETE CASCADE, + user_id VARCHAR(64) NOT NULL REFERENCES users(id) ON DELETE CASCADE, + resolved BOOLEAN NOT NULL DEFAULT FALSE, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP +); + +CREATE TABLE fingerprint_whitelists ( + id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(), + fingerprint VARCHAR(20000) UNIQUE NOT NULL +); + +CREATE INDEX machine_fingerprints_index1 ON machine_fingerprints USING btree (fingerprint, user_id, remote_ip, created_at); diff --git a/ruby/lib/jam_ruby.rb b/ruby/lib/jam_ruby.rb index 09b125e3d..58ebc614a 100755 --- a/ruby/lib/jam_ruby.rb +++ b/ruby/lib/jam_ruby.rb @@ -104,6 +104,9 @@ require "jam_ruby/models/user" require "jam_ruby/models/anonymous_user" require "jam_ruby/models/signup_hint" require "jam_ruby/models/machine_fingerprint" +require "jam_ruby/models/machine_extra" +require "jam_ruby/models/fraud_alert" +require "jam_ruby/models/fingerprint_whitelist" require "jam_ruby/models/rsvp_request" require "jam_ruby/models/rsvp_slot" require "jam_ruby/models/rsvp_request_rsvp_slot" diff --git a/ruby/lib/jam_ruby/models/fingerprint_whitelist.rb b/ruby/lib/jam_ruby/models/fingerprint_whitelist.rb new file mode 100644 index 000000000..88f015aa3 --- /dev/null +++ b/ruby/lib/jam_ruby/models/fingerprint_whitelist.rb @@ -0,0 +1,17 @@ +module JamRuby + class FingerprintWhitelist < ActiveRecord::Base + + @@log = Logging.logger[FingerprintWhitelist] + + validates :fingerprint, presence: true, uniqueness: true + has_many :machine_fingerprint, class_name: 'JamRuby::MachineFingerprint', foreign_key: :fingerprint + + def admin_url + APP_CONFIG.admin_root_url + "/admin/fingerprint_whitelists/" + id + end + + def to_s + "#{fingerprint}" + end + end +end \ No newline at end of file diff --git a/ruby/lib/jam_ruby/models/fraud_alert.rb b/ruby/lib/jam_ruby/models/fraud_alert.rb new file mode 100644 index 000000000..344eb7ddc --- /dev/null +++ b/ruby/lib/jam_ruby/models/fraud_alert.rb @@ -0,0 +1,26 @@ +module JamRuby + class FraudAlert < ActiveRecord::Base + + @@log = Logging.logger[MachineExtra] + + belongs_to :machine_fingerprint, :class_name => "JamRuby::MachineFingerprint" + belongs_to :user, :class_name => "JamRuby::User" + + + def self.create(machine_fingerprint, user) + fraud = FraudAlert.new + fraud.machine_fingerprint = machine_fingerprint + fraud.user = user + fraud.save + + unless fraud.save + @@log.error("unable to create fraud: #{fraud.errors.inspect}") + end + fraud + end + + def admin_url + APP_CONFIG.admin_root_url + "/admin/fraud_alerts/" + id + end + end +end \ No newline at end of file diff --git a/ruby/lib/jam_ruby/models/jam_track_right.rb b/ruby/lib/jam_ruby/models/jam_track_right.rb index fda1ecb97..c77da5ffe 100644 --- a/ruby/lib/jam_ruby/models/jam_track_right.rb +++ b/ruby/lib/jam_ruby/models/jam_track_right.rb @@ -229,8 +229,8 @@ module JamRuby return "no fingerprint specified" end - all_fingerprint = fingerprint[:all] - running_fingerprint = fingerprint[:running] + all_fingerprint = fingerprint.delete(:all) + running_fingerprint = fingerprint.delete(:running) if all_fingerprint.blank? return "no all fingerprint specified" @@ -240,6 +240,9 @@ module JamRuby return "no running fingerprint specified" end + all_fingerprint_extra = fingerprint[all_fingerprint] + running_fingerprint_extra = fingerprint[running_fingerprint] + if redeemed && !redeemed_and_fingerprinted # if this is a free JamTrack, we need to check for fraud or accidental misuse @@ -250,41 +253,80 @@ module JamRuby return "already redeemed another" end - # can we find a jam track that belongs to someone else with the same fingerprint - match = MachineFingerprint.find_by_fingerprint(all_fingerprint) + if FingerprintWhitelist.select('id').find_by_fingerprint(all_fingerprint) + # we can short circuit out of the rest of the check, since this is a known bad fingerprint + @@log.debug("ignoring 'all' hash found in whitelist") + else + # can we find a jam track that belongs to someone else with the same fingerprint + conflict = MachineFingerprint.select('count(id) as count').where('user_id != ?', current_user.id).where(fingerprint: all_fingerprint).where(remote_ip: remote_ip).where('created_at > ?', APP_CONFIG.expire_fingerprint_days.days.ago).first + conflict_count = conflict['count'].to_i - if match && match.user != current_user - AdminMailer.alerts(subject: "'All' fingerprint collision by #{current_user.name}", - body: "MachineFingerprint #{match.inspect}\n\nCurrent User: #{current_user.admin_url}").deliver + if conflict_count >= APP_CONFIG.found_conflict_count + mf = MachineFingerprint.create(all_fingerprint, current_user, MachineFingerprint::TAKEN_ON_FRAUD_CONFLICT, MachineFingerprint::PRINT_TYPE_ACTIVE, remote_ip, all_fingerprint_extra, self) + + # record the alert + fraud = FraudAlert.create(mf, current_user) if mf.valid? + fraud_admin_url = fraud.admin_url if fraud + + + AdminMailer.alerts(subject: "'All' fingerprint collision by #{current_user.name}", + body: "Current User: #{current_user.admin_url}\n\n Fraud Alert: #{fraud_admin_url}").deliver + + # try to record the other fingerprint + mf = MachineFingerprint.create(running_fingerprint, current_user, MachineFingerprint::TAKEN_ON_FRAUD_CONFLICT, MachineFingerprint::PRINT_TYPE_ACTIVE, remote_ip, running_fingerprint_extra, self) + + if APP_CONFIG.error_on_fraud + return "other user has 'all' fingerprint" + else + self.redeemed_and_fingerprinted = true + save! + return nil + end - # try to record the other fingerprint - MachineFingerprint.create(running_fingerprint, current_user, MachineFingerprint::TAKEN_ON_FRAUD_CONFLICT, MachineFingerprint::PRINT_TYPE_ACTIVE, remote_ip, self) - if APP_CONFIG.error_on_fraud - return "other user has 'all' fingerprint" end + end - if all_fingerprint != running_fingerprint - match = MachineFingerprint.find_by_fingerprint(running_fingerprint) - if match && match.user != current_user - AdminMailer.alerts(subject: "'Running' fingerprint collision by #{current_user.name}", - body: "MachineFingerprint #{match.inspect}\n\nCurrent User: #{current_user.admin_url}").deliver - # try to record the other fingerprint - MachineFingerprint.create(all_fingerprint, current_user, MachineFingerprint::TAKEN_ON_FRAUD_CONFLICT, MachineFingerprint::PRINT_TYPE_ALL, remote_ip, self) - if APP_CONFIG.error_on_fraud - return "other user has 'running' fingerprint" + if all_fingerprint != running_fingerprint + if FingerprintWhitelist.select('id').find_by_fingerprint(running_fingerprint) + # we can short circuit out of the rest of the check, since this is a known bad fingerprint + @@log.debug("ignoring 'running' hash found in whitelist") + else + + conflict = MachineFingerprint.select('count(id) as count').where('user_id != ?', current_user.id).where(fingerprint: running_fingerprint).where(remote_ip: remote_ip).where('created_at > ?', APP_CONFIG.expire_fingerprint_days.days.ago).first + conflict_count = conflict['count'].to_i + if conflict_count >= APP_CONFIG.found_conflict_count + mf = MachineFingerprint.create(running_fingerprint, current_user, MachineFingerprint::TAKEN_ON_FRAUD_CONFLICT, MachineFingerprint::PRINT_TYPE_ACTIVE, remote_ip, running_fingerprint_extra, self) + + # record the alert + fraud = FraudAlert.create(mf, current_user) if mf.valid? + fraud_admin_url = fraud.admin_url if fraud + AdminMailer.alerts(subject: "'Running' fingerprint collision by #{current_user.name}", + body: "Current User: #{current_user.admin_url}\n\nFraud Alert: #{fraud_admin_url}").deliver\ + + # try to record the other fingerprint + mf = MachineFingerprint.create(all_fingerprint, current_user, MachineFingerprint::TAKEN_ON_FRAUD_CONFLICT, MachineFingerprint::PRINT_TYPE_ALL, remote_ip, all_fingerprint_extra, self) + + + if APP_CONFIG.error_on_fraud + return "other user has 'running' fingerprint" + else + self.redeemed_and_fingerprinted = true + save! + return nil + end end end + end # we made it past all checks; let's slap on the redeemed_fingerprint self.redeemed_and_fingerprinted = true - - MachineFingerprint.create(all_fingerprint, current_user, MachineFingerprint::TAKEN_ON_SUCCESSFUL_DOWNLOAD, MachineFingerprint::PRINT_TYPE_ALL, remote_ip, self) + MachineFingerprint.create(all_fingerprint, current_user, MachineFingerprint::TAKEN_ON_SUCCESSFUL_DOWNLOAD, MachineFingerprint::PRINT_TYPE_ALL, remote_ip, all_fingerprint_extra, self) if all_fingerprint != running_fingerprint - MachineFingerprint.create(running_fingerprint, current_user, MachineFingerprint::TAKEN_ON_SUCCESSFUL_DOWNLOAD, MachineFingerprint::PRINT_TYPE_ACTIVE, remote_ip, self) + MachineFingerprint.create(running_fingerprint, current_user, MachineFingerprint::TAKEN_ON_SUCCESSFUL_DOWNLOAD, MachineFingerprint::PRINT_TYPE_ACTIVE, remote_ip, running_fingerprint_extra, self) end save! @@ -297,11 +339,12 @@ module JamRuby def self.stats stats = {} - result = JamTrackRight.select('count(id) as total, count(CASE WHEN signing_44 THEN 1 ELSE NULL END) + count(CASE WHEN signing_48 THEN 1 ELSE NULL END) as signing_count, count(CASE WHEN redeemed THEN 1 ELSE NULL END) as redeem_count').where(is_test_purchase: false).first + result = JamTrackRight.select('count(id) as total, count(CASE WHEN signing_44 THEN 1 ELSE NULL END) + count(CASE WHEN signing_48 THEN 1 ELSE NULL END) as signing_count, count(CASE WHEN redeemed THEN 1 ELSE NULL END) as redeem_count, count(CASE WHEN redeemed_and_fingerprinted THEN 1 ELSE NULL END) as redeemed_and_dl_count').where(is_test_purchase: false).first stats['count'] = result['total'].to_i stats['signing_count'] = result['signing_count'].to_i stats['redeemed_count'] = result['redeem_count'].to_i + stats['redeemed_and_dl_count'] = result['redeem_and_dl_count'].to_i stats['purchased_count'] = stats['count'] - stats['redeemed_count'] stats end diff --git a/ruby/lib/jam_ruby/models/machine_extra.rb b/ruby/lib/jam_ruby/models/machine_extra.rb new file mode 100644 index 000000000..74b1402d0 --- /dev/null +++ b/ruby/lib/jam_ruby/models/machine_extra.rb @@ -0,0 +1,35 @@ +module JamRuby + class MachineExtra < ActiveRecord::Base + + @@log = Logging.logger[MachineExtra] + + belongs_to :machine_fingerprint, :class_name => "JamRuby::MachineFingerprint" + + def self.create(machine_fingerprint, data) + me = MachineExtra.new + me.machine_fingerprint = machine_fingerprint + me.mac_address = data[:mac] + me.mac_name = data[:name] + me.upstate = data[:upstate] + me.ipaddr_0 = data[:ipaddr_0] + me.ipaddr_1 = data[:ipaddr_1] + me.ipaddr_2 = data[:ipaddr_2] + me.ipaddr_3 = data[:ipaddr_3] + me.ipaddr_4 = data[:ipaddr_4] + me.ipaddr_5 = data[:ipaddr_5] + me.save + + unless me.save + @@log.error("unable to create machine extra: #{me.errors.inspect}") + end + end + + def admin_url + APP_CONFIG.admin_root_url + "/admin/machine_extras/" + id + end + + def to_s + "#{mac_address} #{mac_name} #{upstate ? 'UP' : 'DOWN'} #{ipaddr_0} #{ipaddr_1} #{ipaddr_2} #{ipaddr_3} #{ipaddr_4} #{ipaddr_5}" + end + end +end \ No newline at end of file diff --git a/ruby/lib/jam_ruby/models/machine_fingerprint.rb b/ruby/lib/jam_ruby/models/machine_fingerprint.rb index 7d0076e50..d4d668052 100644 --- a/ruby/lib/jam_ruby/models/machine_fingerprint.rb +++ b/ruby/lib/jam_ruby/models/machine_fingerprint.rb @@ -5,6 +5,8 @@ module JamRuby belongs_to :user, :class_name => "JamRuby::User" belongs_to :jam_track_right, :class_name => "JamRuby::JamTrackRight" + has_one :detail, :class_name => "JamRuby::MachineExtra" + belongs_to :fingerprint_whitelist, class_name: 'JamRuby::FingerprintWhitelist', foreign_key: :fingerprint TAKEN_ON_SUCCESSFUL_DOWNLOAD = 'dl' TAKEN_ON_FRAUD_CONFLICT = 'fc' @@ -15,11 +17,11 @@ module JamRuby validates :user, presence:true validates :when_taken, :inclusion => {:in => [TAKEN_ON_SUCCESSFUL_DOWNLOAD, TAKEN_ON_FRAUD_CONFLICT]} - validates :fingerprint, presence: true, uniqueness:true + validates :fingerprint, presence: true validates :print_type, presence: true, :inclusion => {:in =>[PRINT_TYPE_ALL, PRINT_TYPE_ACTIVE]} validates :remote_ip, presence: true - def self.create(fingerprint, user, when_taken, print_type, remote_ip, jam_track_right = nil) + def self.create(fingerprint, user, when_taken, print_type, remote_ip, extra, jam_track_right = nil) mf = MachineFingerprint.new mf.fingerprint = fingerprint mf.user = user @@ -27,9 +29,21 @@ module JamRuby mf.print_type = print_type mf.remote_ip = remote_ip mf.jam_track_right = jam_track_right - unless mf.save + if mf.save + MachineExtra.create(mf, extra) if extra + else + @@log.error("unable to create machine fingerprint: #{mf.errors.inspect}") end + mf + end + + def admin_url + APP_CONFIG.admin_root_url + "/admin/machine_fingerprints/" + id + end + + def to_s + "#{fingerprint} #{remote_ip} #{user} #{detail}" end end end \ No newline at end of file diff --git a/ruby/spec/jam_ruby/models/jam_track_right_spec.rb b/ruby/spec/jam_ruby/models/jam_track_right_spec.rb index 1adef7d18..9119bdfd9 100644 --- a/ruby/spec/jam_ruby/models/jam_track_right_spec.rb +++ b/ruby/spec/jam_ruby/models/jam_track_right_spec.rb @@ -168,7 +168,8 @@ describe JamTrackRight do JamTrackRight.stats.should eq('count' => 1, 'signing_count' => 0, 'redeemed_count' => 0, - 'purchased_count' => 1) + 'purchased_count' => 1, + 'redeemed_and_dl_count' => 0) end it "two" do @@ -178,7 +179,8 @@ describe JamTrackRight do JamTrackRight.stats.should eq('count' => 2, 'signing_count' => 0, 'redeemed_count' => 0, - 'purchased_count' => 2) + 'purchased_count' => 2, + 'redeemed_and_dl_count' => 0) right1.signing_44 = true right1.save! @@ -188,7 +190,8 @@ describe JamTrackRight do JamTrackRight.stats.should eq('count' => 2, 'signing_count' => 2, 'redeemed_count' => 0, - 'purchased_count' => 2) + 'purchased_count' => 2, + 'redeemed_and_dl_count' => 0) right1.redeemed = true right1.save! @@ -196,7 +199,8 @@ describe JamTrackRight do JamTrackRight.stats.should eq('count' => 2, 'signing_count' => 2, 'redeemed_count' => 1, - 'purchased_count' => 1) + 'purchased_count' => 1, + 'redeemed_and_dl_count' => 0) right2.is_test_purchase = true right2.save! @@ -204,7 +208,8 @@ describe JamTrackRight do JamTrackRight.stats.should eq('count' => 1, 'signing_count' => 1, 'redeemed_count' => 1, - 'purchased_count' => 0) + 'purchased_count' => 0, + 'redeemed_and_dl_count' => 0) end end @@ -213,7 +218,9 @@ describe JamTrackRight do let(:other) {FactoryGirl.create(:user)} let(:first_fingerprint) { {all: 'all', running: 'running' } } let(:new_fingerprint) { {all: 'all_2', running: 'running' } } + let(:full_fingerprint) { {all: :all_3, running: :running_3, all_3: { mac: "72:00:02:4C:1E:61", name: "en2", upstate: true }, running_3: { mac: "72:00:02:4C:1E:62", name: "en3", upstate: false } } } let(:remote_ip) {'1.1.1.1'} + let(:remote_ip2) {'2.2.2.2'} let(:jam_track_right) { FactoryGirl.create(:jam_track_right, user: user, redeemed: true, redeemed_and_fingerprinted: false) } let(:jam_track_right_purchased) { FactoryGirl.create(:jam_track_right, user: user, redeemed: false, redeemed_and_fingerprinted: false) } let(:jam_track_right_other) { FactoryGirl.create(:jam_track_right, user: other, redeemed: true, redeemed_and_fingerprinted: false) } @@ -233,16 +240,16 @@ describe JamTrackRight do jam_track_right.redeemed_and_fingerprinted.should be_true - mf = MachineFingerprint.find_by_fingerprint(first_fingerprint[:all]) + mf = MachineFingerprint.find_by_fingerprint('all') mf.user.should eq(user) - mf.fingerprint.should eq(first_fingerprint[:all]) + mf.fingerprint.should eq('all') mf.when_taken.should eq(MachineFingerprint::TAKEN_ON_SUCCESSFUL_DOWNLOAD) mf.print_type.should eq(MachineFingerprint::PRINT_TYPE_ALL) mf.jam_track_right.should eq(jam_track_right) - mf = MachineFingerprint.find_by_fingerprint(first_fingerprint[:running]) + mf = MachineFingerprint.find_by_fingerprint('running') mf.user.should eq(user) - mf.fingerprint.should eq(first_fingerprint[:running]) + mf.fingerprint.should eq('running') mf.when_taken.should eq(MachineFingerprint::TAKEN_ON_SUCCESSFUL_DOWNLOAD) mf.print_type.should eq(MachineFingerprint::PRINT_TYPE_ACTIVE) mf.jam_track_right.should eq(jam_track_right) @@ -274,40 +281,80 @@ describe JamTrackRight do end it "protects against re-using fingerprint across users (conflicts on all fp)" do + first_fingerprint2 = first_fingerprint.clone jam_track_right.guard_against_fraud(user, first_fingerprint, remote_ip).should be_nil MachineFingerprint.count.should eq(2) - first_fingerprint[:running] = 'running_2' - jam_track_right_other.guard_against_fraud(other, first_fingerprint, remote_ip).should eq("other user has 'all' fingerprint") + first_fingerprint2[:running] = 'running_2' + jam_track_right_other.guard_against_fraud(other, first_fingerprint2, remote_ip).should eq("other user has 'all' fingerprint") - mf = MachineFingerprint.find_by_fingerprint(first_fingerprint[:running]) - mf.user.should eq(other) - mf.fingerprint.should eq(first_fingerprint[:running]) - mf.when_taken.should eq(MachineFingerprint::TAKEN_ON_FRAUD_CONFLICT) + mf = MachineFingerprint.find_by_fingerprint('running') + mf.user.should eq(user) + mf.fingerprint.should eq('running') + mf.when_taken.should eq(MachineFingerprint::TAKEN_ON_SUCCESSFUL_DOWNLOAD) mf.print_type.should eq(MachineFingerprint::PRINT_TYPE_ACTIVE) - mf.jam_track_right.should eq(jam_track_right_other) - MachineFingerprint.count.should eq(3) + mf.jam_track_right.should eq(jam_track_right) + MachineFingerprint.count.should eq(4) end it "protects against re-using fingerprint across users (conflicts on running fp)" do + first_fingerprint2 = first_fingerprint.clone jam_track_right.guard_against_fraud(user, first_fingerprint, remote_ip).should be_nil MachineFingerprint.count.should eq(2) - first_fingerprint[:all] = 'all_2' - jam_track_right_other.guard_against_fraud(other, first_fingerprint, remote_ip).should eq("other user has 'running' fingerprint") + first_fingerprint2[:all] = 'all_2' + jam_track_right_other.guard_against_fraud(other, first_fingerprint2, remote_ip).should eq("other user has 'running' fingerprint") - mf = MachineFingerprint.find_by_fingerprint(first_fingerprint[:all]) - mf.user.should eq(other) - mf.fingerprint.should eq(first_fingerprint[:all]) - mf.when_taken.should eq(MachineFingerprint::TAKEN_ON_FRAUD_CONFLICT) + mf = MachineFingerprint.find_by_fingerprint('all') + mf.user.should eq(user) + mf.fingerprint.should eq('all') + mf.when_taken.should eq(MachineFingerprint::TAKEN_ON_SUCCESSFUL_DOWNLOAD) mf.print_type.should eq(MachineFingerprint::PRINT_TYPE_ALL) - mf.jam_track_right.should eq(jam_track_right_other) - MachineFingerprint.count.should eq(3) + mf.jam_track_right.should eq(jam_track_right) + MachineFingerprint.count.should eq(4) + + FraudAlert.count.should eq(1) + fraud = FraudAlert.first + fraud.user.should eq(other) + fraud.machine_fingerprint.should eq(MachineFingerprint.where(fingerprint:'running').where(user_id:other.id).first) + end + + it "ignores whitelisted fingerprint" do + whitelist = FingerprintWhitelist.new + whitelist.fingerprint = first_fingerprint[:running] + whitelist.save! + + first_fingerprint2 = first_fingerprint.clone + jam_track_right.guard_against_fraud(user, first_fingerprint, remote_ip).should be_nil + MachineFingerprint.count.should eq(2) + first_fingerprint2[:all] = 'all_2' + jam_track_right_other.guard_against_fraud(other, first_fingerprint2, remote_ip).should be_nil + + FraudAlert.count.should eq(0) + end + + it "does not conflict if same mac, but different IP address" do + first_fingerprint2 = first_fingerprint.clone + jam_track_right.guard_against_fraud(user, first_fingerprint, remote_ip).should be_nil + MachineFingerprint.count.should eq(2) + first_fingerprint2[:all] = 'all_2' + jam_track_right_other.guard_against_fraud(other, first_fingerprint2, remote_ip2).should eq(nil) + + mf = MachineFingerprint.find_by_fingerprint('all') + mf.user.should eq(user) + mf.fingerprint.should eq('all') + mf.when_taken.should eq(MachineFingerprint::TAKEN_ON_SUCCESSFUL_DOWNLOAD) + mf.print_type.should eq(MachineFingerprint::PRINT_TYPE_ALL) + mf.jam_track_right.should eq(jam_track_right) + MachineFingerprint.count.should eq(4) + + FraudAlert.count.should eq(0) end # if you try to buy a regular jamtrack with a fingerprint belonging to another user? so what. you paid for it it "allows re-use of fingerprint if jamtrack is a normal purchase" do + first_fingerprint2 = first_fingerprint.clone jam_track_right.guard_against_fraud(user, first_fingerprint, remote_ip).should be_nil MachineFingerprint.count.should eq(2) - jam_track_right_other_purchased.guard_against_fraud(other, first_fingerprint, remote_ip).should be_nil + jam_track_right_other_purchased.guard_against_fraud(other, first_fingerprint2, remote_ip).should be_nil MachineFingerprint.count.should eq(2) end @@ -319,13 +366,22 @@ describe JamTrackRight do it "let's you download a free jamtrack if you have a second but undownloaded free one" do right1 = FactoryGirl.create(:jam_track_right, user: user, redeemed: true, redeemed_and_fingerprinted: false) + first_fingerprint2 = first_fingerprint.clone jam_track_right.guard_against_fraud(user, first_fingerprint, remote_ip).should be_nil MachineFingerprint.count.should eq(2) - right1.guard_against_fraud(user, first_fingerprint, remote_ip).should eq('already redeemed another') + right1.guard_against_fraud(user, first_fingerprint2, remote_ip).should eq('already redeemed another') MachineFingerprint.count.should eq(2) end + it "creates metadata" do + right1 = FactoryGirl.create(:jam_track_right, user: user, redeemed: true, redeemed_and_fingerprinted: false) + + jam_track_right.guard_against_fraud(user, full_fingerprint, remote_ip).should be_nil + MachineFingerprint.count.should eq(2) + MachineExtra.count.should eq(2) + + end end end diff --git a/ruby/spec/support/utilities.rb b/ruby/spec/support/utilities.rb index 5e9380eac..8d16dffbb 100644 --- a/ruby/spec/support/utilities.rb +++ b/ruby/spec/support/utilities.rb @@ -198,6 +198,14 @@ def app_config true end + def expire_fingerprint_days + 14 + end + + def found_conflict_count + 1 + end + private def audiomixer_workspace_path diff --git a/web/app/assets/javascripts/jam_rest.js b/web/app/assets/javascripts/jam_rest.js index b8fcf54f6..ffccd50d4 100644 --- a/web/app/assets/javascripts/jam_rest.js +++ b/web/app/assets/javascripts/jam_rest.js @@ -1478,12 +1478,13 @@ function enqueueJamTrack(options) { var jamTrackId = options['id']; + delete options['id'] return $.ajax({ type: "POST", - url: '/api/jamtracks/enqueue/' + jamTrackId + '?' + $.param(options), + url: '/api/jamtracks/enqueue/' + jamTrackId, dataType: "json", - contentType: 'applications/json' + data: options }); } diff --git a/web/app/controllers/users_controller.rb b/web/app/controllers/users_controller.rb index 47675f9ce..7c5a06768 100644 --- a/web/app/controllers/users_controller.rb +++ b/web/app/controllers/users_controller.rb @@ -196,9 +196,14 @@ class UsersController < ApplicationController render :layout => "web" end - # DO NOT USE CURRENT_USER IN THIS ROUTINE. IT'S CACHED FOR THE WHOLE SITE + # DO NOT USE CURRENT_USER IN THIS ROUTINE UNLESS REDIRECTING. IT'S CACHED FOR THE WHOLE SITE def home + if current_user + redirect_to "/client#/home" + return + end + @no_user_dropdown = false @promo_buzz = PromoBuzz.active @@ -209,7 +214,6 @@ class UsersController < ApplicationController end - gon.signed_in = !current_user.nil? render :layout => "web" end diff --git a/web/config/application.rb b/web/config/application.rb index 4de4e6d8c..44b5ce2ff 100644 --- a/web/config/application.rb +++ b/web/config/application.rb @@ -341,7 +341,9 @@ if defined?(Bundler) config.remove_whitespace_credit_card = false config.estimate_taxes = true config.ad_sense_enabled = false - config.guard_against_fraud = false + config.guard_against_fraud = true config.error_on_fraud = false + config.expire_fingerprint_days = 14 + config.found_conflict_count = 1 end end diff --git a/web/spec/controllers/api_jam_tracks_controller_spec.rb b/web/spec/controllers/api_jam_tracks_controller_spec.rb index fc4685eb9..74bc1da94 100644 --- a/web/spec/controllers/api_jam_tracks_controller_spec.rb +++ b/web/spec/controllers/api_jam_tracks_controller_spec.rb @@ -15,6 +15,8 @@ describe ApiJamTracksController do end before(:each) do + FingerprintWhitelist.destroy_all + FraudAlert.destroy_all MachineFingerprint.destroy_all JamTrackRight.destroy_all JamTrack.destroy_all @@ -299,6 +301,9 @@ describe ApiJamTracksController do describe "guard fraud" do + after(:each) do + ENV['RAILS_TEST_IP_ADDRESS'] = nil + end it "stops second user from downloading using same machine" do right = JamTrackRight.create(:user=>@user, :jam_track=>@jam_track) @@ -306,6 +311,7 @@ describe ApiJamTracksController do right.save! get :download, :id=>@jam_track.id, sample_rate: 48, all_fp: 'all', running_fp: 'running' response.status.should == 202 + MachineFingerprint.count.should eq(2) user2 = FactoryGirl.create(:user) @@ -315,8 +321,10 @@ describe ApiJamTracksController do right.redeemed = true right.save! get :download, :id=>@jam_track.id, sample_rate: 48, all_fp: 'all', running_fp: 'running' - response.status.should == 403 - JSON.parse(response.body)['message'].should eq("other user has 'all' fingerprint") + response.status.should == 202 + + # no error for the user... but we should have a FraudAlert + FraudAlert.count.should eq(1) end it "stops second user from enqueuing using same machine" do @@ -336,9 +344,10 @@ describe ApiJamTracksController do right.save! right.signing_queued_at.should be_nil post :enqueue, {:format=>'json', :id=>right.jam_track.id, fingerprint: {all: 'all', running: 'running'} } + response.status.should == 200 get :download, :id=>@jam_track.id, sample_rate: 48, all_fp: 'all', running_fp: 'running' - response.status.should == 403 - JSON.parse(response.body)['message'].should eq("other user has 'all' fingerprint") + response.status.should == 202 + FraudAlert.count.should eq(1) end end end diff --git a/web/spec/support/app_config.rb b/web/spec/support/app_config.rb index b7cc08d89..6ee586981 100644 --- a/web/spec/support/app_config.rb +++ b/web/spec/support/app_config.rb @@ -94,6 +94,14 @@ def web_config def secret_token 'ced345e01611593c1b783bae98e4e56dbaee787747e92a141565f7c61d0ab2c6f98f7396fb4b178258301e2713816e158461af58c14b695901692f91e72b6200' end + + def expire_fingerprint_days + 14 + end + + def found_conflict_count + 1 + end end klass.new end diff --git a/web/spec/support/remote_ip_monkey_patch.rb b/web/spec/support/remote_ip_monkey_patch.rb new file mode 100644 index 000000000..7d725d072 --- /dev/null +++ b/web/spec/support/remote_ip_monkey_patch.rb @@ -0,0 +1,17 @@ +module ActionDispatch + class Request + + def remote_ip_with_mocking + test_ip = ENV['RAILS_TEST_IP_ADDRESS'] + + unless test_ip.nil? or test_ip.empty? + return test_ip + else + return remote_ip_without_mocking + end + end + + alias_method_chain :remote_ip, :mocking + + end +end \ No newline at end of file diff --git a/web/spec/support/utilities.rb b/web/spec/support/utilities.rb index 8c06407da..39b109ee9 100644 --- a/web/spec/support/utilities.rb +++ b/web/spec/support/utilities.rb @@ -225,7 +225,7 @@ def should_be_at_root(options={signed_in:nil}) find('h1', text: 'Live music platform & social network for musicians') end when Capybara::RackTest::Driver - signed_in = false # actually, the user may be signed in, but, we only redirect to /client in javascript, so RackTest won't do that + signed_in = !cookie_jar['remember_token'].nil? if signed_in find('h2', text: 'create session') else From 8a82f86e643f932afcab1c5c3eb0b6c1a90fbaa9 Mon Sep 17 00:00:00 2001 From: Seth Call Date: Wed, 20 May 2015 10:17:01 -0500 Subject: [PATCH 02/45] fix the fully redeemed count --- ruby/lib/jam_ruby/models/jam_track_right.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruby/lib/jam_ruby/models/jam_track_right.rb b/ruby/lib/jam_ruby/models/jam_track_right.rb index c77da5ffe..f28410e02 100644 --- a/ruby/lib/jam_ruby/models/jam_track_right.rb +++ b/ruby/lib/jam_ruby/models/jam_track_right.rb @@ -339,7 +339,7 @@ module JamRuby def self.stats stats = {} - result = JamTrackRight.select('count(id) as total, count(CASE WHEN signing_44 THEN 1 ELSE NULL END) + count(CASE WHEN signing_48 THEN 1 ELSE NULL END) as signing_count, count(CASE WHEN redeemed THEN 1 ELSE NULL END) as redeem_count, count(CASE WHEN redeemed_and_fingerprinted THEN 1 ELSE NULL END) as redeemed_and_dl_count').where(is_test_purchase: false).first + result = JamTrackRight.select('count(id) as total, count(CASE WHEN signing_44 THEN 1 ELSE NULL END) + count(CASE WHEN signing_48 THEN 1 ELSE NULL END) as signing_count, count(CASE WHEN redeemed THEN 1 ELSE NULL END) as redeem_count, count(last_downloaded_at) as redeemed_and_dl_count').where(is_test_purchase: false).first stats['count'] = result['total'].to_i stats['signing_count'] = result['signing_count'].to_i From d959a17be4f944529510f40d699f8274db1c7110 Mon Sep 17 00:00:00 2001 From: Seth Call Date: Thu, 28 May 2015 08:20:14 -0500 Subject: [PATCH 03/45] * affiliate program in place VRFS-3030 --- admin/app/admin/affiliates.rb | 57 +- .../app/views/admin/affiliates/_form.html.erb | 6 - db/manifest | 3 +- db/up/affiliate_partners2.sql | 132 + ruby/lib/jam_ruby.rb | 9 +- .../lib/jam_ruby/models/affiliate_legalese.rb | 6 + .../models/affiliate_monthly_payment.rb | 39 + ruby/lib/jam_ruby/models/affiliate_partner.rb | 449 +- ruby/lib/jam_ruby/models/affiliate_payment.rb | 49 + .../models/affiliate_quarterly_payment.rb | 41 + .../models/affiliate_referral_visit.rb | 23 + .../models/affiliate_traffic_total.rb | 39 + ruby/lib/jam_ruby/models/anonymous_user.rb | 2 +- ruby/lib/jam_ruby/models/generic_state.rb | 5 + ruby/lib/jam_ruby/models/jam_track.rb | 5 + ruby/lib/jam_ruby/models/music_session.rb | 3 +- .../models/recurly_transaction_web_hook.rb | 7 +- ruby/lib/jam_ruby/models/sale_line_item.rb | 14 +- ruby/lib/jam_ruby/models/user.rb | 20 +- .../resque/scheduled/tally_affiliates.rb | 31 + ruby/spec/factories.rb | 29 + .../jam_ruby/models/affiliate_partner_spec.rb | 721 ++- .../jam_ruby/models/affiliate_payment_spec.rb | 39 + .../models/affiliate_referral_visit_spec.rb | 40 + ruby/spec/jam_ruby/models/sale_spec.rb | 142 + .../assets/images/content/agree_button.png | Bin 0 -> 13570 bytes .../assets/images/content/disagree_button.png | Bin 0 -> 15683 bytes web/app/assets/javascripts/accounts.js | 19 +- .../assets/javascripts/accounts_affiliate.js | 324 ++ web/app/assets/javascripts/dialog/banner.js | 19 +- web/app/assets/javascripts/jam_rest.js | 84 +- web/app/assets/javascripts/landing/signup.js | 3 + web/app/assets/javascripts/utils.js | 4 + .../javascripts/web/affiliate_links.js.coffee | 55 + .../web/affiliate_program.js.coffee | 119 + web/app/assets/javascripts/web/web.js | 2 + .../stylesheets/client/account.css.scss | 9 +- .../client/account_affiliate.css.scss | 201 + web/app/assets/stylesheets/client/client.css | 2 + .../stylesheets/client/sessionList.css.scss | 4 +- .../landings/affiliate_program.css.scss | 74 + .../landings/partner_agreement_v1.css.scss | 4663 +++++++++++++++ .../stylesheets/web/affiliate_links.css.scss | 65 + web/app/assets/stylesheets/web/web.css | 2 + web/app/controllers/affiliates_controller.rb | 12 + .../controllers/api_affiliate_controller.rb | 53 + web/app/controllers/api_controller.rb | 16 +- web/app/controllers/api_links_controller.rb | 114 + web/app/controllers/api_recurly_controller.rb | 3 +- web/app/controllers/api_users_controller.rb | 39 +- web/app/controllers/application_controller.rb | 22 + web/app/controllers/landings_controller.rb | 5 + web/app/controllers/sessions_controller.rb | 4 +- web/app/controllers/users_controller.rb | 18 +- web/app/helpers/errors_helper.rb | 7 + web/app/helpers/sessions_helper.rb | 1 - .../affiliates/affiliate_links.html.slim | 119 + web/app/views/api_affiliates/create.rabl | 3 + .../views/api_affiliates/monthly_index.rabl | 8 + .../views/api_affiliates/monthly_show.rabl | 3 + .../views/api_affiliates/payment_index.rabl | 8 + .../views/api_affiliates/payment_show.rabl | 3 + .../views/api_affiliates/quarterly_index.rabl | 8 + .../views/api_affiliates/quarterly_show.rabl | 3 + web/app/views/api_affiliates/show.rabl | 2 + .../views/api_affiliates/traffic_index.rabl | 8 + .../views/api_affiliates/traffic_show.rabl | 3 + web/app/views/api_users/show.rabl | 12 + web/app/views/clients/_account.html.erb | 29 + .../_account_affiliate_partner.html.slim | 193 + web/app/views/clients/index.html.erb | 4 + .../landings/affiliate_program.html.slim | 56 + .../legal/_partner_agreement_v1.html.erb | 422 ++ .../legal/partner_agreement_full.html.erb | 5062 +++++++++++++++++ web/app/views/users/new.html.erb | 2 +- web/config/environments/test.rb | 1 + web/config/routes.rb | 18 + web/config/scheduler.yml | 5 + web/db/schema.rb | 1752 ++++++ web/db/structure.sql | 3862 +++++++++++++ web/lib/tasks/email.rake | 13 + web/lib/tasks/google.rake | 13 + web/lib/tasks/sample_data.rake | 11 + web/lib/user_manager.rb | 4 +- web/loop.bash | 7 + web/ruby-bt.txt | 919 +++ .../api_affiliate_controller_spec.rb | 82 + .../controllers/api_links_controller_spec.rb | 106 + web/spec/factories.rb | 33 + web/spec/features/account_affiliate_spec.rb | 152 + web/spec/features/affiliate_program_spec.rb | 90 + web/spec/features/affiliate_referral_spec.rb | 59 + web/spec/features/affiliate_visit_tracking.rb | 36 + web/spec/features/checkout_spec.rb | 117 + web/spec/managers/user_manager_spec.rb | 6 +- web/spec/requests/affilate_referral_spec.rb | 4 +- 96 files changed, 20968 insertions(+), 124 deletions(-) create mode 100644 db/up/affiliate_partners2.sql create mode 100644 ruby/lib/jam_ruby/models/affiliate_legalese.rb create mode 100644 ruby/lib/jam_ruby/models/affiliate_monthly_payment.rb create mode 100644 ruby/lib/jam_ruby/models/affiliate_payment.rb create mode 100644 ruby/lib/jam_ruby/models/affiliate_quarterly_payment.rb create mode 100644 ruby/lib/jam_ruby/models/affiliate_referral_visit.rb create mode 100644 ruby/lib/jam_ruby/models/affiliate_traffic_total.rb create mode 100644 ruby/lib/jam_ruby/resque/scheduled/tally_affiliates.rb create mode 100644 ruby/spec/jam_ruby/models/affiliate_payment_spec.rb create mode 100644 ruby/spec/jam_ruby/models/affiliate_referral_visit_spec.rb create mode 100644 web/app/assets/images/content/agree_button.png create mode 100644 web/app/assets/images/content/disagree_button.png create mode 100644 web/app/assets/javascripts/accounts_affiliate.js create mode 100644 web/app/assets/javascripts/web/affiliate_links.js.coffee create mode 100644 web/app/assets/javascripts/web/affiliate_program.js.coffee create mode 100644 web/app/assets/stylesheets/client/account_affiliate.css.scss create mode 100644 web/app/assets/stylesheets/landings/affiliate_program.css.scss create mode 100644 web/app/assets/stylesheets/landings/partner_agreement_v1.css.scss create mode 100644 web/app/assets/stylesheets/web/affiliate_links.css.scss create mode 100644 web/app/controllers/affiliates_controller.rb create mode 100644 web/app/controllers/api_affiliate_controller.rb create mode 100644 web/app/controllers/api_links_controller.rb create mode 100644 web/app/helpers/errors_helper.rb create mode 100644 web/app/views/affiliates/affiliate_links.html.slim create mode 100644 web/app/views/api_affiliates/create.rabl create mode 100644 web/app/views/api_affiliates/monthly_index.rabl create mode 100644 web/app/views/api_affiliates/monthly_show.rabl create mode 100644 web/app/views/api_affiliates/payment_index.rabl create mode 100644 web/app/views/api_affiliates/payment_show.rabl create mode 100644 web/app/views/api_affiliates/quarterly_index.rabl create mode 100644 web/app/views/api_affiliates/quarterly_show.rabl create mode 100644 web/app/views/api_affiliates/show.rabl create mode 100644 web/app/views/api_affiliates/traffic_index.rabl create mode 100644 web/app/views/api_affiliates/traffic_show.rabl create mode 100644 web/app/views/clients/_account_affiliate_partner.html.slim create mode 100644 web/app/views/landings/affiliate_program.html.slim create mode 100644 web/app/views/legal/_partner_agreement_v1.html.erb create mode 100644 web/app/views/legal/partner_agreement_full.html.erb create mode 100644 web/db/schema.rb create mode 100644 web/db/structure.sql create mode 100644 web/lib/tasks/email.rake create mode 100644 web/lib/tasks/google.rake create mode 100755 web/loop.bash create mode 100644 web/ruby-bt.txt create mode 100644 web/spec/controllers/api_affiliate_controller_spec.rb create mode 100644 web/spec/controllers/api_links_controller_spec.rb create mode 100644 web/spec/features/account_affiliate_spec.rb create mode 100644 web/spec/features/affiliate_program_spec.rb create mode 100644 web/spec/features/affiliate_referral_spec.rb create mode 100644 web/spec/features/affiliate_visit_tracking.rb diff --git a/admin/app/admin/affiliates.rb b/admin/app/admin/affiliates.rb index e517b3e12..0409ee36c 100644 --- a/admin/app/admin/affiliates.rb +++ b/admin/app/admin/affiliates.rb @@ -2,48 +2,47 @@ ActiveAdmin.register JamRuby::AffiliatePartner, :as => 'Affiliates' do menu :label => 'Partners', :parent => 'Affiliates' - config.sort_order = 'created_at DESC' + config.sort_order = 'referral_user_count DESC' config.batch_actions = false # config.clear_action_items! config.filters = false form :partial => 'form' + scope("Active", default: true) { |scope| scope.where('partner_user_id IS NOT NULL') } + scope("Unpaid") { |partner| partner.unpaid } + index do - column 'User' do |oo| link_to(oo.partner_user.name, "http://www.jamkazam.com/client#/profile/#{oo.partner_user.id}", {:title => oo.partner_user.name}) end - column 'Email' do |oo| oo.partner_user.email end + + # default_actions # use this for all view/edit/delete links + + column 'User' do |oo| link_to(oo.partner_user.name, admin_user_path(oo.partner_user.id), {:title => oo.partner_user.name}) end column 'Name' do |oo| oo.partner_name end - column 'Code' do |oo| oo.partner_code end + column 'Type' do |oo| oo.entity_type end + column 'Code' do |oo| oo.id end column 'Referral Count' do |oo| oo.referral_user_count end - # column 'Referrals' do |oo| link_to('View', admin_referrals_path(AffiliatePartner::PARAM_REFERRAL => oo.id)) end + column 'Earnings' do |oo| sprintf("$%.2f", oo.cumulative_earnings_in_dollars) end + column 'Amount Owed' do |oo| sprintf("$%.2f", oo.due_amount_in_cents.to_f / 100.to_f) end + column 'Pay Actions' do |oo| + link_to('Mark Paid', mark_paid_admin_affiliate_path(oo.id), :confirm => "Mark this affiliate as PAID?") if oo.unpaid + end + default_actions end + + action_item :only => [:show] do + link_to("Mark Paid", + mark_paid_admin_affiliate_path(resource.id), + :confirm => "Mark this affiliate as PAID?") if resource.unpaid + end + + member_action :mark_paid, :method => :get do + resource.mark_paid + redirect_to admin_affiliate_path(resource.id) + end + controller do - def show - redirect_to admin_referrals_path(AffiliatePartner::PARAM_REFERRAL => resource.id) - end - - def create - obj = AffiliatePartner.create_with_params(params[:jam_ruby_affiliate_partner]) - if obj.errors.present? - set_resource_ivar(obj) - render active_admin_template('new') - else - redirect_to admin_affiliates_path - end - end - - def update - obj = resource - vals = params[:jam_ruby_affiliate_partner] - obj.partner_name = vals[:partner_name] - obj.user_email = vals[:user_email] if vals[:user_email].present? - obj.save! - set_resource_ivar(obj) - render active_admin_template('show') - end - end end diff --git a/admin/app/views/admin/affiliates/_form.html.erb b/admin/app/views/admin/affiliates/_form.html.erb index a4f14416e..b7a3b047d 100644 --- a/admin/app/views/admin/affiliates/_form.html.erb +++ b/admin/app/views/admin/affiliates/_form.html.erb @@ -1,13 +1,7 @@ <%= semantic_form_for([:admin, resource], :url => resource.new_record? ? admin_affiliates_path : "/admin/affiliates/#{resource.id}") do |f| %> <%= f.semantic_errors *f.object.errors.keys %> <%= f.inputs do %> - <%= f.input(:user_email, :input_html => {:maxlength => 255}) %> <%= f.input(:partner_name, :input_html => {:maxlength => 128}) %> - <% if resource.new_record? %> - <%= f.input(:partner_code, :input_html => {:maxlength => 128}) %> - <% else %> - <%= f.input(:partner_code, :input_html => {:maxlength => 128, :readonly => 'readonly'}) %> - <% end %> <% end %> <%= f.actions %> <% end %> diff --git a/db/manifest b/db/manifest index f2cfbbc71..1fecbf802 100755 --- a/db/manifest +++ b/db/manifest @@ -284,4 +284,5 @@ jam_track_right_private_key.sql first_downloaded_jamtrack_at.sql signing.sql optimized_redeemption.sql -optimized_redemption_warn_mode.sql \ No newline at end of file +optimized_redemption_warn_mode.sql +affiliate_partners2.sql diff --git a/db/up/affiliate_partners2.sql b/db/up/affiliate_partners2.sql new file mode 100644 index 000000000..e8488c8ce --- /dev/null +++ b/db/up/affiliate_partners2.sql @@ -0,0 +1,132 @@ +CREATE TABLE affiliate_legalese ( + id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(), + legalese TEXT, + version INTEGER NOT NULL DEFAULT 1, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP +); + +ALTER TABLE users DROP CONSTRAINT users_affiliate_referral_id_fkey; +ALTER TABLE users DROP COLUMN affiliate_referral_id; +DROP TABLE affiliate_partners; + +CREATE TABLE affiliate_partners ( + id INTEGER PRIMARY KEY, + partner_name VARCHAR(1000), + partner_user_id VARCHAR(64) REFERENCES users(id) ON DELETE SET NULL, + entity_type VARCHAR(64), + legalese_id VARCHAR(64), + signed_at TIMESTAMP, + last_paid_at TIMESTAMP, + address JSON NOT NULL DEFAULT '{}', + tax_identifier VARCHAR(1000), + referral_user_count INTEGER NOT NULL DEFAULT 0, + cumulative_earnings_in_cents INTEGER NOT NULL DEFAULT 0, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP +); +CREATE SEQUENCE partner_key_sequence; +ALTER SEQUENCE partner_key_sequence RESTART WITH 10000; +ALTER TABLE affiliate_partners ALTER COLUMN id SET DEFAULT nextval('partner_key_sequence');; + +ALTER TABLE users ADD COLUMN affiliate_referral_id INTEGER REFERENCES affiliate_partners(id) ON DELETE SET NULL; +CREATE INDEX affiliate_partners_legalese_idx ON affiliate_partners(legalese_id); + +CREATE UNLOGGED TABLE affiliate_referral_visits ( + id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(), + affiliate_partner_id INTEGER NOT NULL, + ip_address VARCHAR NOT NULL, + visited_url VARCHAR, + referral_url VARCHAR, + first_visit BOOLEAN NOT NULL DEFAULT TRUE, + user_id VARCHAR(64), + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP +); + +CREATE INDEX on affiliate_referral_visits (affiliate_partner_id, created_at); + +CREATE TABLE affiliate_quarterly_payments ( + id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(), + quarter INTEGER NOT NULL, + year INTEGER NOT NULL, + affiliate_partner_id INTEGER NOT NULL REFERENCES affiliate_partners(id), + due_amount_in_cents INTEGER NOT NULL DEFAULT 0, + paid BOOLEAN NOT NULL DEFAULT FALSE, + closed BOOLEAN NOT NULL DEFAULT FALSE, + jamtracks_sold INTEGER NOT NULL DEFAULT 0, + closed_at TIMESTAMP, + paid_at TIMESTAMP, + last_updated TIMESTAMP, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP +); + + +CREATE TABLE affiliate_monthly_payments ( + id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(), + month INTEGER NOT NULL, + year INTEGER NOT NULL, + affiliate_partner_id INTEGER NOT NULL REFERENCES affiliate_partners(id), + due_amount_in_cents INTEGER NOT NULL DEFAULT 0, + closed BOOLEAN NOT NULL DEFAULT FALSE, + jamtracks_sold INTEGER NOT NULL DEFAULT 0, + closed_at TIMESTAMP, + last_updated TIMESTAMP, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP +); + + +CREATE INDEX ON affiliate_quarterly_payments (affiliate_partner_id, year, quarter); +CREATE UNIQUE INDEX ON affiliate_quarterly_payments (year, quarter, affiliate_partner_id); +CREATE UNIQUE INDEX ON affiliate_monthly_payments (year, month, affiliate_partner_id); +CREATE INDEX ON affiliate_monthly_payments (affiliate_partner_id, year, month); + + +ALTER TABLE sale_line_items ADD COLUMN affiliate_referral_id INTEGER REFERENCES affiliate_partners(id); +ALTER TABLE sale_line_items ADD COLUMN affiliate_referral_fee_in_cents INTEGER; +ALTER TABLE sale_line_items ADD COLUMN affiliate_refunded BOOLEAN NOT NULL DEFAULT FALSE; +ALTER TABLE sale_line_items ADD COLUMN affiliate_refunded_at TIMESTAMP; +ALTER TABLE generic_state ADD COLUMN affiliate_tallied_at TIMESTAMP; + +CREATE TABLE affiliate_traffic_totals ( + day DATE NOT NULL, + signups INTEGER NOT NULL DEFAULT 0, + visits INTEGER NOT NULL DEFAULT 0, + affiliate_partner_id INTEGER NOT NULL REFERENCES affiliate_partners(id), + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP +); + +CREATE UNIQUE INDEX ON affiliate_traffic_totals (day, affiliate_partner_id); +CREATE INDEX ON affiliate_traffic_totals (affiliate_partner_id, day); + +CREATE VIEW affiliate_payments AS + SELECT id AS monthly_id, + CAST(NULL as VARCHAR) AS quarterly_id, + affiliate_partner_id, + due_amount_in_cents, + jamtracks_sold, + created_at, + closed, + CAST(NULL AS BOOLEAN) AS paid, + year, + month as month, + CAST(NULL AS INTEGER) as quarter, + month as time_sort, + 'monthly' AS payment_type + FROM affiliate_monthly_payments + UNION ALL + SELECT CAST(NULL as VARCHAR) AS monthly_id, + id AS quarterly_id, + affiliate_partner_id, + due_amount_in_cents, + jamtracks_sold, + created_at, + closed, + paid, + year, + CAST(NULL AS INTEGER) as month, + quarter, + (quarter * 3) + 3 as time_sort, + 'quarterly' AS payment_type + FROM affiliate_quarterly_payments; \ No newline at end of file diff --git a/ruby/lib/jam_ruby.rb b/ruby/lib/jam_ruby.rb index 58ebc614a..51e887dc5 100755 --- a/ruby/lib/jam_ruby.rb +++ b/ruby/lib/jam_ruby.rb @@ -59,8 +59,9 @@ require "jam_ruby/resque/scheduled/score_history_sweeper" require "jam_ruby/resque/scheduled/scheduled_music_session_cleaner" require "jam_ruby/resque/scheduled/recordings_cleaner" require "jam_ruby/resque/scheduled/jam_tracks_cleaner" -require "jam_ruby/resque/jam_tracks_builder" require "jam_ruby/resque/scheduled/stats_maker" +require "jam_ruby/resque/scheduled/tally_affiliates" +require "jam_ruby/resque/jam_tracks_builder" require "jam_ruby/resque/google_analytics_event" require "jam_ruby/resque/batch_email_job" require "jam_ruby/resque/long_running" @@ -206,6 +207,12 @@ require "jam_ruby/app/mailers/async_mailer" require "jam_ruby/app/mailers/batch_mailer" require "jam_ruby/app/mailers/progress_mailer" require "jam_ruby/models/affiliate_partner" +require "jam_ruby/models/affiliate_legalese" +require "jam_ruby/models/affiliate_quarterly_payment" +require "jam_ruby/models/affiliate_monthly_payment" +require "jam_ruby/models/affiliate_traffic_total" +require "jam_ruby/models/affiliate_referral_visit" +require "jam_ruby/models/affiliate_payment" require "jam_ruby/models/chat_message" require "jam_ruby/models/shopping_cart" require "jam_ruby/models/generic_state" diff --git a/ruby/lib/jam_ruby/models/affiliate_legalese.rb b/ruby/lib/jam_ruby/models/affiliate_legalese.rb new file mode 100644 index 000000000..732d45025 --- /dev/null +++ b/ruby/lib/jam_ruby/models/affiliate_legalese.rb @@ -0,0 +1,6 @@ +class JamRuby::AffiliateLegalese < ActiveRecord::Base + self.table_name = 'affiliate_legalese' + + has_many :affiliate_partners, :class_name => "JamRuby::AffiliatePartner", :foreign_key => :legalese_id + +end diff --git a/ruby/lib/jam_ruby/models/affiliate_monthly_payment.rb b/ruby/lib/jam_ruby/models/affiliate_monthly_payment.rb new file mode 100644 index 000000000..8aa45ca5a --- /dev/null +++ b/ruby/lib/jam_ruby/models/affiliate_monthly_payment.rb @@ -0,0 +1,39 @@ +class JamRuby::AffiliateMonthlyPayment < ActiveRecord::Base + + belongs_to :affiliate_partner, class_name: 'JamRuby::AffiliatePartner', inverse_of: :months + + + def self.index(user, options) + unless user.affiliate_partner + return [[], nil] + end + + page = options[:page].to_i + per_page = options[:per_page].to_i + + if page == 0 + page = 1 + end + + if per_page == 0 + per_page = 50 + end + + start = (page -1 ) * per_page + limit = per_page + + query = AffiliateMonthlyPayment + .paginate(page: page, per_page: per_page) + .where(affiliate_partner_id: user.affiliate_partner.id) + .order('year ASC, month ASC') + + if query.length == 0 + [query, nil] + elsif query.length < limit + [query, nil] + else + [query, start + limit] + end + end + +end diff --git a/ruby/lib/jam_ruby/models/affiliate_partner.rb b/ruby/lib/jam_ruby/models/affiliate_partner.rb index 6df9dc1a2..58c4a1b8b 100644 --- a/ruby/lib/jam_ruby/models/affiliate_partner.rb +++ b/ruby/lib/jam_ruby/models/affiliate_partner.rb @@ -1,25 +1,75 @@ class JamRuby::AffiliatePartner < ActiveRecord::Base - belongs_to :partner_user, :class_name => "JamRuby::User", :foreign_key => :partner_user_id - has_many :user_referrals, :class_name => "JamRuby::User", :foreign_key => :affiliate_referral_id + self.table_name = 'affiliate_partners' + belongs_to :partner_user, :class_name => "JamRuby::User", :foreign_key => :partner_user_id, inverse_of: :affiliate_partner + has_many :user_referrals, :class_name => "JamRuby::User", :foreign_key => :affiliate_referral_id + belongs_to :affiliate_legalese, :class_name => "JamRuby::AffiliateLegalese", :foreign_key => :legalese_id + has_many :sale_line_items, :class_name => 'JamRuby::SaleLineItem', foreign_key: :affiliate_referral_id + has_many :quarters, :class_name => 'JamRuby::AffiliateQuarterlyPayment', foreign_key: :affiliate_partner_id, inverse_of: :affiliate_partner + has_many :months, :class_name => 'JamRuby::AffiliateMonthlyPayment', foreign_key: :affiliate_partner_id, inverse_of: :affiliate_partner + has_many :traffic_totals, :class_name => 'JamRuby::AffiliateTrafficTotal', foreign_key: :affiliate_partner_id, inverse_of: :affiliate_partner + has_many :visits, :class_name => 'JamRuby::AffiliateReferralVisit', foreign_key: :affiliate_partner_id, inverse_of: :affiliate_partner attr_accessible :partner_name, :partner_code, :partner_user_id + ENTITY_TYPES = %w{ Individual Sole\ Proprietor Limited\ Liability\ Company\ (LLC) Partnership Trust/Estate S\ Corporation C\ Corporation Other } + + KEY_ADDR1 = 'address1' + KEY_ADDR2 = 'address2' + KEY_CITY = 'city' + KEY_STATE = 'state' + KEY_POSTAL = 'postal_code' + KEY_COUNTRY = 'country' + + # ten dollars in cents + PAY_THRESHOLD = 10 * 100 + + AFFILIATE_PARAMS="utm_source=affiliate&utm_medium=affiliate&utm_campaign=2015-affiliate-custom&affiliate=" + + ADDRESS_SCHEMA = { + KEY_ADDR1 => '', + KEY_ADDR2 => '', + KEY_CITY => '', + KEY_STATE => '', + KEY_POSTAL => '', + KEY_COUNTRY => '', + } + PARAM_REFERRAL = :ref PARAM_COOKIE = :affiliate_ref PARTNER_CODE_REGEX = /^[#{Regexp.escape('abcdefghijklmnopqrstuvwxyz0123456789-._+,')}]+{2,128}$/i - validates :user_email, format: {with: JamRuby::User::VALID_EMAIL_REGEX}, :if => :user_email - validates :partner_name, presence: true - validates :partner_code, presence: true, format: { with: PARTNER_CODE_REGEX } - validates :partner_user, presence: true + #validates :user_email, format: {with: JamRuby::User::VALID_EMAIL_REGEX}, :if => :user_email + #validates :partner_code, format: { with: PARTNER_CODE_REGEX }, :allow_blank => true + validates :entity_type, inclusion: {in: ENTITY_TYPES, message: "invalid entity type"} + serialize :address, JSON + + before_save do |record| + record.address ||= ADDRESS_SCHEMA.clone + record.entity_type ||= ENTITY_TYPES.first + end + + # used by admin def self.create_with_params(params={}) + raise 'not supported' oo = self.new oo.partner_name = params[:partner_name].try(:strip) oo.partner_code = params[:partner_code].try(:strip).try(:downcase) oo.partner_user = User.where(:email => params[:user_email].try(:strip)).limit(1).first oo.partner_user_id = oo.partner_user.try(:id) + oo.entity_type = params[:entity_type] || ENTITY_TYPES.first + oo.save + oo + end + + # used by web + def self.create_with_web_params(user, params={}) + oo = self.new + oo.partner_name = params[:partner_name].try(:strip) + oo.partner_user = user if user # user is not required + oo.entity_type = params[:entity_type] || ENTITY_TYPES.first + oo.signed_at = Time.now oo.save oo end @@ -29,16 +79,393 @@ class JamRuby::AffiliatePartner < ActiveRecord::Base end def self.is_code?(code) - self.where(:partner_code => code).limit(1).pluck(:id).present? + self.where(:partner_code => code).limit(1).pluck(:id).present? end def referrals_by_date by_date = User.where(:affiliate_referral_id => self.id) - .group('DATE(created_at)') - .having("COUNT(*) > 0") - .order('date_created_at DESC') - .count + .group('DATE(created_at)') + .having("COUNT(*) > 0") + .order('date_created_at DESC') + .count block_given? ? yield(by_date) : by_date end + def signed_legalese(legalese) + self.affiliate_legalese = legalese + self.signed_at = Time.now + save! + end + + def update_address_value(key, val) + self.address[key] = val + self.update_attribute(:address, self.address) + end + + def address_value(key) + self.address[key] + end + + def created_within_affiliate_window(user, sale_time) + sale_time - user.created_at < 2.years + end + + def should_attribute_sale?(shopping_cart) + if shopping_cart.is_jam_track? + if created_within_affiliate_window(shopping_cart.user, Time.now) + product_info = shopping_cart.product_info + # subtract the total quantity from the freebie quantity, to see how much we should attribute to them + real_quantity = product_info[:quantity].to_i - product_info[:marked_for_redeem].to_i + {fee_in_cents: real_quantity * 20} + else + false + end + else + raise 'shopping cart type not implemented yet' + end + end + + def cumulative_earnings_in_dollars + cumulative_earnings_in_cents.to_f / 100.to_f + end + + def self.quarter_info(date) + + year = date.year + + # which quarter? + quarter = -1 + if date.month >= 1 && date.month <= 3 + quarter = 0 + elsif date.month >= 4 && date.month <= 6 + quarter = 1 + elsif date.month >= 7 && date.month <= 9 + quarter = 2 + elsif date.month >= 10 && date.month <= 12 + quarter = 3 + end + + raise 'quarter should never be -1' if quarter == -1 + + previous_quarter = quarter - 1 + previous_year = date.year + if previous_quarter == -1 + previous_quarter = 3 + previous_year = year - 1 + end + + raise 'previous quarter should never be -1' if previous_quarter == -1 + + {year: year, quarter: quarter, previous_quarter: previous_quarter, previous_year: previous_year} + end + + def self.did_quarter_elapse?(quarter_info, last_tallied_info) + if last_tallied_info.nil? + true + else + quarter_info == last_tallied_info + end + end + + # meant to be run regularly; this routine will make summarized counts in the + # AffiliateQuarterlyPayment table + # AffiliatePartner.cumulative_earnings_in_cents, AffiliatePartner.referral_user_count + def self.tally_up(day) + + AffiliatePartner.transaction do + quarter_info = quarter_info(day) + last_tallied_info = quarter_info(GenericState.affiliate_tallied_at) if GenericState.affiliate_tallied_at + + quarter_elapsed = did_quarter_elapse?(quarter_info, last_tallied_info) + + if quarter_elapsed + tally_monthly_payments(quarter_info[:previous_year], quarter_info[:previous_quarter]) + tally_quarterly_payments(quarter_info[:previous_year], quarter_info[:previous_quarter]) + end + tally_monthly_payments(quarter_info[:year], quarter_info[:quarter]) + tally_quarterly_payments(quarter_info[:year], quarter_info[:quarter]) + + tally_traffic_totals(GenericState.affiliate_tallied_at, day) + + tally_partner_totals + + state = GenericState.singleton + state.affiliate_tallied_at = day + state.save! + end + + end + + # this just makes sure that the quarter rows exist before later manipulations with UPDATEs + def self.ensure_quarters_exist(year, quarter) + + sql = %{ + INSERT INTO affiliate_quarterly_payments (quarter, year, affiliate_partner_id) + (SELECT #{quarter}, #{year}, affiliate_partners.id FROM affiliate_partners WHERE affiliate_partners.partner_user_id IS NOT NULL AND affiliate_partners.id NOT IN + (SELECT affiliate_partner_id FROM affiliate_quarterly_payments WHERE year = #{year} AND quarter = #{quarter})) + } + + ActiveRecord::Base.connection.execute(sql) + end + + # this just makes sure that the quarter rows exist before later manipulations with UPDATEs + def self.ensure_months_exist(year, quarter) + + months = [1, 2, 3].collect! { |i| quarter * 3 + i } + + months.each do |month| + sql = %{ + INSERT INTO affiliate_monthly_payments (month, year, affiliate_partner_id) + (SELECT #{month}, #{year}, affiliate_partners.id FROM affiliate_partners WHERE affiliate_partners.partner_user_id IS NOT NULL AND affiliate_partners.id NOT IN + (SELECT affiliate_partner_id FROM affiliate_monthly_payments WHERE year = #{year} AND month = #{month})) + } + + ActiveRecord::Base.connection.execute(sql) + end + end + + + def self.sale_items_subquery(start_date, end_date, table_name) + %{ + FROM sale_line_items + WHERE + (DATE(sale_line_items.created_at) >= DATE('#{start_date}') AND DATE(sale_line_items.created_at) <= DATE('#{end_date}')) + AND + sale_line_items.affiliate_referral_id = #{table_name}.affiliate_partner_id + } + end + + def self.sale_items_refunded_subquery(start_date, end_date, table_name) + %{ + FROM sale_line_items + WHERE + (DATE(sale_line_items.affiliate_refunded_at) >= DATE('#{start_date}') AND DATE(sale_line_items.affiliate_refunded_at) <= DATE('#{end_date}')) + AND + sale_line_items.affiliate_referral_id = #{table_name}.affiliate_partner_id + AND + sale_line_items.affiliate_refunded = TRUE + } + end + # total up quarters by looking in sale_line_items for items that are marked as having a affiliate_referral_id + # don't forget to substract any sale_line_items that have a affiliate_refunded = TRUE + def self.total_months(year, quarter) + + months = [1, 2, 3].collect! { |i| quarter * 3 + i } + + + months.each do |month| + + start_date, end_date = boundary_dates_for_month(year, month) + + sql = %{ + UPDATE affiliate_monthly_payments + SET + last_updated = NOW(), + jamtracks_sold = + COALESCE( + (SELECT COUNT(CASE WHEN sale_line_items.product_type = 'JamTrack' AND sale_line_items.affiliate_referral_fee_in_cents > 0 THEN 1 ELSE NULL END) + #{sale_items_subquery(start_date, end_date, 'affiliate_monthly_payments')} + ), 0) + + + COALESCE( + (SELECT -COUNT(CASE WHEN sale_line_items.product_type = 'JamTrack' AND sale_line_items.affiliate_referral_fee_in_cents > 0 THEN 1 ELSE NULL END) + #{sale_items_refunded_subquery(start_date, end_date, 'affiliate_monthly_payments')} + ), 0), + due_amount_in_cents = + COALESCE( + (SELECT SUM(affiliate_referral_fee_in_cents) + #{sale_items_subquery(start_date, end_date, 'affiliate_monthly_payments')} + ), 0) + + + COALESCE( + (SELECT -SUM(affiliate_referral_fee_in_cents) + #{sale_items_refunded_subquery(start_date, end_date, 'affiliate_monthly_payments')} + ), 0) + + WHERE closed = FALSE AND year = #{year} AND month = #{month} + } + + ActiveRecord::Base.connection.execute(sql) + end + end + + # close any quarters that are done, so we don't manipulate them again + def self.close_months(year, quarter) + # close any quarters that occurred before this quarter + month = quarter * 3 + 1 + + sql = %{ + UPDATE affiliate_monthly_payments + SET + closed = TRUE, closed_at = NOW() + WHERE year < #{year} OR month < #{month} + } + + ActiveRecord::Base.connection.execute(sql) + + end + + # total up quarters by looking in sale_line_items for items that are marked as having a affiliate_referral_id + # don't forget to substract any sale_line_items that have a affiliate_refunded = TRUE + def self.total_quarters(year, quarter) + start_date, end_date = boundary_dates(year, quarter) + + sql = %{ + UPDATE affiliate_quarterly_payments + SET + last_updated = NOW(), + jamtracks_sold = + COALESCE( + (SELECT COUNT(CASE WHEN sale_line_items.product_type = 'JamTrack' AND sale_line_items.affiliate_referral_fee_in_cents > 0 THEN 1 ELSE NULL END) + #{sale_items_subquery(start_date, end_date, 'affiliate_quarterly_payments')} + ), 0) + + + COALESCE( + (SELECT -COUNT(CASE WHEN sale_line_items.product_type = 'JamTrack' AND sale_line_items.affiliate_referral_fee_in_cents > 0 THEN 1 ELSE NULL END) + #{sale_items_refunded_subquery(start_date, end_date, 'affiliate_quarterly_payments')} + ), 0), + due_amount_in_cents = + COALESCE( + (SELECT SUM(affiliate_referral_fee_in_cents) + #{sale_items_subquery(start_date, end_date, 'affiliate_quarterly_payments')} + ), 0) + + + COALESCE( + (SELECT -SUM(affiliate_referral_fee_in_cents) + #{sale_items_refunded_subquery(start_date, end_date, 'affiliate_quarterly_payments')} + ), 0) + + WHERE closed = FALSE AND paid = FALSE AND year = #{year} AND quarter = #{quarter} + } + + ActiveRecord::Base.connection.execute(sql) + end + + # close any quarters that are done, so we don't manipulate them again + def self.close_quarters(year, quarter) + # close any quarters that occurred before this quarter + sql = %{ + UPDATE affiliate_quarterly_payments + SET + closed = TRUE, closed_at = NOW() + WHERE year < #{year} OR quarter < #{quarter} + } + + ActiveRecord::Base.connection.execute(sql) + end + + def self.tally_quarterly_payments(year, quarter) + ensure_quarters_exist(year, quarter) + + total_quarters(year, quarter) + + close_quarters(year, quarter) + end + + + def self.tally_monthly_payments(year, quarter) + ensure_months_exist(year, quarter) + + total_months(year, quarter) + + close_months(year, quarter) + end + + def self.tally_partner_totals + sql = %{ + UPDATE affiliate_partners SET + referral_user_count = (SELECT count(*) FROM users WHERE affiliate_partners.id = users.affiliate_referral_id), + cumulative_earnings_in_cents = (SELECT COALESCE(SUM(due_amount_in_cents), 0) FROM affiliate_quarterly_payments AS aqp WHERE aqp.affiliate_partner_id = affiliate_partners.id AND closed = TRUE and paid = TRUE) + } + ActiveRecord::Base.connection.execute(sql) + end + + def self.tally_traffic_totals(last_tallied_at, target_day) + + if last_tallied_at + start_date = last_tallied_at.to_date + end_date = target_day.to_date + else + start_date = target_day.to_date - 1 + end_date = target_day.to_date + end + + if start_date == end_date + return + end + + sql = %{ + INSERT INTO affiliate_traffic_totals(SELECT day, 0, 0, ap.id FROM affiliate_partners AS ap CROSS JOIN (select (generate_series('#{start_date}', '#{end_date - 1}', '1 day'::interval))::date as day) AS lurp) + } + ActiveRecord::Base.connection.execute(sql) + + sql = %{ + UPDATE affiliate_traffic_totals traffic SET visits = COALESCE((SELECT COALESCE(count(affiliate_partner_id), 0) FROM affiliate_referral_visits v WHERE DATE(v.created_at) >= DATE('#{start_date}') AND DATE(v.created_at) < DATE('#{end_date}') AND v.created_at::date = traffic.day AND v.affiliate_partner_id = traffic.affiliate_partner_id GROUP BY affiliate_partner_id, v.created_at::date ), 0) WHERE traffic.day >= DATE('#{start_date}') AND traffic.day < DATE('#{end_date}') + } + ActiveRecord::Base.connection.execute(sql) + + sql = %{ + UPDATE affiliate_traffic_totals traffic SET signups = COALESCE((SELECT COALESCE(count(v.id), 0) FROM users v WHERE DATE(v.created_at) >= DATE('#{start_date}') AND DATE(v.created_at) < DATE('#{end_date}') AND v.created_at::date = traffic.day AND v.affiliate_referral_id = traffic.affiliate_partner_id GROUP BY affiliate_referral_id, v.created_at::date ), 0) WHERE traffic.day >= DATE('#{start_date}') AND traffic.day < DATE('#{end_date}') + } + ActiveRecord::Base.connection.execute(sql) + end + + def self.boundary_dates(year, quarter) + if quarter == 0 + [Date.new(year, 1, 1), Date.new(year, 3, 31)] + elsif quarter == 1 + [Date.new(year, 4, 1), Date.new(year, 6, 30)] + elsif quarter == 2 + [Date.new(year, 7, 1), Date.new(year, 9, 30)] + elsif quarter == 3 + [Date.new(year, 7, 1), Date.new(year, 9, 30)] + else + raise "invalid quarter #{quarter}" + end + end + + def self.boundary_dates_for_month(year, month) + [Date.new(year, month, 1), Date.civil(year, month, -1)] + end + + # Finds all affiliates that need to be paid + def self.unpaid + + joins(:quarters) + .where('affiliate_quarterly_payments.paid = false').where('affiliate_quarterly_payments.closed = true') + .group('affiliate_partners.id') + .having('sum(due_amount_in_cents) >= ?', PAY_THRESHOLD) + .order('sum(due_amount_in_cents) DESC') + + end + + # does this one affiliate need to be paid? + def unpaid + due_amount_in_cents > PAY_THRESHOLD + end + + # admin function: mark the affiliate paid + def mark_paid + if unpaid + transaction do + now = Time.now + quarters.where(paid:false, closed:true).update_all(paid:true, paid_at: now) + self.last_paid_at = now + self.save! + end + end + end + + # how much is this affiliate due? + def due_amount_in_cents + total_in_cents = 0 + quarters.where(paid:false, closed:true).each do |quarter| + total_in_cents = total_in_cents + quarter.due_amount_in_cents + end + total_in_cents + end + + def affiliate_query_params + AffiliatePartner::AFFILIATE_PARAMS + self.id.to_s + end end diff --git a/ruby/lib/jam_ruby/models/affiliate_payment.rb b/ruby/lib/jam_ruby/models/affiliate_payment.rb new file mode 100644 index 000000000..81c36a977 --- /dev/null +++ b/ruby/lib/jam_ruby/models/affiliate_payment.rb @@ -0,0 +1,49 @@ +module JamRuby + class AffiliatePayment < ActiveRecord::Base + + belongs_to :affiliate_monthly_payment + belongs_to :affiliate_quarterly_payment + + def self.index(user, options) + + unless user.affiliate_partner + return [[], nil] + end + + affiliate_partner_id = user.affiliate_partner.id + + + page = options[:page].to_i + per_page = options[:per_page].to_i + + if page == 0 + page = 1 + end + + if per_page == 0 + per_page = 50 + end + + start = (page -1 ) * per_page + limit = per_page + + + query = AffiliatePayment + .includes(affiliate_quarterly_payment: [], affiliate_monthly_payment:[]) + .where(affiliate_partner_id: affiliate_partner_id) + .where("payment_type='quarterly' AND closed = true") + .where('(paid = TRUE or due_amount_in_cents < 10000 or paid is NULL)') + .paginate(:page => page, :per_page => limit) + .order('year ASC, time_sort ASC, payment_type ASC') + + if query.length == 0 + [query, nil] + elsif query.length < limit + [query, nil] + else + [query, start + limit] + end + end + end +end + diff --git a/ruby/lib/jam_ruby/models/affiliate_quarterly_payment.rb b/ruby/lib/jam_ruby/models/affiliate_quarterly_payment.rb new file mode 100644 index 000000000..caf9eced7 --- /dev/null +++ b/ruby/lib/jam_ruby/models/affiliate_quarterly_payment.rb @@ -0,0 +1,41 @@ +class JamRuby::AffiliateQuarterlyPayment < ActiveRecord::Base + + belongs_to :affiliate_partner, class_name: 'JamRuby::AffiliatePartner', inverse_of: :quarters + + + def self.index(user, options) + unless user.affiliate_partner + return [[], nil] + end + + page = options[:page].to_i + per_page = options[:per_page].to_i + + if page == 0 + page = 1 + end + + if per_page == 0 + per_page = 50 + end + + start = (page -1 ) * per_page + limit = per_page + + query = AffiliateQuarterlyPayment + .paginate(page: page, per_page: per_page) + .where(affiliate_partner_id: user.affiliate_partner.id) + .where(closed:true) + .where(paid:true) + .order('year ASC, quarter ASC') + + if query.length == 0 + [query, nil] + elsif query.length < limit + [query, nil] + else + [query, start + limit] + end + end + +end diff --git a/ruby/lib/jam_ruby/models/affiliate_referral_visit.rb b/ruby/lib/jam_ruby/models/affiliate_referral_visit.rb new file mode 100644 index 000000000..cf9e9fbc0 --- /dev/null +++ b/ruby/lib/jam_ruby/models/affiliate_referral_visit.rb @@ -0,0 +1,23 @@ +class JamRuby::AffiliateReferralVisit < ActiveRecord::Base + + belongs_to :affiliate_partner, class_name: 'JamRuby::AffiliatePartner', inverse_of: :visits + + validates :affiliate_partner_id, numericality: {only_integer: true}, :allow_nil => true + validates :visited_url, length: {maximum: 1000} + validates :referral_url, length: {maximum: 1000} + validates :ip_address, presence: true, length: {maximum:1000} + validates :first_visit, inclusion: {in: [true, false]} + validates :user_id, length: {maximum:64} + + def self.track(options = {}) + visit = AffiliateReferralVisit.new + visit.affiliate_partner_id = options[:affiliate_id] + visit.ip_address = options[:remote_ip] + visit.visited_url = options[:visited_url] + visit.referral_url = options[:referral_url] + visit.first_visit = options[:visited].nil? + visit.user_id = options[:current_user].id if options[:current_user] + visit.save + visit + end +end diff --git a/ruby/lib/jam_ruby/models/affiliate_traffic_total.rb b/ruby/lib/jam_ruby/models/affiliate_traffic_total.rb new file mode 100644 index 000000000..c85fa4fb5 --- /dev/null +++ b/ruby/lib/jam_ruby/models/affiliate_traffic_total.rb @@ -0,0 +1,39 @@ +class JamRuby::AffiliateTrafficTotal < ActiveRecord::Base + + belongs_to :affiliate_partner, class_name: 'JamRuby::AffiliatePartner', inverse_of: :traffic_totals + + + def self.index(user, options) + unless user.affiliate_partner + return [[], nil] + end + + page = options[:page].to_i + per_page = options[:per_page].to_i + + if page == 0 + page = 1 + end + + if per_page == 0 + per_page = 50 + end + + start = (page -1 ) * per_page + limit = per_page + + query = AffiliateTrafficTotal + .paginate(page: page, per_page: per_page) + .where(affiliate_partner_id: user.affiliate_partner.id) + .where('visits != 0 OR signups != 0') + .order('day ASC') + + if query.length == 0 + [query, nil] + elsif query.length < limit + [query, nil] + else + [query, start + limit] + end + end +end diff --git a/ruby/lib/jam_ruby/models/anonymous_user.rb b/ruby/lib/jam_ruby/models/anonymous_user.rb index ff7b60730..24bc2b104 100644 --- a/ruby/lib/jam_ruby/models/anonymous_user.rb +++ b/ruby/lib/jam_ruby/models/anonymous_user.rb @@ -28,7 +28,7 @@ module JamRuby end def signup_hint - SignupHint.find_by_anonymous_user_id(@id) + SignupHint.where(anonymous_user_id: @id).where('expires_at > ?', Time.now).first end end end diff --git a/ruby/lib/jam_ruby/models/generic_state.rb b/ruby/lib/jam_ruby/models/generic_state.rb index d6c0bc687..6ed4ec7f4 100644 --- a/ruby/lib/jam_ruby/models/generic_state.rb +++ b/ruby/lib/jam_ruby/models/generic_state.rb @@ -23,9 +23,14 @@ module JamRuby (database_environment == 'development' && Environment.mode == 'development') end + def self.affiliate_tallied_at + GenericState.singleton.affiliate_tallied_at + end + def self.singleton GenericState.find('default') end + end end diff --git a/ruby/lib/jam_ruby/models/jam_track.rb b/ruby/lib/jam_ruby/models/jam_track.rb index ae465b2f2..8ab120c62 100644 --- a/ruby/lib/jam_ruby/models/jam_track.rb +++ b/ruby/lib/jam_ruby/models/jam_track.rb @@ -263,5 +263,10 @@ module JamRuby jam_track_rights.where("user_id=?", user).first end + def short_plan_code + prefix = 'jamtrack-' + plan_code[prefix.length..-1] + end + end end diff --git a/ruby/lib/jam_ruby/models/music_session.rb b/ruby/lib/jam_ruby/models/music_session.rb index e2954d9f3..96b9b7831 100644 --- a/ruby/lib/jam_ruby/models/music_session.rb +++ b/ruby/lib/jam_ruby/models/music_session.rb @@ -282,7 +282,7 @@ module JamRuby return query end - def self.scheduled user + def self.scheduled user, only_public = false # keep unstarted sessions around for 12 hours after scheduled_start session_not_started = "(music_sessions.scheduled_start > NOW() - '12 hour'::INTERVAL AND music_sessions.started_at IS NULL)" @@ -293,6 +293,7 @@ module JamRuby session_finished = "(music_sessions.session_removed_at > NOW() - '2 hour'::INTERVAL)" query = MusicSession.where("music_sessions.canceled = FALSE") + query = query.where('music_sessions.fan_access = TRUE or music_sessions.musician_access = TRUE') if only_public query = query.where("music_sessions.user_id = '#{user.id}'") query = query.where("music_sessions.scheduled_start IS NULL OR #{session_not_started} OR #{session_finished} OR #{session_started_not_finished}") query = query.where("music_sessions.create_type IS NULL OR music_sessions.create_type != '#{CREATE_TYPE_QUICK_START}'") diff --git a/ruby/lib/jam_ruby/models/recurly_transaction_web_hook.rb b/ruby/lib/jam_ruby/models/recurly_transaction_web_hook.rb index 05824e322..9d0fc9bd4 100644 --- a/ruby/lib/jam_ruby/models/recurly_transaction_web_hook.rb +++ b/ruby/lib/jam_ruby/models/recurly_transaction_web_hook.rb @@ -100,9 +100,14 @@ module JamRuby if sale && sale.is_jam_track_sale? if sale.sale_line_items.length == 1 if sale.recurly_total_in_cents == transaction.amount_in_cents - jam_track = sale.sale_line_items[0].product + line_item = sale.sale_line_items[0] + jam_track = line_item.product jam_track_right = jam_track.right_for_user(transaction.user) if jam_track if jam_track_right + line_item.affiliate_refunded = true + line_item.affiliate_refunded_at = Time.now + line_item.save! + jam_track_right.destroy # associate which JamTrack we assume this is related to in this one success case diff --git a/ruby/lib/jam_ruby/models/sale_line_item.rb b/ruby/lib/jam_ruby/models/sale_line_item.rb index 2022318b0..7d744cfe5 100644 --- a/ruby/lib/jam_ruby/models/sale_line_item.rb +++ b/ruby/lib/jam_ruby/models/sale_line_item.rb @@ -8,7 +8,8 @@ module JamRuby belongs_to :sale, class_name: 'JamRuby::Sale' belongs_to :jam_track, class_name: 'JamRuby::JamTrack' belongs_to :jam_track_right, class_name: 'JamRuby::JamTrackRight' - has_many :recurly_transactions, class_name: 'JamRuby::RecurlyTransactionWebHook', inverse_of: :sale_line_item, foreign_key: 'subscription_id', primary_key: 'recurly_subscription_uuid' + belongs_to :affiliate_referral, class_name: 'JamRuby::AffiliatePartner', foreign_key: :affiliate_referral_id + has_many :recurly_transactions, class_name: 'JamRuby::RecurlyTransactionWebHook', inverse_of: :sale_line_item, foreign_key: 'subscription_id', primary_key: 'recurly_subscription_uuid' validates :product_type, inclusion: {in: [JAMBLASTER, JAMCLOUD, JAMTRACK]} validates :unit_price, numericality: {only_integer: false} @@ -16,6 +17,7 @@ module JamRuby validates :free, numericality: {only_integer: true} validates :sales_tax, numericality: {only_integer: false}, allow_nil: true validates :shipping_handling, numericality: {only_integer: false} + validates :affiliate_referral_fee_in_cents, numericality: {only_integer: false}, allow_nil: true validates :recurly_plan_code, presence:true validates :sale, presence:true @@ -76,6 +78,16 @@ module JamRuby sale_line_item.recurly_subscription_uuid = recurly_subscription_uuid sale_line_item.recurly_adjustment_uuid = recurly_adjustment_uuid sale_line_item.recurly_adjustment_credit_uuid = recurly_adjustment_credit_uuid + + # determine if we need to associate this sale with a partner + user = shopping_cart.user + referral_info = user.should_attribute_sale?(shopping_cart) + + if referral_info + sale_line_item.affiliate_referral = user.affiliate_referral + sale_line_item.affiliate_referral_fee_in_cents = referral_info[:fee_in_cents] + end + sale.sale_line_items << sale_line_item sale_line_item.save sale_line_item diff --git a/ruby/lib/jam_ruby/models/user.rb b/ruby/lib/jam_ruby/models/user.rb index fcdeffc3c..f91973626 100644 --- a/ruby/lib/jam_ruby/models/user.rb +++ b/ruby/lib/jam_ruby/models/user.rb @@ -144,7 +144,7 @@ module JamRuby has_many :event_sessions, :class_name => "JamRuby::EventSession" # affiliate_partner - has_one :affiliate_partner, :class_name => "JamRuby::AffiliatePartner", :foreign_key => :partner_user_id + has_one :affiliate_partner, :class_name => "JamRuby::AffiliatePartner", :foreign_key => :partner_user_id, inverse_of: :partner_user belongs_to :affiliate_referral, :class_name => "JamRuby::AffiliatePartner", :foreign_key => :affiliate_referral_id, :counter_cache => :referral_user_count # diagnostics has_many :diagnostics, :class_name => "JamRuby::Diagnostic" @@ -954,6 +954,7 @@ module JamRuby any_user = options[:any_user] reuse_card = options[:reuse_card] signup_hint = options[:signup_hint] + affiliate_partner = options[:affiliate_partner] user = User.new @@ -1088,6 +1089,14 @@ module JamRuby if user.errors.any? raise ActiveRecord::Rollback else + # if the partner ID was present and the partner doesn't already have a user associated, associate this new user with the affiliate partner + if affiliate_partner && affiliate_partner.partner_user.nil? + affiliate_partner.partner_user = user + unless affiliate_partner.save + @@log.error("unable to associate #{user.to_s} with affiliate_partner #{affiliate_partner.id} / #{affiliate_partner.partner_name}") + end + end + if user.affiliate_referral = AffiliatePartner.find_by_id(affiliate_referral_id) user.save end if affiliate_referral_id.present? @@ -1603,6 +1612,15 @@ module JamRuby options end + def should_attribute_sale?(shopping_cart) + if affiliate_referral + referral_info = affiliate_referral.should_attribute_sale?(shopping_cart) + else + false + end + + + end private def create_remember_token self.remember_token = SecureRandom.urlsafe_base64 diff --git a/ruby/lib/jam_ruby/resque/scheduled/tally_affiliates.rb b/ruby/lib/jam_ruby/resque/scheduled/tally_affiliates.rb new file mode 100644 index 000000000..2327f281f --- /dev/null +++ b/ruby/lib/jam_ruby/resque/scheduled/tally_affiliates.rb @@ -0,0 +1,31 @@ +require 'json' +require 'resque' +require 'resque-retry' +require 'net/http' +require 'digest/md5' + +module JamRuby + + # periodically scheduled to find jobs that need retrying + class TallyAffiliates + extend Resque::Plugins::JamLonelyJob + + @queue = :tally_affiliates + + @@log = Logging.logger[TallyAffiliates] + + def self.lock_timeout + # this should be enough time to make sure the job has finished, but not so long that the system isn't recovering from a abandoned job + 120 + end + + def self.perform + @@log.debug("waking up") + + AffiliatePartner.tally_up(Date.today) + + @@log.debug("done") + end + end + +end \ No newline at end of file diff --git a/ruby/spec/factories.rb b/ruby/spec/factories.rb index 2c7de6801..f27b85a69 100644 --- a/ruby/spec/factories.rb +++ b/ruby/spec/factories.rb @@ -797,4 +797,33 @@ FactoryGirl.define do transaction_type JamRuby::RecurlyTransactionWebHook::FAILED_PAYMENT end end + + factory :affiliate_partner, class: 'JamRuby::AffiliatePartner' do + sequence(:partner_name) { |n| "partner-#{n}" } + entity_type 'Individual' + signed_at Time.now + association :partner_user, factory: :user + end + + factory :affiliate_quarterly_payment, class: 'JamRuby::AffiliateQuarterlyPayment' do + year 2015 + quarter 0 + association :affiliate_partner, factory: :affiliate_partner + end + + factory :affiliate_monthly_payment, class: 'JamRuby::AffiliateMonthlyPayment' do + year 2015 + month 0 + association :affiliate_partner, factory: :affiliate_partner + end + + factory :affiliate_referral_visit, class: 'JamRuby::AffiliateReferralVisit' do + ip_address '1.1.1.1' + association :affiliate_partner, factory: :affiliate_partner + end + + factory :affiliate_legalese, class: 'JamRuby::AffiliateLegalese' do + legalese Faker::Lorem.paragraphs(6).join("\n\n") + end + end diff --git a/ruby/spec/jam_ruby/models/affiliate_partner_spec.rb b/ruby/spec/jam_ruby/models/affiliate_partner_spec.rb index 9b25931d9..26c660daf 100644 --- a/ruby/spec/jam_ruby/models/affiliate_partner_spec.rb +++ b/ruby/spec/jam_ruby/models/affiliate_partner_spec.rb @@ -3,47 +3,46 @@ require 'spec_helper' describe AffiliatePartner do let!(:user) { FactoryGirl.create(:user) } - let!(:partner) { - AffiliatePartner.create_with_params({:partner_name => 'partner', - :partner_code => 'code', - :user_email => user.email}) - } + let(:partner) { FactoryGirl.create(:affiliate_partner) } + let!(:legalese) { FactoryGirl.create(:affiliate_legalese) } + let(:jam_track) {FactoryGirl.create(:jam_track) } - # Faker::Lorem.word is tripping up the PARTNER_CODE_REGEX. We should not use it. - it 'validates required fields' do - pending - expect(partner.referral_user_count).to eq(0) - expect(partner.partner_user).to eq(user) - user.reload - expect(user.affiliate_partner).to eq(partner) + describe "unpaid" do + it "succeeds with no data" do + AffiliatePartner.unpaid.length.should eq(0) + end - oo = AffiliatePartner.create_with_params({:partner_name => Faker::Company.name, - :partner_code => 'a', - :user_email => user.email}) - expect(oo.errors.messages[:partner_code][0]).to eq('is invalid') - oo = AffiliatePartner.create_with_params({:partner_name => Faker::Company.name, - :partner_code => 'foo bar', - :user_email => user.email}) - expect(oo.errors.messages[:partner_code][0]).to eq('is invalid') - oo = AffiliatePartner.create_with_params({:partner_name => '', - :partner_code => Faker::Lorem.word, - :user_email => user.email}) - expect(oo.errors.messages[:partner_name][0]).to eq("can't be blank") - oo = AffiliatePartner.create_with_params({:partner_name => '', - :partner_code => Faker::Lorem.word, - :user_email => Faker::Internet.email}) - expect(oo.errors.messages[:partner_user][0]).to eq("can't be blank") + it "finds one unpaid partner" do + quarter = FactoryGirl.create(:affiliate_quarterly_payment, affiliate_partner: partner, closed:true, paid:false, due_amount_in_cents: AffiliatePartner::PAY_THRESHOLD) + AffiliatePartner.unpaid.should eq([partner]) + end - code = Faker::Lorem.word.upcase - oo = AffiliatePartner.create_with_params({:partner_name => Faker::Company.name, - :partner_code => " #{code} ", - :user_email => user.email}) - expect(oo.partner_code).to eq(code.downcase) + it "finds one unpaid partner with two quarters that exceed threshold" do + # this $5 quarter is not enough to make the threshold + quarter = FactoryGirl.create(:affiliate_quarterly_payment, affiliate_partner: partner, year:2016, closed:true, paid:false, due_amount_in_cents: AffiliatePartner::PAY_THRESHOLD / 2) + AffiliatePartner.unpaid.should eq([]) + + # this should get the user over the hump + quarter = FactoryGirl.create(:affiliate_quarterly_payment, affiliate_partner: partner, year:2015, closed:true, paid:false, due_amount_in_cents: AffiliatePartner::PAY_THRESHOLD / 2) + AffiliatePartner.unpaid.should eq([partner]) + end + + it "does not find paid or closed quarters" do + quarter = FactoryGirl.create(:affiliate_quarterly_payment, affiliate_partner: partner, year:2016, closed:true, paid:true, due_amount_in_cents: AffiliatePartner::PAY_THRESHOLD) + AffiliatePartner.unpaid.should eq([]) + + quarter = FactoryGirl.create(:affiliate_quarterly_payment, affiliate_partner: partner, year:2015, closed:false, paid:true, due_amount_in_cents: AffiliatePartner::PAY_THRESHOLD) + AffiliatePartner.unpaid.should eq([]) + end + end + + it "user-partner association" do + user_partner = FactoryGirl.create(:user, affiliate_partner: partner) + user_partner.affiliate_partner.should_not be_nil + user_partner.affiliate_partner.present?.should be_true end it 'has user referrals' do - pending - expect(AffiliatePartner.coded_id(partner.partner_code)).to eq(partner.id) expect(partner.referral_user_count).to eq(0) uu = FactoryGirl.create(:user) uu.affiliate_referral = partner @@ -73,4 +72,656 @@ describe AffiliatePartner do expect(by_date[keys.last]).to eq(2) end + it 'updates address correctly' do + addy = partner.address.clone + addy[AffiliatePartner::KEY_ADDR1] = Faker::Address.street_address + addy[AffiliatePartner::KEY_ADDR2] = Faker::Address.secondary_address + addy[AffiliatePartner::KEY_CITY] = Faker::Address.city + addy[AffiliatePartner::KEY_STATE] = Faker::Address.state_abbr + addy[AffiliatePartner::KEY_COUNTRY] = Faker::Address.country + partner.update_address_value(AffiliatePartner::KEY_ADDR1, addy[AffiliatePartner::KEY_ADDR1]) + partner.update_address_value(AffiliatePartner::KEY_ADDR2, addy[AffiliatePartner::KEY_ADDR2]) + partner.update_address_value(AffiliatePartner::KEY_CITY, addy[AffiliatePartner::KEY_CITY]) + partner.update_address_value(AffiliatePartner::KEY_STATE, addy[AffiliatePartner::KEY_STATE]) + partner.update_address_value(AffiliatePartner::KEY_COUNTRY, addy[AffiliatePartner::KEY_COUNTRY]) + + expect(partner.address[AffiliatePartner::KEY_ADDR1]).to eq(addy[AffiliatePartner::KEY_ADDR1]) + expect(partner.address[AffiliatePartner::KEY_ADDR2]).to eq(addy[AffiliatePartner::KEY_ADDR2]) + expect(partner.address[AffiliatePartner::KEY_CITY]).to eq(addy[AffiliatePartner::KEY_CITY]) + expect(partner.address[AffiliatePartner::KEY_STATE]).to eq(addy[AffiliatePartner::KEY_STATE]) + expect(partner.address[AffiliatePartner::KEY_COUNTRY]).to eq(addy[AffiliatePartner::KEY_COUNTRY]) + end + + it 'associates legalese' do + + end + + describe "should_attribute_sale?" do + + it "user with no affiliate relationship" do + shopping_cart = ShoppingCart.create user, jam_track, 1 + user.should_attribute_sale?(shopping_cart).should be_false + end + + it "user with an affiliate relationship buying a jamtrack" do + user.affiliate_referral = partner + user.save! + shopping_cart = ShoppingCart.create user, jam_track, 1, false + user.should_attribute_sale?(shopping_cart).should eq({fee_in_cents:20}) + end + + it "user with an affiliate relationship redeeming a jamtrack" do + user.affiliate_referral = partner + user.save! + shopping_cart = ShoppingCart.create user, jam_track, 1, true + user.should_attribute_sale?(shopping_cart).should eq({fee_in_cents:0}) + end + + it "user with an expired affiliate relationship redeeming a jamtrack" do + user.affiliate_referral = partner + user.created_at = (365 * 2 + 1).days.ago + user.save! + shopping_cart = ShoppingCart.create user, jam_track, 1, false + user.should_attribute_sale?(shopping_cart).should be_false + end + end + + describe "created_within_affiliate_window" do + it "user created very recently" do + partner.created_within_affiliate_window(user, Time.now).should be_true + end + + it "user created 2 years, 1 day asgo" do + days_future = 365 * 2 + 1 + + partner.created_within_affiliate_window(user, days_future.days.from_now).should be_false + end + end + + describe "tally_up" do + let(:partner1) {FactoryGirl.create(:affiliate_partner)} + let(:partner2) {FactoryGirl.create(:affiliate_partner)} + let(:payment1) {FactoryGirl.create(:affiliate_quarterly_payment, affiliate_partner: partner1)} + let(:user_partner1) { FactoryGirl.create(:user, affiliate_referral: partner1)} + let(:user_partner2) { FactoryGirl.create(:user, affiliate_referral: partner2)} + let(:sale) {Sale.create_jam_track_sale(user_partner1)} + + describe "ensure_quarters_exist" do + + it "runs OK with no data" do + AffiliatePartner.ensure_quarters_exist(2015, 0) + AffiliateQuarterlyPayment.count.should eq(0) + end + + it "creates new slots" do + partner1.touch + partner2.touch + AffiliatePartner.ensure_quarters_exist(2015, 0) + AffiliateQuarterlyPayment.count.should eq(2) + quarter = partner1.quarters.first + quarter.year.should eq(2015) + quarter.quarter.should eq(0) + quarter = partner2.quarters.first + quarter.year.should eq(2015) + quarter.quarter.should eq(0) + end + + it "creates one slot, ignoring other" do + partner1.touch + partner2.touch + payment1.touch + AffiliateQuarterlyPayment.count.should eq(1) + AffiliatePartner.ensure_quarters_exist(2015, 0) + AffiliateQuarterlyPayment.count.should eq(2) + quarter = partner1.quarters.first + quarter.year.should eq(2015) + quarter.quarter.should eq(0) + quarter = partner2.quarters.first + quarter.year.should eq(2015) + quarter.quarter.should eq(0) + end + end + + describe "close_quarters" do + it "runs OK with no data" do + AffiliateQuarterlyPayment.count.should eq(0) + AffiliatePartner.close_quarters(2015, 1) + end + + it "ignores current quarter" do + partner1.touch + partner2.touch + AffiliatePartner.ensure_quarters_exist(2015, 0) + AffiliateQuarterlyPayment.count.should eq(2) + AffiliatePartner.close_quarters(2015, 0) + AffiliateQuarterlyPayment.where(closed: true).count.should eq(0) + end + + it "closes previous quarter" do + partner1.touch + partner2.touch + AffiliatePartner.ensure_quarters_exist(2015, 0) + AffiliateQuarterlyPayment.count.should eq(2) + AffiliatePartner.close_quarters(2015, 1) + AffiliateQuarterlyPayment.where(closed: true).count.should eq(2) + end + + it "closes previous quarter (edge case)" do + partner1.touch + partner2.touch + AffiliatePartner.ensure_quarters_exist(2014, 3) + AffiliateQuarterlyPayment.count.should eq(2) + AffiliatePartner.close_quarters(2015, 0) + AffiliateQuarterlyPayment.where(closed: true).count.should eq(2) + end + end + + describe "tally_partner_totals" do + it "runs OK with no data" do + AffiliatePartner.tally_partner_totals + AffiliatePartner.count.should eq(0) + end + + it "updates partner when there is no data to tally" do + partner1.touch + partner1.cumulative_earnings_in_cents.should eq(0) + partner1.referral_user_count.should eq(0) + AffiliatePartner.tally_partner_totals + partner1.reload + partner1.cumulative_earnings_in_cents.should eq(0) + partner1.referral_user_count.should eq(0) + end + + it "updates referral_user_count" do + FactoryGirl.create(:user, affiliate_referral: partner1) + AffiliatePartner.tally_partner_totals + partner1.reload + partner1.referral_user_count.should eq(1) + partner1.cumulative_earnings_in_cents.should eq(0) + + FactoryGirl.create(:user, affiliate_referral: partner2) + AffiliatePartner.tally_partner_totals + partner1.reload + partner1.referral_user_count.should eq(1) + partner1.cumulative_earnings_in_cents.should eq(0) + partner2.reload + partner2.referral_user_count.should eq(1) + partner2.cumulative_earnings_in_cents.should eq(0) + + FactoryGirl.create(:user, affiliate_referral: partner2) + AffiliatePartner.tally_partner_totals + partner1.reload + partner1.referral_user_count.should eq(1) + partner1.cumulative_earnings_in_cents.should eq(0) + partner2.reload + partner2.referral_user_count.should eq(2) + partner2.cumulative_earnings_in_cents.should eq(0) + end + + it "updates cumulative_earnings_in_cents" do + FactoryGirl.create(:affiliate_quarterly_payment, affiliate_partner:partner1, year:2015, quarter:0, due_amount_in_cents: 0, closed:true, paid:true) + AffiliatePartner.tally_partner_totals + partner1.reload + partner1.referral_user_count.should eq(0) + partner1.cumulative_earnings_in_cents.should eq(0) + + FactoryGirl.create(:affiliate_quarterly_payment, affiliate_partner:partner2, year:2015, quarter:0, due_amount_in_cents: 10, closed:true, paid:true) + AffiliatePartner.tally_partner_totals + partner1.reload + partner1.referral_user_count.should eq(0) + partner1.cumulative_earnings_in_cents.should eq(0) + partner2.reload + partner2.referral_user_count.should eq(0) + partner2.cumulative_earnings_in_cents.should eq(10) + + FactoryGirl.create(:affiliate_quarterly_payment, affiliate_partner:partner2, year:2015, quarter:1, due_amount_in_cents: 100, closed:true, paid:true) + AffiliatePartner.tally_partner_totals + partner1.reload + partner1.referral_user_count.should eq(0) + partner1.cumulative_earnings_in_cents.should eq(0) + partner2.reload + partner2.referral_user_count.should eq(0) + partner2.cumulative_earnings_in_cents.should eq(110) + + FactoryGirl.create(:affiliate_quarterly_payment, affiliate_partner:partner1, year:2015, quarter:1, due_amount_in_cents: 100, closed:true, paid:true) + AffiliatePartner.tally_partner_totals + partner1.reload + partner1.referral_user_count.should eq(0) + partner1.cumulative_earnings_in_cents.should eq(100) + partner2.reload + partner2.referral_user_count.should eq(0) + partner2.cumulative_earnings_in_cents.should eq(110) + + # a paid=false quarterly payment does not yet reflect in cumulative earnings + FactoryGirl.create(:affiliate_quarterly_payment, affiliate_partner:partner1, year:2015, quarter:2, due_amount_in_cents: 1000, closed:false, paid:false) + AffiliatePartner.tally_partner_totals + partner1.reload + partner1.referral_user_count.should eq(0) + partner1.cumulative_earnings_in_cents.should eq(100) + partner2.reload + partner2.referral_user_count.should eq(0) + partner2.cumulative_earnings_in_cents.should eq(110) + end + end + + describe "total_quarters" do + it "runs OK with no data" do + AffiliateQuarterlyPayment.count.should eq(0) + AffiliatePartner.total_quarters(2015, 0) + end + + it "totals 0 with no sales data" do + partner1.touch + partner2.touch + AffiliatePartner.ensure_quarters_exist(2015, 0) + AffiliateQuarterlyPayment.count.should eq(2) + AffiliatePartner.total_quarters(2015, 0) + quarter = partner1.quarters.first + quarter.due_amount_in_cents.should eq(0) + quarter.last_updated.should_not be_nil + quarter = partner2.quarters.first + quarter.due_amount_in_cents.should eq(0) + quarter.last_updated.should_not be_nil + end + + it "totals with sales data" do + partner1.touch + partner2.touch + + + # create a freebie for partner1 + shopping_cart = ShoppingCart.create user_partner1, jam_track, 1, true + freebie_sale = SaleLineItem.create_from_shopping_cart(sale, shopping_cart, nil, nil, nil) + freebie_sale.affiliate_referral_fee_in_cents.should eq(0) + freebie_sale.created_at = Date.new(2015, 1, 1) + freebie_sale.save! + + + + AffiliatePartner.ensure_quarters_exist(2015, 0) + AffiliateQuarterlyPayment.count.should eq(2) + AffiliatePartner.total_quarters(2015, 0) + quarter = partner1.quarters.first + quarter.due_amount_in_cents.should eq(0) + quarter.jamtracks_sold.should eq(0) + quarter = partner2.quarters.first + quarter.due_amount_in_cents.should eq(0) + quarter.jamtracks_sold.should eq(0) + + # create a real sale for partner1 + shopping_cart = ShoppingCart.create user_partner1, jam_track, 1, false + real_sale = SaleLineItem.create_from_shopping_cart(sale, shopping_cart, nil, nil, nil) + real_sale.affiliate_referral_fee_in_cents.should eq(20) + real_sale.created_at = Date.new(2015, 1, 1) + real_sale.save! + AffiliatePartner.ensure_quarters_exist(2015, 0) + AffiliatePartner.total_quarters(2015, 0) + quarter = partner1.quarters.first + quarter.due_amount_in_cents.should eq(20) + quarter.jamtracks_sold.should eq(1) + quarter = partner2.quarters.first + quarter.due_amount_in_cents.should eq(0) + quarter.jamtracks_sold.should eq(0) + + # create a real sale for partner2 + shopping_cart = ShoppingCart.create user_partner2, jam_track, 1, false + real_sale = SaleLineItem.create_from_shopping_cart(sale, shopping_cart, nil, nil, nil) + real_sale.affiliate_referral_fee_in_cents.should eq(20) + real_sale.created_at = Date.new(2015, 1, 1) + real_sale.save! + AffiliatePartner.ensure_quarters_exist(2015, 0) + AffiliatePartner.total_quarters(2015, 0) + quarter = partner1.quarters.first + quarter.due_amount_in_cents.should eq(20) + quarter.jamtracks_sold.should eq(1) + quarter = partner2.quarters.first + quarter.due_amount_in_cents.should eq(20) + quarter.jamtracks_sold.should eq(1) + + # create a real sale for partner1 + shopping_cart = ShoppingCart.create user_partner1, jam_track, 1, false + real_sale = SaleLineItem.create_from_shopping_cart(sale, shopping_cart, nil, nil, nil) + real_sale.affiliate_referral_fee_in_cents.should eq(20) + real_sale.created_at = Date.new(2015, 1, 1) + real_sale.save! + AffiliatePartner.ensure_quarters_exist(2015, 0) + AffiliatePartner.total_quarters(2015, 0) + quarter = partner1.quarters.first + quarter.due_amount_in_cents.should eq(40) + quarter.jamtracks_sold.should eq(2) + quarter = partner2.quarters.first + quarter.due_amount_in_cents.should eq(20) + quarter.jamtracks_sold.should eq(1) + + + # create a real sale for a non-affiliated user + shopping_cart = ShoppingCart.create user, jam_track, 1, false + real_sale = SaleLineItem.create_from_shopping_cart(sale, shopping_cart, nil, nil, nil) + real_sale.affiliate_referral_fee_in_cents.should be_nil + real_sale.created_at = Date.new(2015, 1, 1) + real_sale.save! + AffiliatePartner.ensure_quarters_exist(2015, 0) + AffiliatePartner.total_quarters(2015, 0) + quarter = partner1.quarters.first + quarter.due_amount_in_cents.should eq(40) + quarter.jamtracks_sold.should eq(2) + quarter = partner2.quarters.first + quarter.due_amount_in_cents.should eq(20) + quarter.jamtracks_sold.should eq(1) + + # create a real sale but in previous quarter (should no have effect on the quarter being computed) + shopping_cart = ShoppingCart.create user_partner1, jam_track, 1, false + real_sale = SaleLineItem.create_from_shopping_cart(sale, shopping_cart, nil, nil, nil) + real_sale.affiliate_referral_fee_in_cents.should eq(20) + real_sale.created_at = Date.new(2014, 12, 31) + real_sale.save! + AffiliatePartner.ensure_quarters_exist(2015, 0) + AffiliatePartner.total_quarters(2015, 0) + quarter = partner1.quarters.first + quarter.due_amount_in_cents.should eq(40) + quarter.jamtracks_sold.should eq(2) + quarter = partner2.quarters.first + quarter.due_amount_in_cents.should eq(20) + quarter.jamtracks_sold.should eq(1) + + # create a real sale but in later quarter (should no have effect on the quarter being computed) + shopping_cart = ShoppingCart.create user_partner1, jam_track, 1, false + real_sale = SaleLineItem.create_from_shopping_cart(sale, shopping_cart, nil, nil, nil) + real_sale.affiliate_referral_fee_in_cents.should eq(20) + real_sale.created_at = Date.new(2015, 4, 1) + real_sale.save! + real_sale_later = real_sale + AffiliatePartner.ensure_quarters_exist(2015, 0) + AffiliatePartner.total_quarters(2015, 0) + quarter = partner1.quarters.first + quarter.due_amount_in_cents.should eq(40) + quarter.jamtracks_sold.should eq(2) + quarter = partner2.quarters.first + quarter.due_amount_in_cents.should eq(20) + quarter.jamtracks_sold.should eq(1) + + # create a real sale but then refund it + shopping_cart = ShoppingCart.create user_partner1, jam_track, 1, false + real_sale = SaleLineItem.create_from_shopping_cart(sale, shopping_cart, nil, nil, nil) + real_sale.affiliate_referral_fee_in_cents.should eq(20) + real_sale.created_at = Date.new(2015, 3, 31) + real_sale.save! + AffiliatePartner.ensure_quarters_exist(2015, 0) + AffiliatePartner.total_quarters(2015, 0) + quarter = partner1.quarters.first + quarter.due_amount_in_cents.should eq(60) + quarter.jamtracks_sold.should eq(3) + quarter = partner2.quarters.first + quarter.due_amount_in_cents.should eq(20) + # now refund it + real_sale.affiliate_refunded_at = Date.new(2015, 3, 1) + real_sale.affiliate_refunded = true + real_sale.save! + AffiliatePartner.ensure_quarters_exist(2015, 0) + AffiliatePartner.total_quarters(2015, 0) + quarter = partner1.quarters.first + quarter.due_amount_in_cents.should eq(40) + quarter = partner2.quarters.first + quarter.due_amount_in_cents.should eq(20) + quarter.jamtracks_sold.should eq(1) + + + # create the 2nd quarter, which should add up the sale created a few bits up + AffiliatePartner.ensure_quarters_exist(2015, 1) + AffiliatePartner.total_quarters(2015, 1) + payment = AffiliateQuarterlyPayment.find_by_quarter_and_year_and_affiliate_partner_id!(1, 2015, partner1.id) + payment.due_amount_in_cents.should eq(20) + + # and now refund it in the 3rd quarter + real_sale_later.affiliate_refunded_at = Date.new(2015, 7, 1) + real_sale_later.affiliate_refunded = true + real_sale_later.save! + AffiliatePartner.total_quarters(2015, 1) + payment = AffiliateQuarterlyPayment.find_by_quarter_and_year_and_affiliate_partner_id!(1, 2015, partner1.id) + payment.due_amount_in_cents.should eq(20) + payment.jamtracks_sold.should eq(1) + + # now catch the one refund in the 3rd quarter + AffiliatePartner.ensure_quarters_exist(2015, 2) + AffiliatePartner.total_quarters(2015, 2) + payment = AffiliateQuarterlyPayment.find_by_quarter_and_year_and_affiliate_partner_id!(2, 2015, partner1.id) + payment.due_amount_in_cents.should eq(-20) + payment.jamtracks_sold.should eq(-1) + + end + end + + describe "tally_up complete" do + it "runs OK with no data" do + AffiliatePartner.tally_up(Date.new(2015, 1, 1)) + end + + it "successive runs" do + GenericState.singleton.affiliate_tallied_at.should be_nil + AffiliatePartner.tally_up(Date.new(2015, 1, 1)) + GenericState.singleton.affiliate_tallied_at.should_not be_nil + AffiliateQuarterlyPayment.count.should eq(0) + + # partner is created + partner1.touch + + AffiliatePartner.tally_up(Date.new(2015, 1, 1)) + AffiliateQuarterlyPayment.count.should eq(2) + AffiliateMonthlyPayment.count.should eq(6) + + quarter_previous = AffiliateQuarterlyPayment.find_by_quarter_and_year_and_affiliate_partner_id!(3, 2014, partner1.id) + quarter_previous.due_amount_in_cents.should eq(0) + quarter_previous.closed.should be_true + quarter = AffiliateQuarterlyPayment.find_by_quarter_and_year_and_affiliate_partner_id!(0, 2015, partner1.id) + quarter.due_amount_in_cents.should eq(0) + quarter.closed.should be_false + + month_previous= AffiliateMonthlyPayment.find_by_month_and_year_and_affiliate_partner_id!(10, 2014, partner1.id) + month_previous.due_amount_in_cents.should eq(0) + month_previous.closed.should be_true + month_previous.jamtracks_sold.should eq(0) + month_previous= AffiliateMonthlyPayment.find_by_month_and_year_and_affiliate_partner_id!(11, 2014, partner1.id) + month_previous.due_amount_in_cents.should eq(0) + month_previous.closed.should be_true + month_previous.jamtracks_sold.should eq(0) + month_previous= AffiliateMonthlyPayment.find_by_month_and_year_and_affiliate_partner_id!(12, 2014, partner1.id) + month_previous.due_amount_in_cents.should eq(0) + month_previous.closed.should be_true + month_previous.jamtracks_sold.should eq(0) + month = AffiliateMonthlyPayment.find_by_month_and_year_and_affiliate_partner_id!(1, 2015, partner1.id) + month_previous.due_amount_in_cents.should eq(0) + month_previous.closed.should be_true + month_previous.jamtracks_sold.should eq(0) + month = AffiliateMonthlyPayment.find_by_month_and_year_and_affiliate_partner_id!(2, 2015, partner1.id) + month_previous.due_amount_in_cents.should eq(0) + month_previous.closed.should be_true + month.jamtracks_sold.should eq(0) + month = AffiliateMonthlyPayment.find_by_month_and_year_and_affiliate_partner_id!(3, 2015, partner1.id) + month_previous.due_amount_in_cents.should eq(0) + month_previous.closed.should be_true + month_previous.jamtracks_sold.should eq(0) + + + shopping_cart = ShoppingCart.create user_partner1, jam_track, 1, false + real_sale = SaleLineItem.create_from_shopping_cart(sale, shopping_cart, nil, nil, nil) + real_sale.affiliate_referral_fee_in_cents.should eq(20) + real_sale.created_at = Date.new(2015, 4, 1) + real_sale.save! + + AffiliatePartner.tally_up(Date.new(2015, 4, 1)) + AffiliateQuarterlyPayment.count.should eq(3) + quarter = AffiliateQuarterlyPayment.find_by_quarter_and_year_and_affiliate_partner_id!(0, 2015, partner1.id) + quarter.due_amount_in_cents.should eq(0) + quarter.jamtracks_sold.should eq(0) + quarter.closed.should be_true + quarter2 = AffiliateQuarterlyPayment.find_by_quarter_and_year_and_affiliate_partner_id!(1, 2015, partner1.id) + quarter2.due_amount_in_cents.should eq(20) + quarter2.jamtracks_sold.should eq(1) + quarter2.closed.should be_false + + month = AffiliateMonthlyPayment.find_by_month_and_year_and_affiliate_partner_id!(1, 2015, partner1.id) + month.due_amount_in_cents.should eq(0) + month.jamtracks_sold.should eq(0) + month.closed.should be_true + month = AffiliateMonthlyPayment.find_by_month_and_year_and_affiliate_partner_id!(2, 2015, partner1.id) + month.due_amount_in_cents.should eq(0) + month.jamtracks_sold.should eq(0) + month.closed.should be_true + month = AffiliateMonthlyPayment.find_by_month_and_year_and_affiliate_partner_id!(3, 2015, partner1.id) + month.due_amount_in_cents.should eq(0) + month.jamtracks_sold.should eq(0) + month.closed.should be_true + month = AffiliateMonthlyPayment.find_by_month_and_year_and_affiliate_partner_id!(4, 2015, partner1.id) + month.due_amount_in_cents.should eq(20) + month.jamtracks_sold.should eq(1) + month.closed.should be_false + month = AffiliateMonthlyPayment.find_by_month_and_year_and_affiliate_partner_id!(5, 2015, partner1.id) + month.due_amount_in_cents.should eq(0) + month.jamtracks_sold.should eq(0) + month.closed.should be_false + month = AffiliateMonthlyPayment.find_by_month_and_year_and_affiliate_partner_id!(6, 2015, partner1.id) + month.due_amount_in_cents.should eq(0) + month.jamtracks_sold.should eq(0) + month.closed.should be_false + + # now sneak in a purchase in the 1st quarter, which makes no sense, but proves that closed quarters are not touched + + shopping_cart = ShoppingCart.create user_partner1, jam_track, 1, false + real_sale = SaleLineItem.create_from_shopping_cart(sale, shopping_cart, nil, nil, nil) + real_sale.affiliate_referral_fee_in_cents.should eq(20) + real_sale.created_at = Date.new(2015, 1, 1) + real_sale.save! + + AffiliatePartner.tally_up(Date.new(2015, 4, 2)) + quarter = AffiliateQuarterlyPayment.find_by_quarter_and_year_and_affiliate_partner_id!(0, 2015, partner1.id) + quarter.due_amount_in_cents.should eq(0) + quarter.jamtracks_sold.should eq(0) + quarter.closed.should be_true + + month = AffiliateMonthlyPayment.find_by_month_and_year_and_affiliate_partner_id!(1, 2015, partner1.id) + month.due_amount_in_cents.should eq(0) + month.closed.should be_true + month = AffiliateMonthlyPayment.find_by_month_and_year_and_affiliate_partner_id!(2, 2015, partner1.id) + month.due_amount_in_cents.should eq(0) + month.jamtracks_sold.should eq(0) + month.closed.should be_true + month = AffiliateMonthlyPayment.find_by_month_and_year_and_affiliate_partner_id!(3, 2015, partner1.id) + month.due_amount_in_cents.should eq(0) + month.jamtracks_sold.should eq(0) + month.closed.should be_true + end + end + + describe "tally_traffic_totals" do + + it "runs OK with no data" do + AffiliatePartner.tally_traffic_totals(Date.yesterday, Date.today) + end + + it "can deal with simple signup case" do + user_partner1.touch + + day0 = user_partner1.created_at.to_date + + # simulate what happens when this scheduled job first ever runs + AffiliatePartner.tally_traffic_totals(nil, day0) + AffiliateTrafficTotal.count.should eq(1) + traffic_total_day_before = AffiliateTrafficTotal.find_by_day_and_affiliate_partner_id(day0 - 1, user_partner1.affiliate_referral_id) + traffic_total_day_before.visits.should eq(0) + traffic_total_day_before.signups.should eq(0) + + # then simulate when it runs on the same day as it ran on the day before + AffiliatePartner.tally_traffic_totals(day0, day0) + AffiliateTrafficTotal.count.should eq(1) + traffic_total_day_before = AffiliateTrafficTotal.find_by_day_and_affiliate_partner_id(day0 - 1, user_partner1.affiliate_referral_id) + traffic_total_day_before.visits.should eq(0) + traffic_total_day_before.signups.should eq(0) + + # now run it on the next day, which should catch the signup event + + day1 = day0 + 1 + AffiliatePartner.tally_traffic_totals(day0, day1) + AffiliateTrafficTotal.count.should eq(2) + traffic_total_day_before = AffiliateTrafficTotal.find_by_day_and_affiliate_partner_id(day0 - 1, user_partner1.affiliate_referral_id) + traffic_total_day_before.visits.should eq(0) + traffic_total_day_before.signups.should eq(0) + traffic_total_day0 = AffiliateTrafficTotal.find_by_day_and_affiliate_partner_id(day0, user_partner1.affiliate_referral_id) + traffic_total_day0.visits.should eq(0) + traffic_total_day0.signups.should eq(1) + + # add in a visit + visit = FactoryGirl.create(:affiliate_referral_visit, affiliate_partner: user_partner1.affiliate_referral) + + # it won't get seen though because we've moved on + AffiliatePartner.tally_traffic_totals(day1, day1) + AffiliateTrafficTotal.count.should eq(2) + traffic_total_day_before = AffiliateTrafficTotal.find_by_day_and_affiliate_partner_id(day0 - 1, user_partner1.affiliate_referral_id) + traffic_total_day_before.visits.should eq(0) + traffic_total_day_before.signups.should eq(0) + traffic_total_day0 = AffiliateTrafficTotal.find_by_day_and_affiliate_partner_id(day0, user_partner1.affiliate_referral_id) + traffic_total_day0.visits.should eq(0) + traffic_total_day0.signups.should eq(1) + + # manipulate the visit created_at so we can record it + visit.created_at = day1 + visit.save! + day2 = day1 + 1 + AffiliatePartner.tally_traffic_totals(day1, day2) + AffiliateTrafficTotal.count.should eq(3) + traffic_total_day_before = AffiliateTrafficTotal.find_by_day_and_affiliate_partner_id(day0 - 1, user_partner1.affiliate_referral_id) + traffic_total_day_before.visits.should eq(0) + traffic_total_day_before.signups.should eq(0) + traffic_total_day0 = AffiliateTrafficTotal.find_by_day_and_affiliate_partner_id(day0, user_partner1.affiliate_referral_id) + traffic_total_day0.visits.should eq(0) + traffic_total_day0.signups.should eq(1) + traffic_total_day1 = AffiliateTrafficTotal.find_by_day_and_affiliate_partner_id(day1, user_partner1.affiliate_referral_id) + traffic_total_day1.visits.should eq(1) + traffic_total_day1.signups.should eq(0) + + # now create 2 records on day 2 for visits and signups both, and a partner with their own visit and signup, and do a final check + + user_partner2.touch + + visit2 = FactoryGirl.create(:affiliate_referral_visit, affiliate_partner: user_partner1.affiliate_referral) + visit3 = FactoryGirl.create(:affiliate_referral_visit, affiliate_partner: user_partner1.affiliate_referral) + visit_partner2 = FactoryGirl.create(:affiliate_referral_visit, affiliate_partner: user_partner2.affiliate_referral) + visit2.created_at = day2 + visit3.created_at = day2 + visit_partner2.created_at = day2 + visit2.save! + visit3.save! + visit_partner2.save! + + user2 = FactoryGirl.create(:user, affiliate_referral:user_partner1.affiliate_referral) + user3 = FactoryGirl.create(:user, affiliate_referral:user_partner1.affiliate_referral) + user2.created_at = day2 + user3.created_at = day2 + user_partner2.created_at = day2 + user2.save! + user3.save! + user_partner2.save! + + + day3 = day2 + 1 + AffiliatePartner.tally_traffic_totals(day2, day3) + AffiliateTrafficTotal.count.should eq(5) + traffic_total_day_before = AffiliateTrafficTotal.find_by_day_and_affiliate_partner_id(day0 - 1, user_partner1.affiliate_referral_id) + traffic_total_day_before.visits.should eq(0) + traffic_total_day_before.signups.should eq(0) + traffic_total_day0 = AffiliateTrafficTotal.find_by_day_and_affiliate_partner_id(day0, user_partner1.affiliate_referral_id) + traffic_total_day0.visits.should eq(0) + traffic_total_day0.signups.should eq(1) + traffic_total_day1 = AffiliateTrafficTotal.find_by_day_and_affiliate_partner_id(day1, user_partner1.affiliate_referral_id) + traffic_total_day1.visits.should eq(1) + traffic_total_day1.signups.should eq(0) + traffic_total_day2 = AffiliateTrafficTotal.find_by_day_and_affiliate_partner_id(day2, user_partner1.affiliate_referral_id) + traffic_total_day2.visits.should eq(2) + traffic_total_day2.signups.should eq(2) + traffic_total_day2 = AffiliateTrafficTotal.find_by_day_and_affiliate_partner_id(day2, user_partner2.affiliate_referral_id) + traffic_total_day2.visits.should eq(1) + traffic_total_day2.signups.should eq(1) + end + end + end + end diff --git a/ruby/spec/jam_ruby/models/affiliate_payment_spec.rb b/ruby/spec/jam_ruby/models/affiliate_payment_spec.rb new file mode 100644 index 000000000..14f9f4c13 --- /dev/null +++ b/ruby/spec/jam_ruby/models/affiliate_payment_spec.rb @@ -0,0 +1,39 @@ +require 'spec_helper' + +describe AffiliatePayment do + + let(:partner) { FactoryGirl.create(:affiliate_partner) } + let(:user_partner) { FactoryGirl.create(:user, affiliate_partner: partner) } + + it "succeeds with no data" do + results, nex = AffiliatePayment.index(user_partner, {}) + results.length.should eq(0) + end + + it "sorts month and quarters correctly" do + monthly1 = FactoryGirl.create(:affiliate_monthly_payment, affiliate_partner: partner, closed: true, due_amount_in_cents: 10, month: 1, year: 2015) + monthly2 = FactoryGirl.create(:affiliate_monthly_payment, affiliate_partner: partner, closed: true, due_amount_in_cents: 20, month: 2, year: 2015) + monthly3 = FactoryGirl.create(:affiliate_monthly_payment, affiliate_partner: partner, closed: true, due_amount_in_cents: 30, month: 3, year: 2015) + monthly4 = FactoryGirl.create(:affiliate_monthly_payment, affiliate_partner: partner, closed: true, due_amount_in_cents: 40, month: 4, year: 2015) + quarterly = FactoryGirl.create(:affiliate_quarterly_payment, affiliate_partner: partner, closed: true, paid:true, due_amount_in_cents: 50, quarter: 0, year: 2015) + results, nex = AffiliatePayment.index(user_partner, {}) + results.length.should eq(5) + result1 = results[0] + result2 = results[1] + result3 = results[2] + result4 = results[3] + result5 = results[4] + + result1.payment_type.should eq('monthly') + result1.due_amount_in_cents.should eq(10) + result2.payment_type.should eq('monthly') + result2.due_amount_in_cents.should eq(20) + result3.payment_type.should eq('monthly') + result3.due_amount_in_cents.should eq(30) + result4.payment_type.should eq('quarterly') + result4.due_amount_in_cents.should eq(50) + result5.payment_type.should eq('monthly') + result5.due_amount_in_cents.should eq(40) + end + +end \ No newline at end of file diff --git a/ruby/spec/jam_ruby/models/affiliate_referral_visit_spec.rb b/ruby/spec/jam_ruby/models/affiliate_referral_visit_spec.rb new file mode 100644 index 000000000..467127500 --- /dev/null +++ b/ruby/spec/jam_ruby/models/affiliate_referral_visit_spec.rb @@ -0,0 +1,40 @@ +require 'spec_helper' + +describe AffiliateReferralVisit do + + let!(:user) { FactoryGirl.create(:user) } + let(:partner) { FactoryGirl.create(:affiliate_partner) } + let(:valid_track_options) { + { + affiliate_id: partner.id, + visited: false, + remote_ip: '1.2.2.1', + visited_url: '/', + referral_url: 'http://www.youtube.com', + current_user: nil + + } + } + + describe "track" do + it "succeeds" do + visit = AffiliateReferralVisit.track( valid_track_options ) + visit.valid?.should be_true + end + + it "never fails with error" do + visit = AffiliateReferralVisit.track( {}) + visit.valid?.should be_false + + options = valid_track_options + options[:affiliate_id] = 111 + visit = AffiliateReferralVisit.track( options) + visit.valid?.should be_true + + options = valid_track_options + options[:current_user] = user + visit = AffiliateReferralVisit.track( options) + visit.valid?.should be_true + end + end +end diff --git a/ruby/spec/jam_ruby/models/sale_spec.rb b/ruby/spec/jam_ruby/models/sale_spec.rb index 47dda7213..a0d4acf48 100644 --- a/ruby/spec/jam_ruby/models/sale_spec.rb +++ b/ruby/spec/jam_ruby/models/sale_spec.rb @@ -132,6 +132,69 @@ describe Sale do user.has_redeemable_jamtrack.should be_false end + it "for a free jam track with an affiliate association" do + partner = FactoryGirl.create(:affiliate_partner) + user.affiliate_referral = partner + user.save! + + shopping_cart = ShoppingCart.create user, jamtrack, 1, true + client.find_or_create_account(user, billing_info) + + sales = Sale.place_order(user, [shopping_cart]) + + user.reload + user.sales.length.should eq(1) + + sales.should eq(user.sales) + sale = sales[0] + sale.recurly_invoice_id.should be_nil + + sale.recurly_subtotal_in_cents.should eq(0) + sale.recurly_tax_in_cents.should eq(0) + sale.recurly_total_in_cents.should eq(0) + sale.recurly_currency.should eq('USD') + sale.order_total.should eq(0) + sale.sale_line_items.length.should == 1 + sale_line_item = sale.sale_line_items[0] + sale_line_item.recurly_tax_in_cents.should eq(0) + sale_line_item.recurly_total_in_cents.should eq(0) + sale_line_item.recurly_currency.should eq('USD') + sale_line_item.recurly_discount_in_cents.should eq(0) + sale_line_item.product_type.should eq(JamTrack::PRODUCT_TYPE) + sale_line_item.unit_price.should eq(jamtrack.price) + sale_line_item.quantity.should eq(1) + sale_line_item.free.should eq(1) + sale_line_item.sales_tax.should be_nil + sale_line_item.shipping_handling.should eq(0) + sale_line_item.recurly_plan_code.should eq(jamtrack.plan_code) + sale_line_item.product_id.should eq(jamtrack.id) + sale_line_item.recurly_subscription_uuid.should be_nil + sale_line_item.recurly_adjustment_uuid.should be_nil + sale_line_item.recurly_adjustment_credit_uuid.should be_nil + sale_line_item.recurly_adjustment_uuid.should eq(user.jam_track_rights.last.recurly_adjustment_uuid) + sale_line_item.recurly_adjustment_credit_uuid.should eq(user.jam_track_rights.last.recurly_adjustment_credit_uuid) + sale_line_item.affiliate_referral.should eq(partner) + sale_line_item.affiliate_referral_fee_in_cents.should eq(0) + + # verify subscription is in Recurly + recurly_account = client.get_account(user) + adjustments = recurly_account.adjustments + adjustments.should_not be_nil + adjustments.should have(0).items + + invoices = recurly_account.invoices + invoices.should have(0).items + + + # verify jam_track_rights data + user.jam_track_rights.should_not be_nil + user.jam_track_rights.should have(1).items + user.jam_track_rights.last.jam_track.id.should eq(jamtrack.id) + user.jam_track_rights.last.redeemed.should be_true + user.has_redeemable_jamtrack.should be_false + end + + it "for a normally priced jam track" do user.has_redeemable_jamtrack = false user.save! @@ -201,6 +264,85 @@ describe Sale do user.jam_track_rights.last.jam_track.id.should eq(jamtrack.id) user.jam_track_rights.last.redeemed.should be_false user.has_redeemable_jamtrack.should be_false + + sale_line_item.affiliate_referral.should be_nil + sale_line_item.affiliate_referral_fee_in_cents.should be_nil + end + + + it "for a normally priced jam track with an affiliate association" do + user.has_redeemable_jamtrack = false + partner = FactoryGirl.create(:affiliate_partner) + user.affiliate_referral = partner + user.save! + shopping_cart = ShoppingCart.create user, jamtrack, 1, false + client.find_or_create_account(user, billing_info) + + sales = Sale.place_order(user, [shopping_cart]) + + user.reload + user.sales.length.should eq(1) + + sales.should eq(user.sales) + sale = sales[0] + sale.recurly_invoice_id.should_not be_nil + + sale.recurly_subtotal_in_cents.should eq(jam_track_price_in_cents) + sale.recurly_tax_in_cents.should eq(0) + sale.recurly_total_in_cents.should eq(jam_track_price_in_cents) + sale.recurly_currency.should eq('USD') + + sale.order_total.should eq(jamtrack.price) + sale.sale_line_items.length.should == 1 + sale_line_item = sale.sale_line_items[0] + # validate we are storing pricing info from recurly + sale_line_item.recurly_tax_in_cents.should eq(0) + sale_line_item.recurly_total_in_cents.should eq(jam_track_price_in_cents) + sale_line_item.recurly_currency.should eq('USD') + sale_line_item.recurly_discount_in_cents.should eq(0) + sale_line_item.product_type.should eq(JamTrack::PRODUCT_TYPE) + sale_line_item.unit_price.should eq(jamtrack.price) + sale_line_item.quantity.should eq(1) + sale_line_item.free.should eq(0) + sale_line_item.sales_tax.should be_nil + sale_line_item.shipping_handling.should eq(0) + sale_line_item.recurly_plan_code.should eq(jamtrack.plan_code) + sale_line_item.product_id.should eq(jamtrack.id) + sale_line_item.recurly_subscription_uuid.should be_nil + sale_line_item.recurly_adjustment_uuid.should_not be_nil + sale_line_item.recurly_adjustment_credit_uuid.should be_nil + sale_line_item.recurly_adjustment_uuid.should eq(user.jam_track_rights.last.recurly_adjustment_uuid) + sale_line_item.affiliate_referral.should eq(partner) + sale_line_item.affiliate_referral_fee_in_cents.should eq(20) + + # verify subscription is in Recurly + recurly_account = client.get_account(user) + adjustments = recurly_account.adjustments + adjustments.should_not be_nil + adjustments.should have(1).items + purchase= adjustments[0] + purchase.unit_amount_in_cents.should eq((jamtrack.price * 100).to_i) + purchase.accounting_code.should eq(ShoppingCart::PURCHASE_NORMAL) + purchase.description.should eq("JamTrack: " + jamtrack.name) + purchase.state.should eq('invoiced') + purchase.uuid.should eq(sale_line_item.recurly_adjustment_uuid) + + invoices = recurly_account.invoices + invoices.should have(1).items + invoice = invoices[0] + invoice.uuid.should eq(sale.recurly_invoice_id) + invoice.line_items.should have(1).items # should have single adjustment associated + invoice.line_items[0].should eq(purchase) + invoice.subtotal_in_cents.should eq((jamtrack.price * 100).to_i) + invoice.total_in_cents.should eq((jamtrack.price * 100).to_i) + invoice.state.should eq('collected') + + # verify jam_track_rights data + user.jam_track_rights.should_not be_nil + user.jam_track_rights.should have(1).items + user.jam_track_rights.last.jam_track.id.should eq(jamtrack.id) + user.jam_track_rights.last.redeemed.should be_false + user.has_redeemable_jamtrack.should be_false end it "for a jamtrack already owned" do diff --git a/web/app/assets/images/content/agree_button.png b/web/app/assets/images/content/agree_button.png new file mode 100644 index 0000000000000000000000000000000000000000..b30ecf4805d64b4bd71f51c91ff6eb276586e9fa GIT binary patch literal 13570 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 IM6N<$f*IJVk^lez literal 0 HcmV?d00001 diff --git a/web/app/assets/images/content/disagree_button.png b/web/app/assets/images/content/disagree_button.png new file mode 100644 index 0000000000000000000000000000000000000000..9054b08fe263a27d634cbf335bf2a2b4bd7ae41f GIT binary patch literal 15683 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 literal 0 HcmV?d00001 diff --git a/web/app/assets/javascripts/accounts.js b/web/app/assets/javascripts/accounts.js index 8c5ccbabe..3d52d2139 100644 --- a/web/app/assets/javascripts/accounts.js +++ b/web/app/assets/javascripts/accounts.js @@ -8,10 +8,10 @@ var rest = context.JK.Rest(); var userId; var user = {}; + var screen = null; var gearUtils = context.JK.GearUtilsInstance; function beforeShow(data) { - console.log("beforeShow", data) userId = data.id; } @@ -71,8 +71,11 @@ invalidProfiles : invalidProfiles, isNativeClient: gon.isNativeClient, musician: context.JK.currentUserMusician, - webcamName: webcamName, - sales_count: userDetail.sales_count + sales_count: userDetail.sales_count, + is_affiliate_partner: userDetail.is_affiliate_partner, + affiliate_earnings: (userDetail.affiliate_earnings / 100).toFixed(2), + affiliate_referral_count: userDetail.affiliate_referral_count, + webcamName: webcamName } , { variable: 'data' })); $('#account-content-scroller').html($template); @@ -135,6 +138,7 @@ $('#account-content-scroller').on('avatar_changed', '#profile-avatar', function(evt, newAvatarUrl) { evt.stopPropagation(); updateAvatar(newAvatarUrl); return false; }) $("#account-content-scroller").on('click', '#account-payment-history-link', function(evt) {evt.stopPropagation(); navToPaymentHistory(); return false; } ); + $("#account-content-scroller").on('click', '#account-affiliate-partner-link', function(evt) {evt.stopPropagation(); navToAffiliates(); return false; } ); } function renderAccount() { @@ -187,6 +191,11 @@ window.location = '/client#/account/paymentHistory' } + function navToAffiliates() { + resetForm() + window.location = '/client#/account/affiliatePartner' + } + // handle update avatar event function updateAvatar(avatar_url) { var photoUrl = context.JK.resolveAvatarUrl(avatar_url); @@ -203,7 +212,7 @@ } function initialize() { - + screen = $('#account-content-scroller'); var screenBindings = { 'beforeShow': beforeShow, 'afterShow': afterShow @@ -218,4 +227,4 @@ return this; }; -})(window,jQuery); \ No newline at end of file +})(window,jQuery); diff --git a/web/app/assets/javascripts/accounts_affiliate.js b/web/app/assets/javascripts/accounts_affiliate.js new file mode 100644 index 000000000..21d0b8b1c --- /dev/null +++ b/web/app/assets/javascripts/accounts_affiliate.js @@ -0,0 +1,324 @@ +(function (context, $) { + + "use strict"; + + context.JK = context.JK || {}; + context.JK.AccountAffiliateScreen = function (app) { + var logger = context.JK.logger; + var rest = context.JK.Rest(); + var userId; + var user = {}; + var affiliatePartnerTabs = ['account', 'agreement', 'signups', 'earnings']; + var affiliatePartnerData = null; + var $screen = null; + + function beforeShow(data) { + userId = data.id; + affiliatePartnerData = null; + } + + function afterShow(data) { + + rest.getAffiliatePartnerData(userId) + .done(function (response) { + affiliatePartnerData = response; + renderAffiliateTab('account') + }) + .fail(app.ajaxError) + + } + + function events() { + + // Affiliate Partner + $("#account-affiliate-partner-content-scroller").on('click', '#affiliate-partner-account-link', function (evt) { + evt.stopPropagation(); + renderAffiliateTab('account'); + return false; + }); + $("#account-affiliate-partner-content-scroller").on('click', '#affiliate-partner-links-link', function (evt) { + evt.stopPropagation(); + renderAffiliateTab('links'); + return false; + }); + $("#account-affiliate-partner-content-scroller").on('click', '#affiliate-partner-agreement-link', function (evt) { + evt.stopPropagation(); + renderAffiliateTab('agreement'); + return false; + }); + $("#account-affiliate-partner-content-scroller").on('click', '#affiliate-partner-signups-link', function (evt) { + evt.stopPropagation(); + renderAffiliateTab('signups'); + return false; + }); + $("#account-affiliate-partner-content-scroller").on('click', '#affiliate-partner-earnings-link', function (evt) { + evt.stopPropagation(); + renderAffiliateTab('earnings'); + return false; + }); + $("#account-affiliate-partner-content-scroller").on('click', '#affiliate-profile-account-submit', function (evt) { + evt.stopPropagation(); + handleUpdateAffiliateAccount(); + return false; + }); + } + + function _renderAffiliateTableSignups(rows) { + rest.getAffiliateSignups() + .done(onAffiliateSignups) + .fail(app.ajaxError) + } + + function _renderAffiliateTableEarnings(rows) { + rest.getAffiliatePayments() + .done(onAffiliatePayments) + .fail(app.ajaxError) + } + + function _renderAffiliateTableLinks(rows) { + $screen.find('.affiliate-agreement').on('click', function () { + renderAffiliateTab('agreement'); + return false; + }) + + $screen.find('.affiliate-link-page').attr('href', '/affiliate/links/' + affiliatePartnerData.account.id) + + $screen.find('select.link_type').easyDropDown(); + + var $linkType = $screen.find('.link_type') + + $linkType.on('change', function() { + logger.debug("link type changed") + updateLinks(); + }) + + updateLinks(); + } + + function onAffiliateSignups(signups) { + + var $table = $screen.find('table.traffic-table tbody') + $table.empty(); + + var template = $('#template-affiliate-partner-signups-row').html(); + context._.each(signups.traffics, function(item) { + var $link = $(context._.template(template, item, {variable: 'data'})); + + var $day = $link.find('td.day') + + var day = $day.text(); + var bits = day.split('-') + if(bits.length == 3) { + $day.text(context.JK.getMonth(new Number(bits[1]) - 1) + ' ' + new Number(bits[2])) + } + + $table.append($link) + }) + } + + function onAffiliatePayments(payments) { + var $table = $screen.find('table.payment-table tbody') + $table.empty(); + + var template = $('#template-affiliate-partner-earnings-row').html(); + context._.each(payments.payments, function(item) { + + var data = {} + if(item.payment_type == 'quarterly') { + + if(item.quarter == 0) { + data.time = '1st Quarter ' + item.year + } + else if(item.quarter == 1) { + data.time = '2nd Quarter ' + item.year + } + else if(item.quarter == 2) { + data.time = '3rd Quarter ' + item.year + } + else if(item.quarter == 3) { + data.time = '4th Quarter ' + item.year + } + + data.sold = '' + + if(item.paid) { + data.earnings = 'PAID $' + (item.due_amount_in_cents / 100).toFixed(2); + } + else { + data.earnings = 'No earning were paid, as the $10 minimum threshold was not reached.' + } + } + else { + data.time = context.JK.getMonth(item.month - 1) + ' ' + item.year; + if(item.jamtracks_sold == 1) { + data.sold = 'JamTracks: ' + item.jamtracks_sold + ' unit sold'; + } + else { + data.sold = 'JamTracks: ' + item.jamtracks_sold + ' units sold'; + } + data.earnings = '$' + (item.due_amount_in_cents / 100).toFixed(2); + } + + + var $earning = $(context._.template(template, data, {variable: 'data'})); + + $table.append($earning) + }) + } + + + function updateLinks() { + var $select = $screen.find('select.link_type') + var value = $select.val() + + logger.debug("value: " + value) + + var type = 'jamtrack_songs'; + if(value == 'JamTrack Song') { + type = 'jamtrack_songs' + } + else if(value == 'JamTrack Band') { + type = 'jamtrack_bands' + } + else if(value == 'JamTrack General') { + type = 'jamtrack_general' + } + else if(value == 'JamKazam General') { + type = 'jamkazam' + } + else if(value == 'JamKazam Session') { + type = 'sessions' + } + else if(value == 'JamKazam Recording') { + type = 'recordings' + } + else if(value == 'Custom Link') { + type = 'custom_links' + } + + $screen.find('.link-type-prompt').hide(); + $screen.find('.link-type-prompt[data-type="' + type + '"]').show(); + + if(type == 'custom_links') { + $screen.find('table.links-table').hide(); + $screen.find('.link-type-prompt[data-type="custom_links"] span.affiliate_id').text(affiliatePartnerData.account.id) + } + else { + rest.getLinks(type) + .done(populateLinkTable) + .fail(function() { + app.notify({message: 'Unable to fetch links. Please try again later.' }) + }) + } + } + + function _renderAffiliateTab(theTab) { + affiliateTabRefresh(theTab); + var template = $('#template-affiliate-partner-' + theTab).html(); + var tabHtml = context._.template(template, affiliatePartnerData[theTab], {variable: 'data'}); + $('#affiliate-partner-tab-content').html(tabHtml); + + if (theTab == 'signups') { + _renderAffiliateTableSignups(affiliatePartnerData[theTab]); + } else if (theTab == 'earnings') { + _renderAffiliateTableEarnings(affiliatePartnerData[theTab]); + } else if (theTab == 'links') { + _renderAffiliateTableLinks(affiliatePartnerData[theTab]); + } + } + + function renderAffiliateTab(theTab) { + if (affiliatePartnerData) { + return _renderAffiliateTab(theTab); + } + rest.getAffiliatePartnerData(userId) + .done(function (response) { + affiliatePartnerData = response; + _renderAffiliateTab(theTab); + }) + .fail(app.ajaxError) + } + + function affiliateTabRefresh(selectedTab) { + var container = $('#account-affiliate-partner-content-scroller'); + container.find('.affiliate-partner-nav a.active').removeClass('active'); + if (selectedTab) { + container.find('.affiliate-partner-' + selectedTab).show(); + $.each(affiliatePartnerTabs, function (index, val) { + if (val != selectedTab) { + container.find('.affiliate-partner-' + val).hide(); + } + }); + container.find('.affiliate-partner-nav a#affiliate-partner-' + selectedTab + '-link').addClass('active'); + } else { + $.each(affiliatePartnerTabs, function (index, val) { + container.find('.affiliate-partner-' + val).hide(); + }); + container.find('.affiliate-partner-nav a#affiliate-partner-' + affiliatePartnerTabs[0] + '-link').addClass('active'); + } + } + + function handleUpdateAffiliateAccount() { + var tab_content = $('#affiliate-partner-tab-content'); + var affiliate_partner_data = { + 'address': { + 'address1': tab_content.find('#affiliate_partner_address1').val(), + 'address2': tab_content.find('#affiliate_partner_address2').val(), + 'city': tab_content.find('#affiliate_partner_city').val(), + 'state': tab_content.find('#affiliate_partner_state').val(), + 'postal_code': tab_content.find('#affiliate_partner_postal_code').val(), + 'country': tab_content.find('#affiliate_partner_country').val() + }, + 'tax_identifier': tab_content.find('#affiliate_partner_tax_identifier').val() + } + rest.postAffiliatePartnerData(userId, affiliate_partner_data) + .done(postUpdateAffiliateAccountSuccess); + } + + function postUpdateAffiliateAccountSuccess(response) { + app.notify( + { + title: "Affiliate Account", + text: "You have updated your affiliate partner data successfully." + }, + null, true); + } + + function populateLinkTable(response) { + $screen.find('table.links-table').show(); + var $linkTable = $screen.find('.links-table tbody') + + $linkTable.empty(); + var template = $('#template-affiliate-link-entry').html(); + context._.each(response, function(item) { + var $link = $(context._.template(template, item, {variable: 'data'})); + $link.find('td.copy-link a').click(copyLink) + $linkTable.append($link) + }) + } + + function copyLink() { + var element = $(this); + var $url = element.closest('tr').find('td.url input') + $url.select() + + return false; + } + + function initialize() { + var screenBindings = { + 'beforeShow': beforeShow, + 'afterShow': afterShow + }; + app.bindScreen('account/affiliatePartner', screenBindings); + $screen = $('#account-affiliate-partner') + events(); + } + + this.initialize = initialize; + this.beforeShow = beforeShow; + this.afterShow = afterShow; + return this; + }; + +})(window, jQuery); diff --git a/web/app/assets/javascripts/dialog/banner.js b/web/app/assets/javascripts/dialog/banner.js index 7e0fc0f12..2c777c0f0 100644 --- a/web/app/assets/javascripts/dialog/banner.js +++ b/web/app/assets/javascripts/dialog/banner.js @@ -133,20 +133,25 @@ if(options.buttons) { context._.each(options.buttons, function(button, i) { if(!button.name) throw "button.name must be specified"; - if(!button.click) throw "button.click must be specified"; + if(!button.click && !button.href) throw "button.click or button.href must be specified"; var buttonStyle = button.buttonStyle; if(!buttonStyle) { buttonStyle = options.buttons.length == i + 1 ? 'button-orange' : 'button-grey'; } - var $btn = $('' + button.name + ''); - $btn.click(function() { - button.click(); - hide(); - return false; - }); + + if(button.href) { + $btn.attr('href', button.href) + } + else { + $btn.click(function() { + button.click(); + hide(); + return false; + }); + } $buttons.append($btn); }); } diff --git a/web/app/assets/javascripts/jam_rest.js b/web/app/assets/javascripts/jam_rest.js index ffccd50d4..c47f27280 100644 --- a/web/app/assets/javascripts/jam_rest.js +++ b/web/app/assets/javascripts/jam_rest.js @@ -485,6 +485,80 @@ return detail; } + function createAffiliatePartner(options) { + return $.ajax({ + type: "POST", + url: '/api/affiliate_partners', + dataType: "json", + contentType: 'application/json', + data: JSON.stringify(options) + }) + } + + function getAffiliatePartnerData(userId) { + return $.ajax({ + type: "GET", + dataType: "json", + url: "/api/users/"+userId+"/affiliate_partner" + }); + } + + function postAffiliatePartnerData(userId, data) { + return $.ajax({ + type: "POST", + dataType: "json", + url: "/api/users/"+userId+"/affiliate_partner", + contentType: 'application/json', + processData:false, + data: JSON.stringify(data) + }); + } + + function getLinks(type, partner_id) { + var url = "/api/links/" + type; + + if(partner_id) { + url += '?affiliate_id=' + partner_id; + } + return $.ajax({ + type: "GET", + dataType: "json", + url: url + }); + } + + function getAffiliateSignups() { + return $.ajax({ + type: "GET", + dataType: "json", + url: "/api/affiliate_partners/signups" + }); + } + + function getAffiliateMonthly() { + return $.ajax({ + type: "GET", + dataType: "json", + url: "/api/affiliate_partners/monthly_earnings" + }); + } + + function getAffiliateQuarterly() { + return $.ajax({ + type: "GET", + dataType: "json", + url: "/api/affiliate_partners/quarterly_earnings" + }); + } + + function getAffiliatePayments() { + return $.ajax({ + type: "GET", + dataType: "json", + url: "/api/affiliate_partners/payments" + }); + } + function getCities(options) { var country = options['country'] var region = options['region'] @@ -1711,6 +1785,14 @@ this.cancelSession = cancelSession; this.updateScheduledSession = updateScheduledSession; this.getUserDetail = getUserDetail; + this.getAffiliatePartnerData = getAffiliatePartnerData; + this.postAffiliatePartnerData = postAffiliatePartnerData; + this.createAffiliatePartner = createAffiliatePartner; + this.getLinks = getLinks; + this.getAffiliateSignups = getAffiliateSignups; + this.getAffiliateMonthly = getAffiliateMonthly; + this.getAffiliateQuarterly = getAffiliateQuarterly; + this.getAffiliatePayments = getAffiliatePayments; this.getCities = getCities; this.getRegions = getRegions; this.getCountries = getCountries; @@ -1853,4 +1935,4 @@ }; -})(window,jQuery); \ No newline at end of file +})(window,jQuery); diff --git a/web/app/assets/javascripts/landing/signup.js b/web/app/assets/javascripts/landing/signup.js index a91329222..0eec67cf4 100644 --- a/web/app/assets/javascripts/landing/signup.js +++ b/web/app/assets/javascripts/landing/signup.js @@ -156,6 +156,9 @@ submit_data.city = $('#jam_ruby_user_city').val() submit_data.birth_date = gather_birth_date() submit_data.instruments = gather_instruments() + if($.QueryString['affiliate_partner_id']) { + submit_data.affiliate_partner_id = $.QueryString['affiliate_partner_id']; + } //submit_data.photo_url = $('#jam_ruby_user_instruments').val() diff --git a/web/app/assets/javascripts/utils.js b/web/app/assets/javascripts/utils.js index 62addc9e4..cd44c1a76 100644 --- a/web/app/assets/javascripts/utils.js +++ b/web/app/assets/javascripts/utils.js @@ -627,6 +627,10 @@ return (suppressDay ? '' : (days[date.getDay()] + ' ')) + months[date.getMonth()] + ' ' + context.JK.padString(date.getDate(), 2) + ', ' + date.getFullYear(); } + // returns June for months 0-11 + context.JK.getMonth = function(monthNumber) { + return months[monthNumber]; + } context.JK.formatDateYYYYMMDD = function(dateString) { var date = new Date(dateString); diff --git a/web/app/assets/javascripts/web/affiliate_links.js.coffee b/web/app/assets/javascripts/web/affiliate_links.js.coffee new file mode 100644 index 000000000..be15b3e5a --- /dev/null +++ b/web/app/assets/javascripts/web/affiliate_links.js.coffee @@ -0,0 +1,55 @@ + + +$ = jQuery +context = window +context.JK ||= {}; + +class AffiliateLinks + constructor: (@app, @partner_id) -> + @logger = context.JK.logger + @rest = new context.JK.Rest(); + + initialize: () => + @page = $('body') + @sections = ['jamtrack_songs', 'jamtrack_bands', 'jamtrack_general', 'jamkazam', 'sessions', 'recordings'] + @jamtrack_songs = @page.find('table.jamtrack_songs tbody') + @jamtrack_bands = @page.find('table.jamtrack_bands tbody') + @jamtrack_general = @page.find('table.jamtrack_general tbody') + @jamkazam = @page.find('table.jamkazam tbody') + @sessions= @page.find('table.sessions tbody') + @recordings = @page.find('table.recordings tbody') + + @iterate() + + onGetLinks: (links) => + + $table = @page.find('table.' + @section + ' tbody') + template = $('#template-affiliate-link-row').html(); + context._.each(links, (item) => + $link = $(context._.template(template, item, {variable: 'data'})); + $link.find('td.copy-link a').click(@copyLink) + $table.append($link) + ) + + if @sections.length > 0 + @iterate() + + + copyLink: () -> + $element = $(this) + $url = $element.closest('tr').find('td.url input') + $url.select() + + return false; + + + iterate: () => + @section = @sections.shift() + + @rest.getLinks(@section, @partner_id) + .done(@onGetLinks) + + + +context.JK.AffiliateLinks = AffiliateLinks + diff --git a/web/app/assets/javascripts/web/affiliate_program.js.coffee b/web/app/assets/javascripts/web/affiliate_program.js.coffee new file mode 100644 index 000000000..c013abbf2 --- /dev/null +++ b/web/app/assets/javascripts/web/affiliate_program.js.coffee @@ -0,0 +1,119 @@ + + +$ = jQuery +context = window +context.JK ||= {}; + +class AffiliateProgram + constructor: (@app) -> + @logger = context.JK.logger + @rest = new context.JK.Rest(); + @agreeBtn = null + @disagreeBtn = null + @entityForm = null + @disagreeNotice = null + @entityName = null + @entityType = null + @entityRadio = null + @fieldEntityName = null + @fieldEntityType = null + @entityOptions = null + + removeErrors: () => + @fieldEntityName.removeClass('error').find('.error-info').remove(); + @fieldEntityType.removeClass('error').find('.error-info').remove(); + @entityOptions.removeClass('error').find('.error-info').remove(); + + onRadioChanged: () => + @removeErrors() + value = @page.find('input:radio[name="entity"]:checked').val() + + if value == 'individual' + @entityForm.slideUp() + else + @entityForm.slideDown() + + return false + + + onCreatedAffiliatePartner:(response) => + if response.partner_user_id? + # this was an existing user, so tell them to go on in + context.JK.Banner.show({buttons: [{name: 'GO TO AFFILIATE PAGE', href: '/client#/account/affiliatePartner'}], title: 'congratulations', html: 'Thank you for joining the JamKazam affiliate program!

You can visit the Affiliate Page in your JamKazam Account any time to get links to share to refer users, and to view reports on affiliate activity levels.'}) + else + context.JK.Banner.show({buttons: [{name: 'GO SIGNUP', href:'/signup?affiliate_partner_id=' + response.id}], title: 'congratulations', html: 'Thank you for joining the JamKazam affiliate program!

There is still one more step: you still need to create a user account on JamKazam, so that you can access your affiliate information.'}) + + onFailedCreateAffiliatePartner: (jqXHR) => + if jqXHR.status == 422 + body = JSON.parse(jqXHR.responseText) + if body.errors && body.errors.affiliate_partner && body.errors.affiliate_partner[0] == 'You are already an affiliate.' + @app.notify({title:'Error', text:'You are already an affiliate.'}) + else + @app.notifyServerError(jqXHR, 'Unable to Create Affiliate') + else + @app.notifyServerError(jqXHR, 'Unable to Create Affiliate') + + onAgreeClicked: () => + @removeErrors() + + value = @page.find('input:radio[name="entity"]:checked').val() + + error = false + + if value? + if value == 'individual' + entityType = 'Individual' + else + # insist that they fill out entity type info + entityName = @entityName.val() + entityType = @entityType.val() + + entityNameNotEmpty = !!entityName + entityTypeNotEmpty = !!entityType + + if !entityNameNotEmpty + @fieldEntityName.addClass('error').append('
must be specified
') + error = true + + if !entityTypeNotEmpty + @fieldEntityType.addClass('error').append('
must be specified
') + error = true + else + @entityOptions.addClass('error') + error = true + + unless error + @rest.createAffiliatePartner({partner_name: entityName, entity_type: entityType}) + .done(@onCreatedAffiliatePartner) + .fail(@onFailedCreateAffiliatePartner) + + @disagreeNotice.hide ('hidden') + return false + + onDisagreeClicked: () => + @removeErrors() + + @disagreeNotice.slideDown('hidden') + return false + + events:() => + @entityRadio.on('change', @onRadioChanged) + @agreeBtn.on('click', @onAgreeClicked) + @disagreeBtn.on('click', @onDisagreeClicked) + + initialize: () => + @page = $('body') + @agreeBtn = @page.find('.agree-button') + @disagreeBtn = @page.find('.disagree-button') + @entityForm = @page.find('.entity-info') + @disagreeNotice = @page.find('.disagree-text') + @entityName = @page.find('input[name="entity-name"]') + @entityType = @page.find('select[name="entity-type"]') + @entityRadio = @page.find('input[name="entity"]') + @fieldEntityName = @page.find('.field.entity.name') + @fieldEntityType = @page.find('.field.entity.type') + @entityOptions = @page.find('.entity-options') + + @events() + +context.JK.AffiliateProgram = AffiliateProgram \ No newline at end of file diff --git a/web/app/assets/javascripts/web/web.js b/web/app/assets/javascripts/web/web.js index 408eaf41e..99dc9de2d 100644 --- a/web/app/assets/javascripts/web/web.js +++ b/web/app/assets/javascripts/web/web.js @@ -65,6 +65,8 @@ //= require web/tracking //= require web/individual_jamtrack //= require web/individual_jamtrack_band +//= require web/affiliate_program +//= require web/affiliate_links //= require fakeJamClient //= require fakeJamClientMessages //= require fakeJamClientRecordings diff --git a/web/app/assets/stylesheets/client/account.css.scss b/web/app/assets/stylesheets/client/account.css.scss index e8db2e0eb..db80c12b4 100644 --- a/web/app/assets/stylesheets/client/account.css.scss +++ b/web/app/assets/stylesheets/client/account.css.scss @@ -21,6 +21,13 @@ } } + hr { + height:0; + border-width: 1px 0 0 0; + border-style:solid; + border-color:$ColorTextTypical; + } + h4 { margin-top:8px; margin-bottom: 10px; @@ -57,7 +64,7 @@ .subcaption { margin-bottom: 4px; - } + } } .webcam-container { diff --git a/web/app/assets/stylesheets/client/account_affiliate.css.scss b/web/app/assets/stylesheets/client/account_affiliate.css.scss new file mode 100644 index 000000000..e1e36f203 --- /dev/null +++ b/web/app/assets/stylesheets/client/account_affiliate.css.scss @@ -0,0 +1,201 @@ +@import 'common.css.scss'; + +#account-affiliate-partner { + + + p { + font-size: 15px; + line-height: 125%; + margin:0; + } + + .affiliates-header { + float:left; + } + + .affiliate-partner-nav { + width:85%; + position:relative; + float:right; + margin-bottom:20px; + } + + .affiliate-partner-nav a { + width:19%; + text-align:center; + height: 27px; + display: block; + float:right; + margin-right:5px; + vertical-align:bottom; + padding-top:10px; + background-color:#535353; + color:#ccc; + font-size:17px; + text-decoration:none; + } + + .affiliate-partner-nav a:hover { + background-color:#666; + color:#fff; + } + + .affiliate-partner-nav a.active { + background-color:#ed3618; + color:#fff; + } + + .affiliate-partner-nav a.active:hover { + background-color:#ed3618; + cursor:default; + } + + .affiliate-partner-nav a.last { + margin-right:0px !important; + } + + #affiliate-partner-tab-content { + .tab-account { + .left-col { + float: left; + width: 55%; + .affiliate-label { + text-align: left; + width: 130px; + float: left; + display: inline-block; + margin-right: 10px; + margin-top: 3px; + } + input { + margin-bottom: 5px; + @include border_box_sizing; + } + + .button-orange { + margin-right:2px; + } + .spacer { + width:140px; + display:inline-block; + } + .input-buttons { + width:60%; + display:inline-block; + } + } + .right-col { + float: right; + width: 45%; + margin-top: 30px; + line-height:125%; + } + } + } + + .links { + p.prompt { + margin-bottom:20px; + } + } + + .link-type-section { + border-width:0 0 1px 0; + border-style:solid; + border-color:$ColorTextTypical; + padding-bottom:20px; + margin-bottom:20px; + + label { + display:inline-block; + margin-right:20px; + } + select { + + } + } + + .link-type-prompt { + display:none; + + p { + margin-bottom:20px; + } + + .example-link { + font-weight:bold; + } + } + + table.traffic-table { + width:400px; + .signups, .visits { + width:70px; + text-align:right; + } + } + table.links-table { + min-width:100%; + margin-top:20px; + + th { + padding: 10px 0 20px; + white-space:nowrap; + } + + td { + padding:3px 0; + white-space:nowrap; + } + .target { + width:45%; + white-space:normal; + } + .copy-link { + width:100px; + } + + .url { + + input { + background-color: transparent; + -webkit-box-shadow:none; + box-shadow:none; + color:#ccc; + } + } + } + + .agreement { + #partner-agreement-v1 { + height:340px; + overflow:scroll; + padding:20px; + border:1px solid white; + @include border-box_sizing; + } + + label.partner-agreement { + display:inline-block; + margin-right:40px; + } + + h2 { + font-size:20px; + font-weight:bold; + margin:40px 30px 20px 0; + display:inline-block; + } + + .execution-date { + display:inline-block; + } + + .input-buttons { + margin-top:20px; + } + } + + + +} \ No newline at end of file diff --git a/web/app/assets/stylesheets/client/client.css b/web/app/assets/stylesheets/client/client.css index dd1e80976..48b6cbfc7 100644 --- a/web/app/assets/stylesheets/client/client.css +++ b/web/app/assets/stylesheets/client/client.css @@ -32,6 +32,7 @@ *= require ./session *= require ./account *= require ./accountPaymentHistory + *= require ./account_affiliate *= require ./search *= require ./ftue *= require ./jamServer @@ -78,4 +79,5 @@ *= require ./downloadJamTrack *= require ./jamTrackPreview *= require users/signinCommon + *= require landings/partner_agreement_v1 */ \ No newline at end of file diff --git a/web/app/assets/stylesheets/client/sessionList.css.scss b/web/app/assets/stylesheets/client/sessionList.css.scss index ce326ef9c..c39ee2fcd 100644 --- a/web/app/assets/stylesheets/client/sessionList.css.scss +++ b/web/app/assets/stylesheets/client/sessionList.css.scss @@ -1,7 +1,7 @@ @import "client/common"; -table.findsession-table, table.local-recordings, table.open-jam-tracks, table.open-backing-tracks, table.cart-items, #account-session-detail, table.payment-table { +table.findsession-table, table.local-recordings, table.open-jam-tracks, table.open-backing-tracks, table.cart-items, #account-session-detail, table.payment-table, table.jamtable { .latency-unacceptable { width: 50px; @@ -64,7 +64,7 @@ table.findsession-table, table.local-recordings, table.open-jam-tracks, table.op text-align:center; } } -table.findsession-table, table.local-recordings, table.open-jam-tracks, table.open-backing-tracks, table.cart-items, table.payment-table { +table.findsession-table, table.local-recordings, table.open-jam-tracks, table.open-backing-tracks, table.cart-items, table.payment-table, table.jamtable { width:98%; height:10%; font-size:11px; diff --git a/web/app/assets/stylesheets/landings/affiliate_program.css.scss b/web/app/assets/stylesheets/landings/affiliate_program.css.scss new file mode 100644 index 000000000..2bfdeeccd --- /dev/null +++ b/web/app/assets/stylesheets/landings/affiliate_program.css.scss @@ -0,0 +1,74 @@ +@import "client/common.css.scss"; + +body.web.landing_page.full { + &.affiliate_program { + + .agree-disagree-buttons { + margin-top:30px; + } + + .agree-button { + margin-right:20px; + } + + #partner-agreement-v1 { + height:340px; + overflow:scroll; + padding:20px; + border:1px solid white; + @include border-box_sizing; + } + + .wrapper { + padding-top:20px; + } + .row { + text-align:left; + } + + h1 { + display: inline-block; + } + .column { + @include border_box_sizing; + width:50% ! important; + float:left; + + p { + margin-bottom:15px; + } + } + + label { + display:inline-block; + color:#ccc; + } + + p.agreement-notice { + color:white; + margin:20px 0 30px; + } + + .field.radio { + margin-top:10px; + label { + margin-left:10px; + } + } + + .field.entity { + &.name { + margin-top:30px; + } + margin-top:10px; + width:400px; + input, select { + width:300px; + @include border_box_sizing; + } + label { + width:100px; + } + } + } +} diff --git a/web/app/assets/stylesheets/landings/partner_agreement_v1.css.scss b/web/app/assets/stylesheets/landings/partner_agreement_v1.css.scss new file mode 100644 index 000000000..6f1756204 --- /dev/null +++ b/web/app/assets/stylesheets/landings/partner_agreement_v1.css.scss @@ -0,0 +1,4663 @@ +#partner-agreement-v1 { + + * { + color:#CCCCCC ! important; + } + + .c1, .c20 { + border-bottom-color: #CCCCCC ! important; + border-top-color: #CCCCCC ! important; + border-left-color: #CCCCCC ! important; + border-right-color: #CCCCCC ! important; + } + + .c12 { + color: #CCCCCC ! important; + } + + ul { + list-style-type:none; + } + + + + + + + .lst-kix_list_39-2 > li:before { + content: "\0025aa " + } + + .lst-kix_list_30-8 > li:before { + content: "\0025aa " + } + + .lst-kix_list_22-8 > li:before { + content: "\0025cf " + } + + .lst-kix_list_6-7 > li:before { + content: "" counter(lst-ctn-kix_list_6-0, decimal) "." counter(lst-ctn-kix_list_6-1, decimal) "." counter(lst-ctn-kix_list_6-2, decimal) "." counter(lst-ctn-kix_list_6-3, decimal) "." counter(lst-ctn-kix_list_6-4, decimal) "." counter(lst-ctn-kix_list_6-5, decimal) "." counter(lst-ctn-kix_list_6-6, decimal) "." counter(lst-ctn-kix_list_6-7, decimal) " " + } + + .lst-kix_list_34-0 > li:before { + content: "\0025cf " + } + + .lst-kix_list_21-3 > li:before { + content: "" counter(lst-ctn-kix_list_21-0, decimal) "." counter(lst-ctn-kix_list_21-1, decimal) "." counter(lst-ctn-kix_list_21-2, decimal) "." counter(lst-ctn-kix_list_21-3, decimal) " " + } + + .lst-kix_list_43-5 > li:before { + content: "\0025aa " + } + + .lst-kix_list_41-8 > li:before { + content: "\0025aa " + } + + ul.lst-kix_list_29-6 { + list-style-type: none + } + + ul.lst-kix_list_29-5 { + list-style-type: none + } + + ul.lst-kix_list_29-8 { + list-style-type: none + } + + ul.lst-kix_list_29-7 { + list-style-type: none + } + + ul.lst-kix_list_29-2 { + list-style-type: none + } + + ul.lst-kix_list_29-1 { + list-style-type: none + } + + .lst-kix_list_14-7 > li { + counter-increment: lst-ctn-kix_list_14-7 + } + + ul.lst-kix_list_29-4 { + list-style-type: none + } + + ul.lst-kix_list_29-3 { + list-style-type: none + } + + .lst-kix_list_41-3 > li:before { + content: "\0025cf " + } + + .lst-kix_list_8-5 > li:before { + content: "\0025cf " + } + + .lst-kix_list_48-6 > li:before { + content: "\0025cf " + } + + .lst-kix_list_25-2 > li:before { + content: "" counter(lst-ctn-kix_list_25-0, decimal) "." counter(lst-ctn-kix_list_25-1, decimal) "." counter(lst-ctn-kix_list_25-2, decimal) " " + } + + .lst-kix_list_33-2 > li:before { + content: "\0025aa " + } + + ol.lst-kix_list_19-1.start { + counter-reset: lst-ctn-kix_list_19-1 6 + } + + .lst-kix_list_21-2 > li { + counter-increment: lst-ctn-kix_list_21-2 + } + + ol.lst-kix_list_16-4.start { + counter-reset: lst-ctn-kix_list_16-4 0 + } + + ul.lst-kix_list_29-0 { + list-style-type: none + } + + .lst-kix_list_22-1 > li:before { + content: "\0025cf " + } + + .lst-kix_list_16-7 > li { + counter-increment: lst-ctn-kix_list_16-7 + } + + .lst-kix_list_32-7 > li:before { + content: "\0025cf " + } + + ol.lst-kix_list_25-2.start { + counter-reset: lst-ctn-kix_list_25-2 0 + } + + .lst-kix_list_18-0 > li:before { + content: "" counter(lst-ctn-kix_list_18-0, decimal) " " + } + + .lst-kix_list_38-4 > li:before { + content: "o " + } + + .lst-kix_list_13-4 > li:before { + content: "\0025cf " + } + + .lst-kix_list_5-2 > li:before { + content: "\0025cf " + } + + .lst-kix_list_9-1 > li:before { + content: "\0025cf " + } + + .lst-kix_list_18-0 > li { + counter-increment: lst-ctn-kix_list_18-0 + } + + .lst-kix_list_15-8 > li:before { + content: "" counter(lst-ctn-kix_list_15-0, decimal) "." counter(lst-ctn-kix_list_15-1, decimal) "." counter(lst-ctn-kix_list_15-2, decimal) "." counter(lst-ctn-kix_list_15-3, decimal) "." counter(lst-ctn-kix_list_15-4, decimal) "." counter(lst-ctn-kix_list_15-5, decimal) "." counter(lst-ctn-kix_list_15-6, decimal) "." counter(lst-ctn-kix_list_15-7, decimal) "." counter(lst-ctn-kix_list_15-8, decimal) " " + } + + .lst-kix_list_7-2 > li:before { + content: "\0025cf " + } + + .lst-kix_list_21-0 > li { + counter-increment: lst-ctn-kix_list_21-0 + } + + .lst-kix_list_37-6 > li:before { + content: "\0025cf " + } + + .lst-kix_list_37-5 > li:before { + content: "\0025aa " + } + + .lst-kix_list_17-8 > li { + counter-increment: lst-ctn-kix_list_17-8 + } + + .lst-kix_list_40-2 > li:before { + content: "\0025aa " + } + + ol.lst-kix_list_18-3.start { + counter-reset: lst-ctn-kix_list_18-3 0 + } + + .lst-kix_list_19-8 > li { + counter-increment: lst-ctn-kix_list_19-8 + } + + .lst-kix_list_31-7 > li:before { + content: "o " + } + + .lst-kix_list_36-4 > li:before { + content: "o " + } + + .lst-kix_list_9-3 > li:before { + content: "\0025cf " + } + + .lst-kix_list_6-0 > li { + counter-increment: lst-ctn-kix_list_6-0 + } + + ol.lst-kix_list_11-0 { + list-style-type: none + } + + .lst-kix_list_9-6 > li:before { + content: "\0025cf " + } + + .lst-kix_list_2-0 > li:before { + content: "\0025cf " + } + + .lst-kix_list_42-1 > li { + counter-increment: lst-ctn-kix_list_42-1 + } + + .lst-kix_list_28-7 > li:before { + content: "o " + } + + .lst-kix_list_2-4 > li:before { + content: "\0025cf " + } + + .lst-kix_list_45-5 > li:before { + content: "\0025aa " + } + + ol.lst-kix_list_15-6 { + list-style-type: none + } + + ol.lst-kix_list_15-7 { + list-style-type: none + } + + ol.lst-kix_list_15-8 { + list-style-type: none + } + + .lst-kix_list_37-4 > li:before { + content: "o " + } + + ol.lst-kix_list_15-0 { + list-style-type: none + } + + .lst-kix_list_12-7 > li:before { + content: "\0025cf " + } + + ol.lst-kix_list_15-1 { + list-style-type: none + } + + ol.lst-kix_list_15-2 { + list-style-type: none + } + + ol.lst-kix_list_15-3 { + list-style-type: none + } + + ol.lst-kix_list_15-4 { + list-style-type: none + } + + ol.lst-kix_list_15-5 { + list-style-type: none + } + + .lst-kix_list_21-4 > li:before { + content: "" counter(lst-ctn-kix_list_21-0, decimal) "." counter(lst-ctn-kix_list_21-1, decimal) "." counter(lst-ctn-kix_list_21-2, decimal) "." counter(lst-ctn-kix_list_21-3, decimal) "." counter(lst-ctn-kix_list_21-4, decimal) " " + } + + .lst-kix_list_41-2 > li:before { + content: "\0025aa " + } + + .lst-kix_list_34-6 > li:before { + content: "\0025cf " + } + + .lst-kix_list_35-7 > li:before { + content: "o " + } + + ol.lst-kix_list_17-3.start { + counter-reset: lst-ctn-kix_list_17-3 0 + } + + ol.lst-kix_list_21-6 { + list-style-type: none + } + + ol.lst-kix_list_21-5 { + list-style-type: none + } + + ol.lst-kix_list_21-4 { + list-style-type: none + } + + ol.lst-kix_list_21-3 { + list-style-type: none + } + + ol.lst-kix_list_6-5.start { + counter-reset: lst-ctn-kix_list_6-5 0 + } + + ol.lst-kix_list_21-8 { + list-style-type: none + } + + .lst-kix_list_8-1 > li:before { + content: "\0025cf " + } + + .lst-kix_list_31-2 > li:before { + content: "\0025aa " + } + + ol.lst-kix_list_21-7 { + list-style-type: none + } + + ol.lst-kix_list_8-0 { + list-style-type: none + } + + .lst-kix_list_17-6 > li { + counter-increment: lst-ctn-kix_list_17-6 + } + + .lst-kix_list_46-6 > li:before { + content: "\0025cf " + } + + .lst-kix_list_18-3 > li:before { + content: "" counter(lst-ctn-kix_list_18-0, decimal) "." counter(lst-ctn-kix_list_18-1, decimal) "." counter(lst-ctn-kix_list_18-2, decimal) "." counter(lst-ctn-kix_list_18-3, decimal) " " + } + + .lst-kix_list_41-7 > li:before { + content: "o " + } + + ol.lst-kix_list_21-1 { + list-style-type: none + } + + ol.lst-kix_list_21-2 { + list-style-type: none + } + + ol.lst-kix_list_21-0 { + list-style-type: none + } + + .lst-kix_list_33-3 > li:before { + content: "\0025cf " + } + + .lst-kix_list_46-7 > li:before { + content: "o " + } + + .lst-kix_list_25-7 > li:before { + content: "" counter(lst-ctn-kix_list_25-0, decimal) "." counter(lst-ctn-kix_list_25-1, decimal) "." counter(lst-ctn-kix_list_25-2, decimal) "." counter(lst-ctn-kix_list_25-3, decimal) "." counter(lst-ctn-kix_list_25-4, decimal) "." counter(lst-ctn-kix_list_25-5, decimal) "." counter(lst-ctn-kix_list_25-6, decimal) "." counter(lst-ctn-kix_list_25-7, decimal) " " + } + + .lst-kix_list_45-6 > li:before { + content: "\0025cf " + } + + .lst-kix_list_4-0 > li:before { + content: "\0025cf " + } + + .lst-kix_list_27-3 > li:before { + content: "\0025cf " + } + + .lst-kix_list_16-8 > li:before { + content: "" counter(lst-ctn-kix_list_16-0, decimal) "." counter(lst-ctn-kix_list_16-1, decimal) "." counter(lst-ctn-kix_list_16-2, decimal) "." counter(lst-ctn-kix_list_16-3, decimal) "." counter(lst-ctn-kix_list_16-4, decimal) "." counter(lst-ctn-kix_list_16-5, decimal) "." counter(lst-ctn-kix_list_16-6, decimal) "." counter(lst-ctn-kix_list_16-7, decimal) "." counter(lst-ctn-kix_list_16-8, decimal) " " + } + + ol.lst-kix_list_20-5.start { + counter-reset: lst-ctn-kix_list_20-5 0 + } + + .lst-kix_list_10-7 > li:before { + content: "\0025cf " + } + + ol.lst-kix_list_19-7 { + list-style-type: none + } + + .lst-kix_list_14-6 > li:before { + content: "" counter(lst-ctn-kix_list_14-0, decimal) "." counter(lst-ctn-kix_list_14-1, decimal) "." counter(lst-ctn-kix_list_14-2, decimal) "." counter(lst-ctn-kix_list_14-3, decimal) "." counter(lst-ctn-kix_list_14-4, decimal) "." counter(lst-ctn-kix_list_14-5, decimal) "." counter(lst-ctn-kix_list_14-6, decimal) " " + } + + ol.lst-kix_list_19-6 { + list-style-type: none + } + + ol.lst-kix_list_19-8 { + list-style-type: none + } + + ol.lst-kix_list_19-3 { + list-style-type: none + } + + ol.lst-kix_list_19-2 { + list-style-type: none + } + + .lst-kix_list_10-1 > li:before { + content: "\0025cf " + } + + ol.lst-kix_list_19-5 { + list-style-type: none + } + + ol.lst-kix_list_19-4 { + list-style-type: none + } + + ol.lst-kix_list_19-1 { + list-style-type: none + } + + .lst-kix_list_13-1 > li:before { + content: "\0025cf " + } + + ol.lst-kix_list_19-0 { + list-style-type: none + } + + .lst-kix_list_23-6 > li:before { + content: "\0025cf " + } + + .lst-kix_list_18-8 > li { + counter-increment: lst-ctn-kix_list_18-8 + } + + ol.lst-kix_list_20-4.start { + counter-reset: lst-ctn-kix_list_20-4 0 + } + + ol.lst-kix_list_18-5.start { + counter-reset: lst-ctn-kix_list_18-5 0 + } + + ol.lst-kix_list_6-3.start { + counter-reset: lst-ctn-kix_list_6-3 0 + } + + .lst-kix_list_8-6 > li:before { + content: "\0025cf " + } + + .lst-kix_list_1-5 > li:before { + content: "\0025cf " + } + + .lst-kix_list_25-3 > li:before { + content: "" counter(lst-ctn-kix_list_25-0, decimal) "." counter(lst-ctn-kix_list_25-1, decimal) "." counter(lst-ctn-kix_list_25-2, decimal) "." counter(lst-ctn-kix_list_25-3, decimal) " " + } + + .lst-kix_list_29-0 > li:before { + content: "\0025cf " + } + + .lst-kix_list_40-0 > li:before { + content: "\00f031 " + } + + .lst-kix_list_24-1 > li:before { + content: "\0025cf " + } + + .lst-kix_list_2-3 > li:before { + content: "\0025cf " + } + + .lst-kix_list_20-8 > li { + counter-increment: lst-ctn-kix_list_20-8 + } + + .lst-kix_list_13-8 > li:before { + content: "\0025cf " + } + + .lst-kix_list_16-0 > li { + counter-increment: lst-ctn-kix_list_16-0 + } + + .lst-kix_list_42-6 > li:before { + content: "" counter(lst-ctn-kix_list_42-6, decimal) ". " + } + + ul.lst-kix_list_34-8 { + list-style-type: none + } + + .lst-kix_list_42-2 > li:before { + content: "" counter(lst-ctn-kix_list_42-2, lower-roman) ". " + } + + ul.lst-kix_list_34-7 { + list-style-type: none + } + + ul.lst-kix_list_34-3 { + list-style-type: none + } + + ul.lst-kix_list_34-4 { + list-style-type: none + } + + ul.lst-kix_list_34-5 { + list-style-type: none + } + + .lst-kix_list_39-6 > li:before { + content: "\0025cf " + } + + ul.lst-kix_list_34-6 { + list-style-type: none + } + + .lst-kix_list_36-8 > li:before { + content: "\0025aa " + } + + .lst-kix_list_47-6 > li:before { + content: "\0025cf " + } + + ul.lst-kix_list_34-0 { + list-style-type: none + } + + ul.lst-kix_list_34-1 { + list-style-type: none + } + + ul.lst-kix_list_34-2 { + list-style-type: none + } + + .lst-kix_list_20-2 > li:before { + content: "" counter(lst-ctn-kix_list_20-0, decimal) "." counter(lst-ctn-kix_list_20-1, decimal) "." counter(lst-ctn-kix_list_20-2, decimal) " " + } + + .lst-kix_list_10-6 > li:before { + content: "\0025cf " + } + + .lst-kix_list_21-5 > li:before { + content: "" counter(lst-ctn-kix_list_21-0, decimal) "." counter(lst-ctn-kix_list_21-1, decimal) "." counter(lst-ctn-kix_list_21-2, decimal) "." counter(lst-ctn-kix_list_21-3, decimal) "." counter(lst-ctn-kix_list_21-4, decimal) "." counter(lst-ctn-kix_list_21-5, decimal) " " + } + + ol.lst-kix_list_15-3.start { + counter-reset: lst-ctn-kix_list_15-3 0 + } + + ul.lst-kix_list_40-8 { + list-style-type: none + } + + ul.lst-kix_list_40-7 { + list-style-type: none + } + + ul.lst-kix_list_40-6 { + list-style-type: none + } + + .lst-kix_list_49-0 > li:before { + content: "\0025cf " + } + + ul.lst-kix_list_40-5 { + list-style-type: none + } + + ul.lst-kix_list_40-4 { + list-style-type: none + } + + ul.lst-kix_list_40-3 { + list-style-type: none + } + + ol.lst-kix_list_11-0.start { + counter-reset: lst-ctn-kix_list_11-0 0 + } + + .lst-kix_list_15-5 > li { + counter-increment: lst-ctn-kix_list_15-5 + } + + ul.lst-kix_list_40-2 { + list-style-type: none + } + + .lst-kix_list_10-2 > li:before { + content: "\0025cf " + } + + ul.lst-kix_list_40-1 { + list-style-type: none + } + + .lst-kix_list_20-7 > li:before { + content: "" counter(lst-ctn-kix_list_20-0, decimal) "." counter(lst-ctn-kix_list_20-1, decimal) "." counter(lst-ctn-kix_list_20-2, decimal) "." counter(lst-ctn-kix_list_20-3, decimal) "." counter(lst-ctn-kix_list_20-4, decimal) "." counter(lst-ctn-kix_list_20-5, decimal) "." counter(lst-ctn-kix_list_20-6, decimal) "." counter(lst-ctn-kix_list_20-7, decimal) " " + } + + ul.lst-kix_list_40-0 { + list-style-type: none + } + + .lst-kix_list_21-4 > li { + counter-increment: lst-ctn-kix_list_21-4 + } + + .lst-kix_list_6-1 > li:before { + content: "" counter(lst-ctn-kix_list_6-0, decimal) "." counter(lst-ctn-kix_list_6-1, decimal) " " + } + + .lst-kix_list_36-1 > li:before { + content: "o " + } + + .lst-kix_list_41-0 > li:before { + content: "\0025cf " + } + + .lst-kix_list_17-0 > li:before { + content: "" counter(lst-ctn-kix_list_17-0, decimal) " " + } + + .lst-kix_list_38-3 > li:before { + content: "\0025cf " + } + + .lst-kix_list_13-3 > li:before { + content: "\0025cf " + } + + ul.lst-kix_list_44-8 { + list-style-type: none + } + + .lst-kix_list_35-1 > li:before { + content: "o " + } + + ul.lst-kix_list_44-4 { + list-style-type: none + } + + .lst-kix_list_14-7 > li:before { + content: "" counter(lst-ctn-kix_list_14-0, decimal) "." counter(lst-ctn-kix_list_14-1, decimal) "." counter(lst-ctn-kix_list_14-2, decimal) "." counter(lst-ctn-kix_list_14-3, decimal) "." counter(lst-ctn-kix_list_14-4, decimal) "." counter(lst-ctn-kix_list_14-5, decimal) "." counter(lst-ctn-kix_list_14-6, decimal) "." counter(lst-ctn-kix_list_14-7, decimal) " " + } + + ul.lst-kix_list_44-5 { + list-style-type: none + } + + ul.lst-kix_list_44-6 { + list-style-type: none + } + + ul.lst-kix_list_44-7 { + list-style-type: none + } + + ul.lst-kix_list_44-0 { + list-style-type: none + } + + ul.lst-kix_list_44-1 { + list-style-type: none + } + + ul.lst-kix_list_44-2 { + list-style-type: none + } + + ul.lst-kix_list_44-3 { + list-style-type: none + } + + .lst-kix_list_40-6 > li:before { + content: "\0025cf " + } + + .lst-kix_list_23-0 > li:before { + content: "\0025cf " + } + + .lst-kix_list_33-0 > li:before { + content: "\0025cf " + } + + .lst-kix_list_12-6 > li:before { + content: "\0025cf " + } + + .lst-kix_list_39-0 > li:before { + content: "\0025cf " + } + + .lst-kix_list_32-0 > li:before { + content: "" counter(lst-ctn-kix_list_32-0, decimal) ". " + } + + .lst-kix_list_3-7 > li:before { + content: "\0025cf " + } + + .lst-kix_list_49-8 > li:before { + content: "\0025aa " + } + + .lst-kix_list_44-7 > li:before { + content: "o " + } + + ul.lst-kix_list_13-2 { + list-style-type: none + } + + ul.lst-kix_list_13-3 { + list-style-type: none + } + + ul.lst-kix_list_13-4 { + list-style-type: none + } + + ul.lst-kix_list_13-5 { + list-style-type: none + } + + ul.lst-kix_list_13-0 { + list-style-type: none + } + + ul.lst-kix_list_13-1 { + list-style-type: none + } + + .lst-kix_list_12-8 > li:before { + content: "\0025cf " + } + + .lst-kix_list_39-8 > li:before { + content: "\0025aa " + } + + ul.lst-kix_list_13-7 { + list-style-type: none + } + + ul.lst-kix_list_13-6 { + list-style-type: none + } + + .lst-kix_list_36-2 > li:before { + content: "\0025aa " + } + + ul.lst-kix_list_13-8 { + list-style-type: none + } + + .lst-kix_list_9-8 > li:before { + content: "\0025cf " + } + + .lst-kix_list_16-1 > li:before { + content: "" counter(lst-ctn-kix_list_16-0, decimal) "." counter(lst-ctn-kix_list_16-1, decimal) " " + } + + .lst-kix_list_42-7 > li { + counter-increment: lst-ctn-kix_list_42-7 + } + + .lst-kix_list_8-0 > li:before { + content: "" counter(lst-ctn-kix_list_8-0, lower-latin) ". " + } + + ul.lst-kix_list_47-6 { + list-style-type: none + } + + .lst-kix_list_24-5 > li:before { + content: "\0025cf " + } + + .lst-kix_list_38-1 > li:before { + content: "o " + } + + ul.lst-kix_list_47-5 { + list-style-type: none + } + + ul.lst-kix_list_47-8 { + list-style-type: none + } + + .lst-kix_list_20-1 > li:before { + content: "" counter(lst-ctn-kix_list_20-0, decimal) "." counter(lst-ctn-kix_list_20-1, decimal) " " + } + + ul.lst-kix_list_47-7 { + list-style-type: none + } + + ul.lst-kix_list_49-0 { + list-style-type: none + } + + ol.lst-kix_list_15-6.start { + counter-reset: lst-ctn-kix_list_15-6 0 + } + + ul.lst-kix_list_49-2 { + list-style-type: none + } + + ul.lst-kix_list_49-1 { + list-style-type: none + } + + ul.lst-kix_list_49-3 { + list-style-type: none + } + + ul.lst-kix_list_49-4 { + list-style-type: none + } + + ul.lst-kix_list_49-5 { + list-style-type: none + } + + ul.lst-kix_list_47-0 { + list-style-type: none + } + + ul.lst-kix_list_49-6 { + list-style-type: none + } + + ul.lst-kix_list_47-1 { + list-style-type: none + } + + .lst-kix_list_40-8 > li:before { + content: "\0025aa " + } + + ul.lst-kix_list_49-7 { + list-style-type: none + } + + ul.lst-kix_list_47-2 { + list-style-type: none + } + + ul.lst-kix_list_49-8 { + list-style-type: none + } + + ul.lst-kix_list_47-3 { + list-style-type: none + } + + ul.lst-kix_list_47-4 { + list-style-type: none + } + + .lst-kix_list_29-2 > li:before { + content: "\0025aa " + } + + .lst-kix_list_29-8 > li:before { + content: "\0025aa " + } + + .lst-kix_list_35-6 > li:before { + content: "\0025cf " + } + + .lst-kix_list_10-3 > li:before { + content: "\0025cf " + } + + .lst-kix_list_23-5 > li:before { + content: "\0025cf " + } + + .lst-kix_list_16-1 > li { + counter-increment: lst-ctn-kix_list_16-1 + } + + .lst-kix_list_7-4 > li:before { + content: "\0025cf " + } + + .lst-kix_list_34-3 > li:before { + content: "\0025cf " + } + + .lst-kix_list_18-7 > li { + counter-increment: lst-ctn-kix_list_18-7 + } + + ol.lst-kix_list_16-8.start { + counter-reset: lst-ctn-kix_list_16-8 0 + } + + ol.lst-kix_list_20-3.start { + counter-reset: lst-ctn-kix_list_20-3 0 + } + + ol.lst-kix_list_25-6.start { + counter-reset: lst-ctn-kix_list_25-6 0 + } + + .lst-kix_list_36-3 > li:before { + content: "\0025cf " + } + + ol.lst-kix_list_19-4.start { + counter-reset: lst-ctn-kix_list_19-4 0 + } + + .lst-kix_list_24-2 > li:before { + content: "\0025cf " + } + + .lst-kix_list_40-7 > li:before { + content: "o " + } + + .lst-kix_list_8-2 > li:before { + content: "\0025cf " + } + + ol.lst-kix_list_21-6.start { + counter-reset: lst-ctn-kix_list_21-6 0 + } + + .lst-kix_list_14-3 > li:before { + content: "" counter(lst-ctn-kix_list_14-0, decimal) "." counter(lst-ctn-kix_list_14-1, decimal) "." counter(lst-ctn-kix_list_14-2, decimal) "." counter(lst-ctn-kix_list_14-3, decimal) " " + } + + .lst-kix_list_8-8 > li:before { + content: "\0025cf " + } + + .lst-kix_list_30-2 > li:before { + content: "\0025aa " + } + + ol.lst-kix_list_16-1.start { + counter-reset: lst-ctn-kix_list_16-1 1 + } + + ol.lst-kix_list_20-6.start { + counter-reset: lst-ctn-kix_list_20-6 0 + } + + ul.lst-kix_list_36-7 { + list-style-type: none + } + + ul.lst-kix_list_36-8 { + list-style-type: none + } + + ul.lst-kix_list_36-5 { + list-style-type: none + } + + ul.lst-kix_list_36-6 { + list-style-type: none + } + + ol.lst-kix_list_19-3.start { + counter-reset: lst-ctn-kix_list_19-3 0 + } + + .lst-kix_list_48-3 > li:before { + content: "\0025cf " + } + + ol.lst-kix_list_6-2.start { + counter-reset: lst-ctn-kix_list_6-2 0 + } + + ol.lst-kix_list_17-1.start { + counter-reset: lst-ctn-kix_list_17-1 1 + } + + ol.lst-kix_list_42-3.start { + counter-reset: lst-ctn-kix_list_42-3 0 + } + + ul.lst-kix_list_9-0 { + list-style-type: none + } + + .lst-kix_list_22-4 > li:before { + content: "\0025cf " + } + + .lst-kix_list_38-8 > li:before { + content: "\0025aa " + } + + ul.lst-kix_list_9-8 { + list-style-type: none + } + + ul.lst-kix_list_36-0 { + list-style-type: none + } + + ul.lst-kix_list_9-7 { + list-style-type: none + } + + .lst-kix_list_19-6 > li:before { + content: "" counter(lst-ctn-kix_list_19-0, decimal) "." counter(lst-ctn-kix_list_19-1, decimal) "." counter(lst-ctn-kix_list_19-2, decimal) "." counter(lst-ctn-kix_list_19-3, decimal) "." counter(lst-ctn-kix_list_19-4, decimal) "." counter(lst-ctn-kix_list_19-5, decimal) "." counter(lst-ctn-kix_list_19-6, decimal) " " + } + + ul.lst-kix_list_9-6 { + list-style-type: none + } + + .lst-kix_list_43-7 > li:before { + content: "o " + } + + ul.lst-kix_list_9-5 { + list-style-type: none + } + + .lst-kix_list_13-6 > li:before { + content: "\0025cf " + } + + ul.lst-kix_list_9-4 { + list-style-type: none + } + + ul.lst-kix_list_36-4 { + list-style-type: none + } + + ul.lst-kix_list_9-3 { + list-style-type: none + } + + ul.lst-kix_list_36-3 { + list-style-type: none + } + + .lst-kix_list_46-4 > li:before { + content: "o " + } + + ul.lst-kix_list_9-2 { + list-style-type: none + } + + ul.lst-kix_list_36-2 { + list-style-type: none + } + + ul.lst-kix_list_9-1 { + list-style-type: none + } + + ul.lst-kix_list_36-1 { + list-style-type: none + } + + ul.lst-kix_list_5-1 { + list-style-type: none + } + + ul.lst-kix_list_5-2 { + list-style-type: none + } + + ul.lst-kix_list_5-3 { + list-style-type: none + } + + ul.lst-kix_list_5-4 { + list-style-type: none + } + + .lst-kix_list_10-0 > li:before { + content: "" counter(lst-ctn-kix_list_10-0, lower-latin) ". " + } + + .lst-kix_list_17-7 > li:before { + content: "" counter(lst-ctn-kix_list_17-0, decimal) "." counter(lst-ctn-kix_list_17-1, decimal) "." counter(lst-ctn-kix_list_17-2, decimal) "." counter(lst-ctn-kix_list_17-3, decimal) "." counter(lst-ctn-kix_list_17-4, decimal) "." counter(lst-ctn-kix_list_17-5, decimal) "." counter(lst-ctn-kix_list_17-6, decimal) "." counter(lst-ctn-kix_list_17-7, decimal) " " + } + + .lst-kix_list_40-5 > li:before { + content: "\0025aa " + } + + ul.lst-kix_list_5-0 { + list-style-type: none + } + + .lst-kix_list_37-1 > li:before { + content: "o " + } + + .lst-kix_list_13-2 > li:before { + content: "\0025cf " + } + + .lst-kix_list_31-0 > li:before { + content: "\0025a1 " + } + + .lst-kix_list_42-6 > li { + counter-increment: lst-ctn-kix_list_42-6 + } + + ul.lst-kix_list_5-5 { + list-style-type: none + } + + ul.lst-kix_list_5-6 { + list-style-type: none + } + + ul.lst-kix_list_5-7 { + list-style-type: none + } + + ul.lst-kix_list_5-8 { + list-style-type: none + } + + ul.lst-kix_list_7-8 { + list-style-type: none + } + + ul.lst-kix_list_7-7 { + list-style-type: none + } + + .lst-kix_list_4-3 > li:before { + content: "\0025cf " + } + + ul.lst-kix_list_7-4 { + list-style-type: none + } + + ul.lst-kix_list_7-3 { + list-style-type: none + } + + ul.lst-kix_list_7-6 { + list-style-type: none + } + + ul.lst-kix_list_7-5 { + list-style-type: none + } + + ul.lst-kix_list_7-2 { + list-style-type: none + } + + ul.lst-kix_list_7-1 { + list-style-type: none + } + + .lst-kix_list_19-4 > li:before { + content: "" counter(lst-ctn-kix_list_19-0, decimal) "." counter(lst-ctn-kix_list_19-1, decimal) "." counter(lst-ctn-kix_list_19-2, decimal) "." counter(lst-ctn-kix_list_19-3, decimal) "." counter(lst-ctn-kix_list_19-4, decimal) " " + } + + .lst-kix_list_14-1 > li:before { + content: "" counter(lst-ctn-kix_list_14-0, decimal) "." counter(lst-ctn-kix_list_14-1, decimal) " " + } + + .lst-kix_list_30-4 > li:before { + content: "o " + } + + ol.lst-kix_list_15-7.start { + counter-reset: lst-ctn-kix_list_15-7 0 + } + + .lst-kix_list_6-8 > li:before { + content: "" counter(lst-ctn-kix_list_6-0, decimal) "." counter(lst-ctn-kix_list_6-1, decimal) "." counter(lst-ctn-kix_list_6-2, decimal) "." counter(lst-ctn-kix_list_6-3, decimal) "." counter(lst-ctn-kix_list_6-4, decimal) "." counter(lst-ctn-kix_list_6-5, decimal) "." counter(lst-ctn-kix_list_6-6, decimal) "." counter(lst-ctn-kix_list_6-7, decimal) "." counter(lst-ctn-kix_list_6-8, decimal) " " + } + + .lst-kix_list_37-2 > li:before { + content: "\0025aa " + } + + ul.lst-kix_list_3-7 { + list-style-type: none + } + + ul.lst-kix_list_3-8 { + list-style-type: none + } + + .lst-kix_list_1-6 > li:before { + content: "\0025cf " + } + + ul.lst-kix_list_3-0 { + list-style-type: none + } + + ul.lst-kix_list_3-1 { + list-style-type: none + } + + ul.lst-kix_list_3-2 { + list-style-type: none + } + + ul.lst-kix_list_3-3 { + list-style-type: none + } + + .lst-kix_list_16-6 > li { + counter-increment: lst-ctn-kix_list_16-6 + } + + ul.lst-kix_list_3-4 { + list-style-type: none + } + + ul.lst-kix_list_3-5 { + list-style-type: none + } + + ul.lst-kix_list_1-0 { + list-style-type: none + } + + ul.lst-kix_list_3-6 { + list-style-type: none + } + + .lst-kix_list_16-7 > li:before { + content: "" counter(lst-ctn-kix_list_16-0, decimal) "." counter(lst-ctn-kix_list_16-1, decimal) "." counter(lst-ctn-kix_list_16-2, decimal) "." counter(lst-ctn-kix_list_16-3, decimal) "." counter(lst-ctn-kix_list_16-4, decimal) "." counter(lst-ctn-kix_list_16-5, decimal) "." counter(lst-ctn-kix_list_16-6, decimal) "." counter(lst-ctn-kix_list_16-7, decimal) " " + } + + .lst-kix_list_41-5 > li:before { + content: "\0025aa " + } + + ul.lst-kix_list_1-2 { + list-style-type: none + } + + ul.lst-kix_list_1-1 { + list-style-type: none + } + + .lst-kix_list_29-6 > li:before { + content: "\0025cf " + } + + .lst-kix_list_35-4 > li:before { + content: "o " + } + + ul.lst-kix_list_1-4 { + list-style-type: none + } + + .lst-kix_list_6-8 > li { + counter-increment: lst-ctn-kix_list_6-8 + } + + ul.lst-kix_list_1-3 { + list-style-type: none + } + + ul.lst-kix_list_1-6 { + list-style-type: none + } + + ul.lst-kix_list_1-5 { + list-style-type: none + } + + ul.lst-kix_list_1-8 { + list-style-type: none + } + + ul.lst-kix_list_1-7 { + list-style-type: none + } + + ol.lst-kix_list_19-5.start { + counter-reset: lst-ctn-kix_list_19-5 0 + } + + .lst-kix_list_2-1 > li:before { + content: "\0025cf " + } + + .lst-kix_list_4-8 > li:before { + content: "\0025cf " + } + + .lst-kix_list_36-5 > li:before { + content: "\0025aa " + } + + .lst-kix_list_30-6 > li:before { + content: "\0025cf " + } + + .lst-kix_list_15-6 > li { + counter-increment: lst-ctn-kix_list_15-6 + } + + .lst-kix_list_31-1 > li:before { + content: "o " + } + + .lst-kix_list_48-1 > li:before { + content: "o " + } + + .lst-kix_list_43-2 > li:before { + content: "\0025aa " + } + + .lst-kix_list_25-3 > li { + counter-increment: lst-ctn-kix_list_25-3 + } + + .lst-kix_list_47-5 > li:before { + content: "\0025aa " + } + + .lst-kix_list_38-7 > li:before { + content: "o " + } + + .lst-kix_list_42-4 > li { + counter-increment: lst-ctn-kix_list_42-4 + } + + ul.lst-kix_list_11-3 { + list-style-type: none + } + + .lst-kix_list_47-0 > li:before { + content: "\0025cf " + } + + ul.lst-kix_list_11-2 { + list-style-type: none + } + + ol.lst-kix_list_42-6.start { + counter-reset: lst-ctn-kix_list_42-6 0 + } + + ul.lst-kix_list_11-1 { + list-style-type: none + } + + ol.lst-kix_list_20-8.start { + counter-reset: lst-ctn-kix_list_20-8 0 + } + + ul.lst-kix_list_11-7 { + list-style-type: none + } + + ul.lst-kix_list_11-6 { + list-style-type: none + } + + ul.lst-kix_list_11-5 { + list-style-type: none + } + + .lst-kix_list_22-7 > li:before { + content: "\0025cf " + } + + ul.lst-kix_list_11-4 { + list-style-type: none + } + + .lst-kix_list_46-8 > li:before { + content: "\0025aa " + } + + .lst-kix_list_14-1 > li { + counter-increment: lst-ctn-kix_list_14-1 + } + + .lst-kix_list_45-0 > li:before { + content: "\0025cf " + } + + .lst-kix_list_4-1 > li:before { + content: "\0025cf " + } + + .lst-kix_list_21-0 > li:before { + content: "" counter(lst-ctn-kix_list_21-0, decimal) " " + } + + .lst-kix_list_35-0 > li:before { + content: "\0025cf " + } + + .lst-kix_list_1-0 > li:before { + content: "\0025cf " + } + + .lst-kix_list_28-0 > li:before { + content: "\0025cf " + } + + .lst-kix_list_21-3 > li { + counter-increment: lst-ctn-kix_list_21-3 + } + + .lst-kix_list_21-6 > li { + counter-increment: lst-ctn-kix_list_21-6 + } + + ul.lst-kix_list_11-8 { + list-style-type: none + } + + ul.lst-kix_list_31-8 { + list-style-type: none + } + + .lst-kix_list_17-0 > li { + counter-increment: lst-ctn-kix_list_17-0 + } + + .lst-kix_list_1-3 > li:before { + content: "\0025cf " + } + + .lst-kix_list_8-3 > li:before { + content: "\0025cf " + } + + ul.lst-kix_list_31-6 { + list-style-type: none + } + + ul.lst-kix_list_31-7 { + list-style-type: none + } + + ul.lst-kix_list_31-4 { + list-style-type: none + } + + ul.lst-kix_list_31-5 { + list-style-type: none + } + + .lst-kix_list_14-0 > li:before { + content: "" counter(lst-ctn-kix_list_14-0, decimal) " " + } + + ul.lst-kix_list_31-2 { + list-style-type: none + } + + ol.lst-kix_list_20-7.start { + counter-reset: lst-ctn-kix_list_20-7 0 + } + + ul.lst-kix_list_31-3 { + list-style-type: none + } + + ul.lst-kix_list_31-0 { + list-style-type: none + } + + .lst-kix_list_19-1 > li { + counter-increment: lst-ctn-kix_list_19-1 + } + + .lst-kix_list_12-0 > li:before { + content: "\002751 " + } + + .lst-kix_list_29-7 > li:before { + content: "o " + } + + ul.lst-kix_list_31-1 { + list-style-type: none + } + + ol.lst-kix_list_15-2.start { + counter-reset: lst-ctn-kix_list_15-2 0 + } + + .lst-kix_list_44-3 > li:before { + content: "\0025cf " + } + + .lst-kix_list_15-7 > li:before { + content: "" counter(lst-ctn-kix_list_15-0, decimal) "." counter(lst-ctn-kix_list_15-1, decimal) "." counter(lst-ctn-kix_list_15-2, decimal) "." counter(lst-ctn-kix_list_15-3, decimal) "." counter(lst-ctn-kix_list_15-4, decimal) "." counter(lst-ctn-kix_list_15-5, decimal) "." counter(lst-ctn-kix_list_15-6, decimal) "." counter(lst-ctn-kix_list_15-7, decimal) " " + } + + .lst-kix_list_21-7 > li:before { + content: "" counter(lst-ctn-kix_list_21-0, decimal) "." counter(lst-ctn-kix_list_21-1, decimal) "." counter(lst-ctn-kix_list_21-2, decimal) "." counter(lst-ctn-kix_list_21-3, decimal) "." counter(lst-ctn-kix_list_21-4, decimal) "." counter(lst-ctn-kix_list_21-5, decimal) "." counter(lst-ctn-kix_list_21-6, decimal) "." counter(lst-ctn-kix_list_21-7, decimal) " " + } + + ol.lst-kix_list_15-0.start { + counter-reset: lst-ctn-kix_list_15-0 3 + } + + ol.lst-kix_list_21-5.start { + counter-reset: lst-ctn-kix_list_21-5 0 + } + + .lst-kix_list_42-0 > li:before { + content: "(" counter(lst-ctn-kix_list_42-0, lower-roman) ") " + } + + .lst-kix_list_21-8 > li { + counter-increment: lst-ctn-kix_list_21-8 + } + + .lst-kix_list_26-0 > li:before { + content: "\0025cf " + } + + .lst-kix_list_19-5 > li:before { + content: "" counter(lst-ctn-kix_list_19-0, decimal) "." counter(lst-ctn-kix_list_19-1, decimal) "." counter(lst-ctn-kix_list_19-2, decimal) "." counter(lst-ctn-kix_list_19-3, decimal) "." counter(lst-ctn-kix_list_19-4, decimal) "." counter(lst-ctn-kix_list_19-5, decimal) " " + } + + ol.lst-kix_list_42-1.start { + counter-reset: lst-ctn-kix_list_42-1 0 + } + + .lst-kix_list_32-0 > li { + counter-increment: lst-ctn-kix_list_32-0 + } + + .lst-kix_list_35-2 > li:before { + content: "\0025aa " + } + + .lst-kix_list_7-8 > li:before { + content: "\0025cf " + } + + .lst-kix_list_25-1 > li:before { + content: "" counter(lst-ctn-kix_list_25-0, decimal) "." counter(lst-ctn-kix_list_25-1, decimal) " " + } + + .lst-kix_list_24-3 > li:before { + content: "\0025cf " + } + + .lst-kix_list_15-1 > li { + counter-increment: lst-ctn-kix_list_15-1 + } + + .lst-kix_list_13-7 > li:before { + content: "\0025cf " + } + + .lst-kix_list_28-6 > li:before { + content: "\0025cf " + } + + .lst-kix_list_33-8 > li:before { + content: "\0025aa " + } + + .lst-kix_list_5-1 > li:before { + content: "\0025cf " + } + + .lst-kix_list_44-0 > li:before { + content: "\0025cf " + } + + .lst-kix_list_1-1 > li:before { + content: "\0025cf " + } + + ol.lst-kix_list_14-0.start { + counter-reset: lst-ctn-kix_list_14-0 0 + } + + .lst-kix_list_32-4 > li:before { + content: "\0025cf " + } + + .lst-kix_list_25-5 > li:before { + content: "" counter(lst-ctn-kix_list_25-0, decimal) "." counter(lst-ctn-kix_list_25-1, decimal) "." counter(lst-ctn-kix_list_25-2, decimal) "." counter(lst-ctn-kix_list_25-3, decimal) "." counter(lst-ctn-kix_list_25-4, decimal) "." counter(lst-ctn-kix_list_25-5, decimal) " " + } + + .lst-kix_list_15-1 > li:before { + content: "" counter(lst-ctn-kix_list_15-0, decimal) "." counter(lst-ctn-kix_list_15-1, decimal) " " + } + + ol.lst-kix_list_18-8.start { + counter-reset: lst-ctn-kix_list_18-8 0 + } + + .lst-kix_list_23-7 > li:before { + content: "\0025cf " + } + + ol.lst-kix_list_17-2.start { + counter-reset: lst-ctn-kix_list_17-2 0 + } + + .lst-kix_list_20-8 > li:before { + content: "" counter(lst-ctn-kix_list_20-0, decimal) "." counter(lst-ctn-kix_list_20-1, decimal) "." counter(lst-ctn-kix_list_20-2, decimal) "." counter(lst-ctn-kix_list_20-3, decimal) "." counter(lst-ctn-kix_list_20-4, decimal) "." counter(lst-ctn-kix_list_20-5, decimal) "." counter(lst-ctn-kix_list_20-6, decimal) "." counter(lst-ctn-kix_list_20-7, decimal) "." counter(lst-ctn-kix_list_20-8, decimal) " " + } + + .lst-kix_list_11-7 > li:before { + content: "\0025cf " + } + + ul.lst-kix_list_38-2 { + list-style-type: none + } + + .lst-kix_list_16-5 > li { + counter-increment: lst-ctn-kix_list_16-5 + } + + ul.lst-kix_list_38-1 { + list-style-type: none + } + + ul.lst-kix_list_38-0 { + list-style-type: none + } + + .lst-kix_list_5-7 > li:before { + content: "\0025cf " + } + + .lst-kix_list_25-6 > li:before { + content: "" counter(lst-ctn-kix_list_25-0, decimal) "." counter(lst-ctn-kix_list_25-1, decimal) "." counter(lst-ctn-kix_list_25-2, decimal) "." counter(lst-ctn-kix_list_25-3, decimal) "." counter(lst-ctn-kix_list_25-4, decimal) "." counter(lst-ctn-kix_list_25-5, decimal) "." counter(lst-ctn-kix_list_25-6, decimal) " " + } + + .lst-kix_list_40-4 > li:before { + content: "o " + } + + .lst-kix_list_9-4 > li:before { + content: "\0025cf " + } + + .lst-kix_list_34-8 > li:before { + content: "\0025aa " + } + + ol.lst-kix_list_15-8.start { + counter-reset: lst-ctn-kix_list_15-8 0 + } + + .lst-kix_list_45-4 > li:before { + content: "o " + } + + .lst-kix_list_18-1 > li:before { + content: "" counter(lst-ctn-kix_list_18-0, decimal) "." counter(lst-ctn-kix_list_18-1, decimal) " " + } + + ul.lst-kix_list_38-5 { + list-style-type: none + } + + ol.lst-kix_list_42-2.start { + counter-reset: lst-ctn-kix_list_42-2 0 + } + + ul.lst-kix_list_38-6 { + list-style-type: none + } + + ul.lst-kix_list_38-3 { + list-style-type: none + } + + .lst-kix_list_47-2 > li:before { + content: "\0025aa " + } + + ul.lst-kix_list_38-4 { + list-style-type: none + } + + ul.lst-kix_list_38-7 { + list-style-type: none + } + + ul.lst-kix_list_38-8 { + list-style-type: none + } + + ul.lst-kix_list_27-1 { + list-style-type: none + } + + ul.lst-kix_list_27-2 { + list-style-type: none + } + + .lst-kix_list_26-5 > li:before { + content: "\0025aa " + } + + .lst-kix_list_19-2 > li:before { + content: "" counter(lst-ctn-kix_list_19-0, decimal) "." counter(lst-ctn-kix_list_19-1, decimal) "." counter(lst-ctn-kix_list_19-2, decimal) " " + } + + ul.lst-kix_list_27-0 { + list-style-type: none + } + + ol.lst-kix_list_25-7.start { + counter-reset: lst-ctn-kix_list_25-7 0 + } + + .lst-kix_list_19-8 > li:before { + content: "" counter(lst-ctn-kix_list_19-0, decimal) "." counter(lst-ctn-kix_list_19-1, decimal) "." counter(lst-ctn-kix_list_19-2, decimal) "." counter(lst-ctn-kix_list_19-3, decimal) "." counter(lst-ctn-kix_list_19-4, decimal) "." counter(lst-ctn-kix_list_19-5, decimal) "." counter(lst-ctn-kix_list_19-6, decimal) "." counter(lst-ctn-kix_list_19-7, decimal) "." counter(lst-ctn-kix_list_19-8, decimal) " " + } + + .lst-kix_list_16-2 > li:before { + content: "" counter(lst-ctn-kix_list_16-0, decimal) "." counter(lst-ctn-kix_list_16-1, decimal) "." counter(lst-ctn-kix_list_16-2, decimal) " " + } + + ol.lst-kix_list_16-5.start { + counter-reset: lst-ctn-kix_list_16-5 0 + } + + ol.lst-kix_list_25-5.start { + counter-reset: lst-ctn-kix_list_25-5 0 + } + + .lst-kix_list_18-2 > li:before { + content: "" counter(lst-ctn-kix_list_18-0, decimal) "." counter(lst-ctn-kix_list_18-1, decimal) "." counter(lst-ctn-kix_list_18-2, decimal) " " + } + + .lst-kix_list_42-2 > li { + counter-increment: lst-ctn-kix_list_42-2 + } + + .lst-kix_list_18-1 > li { + counter-increment: lst-ctn-kix_list_18-1 + } + + .lst-kix_list_9-5 > li:before { + content: "\0025cf " + } + + ul.lst-kix_list_27-8 { + list-style-type: none + } + + ul.lst-kix_list_27-7 { + list-style-type: none + } + + ul.lst-kix_list_27-6 { + list-style-type: none + } + + ul.lst-kix_list_27-5 { + list-style-type: none + } + + ul.lst-kix_list_27-4 { + list-style-type: none + } + + ol.lst-kix_list_25-1.start { + counter-reset: lst-ctn-kix_list_25-1 0 + } + + ul.lst-kix_list_27-3 { + list-style-type: none + } + + ol.lst-kix_list_19-7.start { + counter-reset: lst-ctn-kix_list_19-7 0 + } + + .lst-kix_list_2-6 > li:before { + content: "\0025cf " + } + + .lst-kix_list_6-5 > li:before { + content: "" counter(lst-ctn-kix_list_6-0, decimal) "." counter(lst-ctn-kix_list_6-1, decimal) "." counter(lst-ctn-kix_list_6-2, decimal) "." counter(lst-ctn-kix_list_6-3, decimal) "." counter(lst-ctn-kix_list_6-4, decimal) "." counter(lst-ctn-kix_list_6-5, decimal) " " + } + + .lst-kix_list_17-4 > li { + counter-increment: lst-ctn-kix_list_17-4 + } + + ul.lst-kix_list_23-7 { + list-style-type: none + } + + .lst-kix_list_28-5 > li:before { + content: "\0025aa " + } + + ul.lst-kix_list_23-8 { + list-style-type: none + } + + ol.lst-kix_list_25-0.start { + counter-reset: lst-ctn-kix_list_25-0 1 + } + + .lst-kix_list_34-7 > li:before { + content: "o " + } + + ul.lst-kix_list_23-4 { + list-style-type: none + } + + .lst-kix_list_20-7 > li { + counter-increment: lst-ctn-kix_list_20-7 + } + + ul.lst-kix_list_23-3 { + list-style-type: none + } + + ul.lst-kix_list_23-6 { + list-style-type: none + } + + ol.lst-kix_list_14-3.start { + counter-reset: lst-ctn-kix_list_14-3 0 + } + + ul.lst-kix_list_23-5 { + list-style-type: none + } + + ol.lst-kix_list_14-6.start { + counter-reset: lst-ctn-kix_list_14-6 0 + } + + ul.lst-kix_list_23-0 { + list-style-type: none + } + + ol.lst-kix_list_17-6.start { + counter-reset: lst-ctn-kix_list_17-6 0 + } + + ul.lst-kix_list_23-2 { + list-style-type: none + } + + ul.lst-kix_list_23-1 { + list-style-type: none + } + + .lst-kix_list_49-5 > li:before { + content: "\0025aa " + } + + .lst-kix_list_20-6 > li:before { + content: "" counter(lst-ctn-kix_list_20-0, decimal) "." counter(lst-ctn-kix_list_20-1, decimal) "." counter(lst-ctn-kix_list_20-2, decimal) "." counter(lst-ctn-kix_list_20-3, decimal) "." counter(lst-ctn-kix_list_20-4, decimal) "." counter(lst-ctn-kix_list_20-5, decimal) "." counter(lst-ctn-kix_list_20-6, decimal) " " + } + + ol.lst-kix_list_10-0 { + list-style-type: none + } + + .lst-kix_list_9-0 > li:before { + content: "\002751 " + } + + .lst-kix_list_49-4 > li:before { + content: "o " + } + + .lst-kix_list_14-5 > li { + counter-increment: lst-ctn-kix_list_14-5 + } + + .lst-kix_list_7-0 > li:before { + content: "" counter(lst-ctn-kix_list_7-0, lower-latin) ". " + } + + .lst-kix_list_19-6 > li { + counter-increment: lst-ctn-kix_list_19-6 + } + + .lst-kix_list_3-5 > li:before { + content: "\0025cf " + } + + .lst-kix_list_44-6 > li:before { + content: "\0025cf " + } + + .lst-kix_list_29-3 > li:before { + content: "\0025cf " + } + + .lst-kix_list_17-1 > li { + counter-increment: lst-ctn-kix_list_17-1 + } + + ol.lst-kix_list_7-0.start { + counter-reset: lst-ctn-kix_list_7-0 0 + } + + .lst-kix_list_19-3 > li:before { + content: "" counter(lst-ctn-kix_list_19-0, decimal) "." counter(lst-ctn-kix_list_19-1, decimal) "." counter(lst-ctn-kix_list_19-2, decimal) "." counter(lst-ctn-kix_list_19-3, decimal) " " + } + + .lst-kix_list_19-3 > li { + counter-increment: lst-ctn-kix_list_19-3 + } + + .lst-kix_list_10-0 > li { + counter-increment: lst-ctn-kix_list_10-0 + } + + .lst-kix_list_4-6 > li:before { + content: "\0025cf " + } + + .lst-kix_list_17-8 > li:before { + content: "" counter(lst-ctn-kix_list_17-0, decimal) "." counter(lst-ctn-kix_list_17-1, decimal) "." counter(lst-ctn-kix_list_17-2, decimal) "." counter(lst-ctn-kix_list_17-3, decimal) "." counter(lst-ctn-kix_list_17-4, decimal) "." counter(lst-ctn-kix_list_17-5, decimal) "." counter(lst-ctn-kix_list_17-6, decimal) "." counter(lst-ctn-kix_list_17-7, decimal) "." counter(lst-ctn-kix_list_17-8, decimal) " " + } + + ol.lst-kix_list_6-4 { + list-style-type: none + } + + ol.lst-kix_list_6-5 { + list-style-type: none + } + + .lst-kix_list_16-3 > li { + counter-increment: lst-ctn-kix_list_16-3 + } + + ol.lst-kix_list_6-2 { + list-style-type: none + } + + .lst-kix_list_20-2 > li { + counter-increment: lst-ctn-kix_list_20-2 + } + + ol.lst-kix_list_6-3 { + list-style-type: none + } + + ol.lst-kix_list_20-1 { + list-style-type: none + } + + ol.lst-kix_list_6-8 { + list-style-type: none + } + + ol.lst-kix_list_20-0 { + list-style-type: none + } + + ol.lst-kix_list_20-3 { + list-style-type: none + } + + ol.lst-kix_list_6-6 { + list-style-type: none + } + + ol.lst-kix_list_20-2 { + list-style-type: none + } + + .lst-kix_list_12-5 > li:before { + content: "\0025cf " + } + + ol.lst-kix_list_6-7 { + list-style-type: none + } + + ol.lst-kix_list_20-4 { + list-style-type: none + } + + ol.lst-kix_list_20-5 { + list-style-type: none + } + + .lst-kix_list_3-0 > li:before { + content: "\0025cf " + } + + ol.lst-kix_list_20-6 { + list-style-type: none + } + + ol.lst-kix_list_20-7 { + list-style-type: none + } + + ol.lst-kix_list_20-8 { + list-style-type: none + } + + .lst-kix_list_12-2 > li:before { + content: "\0025cf " + } + + ol.lst-kix_list_6-1 { + list-style-type: none + } + + .lst-kix_list_19-7 > li:before { + content: "" counter(lst-ctn-kix_list_19-0, decimal) "." counter(lst-ctn-kix_list_19-1, decimal) "." counter(lst-ctn-kix_list_19-2, decimal) "." counter(lst-ctn-kix_list_19-3, decimal) "." counter(lst-ctn-kix_list_19-4, decimal) "." counter(lst-ctn-kix_list_19-5, decimal) "." counter(lst-ctn-kix_list_19-6, decimal) "." counter(lst-ctn-kix_list_19-7, decimal) " " + } + + ol.lst-kix_list_6-0 { + list-style-type: none + } + + .lst-kix_list_5-4 > li:before { + content: "\0025cf " + } + + .lst-kix_list_32-3 > li:before { + content: "\0025cf " + } + + .lst-kix_list_33-7 > li:before { + content: "o " + } + + ol.lst-kix_list_6-6.start { + counter-reset: lst-ctn-kix_list_6-6 0 + } + + ol.lst-kix_list_42-0.start { + counter-reset: lst-ctn-kix_list_42-0 0 + } + + ol.lst-kix_list_42-5.start { + counter-reset: lst-ctn-kix_list_42-5 0 + } + + .lst-kix_list_6-5 > li { + counter-increment: lst-ctn-kix_list_6-5 + } + + ol.lst-kix_list_14-2.start { + counter-reset: lst-ctn-kix_list_14-2 0 + } + + ol.lst-kix_list_18-7.start { + counter-reset: lst-ctn-kix_list_18-7 0 + } + + ol.lst-kix_list_17-2 { + list-style-type: none + } + + ol.lst-kix_list_17-3 { + list-style-type: none + } + + ol.lst-kix_list_17-0 { + list-style-type: none + } + + ol.lst-kix_list_17-1 { + list-style-type: none + } + + ol.lst-kix_list_17-6 { + list-style-type: none + } + + ol.lst-kix_list_17-7 { + list-style-type: none + } + + ol.lst-kix_list_17-4 { + list-style-type: none + } + + ol.lst-kix_list_17-5 { + list-style-type: none + } + + .lst-kix_list_25-1 > li { + counter-increment: lst-ctn-kix_list_25-1 + } + + .lst-kix_list_10-8 > li:before { + content: "\0025cf " + } + + .lst-kix_list_35-3 > li:before { + content: "\0025cf " + } + + ol.lst-kix_list_17-8 { + list-style-type: none + } + + .lst-kix_list_6-2 > li { + counter-increment: lst-ctn-kix_list_6-2 + } + + .lst-kix_list_13-5 > li:before { + content: "\0025cf " + } + + .lst-kix_list_13-0 > li:before { + content: "\0025cf " + } + + .lst-kix_list_34-1 > li:before { + content: "o " + } + + .lst-kix_list_44-4 > li:before { + content: "o " + } + + ol.lst-kix_list_21-3.start { + counter-reset: lst-ctn-kix_list_21-3 0 + } + + .lst-kix_list_19-2 > li { + counter-increment: lst-ctn-kix_list_19-2 + } + + .lst-kix_list_6-7 > li { + counter-increment: lst-ctn-kix_list_6-7 + } + + .lst-kix_list_45-7 > li:before { + content: "o " + } + + ol.lst-kix_list_14-4.start { + counter-reset: lst-ctn-kix_list_14-4 0 + } + + .lst-kix_list_43-3 > li:before { + content: "\0025cf " + } + + .lst-kix_list_42-5 > li { + counter-increment: lst-ctn-kix_list_42-5 + } + + .lst-kix_list_32-5 > li:before { + content: "\0025cf " + } + + .lst-kix_list_32-6 > li:before { + content: "\0025cf " + } + + .lst-kix_list_15-5 > li:before { + content: "" counter(lst-ctn-kix_list_15-0, decimal) "." counter(lst-ctn-kix_list_15-1, decimal) "." counter(lst-ctn-kix_list_15-2, decimal) "." counter(lst-ctn-kix_list_15-3, decimal) "." counter(lst-ctn-kix_list_15-4, decimal) "." counter(lst-ctn-kix_list_15-5, decimal) " " + } + + .lst-kix_list_6-3 > li:before { + content: "" counter(lst-ctn-kix_list_6-0, decimal) "." counter(lst-ctn-kix_list_6-1, decimal) "." counter(lst-ctn-kix_list_6-2, decimal) "." counter(lst-ctn-kix_list_6-3, decimal) " " + } + + .lst-kix_list_44-8 > li:before { + content: "\0025aa " + } + + .lst-kix_list_11-3 > li:before { + content: "\0025cf " + } + + .lst-kix_list_37-0 > li:before { + content: "\0025cf " + } + + .lst-kix_list_20-4 > li { + counter-increment: lst-ctn-kix_list_20-4 + } + + ol.lst-kix_list_17-5.start { + counter-reset: lst-ctn-kix_list_17-5 0 + } + + .lst-kix_list_31-6 > li:before { + content: "\0025cf " + } + + .lst-kix_list_24-8 > li:before { + content: "\0025cf " + } + + ol.lst-kix_list_15-4.start { + counter-reset: lst-ctn-kix_list_15-4 0 + } + + .lst-kix_list_27-2 > li:before { + content: "\0025aa " + } + + .lst-kix_list_45-1 > li:before { + content: "o " + } + + .lst-kix_list_37-7 > li:before { + content: "o " + } + + .lst-kix_list_3-6 > li:before { + content: "\0025cf " + } + + .lst-kix_list_41-6 > li:before { + content: "\0025cf " + } + + ol.lst-kix_list_16-3.start { + counter-reset: lst-ctn-kix_list_16-3 0 + } + + .lst-kix_list_22-0 > li:before { + content: "\0025cf " + } + + .lst-kix_list_26-3 > li:before { + content: "\0025cf " + } + + .lst-kix_list_38-5 > li:before { + content: "\0025aa " + } + + .lst-kix_list_34-5 > li:before { + content: "\0025aa " + } + + ol.lst-kix_list_42-8 { + list-style-type: none + } + + ol.lst-kix_list_42-7 { + list-style-type: none + } + + ol.lst-kix_list_42-6 { + list-style-type: none + } + + ol.lst-kix_list_42-5 { + list-style-type: none + } + + ol.lst-kix_list_42-4 { + list-style-type: none + } + + ol.lst-kix_list_42-2 { + list-style-type: none + } + + ol.lst-kix_list_42-3 { + list-style-type: none + } + + ol.lst-kix_list_42-0 { + list-style-type: none + } + + ol.lst-kix_list_42-1 { + list-style-type: none + } + + .lst-kix_list_5-5 > li:before { + content: "\0025cf " + } + + .lst-kix_list_19-7 > li { + counter-increment: lst-ctn-kix_list_19-7 + } + + .lst-kix_list_18-5 > li { + counter-increment: lst-ctn-kix_list_18-5 + } + + ol.lst-kix_list_17-0.start { + counter-reset: lst-ctn-kix_list_17-0 1 + } + + .lst-kix_list_39-4 > li:before { + content: "o " + } + + .lst-kix_list_9-2 > li:before { + content: "\0025cf " + } + + .lst-kix_list_42-3 > li { + counter-increment: lst-ctn-kix_list_42-3 + } + + .lst-kix_list_15-8 > li { + counter-increment: lst-ctn-kix_list_15-8 + } + + ul.lst-kix_list_28-2 { + list-style-type: none + } + + ol.lst-kix_list_16-1 { + list-style-type: none + } + + ul.lst-kix_list_28-3 { + list-style-type: none + } + + ol.lst-kix_list_16-2 { + list-style-type: none + } + + ul.lst-kix_list_28-4 { + list-style-type: none + } + + ol.lst-kix_list_16-3 { + list-style-type: none + } + + ul.lst-kix_list_28-5 { + list-style-type: none + } + + .lst-kix_list_28-1 > li:before { + content: "o " + } + + ol.lst-kix_list_16-4 { + list-style-type: none + } + + .lst-kix_list_44-1 > li:before { + content: "o " + } + + ul.lst-kix_list_28-6 { + list-style-type: none + } + + ul.lst-kix_list_28-7 { + list-style-type: none + } + + ul.lst-kix_list_28-8 { + list-style-type: none + } + + .lst-kix_list_20-4 > li:before { + content: "" counter(lst-ctn-kix_list_20-0, decimal) "." counter(lst-ctn-kix_list_20-1, decimal) "." counter(lst-ctn-kix_list_20-2, decimal) "." counter(lst-ctn-kix_list_20-3, decimal) "." counter(lst-ctn-kix_list_20-4, decimal) " " + } + + ol.lst-kix_list_16-0 { + list-style-type: none + } + + .lst-kix_list_41-4 > li:before { + content: "o " + } + + .lst-kix_list_32-1 > li:before { + content: "\0025cf " + } + + .lst-kix_list_31-8 > li:before { + content: "\0025aa " + } + + ol.lst-kix_list_16-5 { + list-style-type: none + } + + .lst-kix_list_42-5 > li:before { + content: "" counter(lst-ctn-kix_list_42-5, lower-roman) ". " + } + + .lst-kix_list_28-2 > li:before { + content: "\0025aa " + } + + ol.lst-kix_list_16-6 { + list-style-type: none + } + + ol.lst-kix_list_16-7 { + list-style-type: none + } + + ol.lst-kix_list_16-8 { + list-style-type: none + } + + .lst-kix_list_38-0 > li:before { + content: "\0025cf " + } + + .lst-kix_list_30-1 > li:before { + content: "o " + } + + .lst-kix_list_5-8 > li:before { + content: "\0025cf " + } + + .lst-kix_list_14-5 > li:before { + content: "" counter(lst-ctn-kix_list_14-0, decimal) "." counter(lst-ctn-kix_list_14-1, decimal) "." counter(lst-ctn-kix_list_14-2, decimal) "." counter(lst-ctn-kix_list_14-3, decimal) "." counter(lst-ctn-kix_list_14-4, decimal) "." counter(lst-ctn-kix_list_14-5, decimal) " " + } + + .lst-kix_list_40-1 > li:before { + content: "o " + } + + ol.lst-kix_list_19-8.start { + counter-reset: lst-ctn-kix_list_19-8 0 + } + + ul.lst-kix_list_28-1 { + list-style-type: none + } + + .lst-kix_list_42-3 > li:before { + content: "" counter(lst-ctn-kix_list_42-3, decimal) ". " + } + + ul.lst-kix_list_28-0 { + list-style-type: none + } + + ul.lst-kix_list_22-6 { + list-style-type: none + } + + ul.lst-kix_list_22-7 { + list-style-type: none + } + + ul.lst-kix_list_22-4 { + list-style-type: none + } + + ul.lst-kix_list_22-5 { + list-style-type: none + } + + ul.lst-kix_list_22-2 { + list-style-type: none + } + + ul.lst-kix_list_22-3 { + list-style-type: none + } + + ul.lst-kix_list_22-0 { + list-style-type: none + } + + .lst-kix_list_42-8 > li { + counter-increment: lst-ctn-kix_list_42-8 + } + + ol.lst-kix_list_42-8.start { + counter-reset: lst-ctn-kix_list_42-8 0 + } + + ul.lst-kix_list_22-1 { + list-style-type: none + } + + .lst-kix_list_43-8 > li:before { + content: "\0025aa " + } + + .lst-kix_list_21-1 > li:before { + content: "" counter(lst-ctn-kix_list_21-0, decimal) "." counter(lst-ctn-kix_list_21-1, decimal) " " + } + + .lst-kix_list_15-3 > li:before { + content: "" counter(lst-ctn-kix_list_15-0, decimal) "." counter(lst-ctn-kix_list_15-1, decimal) "." counter(lst-ctn-kix_list_15-2, decimal) "." counter(lst-ctn-kix_list_15-3, decimal) " " + } + + .lst-kix_list_39-5 > li:before { + content: "\0025aa " + } + + .lst-kix_list_11-8 > li:before { + content: "\0025cf " + } + + .lst-kix_list_6-0 > li:before { + content: "" counter(lst-ctn-kix_list_6-0, decimal) " " + } + + .lst-kix_list_40-3 > li:before { + content: "\0025cf " + } + + .lst-kix_list_15-2 > li { + counter-increment: lst-ctn-kix_list_15-2 + } + + .lst-kix_list_28-4 > li:before { + content: "o " + } + + ul.lst-kix_list_22-8 { + list-style-type: none + } + + .lst-kix_list_24-6 > li:before { + content: "\0025cf " + } + + .lst-kix_list_45-8 > li:before { + content: "\0025aa " + } + + .lst-kix_list_42-0 > li { + counter-increment: lst-ctn-kix_list_42-0 + } + + .lst-kix_list_46-2 > li:before { + content: "\0025aa " + } + + ol.lst-kix_list_20-1.start { + counter-reset: lst-ctn-kix_list_20-1 6 + } + + .lst-kix_list_29-1 > li:before { + content: "o " + } + + .lst-kix_list_46-5 > li:before { + content: "\0025aa " + } + + .lst-kix_list_8-7 > li:before { + content: "\0025cf " + } + + .lst-kix_list_1-7 > li:before { + content: "\0025cf " + } + + .lst-kix_list_35-5 > li:before { + content: "\0025aa " + } + + .lst-kix_list_28-8 > li:before { + content: "\0025aa " + } + + .lst-kix_list_33-1 > li:before { + content: "o " + } + + .lst-kix_list_15-0 > li { + counter-increment: lst-ctn-kix_list_15-0 + } + + .lst-kix_list_20-1 > li { + counter-increment: lst-ctn-kix_list_20-1 + } + + .lst-kix_list_7-3 > li:before { + content: "\0025cf " + } + + ul.lst-kix_list_12-8 { + list-style-type: none + } + + .lst-kix_list_30-5 > li:before { + content: "\0025aa " + } + + ul.lst-kix_list_12-7 { + list-style-type: none + } + + .lst-kix_list_1-2 > li:before { + content: "\0025cf " + } + + .lst-kix_list_22-3 > li:before { + content: "\0025cf " + } + + ul.lst-kix_list_12-0 { + list-style-type: none + } + + ul.lst-kix_list_12-1 { + list-style-type: none + } + + ol.lst-kix_list_6-0.start { + counter-reset: lst-ctn-kix_list_6-0 1 + } + + ul.lst-kix_list_12-2 { + list-style-type: none + } + + ul.lst-kix_list_12-3 { + list-style-type: none + } + + .lst-kix_list_19-0 > li:before { + content: "" counter(lst-ctn-kix_list_19-0, decimal) " " + } + + ul.lst-kix_list_12-4 { + list-style-type: none + } + + ul.lst-kix_list_12-5 { + list-style-type: none + } + + .lst-kix_list_25-2 > li { + counter-increment: lst-ctn-kix_list_25-2 + } + + ul.lst-kix_list_12-6 { + list-style-type: none + } + + .lst-kix_list_49-3 > li:before { + content: "\0025cf " + } + + .lst-kix_list_12-3 > li:before { + content: "\0025cf " + } + + .lst-kix_list_38-6 > li:before { + content: "\0025cf " + } + + ol.lst-kix_list_21-0.start { + counter-reset: lst-ctn-kix_list_21-0 0 + } + + ul.lst-kix_list_33-8 { + list-style-type: none + } + + .lst-kix_list_43-0 > li:before { + content: "\0025cf " + } + + .lst-kix_list_48-7 > li:before { + content: "o " + } + + .lst-kix_list_14-4 > li { + counter-increment: lst-ctn-kix_list_14-4 + } + + .lst-kix_list_27-7 > li:before { + content: "o " + } + + .lst-kix_list_2-7 > li:before { + content: "\0025cf " + } + + .lst-kix_list_17-7 > li { + counter-increment: lst-ctn-kix_list_17-7 + } + + ul.lst-kix_list_33-0 { + list-style-type: none + } + + .lst-kix_list_25-0 > li:before { + content: "" counter(lst-ctn-kix_list_25-0, decimal) " " + } + + ul.lst-kix_list_33-1 { + list-style-type: none + } + + ul.lst-kix_list_33-2 { + list-style-type: none + } + + ul.lst-kix_list_33-3 { + list-style-type: none + } + + ol.lst-kix_list_42-7.start { + counter-reset: lst-ctn-kix_list_42-7 0 + } + + ul.lst-kix_list_33-4 { + list-style-type: none + } + + .lst-kix_list_18-2 > li { + counter-increment: lst-ctn-kix_list_18-2 + } + + ul.lst-kix_list_33-5 { + list-style-type: none + } + + .lst-kix_list_14-8 > li:before { + content: "" counter(lst-ctn-kix_list_14-0, decimal) "." counter(lst-ctn-kix_list_14-1, decimal) "." counter(lst-ctn-kix_list_14-2, decimal) "." counter(lst-ctn-kix_list_14-3, decimal) "." counter(lst-ctn-kix_list_14-4, decimal) "." counter(lst-ctn-kix_list_14-5, decimal) "." counter(lst-ctn-kix_list_14-6, decimal) "." counter(lst-ctn-kix_list_14-7, decimal) "." counter(lst-ctn-kix_list_14-8, decimal) " " + } + + ul.lst-kix_list_33-6 { + list-style-type: none + } + + ul.lst-kix_list_33-7 { + list-style-type: none + } + + .lst-kix_list_27-4 > li:before { + content: "o " + } + + ul.lst-kix_list_41-2 { + list-style-type: none + } + + ul.lst-kix_list_41-1 { + list-style-type: none + } + + ul.lst-kix_list_41-0 { + list-style-type: none + } + + ul.lst-kix_list_41-6 { + list-style-type: none + } + + ul.lst-kix_list_41-5 { + list-style-type: none + } + + ol.lst-kix_list_19-6.start { + counter-reset: lst-ctn-kix_list_19-6 0 + } + + ul.lst-kix_list_41-4 { + list-style-type: none + } + + ul.lst-kix_list_41-3 { + list-style-type: none + } + + .lst-kix_list_18-8 > li:before { + content: "" counter(lst-ctn-kix_list_18-0, decimal) "." counter(lst-ctn-kix_list_18-1, decimal) "." counter(lst-ctn-kix_list_18-2, decimal) "." counter(lst-ctn-kix_list_18-3, decimal) "." counter(lst-ctn-kix_list_18-4, decimal) "." counter(lst-ctn-kix_list_18-5, decimal) "." counter(lst-ctn-kix_list_18-6, decimal) "." counter(lst-ctn-kix_list_18-7, decimal) "." counter(lst-ctn-kix_list_18-8, decimal) " " + } + + .lst-kix_list_21-2 > li:before { + content: "" counter(lst-ctn-kix_list_21-0, decimal) "." counter(lst-ctn-kix_list_21-1, decimal) "." counter(lst-ctn-kix_list_21-2, decimal) " " + } + + ul.lst-kix_list_41-8 { + list-style-type: none + } + + ul.lst-kix_list_41-7 { + list-style-type: none + } + + .lst-kix_list_14-4 > li:before { + content: "" counter(lst-ctn-kix_list_14-0, decimal) "." counter(lst-ctn-kix_list_14-1, decimal) "." counter(lst-ctn-kix_list_14-2, decimal) "." counter(lst-ctn-kix_list_14-3, decimal) "." counter(lst-ctn-kix_list_14-4, decimal) " " + } + + ol.lst-kix_list_21-1.start { + counter-reset: lst-ctn-kix_list_21-1 6 + } + + .lst-kix_list_30-3 > li:before { + content: "\0025cf " + } + + .lst-kix_list_26-4 > li:before { + content: "o " + } + + .lst-kix_list_6-1 > li { + counter-increment: lst-ctn-kix_list_6-1 + } + + .lst-kix_list_34-2 > li:before { + content: "\0025aa " + } + + ul.lst-kix_list_45-8 { + list-style-type: none + } + + ul.lst-kix_list_43-2 { + list-style-type: none + } + + .lst-kix_list_4-7 > li:before { + content: "\0025cf " + } + + ul.lst-kix_list_45-7 { + list-style-type: none + } + + ul.lst-kix_list_43-1 { + list-style-type: none + } + + ul.lst-kix_list_43-4 { + list-style-type: none + } + + ul.lst-kix_list_43-3 { + list-style-type: none + } + + ul.lst-kix_list_43-6 { + list-style-type: none + } + + ul.lst-kix_list_43-5 { + list-style-type: none + } + + ul.lst-kix_list_43-8 { + list-style-type: none + } + + .lst-kix_list_14-6 > li { + counter-increment: lst-ctn-kix_list_14-6 + } + + ul.lst-kix_list_43-7 { + list-style-type: none + } + + .lst-kix_list_18-4 > li { + counter-increment: lst-ctn-kix_list_18-4 + } + + .lst-kix_list_37-8 > li:before { + content: "\0025aa " + } + + .lst-kix_list_16-4 > li:before { + content: "" counter(lst-ctn-kix_list_16-0, decimal) "." counter(lst-ctn-kix_list_16-1, decimal) "." counter(lst-ctn-kix_list_16-2, decimal) "." counter(lst-ctn-kix_list_16-3, decimal) "." counter(lst-ctn-kix_list_16-4, decimal) " " + } + + ul.lst-kix_list_43-0 { + list-style-type: none + } + + .lst-kix_list_43-4 > li:before { + content: "o " + } + + .lst-kix_list_17-3 > li { + counter-increment: lst-ctn-kix_list_17-3 + } + + .lst-kix_list_49-1 > li:before { + content: "o " + } + + ul.lst-kix_list_45-0 { + list-style-type: none + } + + ul.lst-kix_list_45-1 { + list-style-type: none + } + + .lst-kix_list_23-8 > li:before { + content: "\0025cf " + } + + ul.lst-kix_list_45-2 { + list-style-type: none + } + + ul.lst-kix_list_45-3 { + list-style-type: none + } + + ul.lst-kix_list_45-4 { + list-style-type: none + } + + ul.lst-kix_list_45-5 { + list-style-type: none + } + + .lst-kix_list_17-1 > li:before { + content: "" counter(lst-ctn-kix_list_17-0, decimal) "." counter(lst-ctn-kix_list_17-1, decimal) " " + } + + ul.lst-kix_list_45-6 { + list-style-type: none + } + + .lst-kix_list_6-6 > li:before { + content: "" counter(lst-ctn-kix_list_6-0, decimal) "." counter(lst-ctn-kix_list_6-1, decimal) "." counter(lst-ctn-kix_list_6-2, decimal) "." counter(lst-ctn-kix_list_6-3, decimal) "." counter(lst-ctn-kix_list_6-4, decimal) "." counter(lst-ctn-kix_list_6-5, decimal) "." counter(lst-ctn-kix_list_6-6, decimal) " " + } + + .lst-kix_list_42-8 > li:before { + content: "" counter(lst-ctn-kix_list_42-8, lower-roman) ". " + } + + .lst-kix_list_21-5 > li { + counter-increment: lst-ctn-kix_list_21-5 + } + + .lst-kix_list_16-6 > li:before { + content: "" counter(lst-ctn-kix_list_16-0, decimal) "." counter(lst-ctn-kix_list_16-1, decimal) "." counter(lst-ctn-kix_list_16-2, decimal) "." counter(lst-ctn-kix_list_16-3, decimal) "." counter(lst-ctn-kix_list_16-4, decimal) "." counter(lst-ctn-kix_list_16-5, decimal) "." counter(lst-ctn-kix_list_16-6, decimal) " " + } + + .lst-kix_list_43-6 > li:before { + content: "\0025cf " + } + + ol.lst-kix_list_16-7.start { + counter-reset: lst-ctn-kix_list_16-7 0 + } + + ul.lst-kix_list_48-1 { + list-style-type: none + } + + ol.lst-kix_list_18-4.start { + counter-reset: lst-ctn-kix_list_18-4 0 + } + + ul.lst-kix_list_48-0 { + list-style-type: none + } + + ul.lst-kix_list_48-3 { + list-style-type: none + } + + ul.lst-kix_list_48-2 { + list-style-type: none + } + + ul.lst-kix_list_46-7 { + list-style-type: none + } + + ul.lst-kix_list_46-6 { + list-style-type: none + } + + ol.lst-kix_list_14-8 { + list-style-type: none + } + + ul.lst-kix_list_46-8 { + list-style-type: none + } + + ol.lst-kix_list_14-7 { + list-style-type: none + } + + ol.lst-kix_list_21-4.start { + counter-reset: lst-ctn-kix_list_21-4 0 + } + + ol.lst-kix_list_14-6 { + list-style-type: none + } + + ol.lst-kix_list_14-5 { + list-style-type: none + } + + ol.lst-kix_list_14-4 { + list-style-type: none + } + + .lst-kix_list_5-3 > li:before { + content: "\0025cf " + } + + ol.lst-kix_list_14-3 { + list-style-type: none + } + + ol.lst-kix_list_14-2 { + list-style-type: none + } + + ol.lst-kix_list_14-1 { + list-style-type: none + } + + ol.lst-kix_list_14-0 { + list-style-type: none + } + + .lst-kix_list_11-0 > li:before { + content: "" counter(lst-ctn-kix_list_11-0, decimal) ". " + } + + ul.lst-kix_list_46-2 { + list-style-type: none + } + + ul.lst-kix_list_48-8 { + list-style-type: none + } + + ul.lst-kix_list_46-3 { + list-style-type: none + } + + ul.lst-kix_list_46-4 { + list-style-type: none + } + + ul.lst-kix_list_46-5 { + list-style-type: none + } + + ul.lst-kix_list_48-4 { + list-style-type: none + } + + ul.lst-kix_list_48-5 { + list-style-type: none + } + + ul.lst-kix_list_46-0 { + list-style-type: none + } + + ul.lst-kix_list_48-6 { + list-style-type: none + } + + ul.lst-kix_list_46-1 { + list-style-type: none + } + + ul.lst-kix_list_48-7 { + list-style-type: none + } + + .lst-kix_list_19-4 > li { + counter-increment: lst-ctn-kix_list_19-4 + } + + .lst-kix_list_47-4 > li:before { + content: "o " + } + + .lst-kix_list_16-2 > li { + counter-increment: lst-ctn-kix_list_16-2 + } + + .lst-kix_list_20-6 > li { + counter-increment: lst-ctn-kix_list_20-6 + } + + .lst-kix_list_8-0 > li { + counter-increment: lst-ctn-kix_list_8-0 + } + + ul.lst-kix_list_4-8 { + list-style-type: none + } + + ul.lst-kix_list_4-7 { + list-style-type: none + } + + ul.lst-kix_list_4-6 { + list-style-type: none + } + + .lst-kix_list_17-2 > li:before { + content: "" counter(lst-ctn-kix_list_17-0, decimal) "." counter(lst-ctn-kix_list_17-1, decimal) "." counter(lst-ctn-kix_list_17-2, decimal) " " + } + + .lst-kix_list_11-4 > li:before { + content: "\0025cf " + } + + ul.lst-kix_list_4-1 { + list-style-type: none + } + + .lst-kix_list_48-8 > li:before { + content: "\0025aa " + } + + ul.lst-kix_list_4-0 { + list-style-type: none + } + + .lst-kix_list_7-5 > li:before { + content: "\0025cf " + } + + .lst-kix_list_46-3 > li:before { + content: "\0025cf " + } + + .lst-kix_list_10-4 > li:before { + content: "\0025cf " + } + + ul.lst-kix_list_4-5 { + list-style-type: none + } + + ul.lst-kix_list_4-4 { + list-style-type: none + } + + .lst-kix_list_25-6 > li { + counter-increment: lst-ctn-kix_list_25-6 + } + + ul.lst-kix_list_4-3 { + list-style-type: none + } + + ul.lst-kix_list_4-2 { + list-style-type: none + } + + .lst-kix_list_27-1 > li:before { + content: "o " + } + + .lst-kix_list_25-7 > li { + counter-increment: lst-ctn-kix_list_25-7 + } + + .lst-kix_list_26-8 > li:before { + content: "\0025aa " + } + + .lst-kix_list_49-6 > li:before { + content: "\0025cf " + } + + .lst-kix_list_30-7 > li:before { + content: "o " + } + + ol.lst-kix_list_18-6.start { + counter-reset: lst-ctn-kix_list_18-6 0 + } + + .lst-kix_list_15-6 > li:before { + content: "" counter(lst-ctn-kix_list_15-0, decimal) "." counter(lst-ctn-kix_list_15-1, decimal) "." counter(lst-ctn-kix_list_15-2, decimal) "." counter(lst-ctn-kix_list_15-3, decimal) "." counter(lst-ctn-kix_list_15-4, decimal) "." counter(lst-ctn-kix_list_15-5, decimal) "." counter(lst-ctn-kix_list_15-6, decimal) " " + } + + .lst-kix_list_18-4 > li:before { + content: "" counter(lst-ctn-kix_list_18-0, decimal) "." counter(lst-ctn-kix_list_18-1, decimal) "." counter(lst-ctn-kix_list_18-2, decimal) "." counter(lst-ctn-kix_list_18-3, decimal) "." counter(lst-ctn-kix_list_18-4, decimal) " " + } + + .lst-kix_list_10-5 > li:before { + content: "\0025cf " + } + + .lst-kix_list_48-5 > li:before { + content: "\0025aa " + } + + .lst-kix_list_17-2 > li { + counter-increment: lst-ctn-kix_list_17-2 + } + + ul.lst-kix_list_35-8 { + list-style-type: none + } + + ul.lst-kix_list_35-6 { + list-style-type: none + } + + ul.lst-kix_list_35-7 { + list-style-type: none + } + + .lst-kix_list_45-3 > li:before { + content: "\0025cf " + } + + .lst-kix_list_6-6 > li { + counter-increment: lst-ctn-kix_list_6-6 + } + + ul.lst-kix_list_35-5 { + list-style-type: none + } + + ul.lst-kix_list_35-4 { + list-style-type: none + } + + ul.lst-kix_list_35-3 { + list-style-type: none + } + + ul.lst-kix_list_35-2 { + list-style-type: none + } + + .lst-kix_list_17-3 > li:before { + content: "" counter(lst-ctn-kix_list_17-0, decimal) "." counter(lst-ctn-kix_list_17-1, decimal) "." counter(lst-ctn-kix_list_17-2, decimal) "." counter(lst-ctn-kix_list_17-3, decimal) " " + } + + ul.lst-kix_list_35-1 { + list-style-type: none + } + + ul.lst-kix_list_35-0 { + list-style-type: none + } + + .lst-kix_list_15-2 > li:before { + content: "" counter(lst-ctn-kix_list_15-0, decimal) "." counter(lst-ctn-kix_list_15-1, decimal) "." counter(lst-ctn-kix_list_15-2, decimal) " " + } + + .lst-kix_list_6-2 > li:before { + content: "" counter(lst-ctn-kix_list_6-0, decimal) "." counter(lst-ctn-kix_list_6-1, decimal) "." counter(lst-ctn-kix_list_6-2, decimal) " " + } + + .lst-kix_list_19-1 > li:before { + content: "" counter(lst-ctn-kix_list_19-0, decimal) "." counter(lst-ctn-kix_list_19-1, decimal) " " + } + + ul.lst-kix_list_39-0 { + list-style-type: none + } + + ul.lst-kix_list_39-1 { + list-style-type: none + } + + .lst-kix_list_6-3 > li { + counter-increment: lst-ctn-kix_list_6-3 + } + + ol.lst-kix_list_10-0.start { + counter-reset: lst-ctn-kix_list_10-0 0 + } + + .lst-kix_list_19-0 > li { + counter-increment: lst-ctn-kix_list_19-0 + } + + ol.lst-kix_list_6-4.start { + counter-reset: lst-ctn-kix_list_6-4 0 + } + + ul.lst-kix_list_39-7 { + list-style-type: none + } + + ol.lst-kix_list_16-0.start { + counter-reset: lst-ctn-kix_list_16-0 1 + } + + ul.lst-kix_list_39-6 { + list-style-type: none + } + + ul.lst-kix_list_39-8 { + list-style-type: none + } + + ol.lst-kix_list_25-4.start { + counter-reset: lst-ctn-kix_list_25-4 0 + } + + ul.lst-kix_list_39-3 { + list-style-type: none + } + + ul.lst-kix_list_39-2 { + list-style-type: none + } + + .lst-kix_list_15-4 > li { + counter-increment: lst-ctn-kix_list_15-4 + } + + ul.lst-kix_list_39-5 { + list-style-type: none + } + + ul.lst-kix_list_39-4 { + list-style-type: none + } + + ol.lst-kix_list_16-2.start { + counter-reset: lst-ctn-kix_list_16-2 0 + } + + ol.lst-kix_list_21-2.start { + counter-reset: lst-ctn-kix_list_21-2 0 + } + + .lst-kix_list_31-3 > li:before { + content: "\0025cf " + } + + ol.lst-kix_list_14-1.start { + counter-reset: lst-ctn-kix_list_14-1 12 + } + + ol.lst-kix_list_18-1.start { + counter-reset: lst-ctn-kix_list_18-1 6 + } + + .lst-kix_list_28-3 > li:before { + content: "\0025cf " + } + + .lst-kix_list_8-4 > li:before { + content: "\0025cf " + } + + .lst-kix_list_47-1 > li:before { + content: "o " + } + + .lst-kix_list_15-7 > li { + counter-increment: lst-ctn-kix_list_15-7 + } + + .lst-kix_list_26-7 > li:before { + content: "o " + } + + .lst-kix_list_12-1 > li:before { + content: "\0025cf " + } + + ol.lst-kix_list_14-8.start { + counter-reset: lst-ctn-kix_list_14-8 0 + } + + .lst-kix_list_31-4 > li:before { + content: "o " + } + + .lst-kix_list_20-3 > li:before { + content: "" counter(lst-ctn-kix_list_20-0, decimal) "." counter(lst-ctn-kix_list_20-1, decimal) "." counter(lst-ctn-kix_list_20-2, decimal) "." counter(lst-ctn-kix_list_20-3, decimal) " " + } + + .lst-kix_list_19-5 > li { + counter-increment: lst-ctn-kix_list_19-5 + } + + .lst-kix_list_49-2 > li:before { + content: "\0025aa " + } + + .lst-kix_list_16-3 > li:before { + content: "" counter(lst-ctn-kix_list_16-0, decimal) "." counter(lst-ctn-kix_list_16-1, decimal) "." counter(lst-ctn-kix_list_16-2, decimal) "." counter(lst-ctn-kix_list_16-3, decimal) " " + } + + .lst-kix_list_25-0 > li { + counter-increment: lst-ctn-kix_list_25-0 + } + + .lst-kix_list_34-4 > li:before { + content: "o " + } + + .lst-kix_list_39-3 > li:before { + content: "\0025cf " + } + + ol.lst-kix_list_8-0.start { + counter-reset: lst-ctn-kix_list_8-0 3 + } + + .lst-kix_list_4-2 > li:before { + content: "\0025cf " + } + + ol.lst-kix_list_17-8.start { + counter-reset: lst-ctn-kix_list_17-8 0 + } + + .lst-kix_list_24-4 > li:before { + content: "\0025cf " + } + + .lst-kix_list_47-8 > li:before { + content: "\0025aa " + } + + .lst-kix_list_42-1 > li:before { + content: "" counter(lst-ctn-kix_list_42-1, lower-latin) ". " + } + + .lst-kix_list_17-6 > li:before { + content: "" counter(lst-ctn-kix_list_17-0, decimal) "." counter(lst-ctn-kix_list_17-1, decimal) "." counter(lst-ctn-kix_list_17-2, decimal) "." counter(lst-ctn-kix_list_17-3, decimal) "." counter(lst-ctn-kix_list_17-4, decimal) "." counter(lst-ctn-kix_list_17-5, decimal) "." counter(lst-ctn-kix_list_17-6, decimal) " " + } + + .lst-kix_list_21-8 > li:before { + content: "" counter(lst-ctn-kix_list_21-0, decimal) "." counter(lst-ctn-kix_list_21-1, decimal) "." counter(lst-ctn-kix_list_21-2, decimal) "." counter(lst-ctn-kix_list_21-3, decimal) "." counter(lst-ctn-kix_list_21-4, decimal) "." counter(lst-ctn-kix_list_21-5, decimal) "." counter(lst-ctn-kix_list_21-6, decimal) "." counter(lst-ctn-kix_list_21-7, decimal) "." counter(lst-ctn-kix_list_21-8, decimal) " " + } + + ol.lst-kix_list_42-4.start { + counter-reset: lst-ctn-kix_list_42-4 0 + } + + .lst-kix_list_31-5 > li:before { + content: "\0025aa " + } + + .lst-kix_list_18-5 > li:before { + content: "" counter(lst-ctn-kix_list_18-0, decimal) "." counter(lst-ctn-kix_list_18-1, decimal) "." counter(lst-ctn-kix_list_18-2, decimal) "." counter(lst-ctn-kix_list_18-3, decimal) "." counter(lst-ctn-kix_list_18-4, decimal) "." counter(lst-ctn-kix_list_18-5, decimal) " " + } + + .lst-kix_list_3-4 > li:before { + content: "\0025cf " + } + + .lst-kix_list_36-0 > li:before { + content: "\0025cf " + } + + .lst-kix_list_18-6 > li:before { + content: "" counter(lst-ctn-kix_list_18-0, decimal) "." counter(lst-ctn-kix_list_18-1, decimal) "." counter(lst-ctn-kix_list_18-2, decimal) "." counter(lst-ctn-kix_list_18-3, decimal) "." counter(lst-ctn-kix_list_18-4, decimal) "." counter(lst-ctn-kix_list_18-5, decimal) "." counter(lst-ctn-kix_list_18-6, decimal) " " + } + + .lst-kix_list_27-0 > li:before { + content: "\0025cf " + } + + ul.lst-kix_list_26-4 { + list-style-type: none + } + + ul.lst-kix_list_32-3 { + list-style-type: none + } + + ul.lst-kix_list_26-5 { + list-style-type: none + } + + ul.lst-kix_list_32-4 { + list-style-type: none + } + + ul.lst-kix_list_26-6 { + list-style-type: none + } + + ul.lst-kix_list_32-1 { + list-style-type: none + } + + ul.lst-kix_list_24-0 { + list-style-type: none + } + + ul.lst-kix_list_24-1 { + list-style-type: none + } + + ul.lst-kix_list_26-7 { + list-style-type: none + } + + ul.lst-kix_list_32-2 { + list-style-type: none + } + + ul.lst-kix_list_24-2 { + list-style-type: none + } + + ul.lst-kix_list_26-8 { + list-style-type: none + } + + .lst-kix_list_26-1 > li:before { + content: "o " + } + + ul.lst-kix_list_32-7 { + list-style-type: none + } + + ul.lst-kix_list_24-3 { + list-style-type: none + } + + ul.lst-kix_list_32-8 { + list-style-type: none + } + + ul.lst-kix_list_24-4 { + list-style-type: none + } + + .lst-kix_list_49-7 > li:before { + content: "o " + } + + ol.lst-kix_list_32-0 { + list-style-type: none + } + + ul.lst-kix_list_32-5 { + list-style-type: none + } + + ul.lst-kix_list_24-5 { + list-style-type: none + } + + ul.lst-kix_list_32-6 { + list-style-type: none + } + + ul.lst-kix_list_24-7 { + list-style-type: none + } + + ul.lst-kix_list_24-6 { + list-style-type: none + } + + .lst-kix_list_12-4 > li:before { + content: "\0025cf " + } + + ul.lst-kix_list_24-8 { + list-style-type: none + } + + ul.lst-kix_list_26-1 { + list-style-type: none + } + + .lst-kix_list_43-1 > li:before { + content: "o " + } + + ul.lst-kix_list_26-0 { + list-style-type: none + } + + ul.lst-kix_list_26-3 { + list-style-type: none + } + + ul.lst-kix_list_26-2 { + list-style-type: none + } + + ol.lst-kix_list_17-7.start { + counter-reset: lst-ctn-kix_list_17-7 0 + } + + .lst-kix_list_25-8 > li { + counter-increment: lst-ctn-kix_list_25-8 + } + + .lst-kix_list_11-1 > li:before { + content: "\0025cf " + } + + ol.lst-kix_list_14-5.start { + counter-reset: lst-ctn-kix_list_14-5 0 + } + + .lst-kix_list_33-4 > li:before { + content: "o " + } + + .lst-kix_list_46-1 > li:before { + content: "o " + } + + .lst-kix_list_44-2 > li:before { + content: "\0025aa " + } + + ol.lst-kix_list_19-0.start { + counter-reset: lst-ctn-kix_list_19-0 0 + } + + .lst-kix_list_17-4 > li:before { + content: "" counter(lst-ctn-kix_list_17-0, decimal) "." counter(lst-ctn-kix_list_17-1, decimal) "." counter(lst-ctn-kix_list_17-2, decimal) "." counter(lst-ctn-kix_list_17-3, decimal) "." counter(lst-ctn-kix_list_17-4, decimal) " " + } + + .lst-kix_list_48-4 > li:before { + content: "o " + } + + .lst-kix_list_47-3 > li:before { + content: "\0025cf " + } + + .lst-kix_list_14-3 > li { + counter-increment: lst-ctn-kix_list_14-3 + } + + .lst-kix_list_3-1 > li:before { + content: "\0025cf " + } + + ul.lst-kix_list_2-4 { + list-style-type: none + } + + ol.lst-kix_list_19-2.start { + counter-reset: lst-ctn-kix_list_19-2 0 + } + + ul.lst-kix_list_2-5 { + list-style-type: none + } + + ul.lst-kix_list_2-6 { + list-style-type: none + } + + ul.lst-kix_list_2-7 { + list-style-type: none + } + + ul.lst-kix_list_2-0 { + list-style-type: none + } + + .lst-kix_list_45-2 > li:before { + content: "\0025aa " + } + + .lst-kix_list_42-7 > li:before { + content: "" counter(lst-ctn-kix_list_42-7, lower-latin) ". " + } + + ul.lst-kix_list_2-1 { + list-style-type: none + } + + .lst-kix_list_23-3 > li:before { + content: "\0025cf " + } + + ul.lst-kix_list_2-2 { + list-style-type: none + } + + ul.lst-kix_list_2-3 { + list-style-type: none + } + + ol.lst-kix_list_18-0.start { + counter-reset: lst-ctn-kix_list_18-0 0 + } + + .lst-kix_list_15-3 > li { + counter-increment: lst-ctn-kix_list_15-3 + } + + .lst-kix_list_21-1 > li { + counter-increment: lst-ctn-kix_list_21-1 + } + + ul.lst-kix_list_2-8 { + list-style-type: none + } + + .lst-kix_list_9-7 > li:before { + content: "\0025cf " + } + + .lst-kix_list_23-2 > li:before { + content: "\0025cf " + } + + .lst-kix_list_22-6 > li:before { + content: "\0025cf " + } + + .lst-kix_list_15-0 > li:before { + content: "" counter(lst-ctn-kix_list_15-0, decimal) " " + } + + .lst-kix_list_11-0 > li { + counter-increment: lst-ctn-kix_list_11-0 + } + + .lst-kix_list_3-2 > li:before { + content: "\0025cf " + } + + .lst-kix_list_24-0 > li:before { + content: "\0025cf " + } + + .lst-kix_list_7-0 > li { + counter-increment: lst-ctn-kix_list_7-0 + } + + .lst-kix_list_32-8 > li:before { + content: "\0025cf " + } + + .lst-kix_list_29-4 > li:before { + content: "o " + } + + .lst-kix_list_36-7 > li:before { + content: "o " + } + + .lst-kix_list_39-7 > li:before { + content: "o " + } + + .lst-kix_list_17-5 > li:before { + content: "" counter(lst-ctn-kix_list_17-0, decimal) "." counter(lst-ctn-kix_list_17-1, decimal) "." counter(lst-ctn-kix_list_17-2, decimal) "." counter(lst-ctn-kix_list_17-3, decimal) "." counter(lst-ctn-kix_list_17-4, decimal) "." counter(lst-ctn-kix_list_17-5, decimal) " " + } + + ul.lst-kix_list_10-7 { + list-style-type: none + } + + ul.lst-kix_list_10-8 { + list-style-type: none + } + + ul.lst-kix_list_10-5 { + list-style-type: none + } + + .lst-kix_list_39-1 > li:before { + content: "o " + } + + .lst-kix_list_11-5 > li:before { + content: "\0025cf " + } + + ul.lst-kix_list_10-6 { + list-style-type: none + } + + .lst-kix_list_11-2 > li:before { + content: "\0025cf " + } + + ul.lst-kix_list_10-3 { + list-style-type: none + } + + ul.lst-kix_list_10-4 { + list-style-type: none + } + + .lst-kix_list_22-5 > li:before { + content: "\0025cf " + } + + ul.lst-kix_list_10-1 { + list-style-type: none + } + + .lst-kix_list_1-4 > li:before { + content: "\0025cf " + } + + ul.lst-kix_list_10-2 { + list-style-type: none + } + + .lst-kix_list_22-2 > li:before { + content: "\0025cf " + } + + ol.lst-kix_list_25-4 { + list-style-type: none + } + + ol.lst-kix_list_25-3 { + list-style-type: none + } + + .lst-kix_list_48-0 > li:before { + content: "\0025cf " + } + + ol.lst-kix_list_25-6 { + list-style-type: none + } + + ol.lst-kix_list_25-5 { + list-style-type: none + } + + ol.lst-kix_list_25-0 { + list-style-type: none + } + + .lst-kix_list_18-3 > li { + counter-increment: lst-ctn-kix_list_18-3 + } + + ol.lst-kix_list_25-2 { + list-style-type: none + } + + ol.lst-kix_list_25-1 { + list-style-type: none + } + + .lst-kix_list_16-4 > li { + counter-increment: lst-ctn-kix_list_16-4 + } + + ul.lst-kix_list_37-3 { + list-style-type: none + } + + .lst-kix_list_44-5 > li:before { + content: "\0025aa " + } + + ul.lst-kix_list_37-2 { + list-style-type: none + } + + ul.lst-kix_list_37-1 { + list-style-type: none + } + + ul.lst-kix_list_37-0 { + list-style-type: none + } + + ol.lst-kix_list_17-4.start { + counter-reset: lst-ctn-kix_list_17-4 0 + } + + .lst-kix_list_20-3 > li { + counter-increment: lst-ctn-kix_list_20-3 + } + + ol.lst-kix_list_25-8 { + list-style-type: none + } + + ol.lst-kix_list_25-7 { + list-style-type: none + } + + .lst-kix_list_14-8 > li { + counter-increment: lst-ctn-kix_list_14-8 + } + + .lst-kix_list_46-0 > li:before { + content: "\0025cf " + } + + ol.lst-kix_list_6-7.start { + counter-reset: lst-ctn-kix_list_6-7 0 + } + + ul.lst-kix_list_37-8 { + list-style-type: none + } + + .lst-kix_list_20-5 > li:before { + content: "" counter(lst-ctn-kix_list_20-0, decimal) "." counter(lst-ctn-kix_list_20-1, decimal) "." counter(lst-ctn-kix_list_20-2, decimal) "." counter(lst-ctn-kix_list_20-3, decimal) "." counter(lst-ctn-kix_list_20-4, decimal) "." counter(lst-ctn-kix_list_20-5, decimal) " " + } + + ul.lst-kix_list_37-6 { + list-style-type: none + } + + ul.lst-kix_list_37-7 { + list-style-type: none + } + + .lst-kix_list_1-8 > li:before { + content: "\0025cf " + } + + ul.lst-kix_list_37-4 { + list-style-type: none + } + + ul.lst-kix_list_37-5 { + list-style-type: none + } + + ol.lst-kix_list_15-5.start { + counter-reset: lst-ctn-kix_list_15-5 0 + } + + .lst-kix_list_3-3 > li:before { + content: "\0025cf " + } + + .lst-kix_list_20-5 > li { + counter-increment: lst-ctn-kix_list_20-5 + } + + .lst-kix_list_25-8 > li:before { + content: "" counter(lst-ctn-kix_list_25-0, decimal) "." counter(lst-ctn-kix_list_25-1, decimal) "." counter(lst-ctn-kix_list_25-2, decimal) "." counter(lst-ctn-kix_list_25-3, decimal) "." counter(lst-ctn-kix_list_25-4, decimal) "." counter(lst-ctn-kix_list_25-5, decimal) "." counter(lst-ctn-kix_list_25-6, decimal) "." counter(lst-ctn-kix_list_25-7, decimal) "." counter(lst-ctn-kix_list_25-8, decimal) " " + } + + .lst-kix_list_25-5 > li { + counter-increment: lst-ctn-kix_list_25-5 + } + + ol.lst-kix_list_20-0.start { + counter-reset: lst-ctn-kix_list_20-0 0 + } + + ol.lst-kix_list_6-1.start { + counter-reset: lst-ctn-kix_list_6-1 3 + } + + .lst-kix_list_6-4 > li:before { + content: "" counter(lst-ctn-kix_list_6-0, decimal) "." counter(lst-ctn-kix_list_6-1, decimal) "." counter(lst-ctn-kix_list_6-2, decimal) "." counter(lst-ctn-kix_list_6-3, decimal) "." counter(lst-ctn-kix_list_6-4, decimal) " " + } + + .lst-kix_list_18-7 > li:before { + content: "" counter(lst-ctn-kix_list_18-0, decimal) "." counter(lst-ctn-kix_list_18-1, decimal) "." counter(lst-ctn-kix_list_18-2, decimal) "." counter(lst-ctn-kix_list_18-3, decimal) "." counter(lst-ctn-kix_list_18-4, decimal) "." counter(lst-ctn-kix_list_18-5, decimal) "." counter(lst-ctn-kix_list_18-6, decimal) "." counter(lst-ctn-kix_list_18-7, decimal) " " + } + + .lst-kix_list_14-2 > li { + counter-increment: lst-ctn-kix_list_14-2 + } + + ol.lst-kix_list_16-6.start { + counter-reset: lst-ctn-kix_list_16-6 0 + } + + .lst-kix_list_6-4 > li { + counter-increment: lst-ctn-kix_list_6-4 + } + + ol.lst-kix_list_6-8.start { + counter-reset: lst-ctn-kix_list_6-8 0 + } + + .lst-kix_list_18-6 > li { + counter-increment: lst-ctn-kix_list_18-6 + } + + .lst-kix_list_16-0 > li:before { + content: "" counter(lst-ctn-kix_list_16-0, decimal) " " + } + + ol.lst-kix_list_21-7.start { + counter-reset: lst-ctn-kix_list_21-7 0 + } + + .lst-kix_list_23-4 > li:before { + content: "\0025cf " + } + + .lst-kix_list_16-5 > li:before { + content: "" counter(lst-ctn-kix_list_16-0, decimal) "." counter(lst-ctn-kix_list_16-1, decimal) "." counter(lst-ctn-kix_list_16-2, decimal) "." counter(lst-ctn-kix_list_16-3, decimal) "." counter(lst-ctn-kix_list_16-4, decimal) "." counter(lst-ctn-kix_list_16-5, decimal) " " + } + + ol.lst-kix_list_18-2.start { + counter-reset: lst-ctn-kix_list_18-2 0 + } + + ol.lst-kix_list_21-8.start { + counter-reset: lst-ctn-kix_list_21-8 0 + } + + .lst-kix_list_14-0 > li { + counter-increment: lst-ctn-kix_list_14-0 + } + + .lst-kix_list_2-2 > li:before { + content: "\0025cf " + } + + .lst-kix_list_47-7 > li:before { + content: "o " + } + + ol.lst-kix_list_25-8.start { + counter-reset: lst-ctn-kix_list_25-8 0 + } + + .lst-kix_list_7-7 > li:before { + content: "\0025cf " + } + + ol.lst-kix_list_14-7.start { + counter-reset: lst-ctn-kix_list_14-7 0 + } + + .lst-kix_list_7-1 > li:before { + content: "\0025cf " + } + + .lst-kix_list_32-2 > li:before { + content: "\0025cf " + } + + .lst-kix_list_33-6 > li:before { + content: "\0025cf " + } + + .lst-kix_list_2-8 > li:before { + content: "\0025cf " + } + + .lst-kix_list_27-6 > li:before { + content: "\0025cf " + } + + .lst-kix_list_29-5 > li:before { + content: "\0025aa " + } + + .lst-kix_list_21-6 > li:before { + content: "" counter(lst-ctn-kix_list_21-0, decimal) "." counter(lst-ctn-kix_list_21-1, decimal) "." counter(lst-ctn-kix_list_21-2, decimal) "." counter(lst-ctn-kix_list_21-3, decimal) "." counter(lst-ctn-kix_list_21-4, decimal) "." counter(lst-ctn-kix_list_21-5, decimal) "." counter(lst-ctn-kix_list_21-6, decimal) " " + } + + .lst-kix_list_41-1 > li:before { + content: "o " + } + + .lst-kix_list_27-5 > li:before { + content: "\0025aa " + } + + .lst-kix_list_20-0 > li:before { + content: "" counter(lst-ctn-kix_list_20-0, decimal) " " + } + + ol.lst-kix_list_20-2.start { + counter-reset: lst-ctn-kix_list_20-2 0 + } + + .lst-kix_list_27-8 > li:before { + content: "\0025aa " + } + + .lst-kix_list_11-6 > li:before { + content: "\0025cf " + } + + ul.lst-kix_list_8-4 { + list-style-type: none + } + + ul.lst-kix_list_8-5 { + list-style-type: none + } + + ul.lst-kix_list_8-2 { + list-style-type: none + } + + ul.lst-kix_list_8-3 { + list-style-type: none + } + + ul.lst-kix_list_8-8 { + list-style-type: none + } + + ul.lst-kix_list_8-6 { + list-style-type: none + } + + .lst-kix_list_42-4 > li:before { + content: "" counter(lst-ctn-kix_list_42-4, lower-latin) ". " + } + + ul.lst-kix_list_8-7 { + list-style-type: none + } + + .lst-kix_list_4-5 > li:before { + content: "\0025cf " + } + + ol.lst-kix_list_15-1.start { + counter-reset: lst-ctn-kix_list_15-1 2 + } + + ul.lst-kix_list_8-1 { + list-style-type: none + } + + .lst-kix_list_26-2 > li:before { + content: "\0025aa " + } + + .lst-kix_list_37-3 > li:before { + content: "\0025cf " + } + + .lst-kix_list_2-5 > li:before { + content: "\0025cf " + } + + .lst-kix_list_7-6 > li:before { + content: "\0025cf " + } + + ol.lst-kix_list_7-0 { + list-style-type: none + } + + ol.lst-kix_list_32-0.start { + counter-reset: lst-ctn-kix_list_32-0 0 + } + + .lst-kix_list_4-4 > li:before { + content: "\0025cf " + } + + .lst-kix_list_30-0 > li:before { + content: "\0025cf " + } + + ul.lst-kix_list_30-4 { + list-style-type: none + } + + ul.lst-kix_list_30-3 { + list-style-type: none + } + + ul.lst-kix_list_30-6 { + list-style-type: none + } + + ul.lst-kix_list_30-5 { + list-style-type: none + } + + ul.lst-kix_list_30-8 { + list-style-type: none + } + + .lst-kix_list_35-8 > li:before { + content: "\0025aa " + } + + ol.lst-kix_list_25-3.start { + counter-reset: lst-ctn-kix_list_25-3 0 + } + + ul.lst-kix_list_30-7 { + list-style-type: none + } + + .lst-kix_list_36-6 > li:before { + content: "\0025cf " + } + + ul.lst-kix_list_30-0 { + list-style-type: none + } + + ul.lst-kix_list_30-2 { + list-style-type: none + } + + .lst-kix_list_38-2 > li:before { + content: "\0025aa " + } + + ul.lst-kix_list_30-1 { + list-style-type: none + } + + .lst-kix_list_5-0 > li:before { + content: "\0025cf " + } + + ol.lst-kix_list_18-7 { + list-style-type: none + } + + ol.lst-kix_list_18-8 { + list-style-type: none + } + + ol.lst-kix_list_18-5 { + list-style-type: none + } + + .lst-kix_list_25-4 > li:before { + content: "" counter(lst-ctn-kix_list_25-0, decimal) "." counter(lst-ctn-kix_list_25-1, decimal) "." counter(lst-ctn-kix_list_25-2, decimal) "." counter(lst-ctn-kix_list_25-3, decimal) "." counter(lst-ctn-kix_list_25-4, decimal) " " + } + + .lst-kix_list_14-2 > li:before { + content: "" counter(lst-ctn-kix_list_14-0, decimal) "." counter(lst-ctn-kix_list_14-1, decimal) "." counter(lst-ctn-kix_list_14-2, decimal) " " + } + + ol.lst-kix_list_18-6 { + list-style-type: none + } + + ol.lst-kix_list_18-3 { + list-style-type: none + } + + ol.lst-kix_list_18-4 { + list-style-type: none + } + + ol.lst-kix_list_18-1 { + list-style-type: none + } + + .lst-kix_list_17-5 > li { + counter-increment: lst-ctn-kix_list_17-5 + } + + .lst-kix_list_15-4 > li:before { + content: "" counter(lst-ctn-kix_list_15-0, decimal) "." counter(lst-ctn-kix_list_15-1, decimal) "." counter(lst-ctn-kix_list_15-2, decimal) "." counter(lst-ctn-kix_list_15-3, decimal) "." counter(lst-ctn-kix_list_15-4, decimal) " " + } + + ol.lst-kix_list_18-2 { + list-style-type: none + } + + ol.lst-kix_list_18-0 { + list-style-type: none + } + + .lst-kix_list_3-8 > li:before { + content: "\0025cf " + } + + .lst-kix_list_26-6 > li:before { + content: "\0025cf " + } + + .lst-kix_list_48-2 > li:before { + content: "\0025aa " + } + + .lst-kix_list_21-7 > li { + counter-increment: lst-ctn-kix_list_21-7 + } + + .lst-kix_list_33-5 > li:before { + content: "\0025aa " + } + + .lst-kix_list_5-6 > li:before { + content: "\0025cf " + } + + .lst-kix_list_16-8 > li { + counter-increment: lst-ctn-kix_list_16-8 + } + + .lst-kix_list_23-1 > li:before { + content: "\0025cf " + } + + .lst-kix_list_25-4 > li { + counter-increment: lst-ctn-kix_list_25-4 + } + + .lst-kix_list_20-0 > li { + counter-increment: lst-ctn-kix_list_20-0 + } + + .lst-kix_list_24-7 > li:before { + content: "\0025cf " + } + + ol { + margin: 0; + padding: 0 + } + + .c1 { + border-bottom-width: 1pt; + border-top-style: solid; + width: 193.2pt; + border-right-style: solid; + padding: 0pt 5.8pt 0pt 5.8pt; + border-bottom-color: #000000; + border-top-width: 1pt; + border-bottom-style: solid; + vertical-align: top; + border-top-color: #000000; + border-left-color: #000000; + border-right-color: #000000; + border-left-style: solid; + border-right-width: 1pt; + border-left-width: 1pt + } + + .c20 { + border-bottom-width: 1pt; + border-top-style: solid; + width: 238.2pt; + border-right-style: solid; + padding: 0pt 5.8pt 0pt 5.8pt; + border-bottom-color: #000000; + border-top-width: 1pt; + border-bottom-style: solid; + vertical-align: top; + border-top-color: #000000; + border-left-color: #000000; + border-right-color: #000000; + border-left-style: solid; + border-right-width: 1pt; + border-left-width: 1pt + } + + .c3 { + padding-left: 0pt; + line-height: 1.0; + padding-top: 0pt; + margin-left: 36pt; + padding-bottom: 0pt + } + + .c12 { + vertical-align: baseline; + color: #000000; + font-style: normal; + text-decoration: none + } + + .c4 { + line-height: 1.0; + padding-top: 0pt; + text-align: left; + padding-bottom: 0pt + } + + .c11 { + max-width: 432pt; + background-color: #ffffff; + padding: 72pt 90pt 72pt 90pt + } + + .c2 { + widows: 2; + orphans: 2; + direction: ltr + } + + .c16 { + margin-right: auto; + border-collapse: collapse; + margin-left: -5.8pt + } + + .c9 { + line-height: 1.0; + padding-top: 36pt; + padding-bottom: 0pt + } + + .c21 { + line-height: 1.0; + padding-top: 0pt; + padding-bottom: 36pt + } + + .c15 { + font-size: 14pt; + font-family: "Calibri" + } + + .c18 { + font-size: 12pt; + font-family: "Times New Roman" + } + + .c6 { + margin: 0; + padding: 0 + } + + .c0 { + font-size: 12pt; + font-family: "Calibri" + } + + .c22 { + font-size: 10pt; + font-family: "Times New Roman" + } + + .c13 { + color: #000000; + background-color: #ffff00 + } + + .c14 { + font-size: 9pt; + font-family: "Times New Roman" + } + + .c10 { + text-decoration: underline + } + + .c17 { + color: #ff0000 + } + + .c7 { + font-weight: bold + } + + .c19 { + height: 0pt + } + + .c8 { + font-weight: normal + } + + .c5 { + height: 10pt + } + + .title { + widows: 2; + padding-top: 0pt; + line-height: 1.0; + orphans: 2; + text-align: center; + color: #000000; + font-size: 14pt; + font-family: "Times New Roman"; + font-weight: bold; + padding-bottom: 0pt; + page-break-after: avoid + } + + .subtitle { + widows: 2; + padding-top: 18pt; + line-height: 1.0; + orphans: 2; + text-align: left; + color: #666666; + font-style: italic; + font-size: 24pt; + font-family: "Georgia"; + padding-bottom: 4pt; + page-break-after: avoid + } + + li { + color: #000000; + font-size: 10pt; + font-family: "Times New Roman" + } + + p { + color: #000000; + font-size: 10pt; + margin: 0; + font-family: "Times New Roman" + } + + h1 { + widows: 2; + padding-top: 0pt; + line-height: 1.0; + orphans: 2; + text-align: center; + color: #000000; + font-size: 12pt; + font-family: "Times New Roman"; + font-weight: bold; + padding-bottom: 0pt; + page-break-after: avoid + } + + h2 { + widows: 2; + padding-top: 0pt; + line-height: 1.0; + orphans: 2; + text-align: left; + color: #000000; + font-size: 10pt; + font-family: "Times New Roman"; + font-weight: bold; + padding-bottom: 0pt; + page-break-after: avoid + } + + h3 { + widows: 2; + padding-top: 0pt; + line-height: 1.0; + orphans: 2; + text-align: left; + color: #000000; + font-size: 10pt; + text-decoration: underline; + font-family: "Times New Roman"; + padding-bottom: 0pt; + page-break-after: avoid + } + + h4 { + widows: 2; + padding-top: 12pt; + line-height: 1.0; + orphans: 2; + text-align: left; + color: #000000; + font-size: 12pt; + font-family: "Times New Roman"; + font-weight: bold; + padding-bottom: 2pt; + page-break-after: avoid + } + + h5 { + widows: 2; + padding-top: 11pt; + line-height: 1.0; + orphans: 2; + text-align: left; + color: #000000; + font-size: 11pt; + font-family: "Times New Roman"; + font-weight: bold; + padding-bottom: 2pt; + page-break-after: avoid + } + + h6 { + widows: 2; + padding-top: 10pt; + line-height: 1.0; + orphans: 2; + text-align: left; + color: #000000; + font-size: 10pt; + font-family: "Times New Roman"; + font-weight: bold; + padding-bottom: 2pt; + page-break-after: avoid + } +} \ No newline at end of file diff --git a/web/app/assets/stylesheets/web/affiliate_links.css.scss b/web/app/assets/stylesheets/web/affiliate_links.css.scss new file mode 100644 index 000000000..b788146b5 --- /dev/null +++ b/web/app/assets/stylesheets/web/affiliate_links.css.scss @@ -0,0 +1,65 @@ +@import 'client/common.css.scss'; + +body.affiliate_links { + + h2 { + color:white !important; + } + + h2, h3 { + margin-bottom:2px; + } + + .intro { + margin-bottom:30px; + } + + .link-type-prompt { + color:$ColorTextTypical; + line-height:125%; + + + p { + margin-bottom:20px; + } + + .example-link { + font-weight:bold; + } + + } + + table.links-table { + min-width:100%; + margin-top:20px; + margin-bottom:30px; + + th { + padding: 10px 0 20px; + white-space:nowrap; + } + + td { + padding:3px 0; + white-space:nowrap; + } + .target { + width:45%; + white-space:normal; + } + .copy-link { + width:100px; + } + + .url { + + input { + background-color: transparent; + -webkit-box-shadow:none; + box-shadow:none; + color:#ccc; + width:100%; + } + } + } +} \ No newline at end of file diff --git a/web/app/assets/stylesheets/web/web.css b/web/app/assets/stylesheets/web/web.css index 5761892c5..4a5ad0b12 100644 --- a/web/app/assets/stylesheets/web/web.css +++ b/web/app/assets/stylesheets/web/web.css @@ -28,6 +28,8 @@ *= require users/signinCommon *= require dialogs/dialog *= require client/help +*= require landings/partner_agreement_v1 +*= require web/affiliate_links *= require_directory ../landings *= require icheck/minimal/minimal */ \ No newline at end of file diff --git a/web/app/controllers/affiliates_controller.rb b/web/app/controllers/affiliates_controller.rb new file mode 100644 index 000000000..2b5ed0876 --- /dev/null +++ b/web/app/controllers/affiliates_controller.rb @@ -0,0 +1,12 @@ +class AffiliatesController < ApplicationController + + respond_to :html + + def links + + @partner = AffiliatePartner.find(params[:id]) + + render 'affiliate_links', layout: 'web' + end +end + diff --git a/web/app/controllers/api_affiliate_controller.rb b/web/app/controllers/api_affiliate_controller.rb new file mode 100644 index 000000000..98b59e89d --- /dev/null +++ b/web/app/controllers/api_affiliate_controller.rb @@ -0,0 +1,53 @@ +class ApiAffiliateController < ApiController + + before_filter :api_signed_in_user, :except => [ :create ] + + include ErrorsHelper + + respond_to :json + + def log + @log || Logging.logger[ApiAffiliateController] + end + + def create + if current_user + # is this user already an affiliate? Then kick this back + if current_user.affiliate_partner + render :json => simple_error('affiliate_partner', 'You are already an affiliate.'), status: 422 + return + else + @partner = AffiliatePartner.create_with_web_params(current_user, params) + respond_with_model(@partner) + return + end + else + @partner = AffiliatePartner.create_with_web_params(nil, params) + respond_with_model(@partner) + end + end + + def traffic_index + data = AffiliateTrafficTotal.index(current_user, params) + @traffics, @next = data[0], data[1] + render "api_affiliates/traffic_index", :layout => nil + end + + def monthly_index + data = AffiliateMonthlyPayment.index(current_user, params) + @monthlies, @next = data[0], data[1] + render "api_affiliates/monthly_index", :layout => nil + end + + def quarterly_index + data = AffiliateQuarterlyPayment.index(current_user, params) + @quarterlies, @next = data[0], data[1] + render "api_affiliates/quarterly_index", :layout => nil + end + + def payment_index + data = AffiliatePayment.index(current_user, params) + @payments, @next = data[0], data[1] + render "api_affiliates/payment_index", :layout => nil + end +end diff --git a/web/app/controllers/api_controller.rb b/web/app/controllers/api_controller.rb index ce17dbd9c..7aa20de41 100644 --- a/web/app/controllers/api_controller.rb +++ b/web/app/controllers/api_controller.rb @@ -69,6 +69,18 @@ class ApiController < ApplicationController else auth_user end - end -end \ No newline at end of file + + def affiliate_partner + if params[:affiliate_id] + @partner = AffiliatePartner.find(params[:affiliate_id]) + if @partner.partner_user.nil? + raise JamPermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR + end + elsif current_user + @partner = current_user.affiliate_partner + else + raise JamPermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR + end + end +end diff --git a/web/app/controllers/api_links_controller.rb b/web/app/controllers/api_links_controller.rb new file mode 100644 index 000000000..9f50d979f --- /dev/null +++ b/web/app/controllers/api_links_controller.rb @@ -0,0 +1,114 @@ +class ApiLinksController < ApiController + + respond_to :json + + before_filter :api_any_user + before_filter :affiliate_partner + + def log + @log || Logging.logger[ApiLinksController] + end + + def jamtrack_song_index + @affiliate_params = affiliate_params('jamtrack-song') + + results = [] + + @jamtracks, @next = JamTrack.index({offset: 0, limit:1000}, any_user) + + @jamtracks.each do |jamtrack| + results << {url: individual_jamtrack_url(jamtrack.short_plan_code, @affiliate_params), + target: "#{jamtrack.original_artist} - #{jamtrack.name}" } + end + + render json: results, status: 200 + end + + def jamtrack_band_index + @affiliate_params = affiliate_params('jamtrack-band') + + results = [] + + @jamtracks, @next = JamTrack.index({offset: 0, limit:1000}, any_user) + @jamtracks.each do |jamtrack| + results << {url: individual_jamtrack_band_url(jamtrack.short_plan_code, @affiliate_params), + target: "#{jamtrack.original_artist} - #{jamtrack.name}" } + end + + render json: results, status: 200 + end + + def jamtrack_general_index + @affiliate_params = affiliate_params('jamtrack-general') + @affiliate_params[:generic] = 1 + + results = [] + + @jamtracks, @next = JamTrack.index({offset: 0, limit:1000}, any_user) + + @jamtracks.each do |jamtrack| + results << {url: individual_jamtrack_url(jamtrack.short_plan_code, @affiliate_params), + target: "#{jamtrack.original_artist} - #{jamtrack.name}" } + end + + render json: results, status: 200 + end + + def jamkazam_general_index + + results = [] + + @affiliate_params = affiliate_params('home') + results << {url: root_url(@affiliate_params), target: 'JamKazam Home'} + + @affiliate_params = affiliate_params('products-jamblaster') + results << {url: product_jamblaster_url(@affiliate_params), target: 'JamBlaster'} + + @affiliate_params = affiliate_params('products-jamtracks') + results << {url: product_jamtracks_url(@affiliate_params), target: 'JamTracks'} + + + render json: results, status: 200 + end + + def session_index + + @affiliate_params = affiliate_params('session') + + results = [] + + ActiveRecord::Base.transaction do + options = {offset:0, limit:50} + @music_sessions = MusicSession.scheduled(@partner.partner_user, true) + + @music_sessions.each do |session| + results << {url: music_scheduled_session_detail_url(session.id, @affiliate_params), target: session.name} + end + end + + render json: results, status: 200 + end + + def recording_index + + @affiliate_params = affiliate_params('recording') + + results = [] + + feeds, next_page = Feed.index(@partner.partner_user, :type => 'recording', time_range: 'all', limit:100, user: @partner.partner_user.id, ) + + feeds.each do |feed| + claim = feed.recording.candidate_claimed_recording + if claim + results << {url: share_token_url(claim.share_token.token, @affiliate_params), target: claim.name} + end + end + + render json: results, status: 200 + end + + private + def affiliate_params(campaign) + {utm_source:'affiliate', utm_medium: 'affiliate', utm_campaign: "#{Date.today.year}-affiliate-#{campaign}", affiliate: @partner.id} + end +end diff --git a/web/app/controllers/api_recurly_controller.rb b/web/app/controllers/api_recurly_controller.rb index f3090e7a2..41c9c041e 100644 --- a/web/app/controllers/api_recurly_controller.rb +++ b/web/app/controllers/api_recurly_controller.rb @@ -34,7 +34,8 @@ class ApiRecurlyController < ApiController password_confirmation: params[:password], terms_of_service: terms_of_service, location: {:country => billing_info[:country], :state => billing_info[:state], :city => billing_info[:city]}, - reuse_card: reuse_card_next_time + reuse_card: reuse_card_next_time, + affiliate_referral_id: cookies[:affiliate_visitor] } options = User.musician_defaults(request.remote_ip, ApplicationHelper.base_uri(request) + "/confirm", any_user, options) diff --git a/web/app/controllers/api_users_controller.rb b/web/app/controllers/api_users_controller.rb index 3114fc26b..09b891261 100644 --- a/web/app/controllers/api_users_controller.rb +++ b/web/app/controllers/api_users_controller.rb @@ -26,7 +26,7 @@ class ApiUsersController < ApiController @user = User.includes([{musician_instruments: :instrument}, {band_musicians: :user}, {genre_players: :genre}, - :bands, :instruments, :genres, :jam_track_rights]) + :bands, :instruments, :genres, :jam_track_rights, :affiliate_partner]) .find(params[:id]) respond_with @user, responder: ApiResponder, :status => 200 @@ -53,7 +53,8 @@ class ApiUsersController < ApiController password_confirmation: params[:password], terms_of_service: params[:terms], location: {:country => nil, :state => nil, :city => nil}, - signup_hint: signup_hint + signup_hint: signup_hint, + affiliate_referral_id: cookies[:affiliate_visitor] } options = User.musician_defaults(request.remote_ip, ApplicationHelper.base_uri(request) + "/confirm", any_user, options) @@ -670,6 +671,40 @@ class ApiUsersController < ApiController end end + def affiliate_partner + if oo = current_user.affiliate_partner + if request.post? + oo.address = params[:address] + oo.tax_identifier = params[:tax_identifier] + oo.save! + render nothing: true + + elsif request.get? + result = {} + result['account'] = { + 'address' => oo.address.clone, + 'tax_identifier' => oo.tax_identifier, + 'entity_type' => oo.entity_type, + 'partner_name' => oo.partner_name, + 'partner_id' => oo.partner_user_id, + 'id' => oo.id + } + if txt = oo.affiliate_legalese.try(:legalese) + txt = ControllerHelp.instance.simple_format(txt) + end + result['agreement'] = { + 'legalese' => txt, + 'signed_at' => oo.signed_at + } + #result['signups'] = oo.referrals_by_date + #result['earnings'] = [['April 2015', '1000 units', '$100']] + render json: result.to_json, status: 200 + end + else + render :json => { :message => 'user not affiliate partner' }, :status => 400 + end + end + def affiliate_report begin affiliate = User diff --git a/web/app/controllers/application_controller.rb b/web/app/controllers/application_controller.rb index 7f242aff0..114666eec 100644 --- a/web/app/controllers/application_controller.rb +++ b/web/app/controllers/application_controller.rb @@ -15,6 +15,7 @@ class ApplicationController < ActionController::Base end before_filter :set_tracking_cookie + before_filter :track_affiliate_visits before_filter do if params[AffiliatePartner::PARAM_REFERRAL].present? && current_user.nil? @@ -35,6 +36,16 @@ class ApplicationController < ActionController::Base cookies.permanent[:user_uuid] = SecureRandom.uuid unless cookies[:user_uuid] end + def track_affiliate_visits + if params[:affiliate] && params[:utm_medium] == 'affiliate' && params[:utm_source] == 'affiliate' + visit_cookie = cookies[:affiliate_visitor] + AffiliateReferralVisit.track(affiliate_id: params[:affiliate], visited: visit_cookie, remote_ip: request.remote_ip, visited_url: request.fullpath, referral_url: request.referer, current_user: current_user) + + # set a cookie with the ID of the partner, and expires in 24 hours + cookies[:affiliate_visitor] = { :value => params[:affiliate], :expires => Time.now + 3600 * 24} # 1 day from now + end + end + private def add_user_info_to_bugsnag(notif) @@ -49,3 +60,14 @@ class ApplicationController < ActionController::Base end end end + +class ControllerHelp + include Singleton + include ActionView::Helpers::TextHelper + include ActionView::Helpers::UrlHelper + include ActionView::Helpers::SanitizeHelper + extend ActionView::Helpers::SanitizeHelper::ClassMethods + include ActionView::Helpers::JavaScriptHelper + include ActionView::Helpers::TagHelper + include ActionView::Helpers::AssetTagHelper +end diff --git a/web/app/controllers/landings_controller.rb b/web/app/controllers/landings_controller.rb index 5700ac543..ef23ba7d8 100644 --- a/web/app/controllers/landings_controller.rb +++ b/web/app/controllers/landings_controller.rb @@ -103,5 +103,10 @@ class LandingsController < ApplicationController gon.jam_track_plan_code = jam_track.plan_code if jam_track render 'product_jamtracks', layout: 'web' end + + def affiliate_program + render 'affiliate_program', layout: 'web' + end + end diff --git a/web/app/controllers/sessions_controller.rb b/web/app/controllers/sessions_controller.rb index 36c54e58c..931960fdb 100644 --- a/web/app/controllers/sessions_controller.rb +++ b/web/app/controllers/sessions_controller.rb @@ -65,7 +65,8 @@ class SessionsController < ApplicationController user = UserManager.new.signup(remote_ip: remote_ip(), first_name: auth_hash[:info][:first_name], last_name: auth_hash[:info][:last_name], - email: auth_hash[:info][:email]) + email: auth_hash[:info][:email], + affiliate_referral_id: cookies[:affiliate_visitor]) # Users who sign up using oauth are presumed to have valid email adddresses. user.confirm_email! @@ -132,6 +133,7 @@ class SessionsController < ApplicationController email: email, terms_of_service: true, location: {:country => nil, :state => nil, :city => nil}, + affiliate_referral_id: cookies[:affiliate_visitor] } options = User.musician_defaults(request.remote_ip, ApplicationHelper.base_uri(request) + "/confirm", any_user, options) diff --git a/web/app/controllers/users_controller.rb b/web/app/controllers/users_controller.rb index 7c5a06768..92fbb1f52 100644 --- a/web/app/controllers/users_controller.rb +++ b/web/app/controllers/users_controller.rb @@ -70,6 +70,7 @@ class UsersController < ApplicationController end end + @affiliate_partner = load_affiliate_partner(params) @invited_user = load_invited_user(params) if !@invited_user.nil? && @invited_user.has_required_email? && @invited_user.accepted @@ -77,7 +78,7 @@ class UsersController < ApplicationController render "already_signed_up", :layout => 'landing' return end - @signup_postback = load_postback(@invited_user, @fb_signup) + @signup_postback = load_postback(@invited_user, @fb_signup, @affiliate_partner) load_location(request.remote_ip) @@ -136,7 +137,8 @@ class UsersController < ApplicationController end @invited_user = load_invited_user(params) - @signup_postback = load_postback(@invited_user, @fb_signup) + @affiliate_partner = load_affiliate_partner(params) + @signup_postback = load_postback(@invited_user, @fb_signup, @affiliate_partner) instruments = fixup_instruments(params[:jam_ruby_user][:instruments]) @@ -161,7 +163,8 @@ class UsersController < ApplicationController invited_user: @invited_user, fb_signup: @fb_signup, signup_confirm_url: ApplicationHelper.base_uri(request) + "/confirm", - affiliate_referral_id: AffiliatePartner.coded_id(self.affiliate_code)) + affiliate_referral_id: cookies[:affiliate_visitor], + affiliate_partner: @affiliate_partner) # check for errors if @user.errors.any? @@ -468,6 +471,12 @@ JS return invited_user end + def load_affiliate_partner(params) + partner_id = params[:affiliate_partner_id] + + AffiliatePartner.find(partner_id) if partner_id + end + def load_location(remote_ip, location = nil) # useful if you need to repro something on 127.0.0.1 # remote_ip = ' 23.119.29.89' @@ -486,10 +495,11 @@ JS @cities = @location[:state].nil? ? [] : MaxMindManager.cities(@location[:country], @location[:state]) end - def load_postback(invited_user, fb_signup) + def load_postback(invited_user, fb_signup, affiliate_partner) query = {} query[:invitation_code] = invited_user.invitation_code if invited_user query[:facebook_signup] = fb_signup.lookup_id if fb_signup + query[:affiliate_partner_id] = affiliate_partner.id if affiliate_partner if query.length > 0 signup_path + "?" + query.to_query else diff --git a/web/app/helpers/errors_helper.rb b/web/app/helpers/errors_helper.rb new file mode 100644 index 000000000..bb97b5367 --- /dev/null +++ b/web/app/helpers/errors_helper.rb @@ -0,0 +1,7 @@ +module ErrorsHelper + + def simple_error(field, error_msg) + {"errors" => {field => [error_msg]}} + end + +end \ No newline at end of file diff --git a/web/app/helpers/sessions_helper.rb b/web/app/helpers/sessions_helper.rb index a5e914512..8ce8f71f2 100644 --- a/web/app/helpers/sessions_helper.rb +++ b/web/app/helpers/sessions_helper.rb @@ -22,7 +22,6 @@ module SessionsHelper end end - # should be set whenever a user logs in who has redeemed a free jamtrack, or whenever the user def set_purchased_jamtrack_cookie cookies.permanent[:redeemed_jamtrack] = true diff --git a/web/app/views/affiliates/affiliate_links.html.slim b/web/app/views/affiliates/affiliate_links.html.slim new file mode 100644 index 000000000..c86d86fb2 --- /dev/null +++ b/web/app/views/affiliates/affiliate_links.html.slim @@ -0,0 +1,119 @@ +- provide(:page_name, 'landing_page full landing_product affiliate_links') +- provide(:description, 'Affiliate Links') + +h2 Affiliate Links +p.intro + | This page provides you with lists of ready-to-use links you can use to direct your followers to JamKazam.  + | These links include your unique affiliate ID, and users who follow these links to JamKazam and register for an account will be  + | tagged with your affiliate ID, so that you will be paid on their purchase per the terms of the affiliate agreement. + +h3 Table of Contents +ul + li + a href='#header_jamtrack_songs' JamTrack Songs + li + a href='#header_jamtrack_bands' JamTrack Bands + li + a href='#header_jamtrack_general' JamTrack Generic + li + a href='#header_jamkazam' JamKazam General + li + a href='#header_sessions' Sessions + li + a href='#header_recordings' Recordings + li + a href='#header_custom_links' Custom Links +h3#header_jamtrack_songs JamTrack Songs +.link-type-prompt data-type='jamtrack_songs' + | These links take users directly to the "landing page" for a JamTrack - i.e. an individual piece of music. This would be a great fit, for example, if you have produced a YouTube tutorial on how to play a particular song, or if you have music notation for a particular song, etc. +table.links-table.jamtrack_songs + thead + tr + th.target TARGET PAGE + th.copy-link + th.url URL + tbody + +h3#header_jamtrack_bands JamTrack Bands +.link-type-prompt data-type='jamtrack_bands' + | These links take users directly to the "landing page" for a band to promote all the JamTracks by that band, not just an individual song. This would be a great fit, for example, if you have music notation for several songs by a band, etc. +table.links-table.jamtrack_bands + thead + tr + th.target TARGET PAGE + th.copy-link + th.url URL + tbody + +h3#header_jamtrack_general JamTrack General +.link-type-prompt data-type='jamtrack_general' + | These links take users directly to a"landing page" that promotes JamTracks in general. This page will feature the song listed in the link as an example of a JamTrack, but the landing page is built to promote JamTracks in general versus promoting just the one song. This is a good fit if you want to let your followers know about JamTracks in general. +table.links-table.jamtrack_general + thead + tr + th.target TARGET PAGE + th.copy-link + th.url URL + tbody + +h3#header_jamkazam JamKazam Generic +.link-type-prompt data-type='jamkazam' + | These links take users directly to a product page that promotes JamKazam more generally. This is a good fit if you want to let your followers know about JamKazam or its products in general. +table.links-table.jamkazam + thead + tr + th.target TARGET PAGE + th.copy-link + th.url URL + tbody + +h3#header_sessions Sessions +.link-type-prompt data-type='sessions' + | These links take users to a page where they can listen to a session you have organized, and in which you are scheduled to perform, either alone or with others. This is a good fit if you can perform either solo or in a group with other musicians in a JamKazam session, and draw an audience to listen to your session. During the session, you can recommend that your audience members sign up for JamKazam from this page. Below is a list of your currently scheduled JamKazam sessions for which you may share links. +table.links-table.sessions + thead + tr + th.target TARGET PAGE + th.copy-link + th.url URL + tbody + +h3#header_recordings Recordings +.link-type-prompt data-type='recordings' + | These links take users to a page with a recording you have made in a JamKazam session. This is a good fit if you have made a nice recording in a JamKazam session and can share it with your followers via Facebook, Twitter, email, and so on. Below is a list of your most recent JamKazam recordings for which you may share links. +table.links-table.recordings + thead + tr + th.target TARGET PAGE + th.copy-link + th.url URL + tbody + +h3#header_custom_links Custom Links +.link-type-prompt data-type='custom_links' + p You may also link to any page on the JamKazam website and append the following text to the URL of the page to which you are linking: + + p.example-link + | ?utm_source=affiliate&utm_medium=affiliate&utm_campaign=2015-affiliate-custom&affiliate= + span.affiliate_id = @partner.id + + p For example, if you were linking to the JamKazam home page, you would combine https://www.jamkazam.com with the text above, and the result would be: + + p.example-link + | https://www.jamkazam.com?utm_source=affiliate&utm_medium=affiliate&utm_campaign=2015-affiliate-custom&affiliate= + span.affiliate_id = @partner.id + +javascript: + $(document).on('JAMKAZAM_READY', function (e, data) { + var affiliateLinks = new JK.AffiliateLinks(data.app, '#{@partner.id}'); + affiliateLinks.initialize(); + }) + +script type="text/template" id="template-affiliate-link-row" + tr + td.target + | {{data.target}} + td.copy-link + a href='#' select link + td.url + input type="text" value="{{data.url}}" \ No newline at end of file diff --git a/web/app/views/api_affiliates/create.rabl b/web/app/views/api_affiliates/create.rabl new file mode 100644 index 000000000..bd016e7bc --- /dev/null +++ b/web/app/views/api_affiliates/create.rabl @@ -0,0 +1,3 @@ +object @partner + +extends "api_affiliates/show" \ No newline at end of file diff --git a/web/app/views/api_affiliates/monthly_index.rabl b/web/app/views/api_affiliates/monthly_index.rabl new file mode 100644 index 000000000..3446d43ea --- /dev/null +++ b/web/app/views/api_affiliates/monthly_index.rabl @@ -0,0 +1,8 @@ +node :next do |page| + @next +end + +node :monthlies do |page| + partial "api_affiliates/monthly_show", object: @monthlies +end + diff --git a/web/app/views/api_affiliates/monthly_show.rabl b/web/app/views/api_affiliates/monthly_show.rabl new file mode 100644 index 000000000..7efad0339 --- /dev/null +++ b/web/app/views/api_affiliates/monthly_show.rabl @@ -0,0 +1,3 @@ +object @monthly + +attribute :closed, :due_amount_in_cents, :affiliate_partner_id, :month, :year \ No newline at end of file diff --git a/web/app/views/api_affiliates/payment_index.rabl b/web/app/views/api_affiliates/payment_index.rabl new file mode 100644 index 000000000..505f0d0e0 --- /dev/null +++ b/web/app/views/api_affiliates/payment_index.rabl @@ -0,0 +1,8 @@ +node :next do |page| + @next +end + +node :payments do |page| + partial "api_affiliates/payment_show", object: @payments +end + diff --git a/web/app/views/api_affiliates/payment_show.rabl b/web/app/views/api_affiliates/payment_show.rabl new file mode 100644 index 000000000..1ac51e258 --- /dev/null +++ b/web/app/views/api_affiliates/payment_show.rabl @@ -0,0 +1,3 @@ +object @quarterly + +attribute :closed, :paid, :due_amount_in_cents, :affiliate_partner_id, :quarter, :month, :year, :payment_type, :jamtracks_sold \ No newline at end of file diff --git a/web/app/views/api_affiliates/quarterly_index.rabl b/web/app/views/api_affiliates/quarterly_index.rabl new file mode 100644 index 000000000..a492bfa6a --- /dev/null +++ b/web/app/views/api_affiliates/quarterly_index.rabl @@ -0,0 +1,8 @@ +node :next do |page| + @next +end + +node :quarterlies do |page| + partial "api_affiliates/quarterly_show", object: @quarterlies +end + diff --git a/web/app/views/api_affiliates/quarterly_show.rabl b/web/app/views/api_affiliates/quarterly_show.rabl new file mode 100644 index 000000000..6238f5bc6 --- /dev/null +++ b/web/app/views/api_affiliates/quarterly_show.rabl @@ -0,0 +1,3 @@ +object @quarterly + +attribute :closed, :paid, :due_amount_in_cents, :affiliate_partner_id, :quarter, :year \ No newline at end of file diff --git a/web/app/views/api_affiliates/show.rabl b/web/app/views/api_affiliates/show.rabl new file mode 100644 index 000000000..837dc9eed --- /dev/null +++ b/web/app/views/api_affiliates/show.rabl @@ -0,0 +1,2 @@ + +attributes :id, :partner_user_id, :partner_name, :entity_type \ No newline at end of file diff --git a/web/app/views/api_affiliates/traffic_index.rabl b/web/app/views/api_affiliates/traffic_index.rabl new file mode 100644 index 000000000..f5647a946 --- /dev/null +++ b/web/app/views/api_affiliates/traffic_index.rabl @@ -0,0 +1,8 @@ +node :next do |page| + @next +end + +node :traffics do |page| + partial "api_affiliates/traffic_show", object: @traffics +end + diff --git a/web/app/views/api_affiliates/traffic_show.rabl b/web/app/views/api_affiliates/traffic_show.rabl new file mode 100644 index 000000000..e60d6da02 --- /dev/null +++ b/web/app/views/api_affiliates/traffic_show.rabl @@ -0,0 +1,3 @@ +object @traffic + +attribute :day, :visits, :signups, :affiliate_partner_id \ No newline at end of file diff --git a/web/app/views/api_users/show.rabl b/web/app/views/api_users/show.rabl index a7585f4e3..40cc96a77 100644 --- a/web/app/views/api_users/show.rabl +++ b/web/app/views/api_users/show.rabl @@ -33,6 +33,18 @@ if @user == current_user @user.recurly_code == @user.id end + node :is_affiliate_partner do + @user.affiliate_partner.present? + end + + node :affiliate_referral_count do + @user.affiliate_partner.try(:referral_user_count) + end + + node :affiliate_earnings do + @user.affiliate_partner.try(:cumulative_earnings_in_cents) + end + elsif current_user node :is_friend do |uu| current_user.friends?(@user) diff --git a/web/app/views/clients/_account.html.erb b/web/app/views/clients/_account.html.erb index af5e85f10..29d806a94 100644 --- a/web/app/views/clients/_account.html.erb +++ b/web/app/views/clients/_account.html.erb @@ -151,6 +151,35 @@
{% } %} + +
+ + + + {% if (data.is_affiliate_partner) { %} + +
+ VIEW +
+ {% } else { %} + + {% } %} +
+ diff --git a/web/app/views/clients/_account_affiliate_partner.html.slim b/web/app/views/clients/_account_affiliate_partner.html.slim new file mode 100644 index 000000000..8280cf9b9 --- /dev/null +++ b/web/app/views/clients/_account_affiliate_partner.html.slim @@ -0,0 +1,193 @@ +/! Account affiliates Dialog +#account-affiliate-partner.screen.secondary layout='screen' layout-id='account/affiliatePartner' + .content-head + .content-icon + = image_tag "content/icon_account.png", :width => 27, :height => 20 + h1 my account + = render "screen_navigation" + + /! affiliates scrolling area + .content-body + .content-body-scroller.account-content-scroller#account-affiliate-partner-content-scroller + .content-wrapper.account-affiliates + .affiliates-header + .left.affiliates-caption + h2 affiliate: + .clearall + .affiliate-partner-nav + a#affiliate-partner-agreement-link agreement + a#affiliate-partner-earnings-link earnings + a#affiliate-partner-signups-link signups + a#affiliate-partner-links-link links + a#affiliate-partner-account-link.active account + .clearall + + .affiliate-partner-account + .clearall + .affiliate-partner-links + .clearall + .affiliate-partner-agreement + .clearall + .affiliate-partner-signups + .clearall + .affiliate-partner-earnings + .clearall + #affiliate-partner-tab-content + + .clearall + +script type="text/template" id="template-affiliate-partner-account" + .tab-account + .right-col + | We must have a complete mailing address and a valid tax ID in order to process and mail payments due to all affiliates.  Per the terms of the affiliate agreement, if this information is not available within 90 days of the end of a calendar quarter, then any payment obligation due to the affiliate for such calendar quarter shall be considered fully and permanently discharged, and no further payment for such calendar quarter shall be due or payable to affiliate. + br + | So please provide this data, and be sure to keep it current! + + .left-col + .affiliate-label Affiliate: + .w80= "{{ data.partner_name }} ({{data.entity_type}})" + br + .affiliate-label Street Address 1: + = text_field_tag('affiliate_partner_address1', "{{ data.address.address1 }}", {class: 'w60'}) + br + .affiliate-label Street Address 2: + = text_field_tag('affiliate_partner_address2', "{{ data.address.address2 }}", {class: 'w60'}) + br + .affiliate-label City: + = text_field_tag('affiliate_partner_city', "{{ data.address.city }}", {class: 'w60'}) + br + .affiliate-label State/Region: + = text_field_tag('affiliate_partner_state', "{{ data.address.state }}", {class: 'w60'}) + br + .affiliate-label Zip/Postal Code: + = text_field_tag('affiliate_partner_postal_code', "{{ data.address.postal_code }}", {class: 'w60'}) + br + .affiliate-label Country: + = text_field_tag('affiliate_partner_country', "{{ data.address.country }}", {class: 'w60'}) + br + br + .affiliate-label Tax ID: + = text_field_tag('affiliate_partner_tax_identifier', "{{ data.tax_identifier }}", {class: 'w60'}) + br + .spacer + .input-buttons + .right + a.button-grey href="javascript:history.go(-1)" CANCEL + a.button-orange id="affiliate-profile-account-submit" href="#" UPDATE + .clearall + .clearall + +script type="text/template" id="template-affiliate-partner-agreement" + .agreement + label.partner-agreement You are viewing: + select.easydropdown name='agreement' + option value="Current agreement in effect" Current agreement in effect + br + h2 JamKazam Affiliate Agreement + .execution-date + | (you executed this Agreement on {{ window.JK.formatDate(data.signed_at) }}) + + = render "legal/partner_agreement_v1" + + .input-buttons + .right + a.button-orange href='/client#/account' BACK TO ACCOUNT + +script type="text/template" id="template-affiliate-partner-signups" + table.traffic-table.jamtable + thead + tr + th.day DATE + th.signups SIGNUPS + th.visits VISITS + tbody + +script type="text/template" id="template-affiliate-partner-links" + .links + p.prompt + | This page provides you with lists of ready-to-use links you can use to direct your followers to JamKazam.  + | These links include your unique affiliate ID, and users who follow these links to JamKazam and register for an account will be  + | tagged with your affiliate ID, so that you will be paid on their purchase per the terms of the  + a.affiliate-agreement rel='#' affiliate agreement + | . You can also find a  + a.affiliate-link-page href='#' rel="external" single page listing all affiliate links + |  which you can share with others who may need to share out affiliate links on your behalf. + .link-type-section + label Link Type: + select.link_type.easydropdown name="link_type" + option value="JamTrack Song" JamTrack Song + option value="JamTrack Band" JamTrack Band + option value="JamTrack General" JamTrack General + option value="JamKazam General" JamKazam General + option value="JamKazam Session" JamKazam Session + option value="JamKazam Recording" JamKazam Recording + option value="Custom Link" Custom Link + .link-type-prompt data-type='jamtrack_songs' + | These links take users directly to the "landing page" for a JamTrack - i.e. an individual piece of music. This would be a great fit, for example, if you have produced a YouTube tutorial on how to play a particular song, or if you have music notation for a particular song, etc. + .link-type-prompt data-type='jamtrack_bands' + | These links take users directly to the "landing page" for a band to promote all the JamTracks by that band, not just an individual song. This would be a great fit, for example, if you have music notation for several songs by a band, etc. + .link-type-prompt data-type='jamtrack_general' + | These links take users directly to a"landing page" that promotes JamTracks in general. This page will feature the song listed in the link as an example of a JamTrack, but the landing page is built to promote JamTracks in general versus promoting just the one song. This is a good fit if you want to let your followers know about JamTracks in general. + .link-type-prompt data-type='jamkazam' + | These links take users directly to a product page that promotes JamKazam more generally. This is a good fit if you want to let your followers know about JamKazam or its products in general. + .link-type-prompt data-type='sessions' + | These links take users to a page where they can listen to a session you have organized, and in which you are scheduled to perform, either alone or with others. This is a good fit if you can perform either solo or in a group with other musicians in a JamKazam session, and draw an audience to listen to your session. During the session, you can recommend that your audience members sign up for JamKazam from this page. Below is a list of your currently scheduled JamKazam sessions for which you may share links. + .link-type-prompt data-type='recordings' + | These links take users to a page with a recording you have made in a JamKazam session. This is a good fit if you have made a nice recording in a JamKazam session and can share it with your followers via Facebook, Twitter, email, and so on. Below is a list of your most recent JamKazam recordings for which you may share links. + .link-type-prompt data-type='custom_links' + p You may also link to any page on the JamKazam website and append the following text to the URL of the page to which you are linking: + + p.example-link + | ?utm_source=affiliate&utm_medium=affiliate&utm_campaign=2015-affiliate-custom&affiliate= + span.affiliate_id + + p For example, if you were linking to the JamKazam home page, you would combine https://www.jamkazam.com with the text above, and the result would be: + + p.example-link + | https://www.jamkazam.com?utm_source=affiliate&utm_medium=affiliate&utm_campaign=2015-affiliate-custom&affiliate= + span.affiliate_id + + table.links-table + thead + tr + th.target TARGET PAGE + th.copy-link + th.url URL + tbody + +script type="text/template" id="template-affiliate-partner-signups-row" + tr + td.day + | {{data.day}} + td.signups + | {{data.signups}} + td.visits + | {{data.visits}} + +script type="text/template" id="template-affiliate-partner-earnings" + table.payment-table.jamtable + thead + tr + th.month MONTH + th.sales SALES + th.earnings AFFILIATE EARNINGS + tbody + +script type="text/template" id="template-affiliate-partner-earnings-row" + tr data-type="{{data.payment_type}}" + td.month + | {{data.time}} + td.sales + | {{data.sold}} + td.earnings + | {{data.earnings}} + + +script type="text/template" id="template-affiliate-link-entry" + tr + td.target + | {{data.target}} + td.copy-link + a href='#' select link + td.url + input type="text" value="{{data.url}}" \ No newline at end of file diff --git a/web/app/views/clients/index.html.erb b/web/app/views/clients/index.html.erb index 4296ced1a..48b735e2c 100644 --- a/web/app/views/clients/index.html.erb +++ b/web/app/views/clients/index.html.erb @@ -60,6 +60,7 @@ <%= render "account_video_profile" %> <%= render "account_sessions" %> <%= render "account_jamtracks" %> +<%= render "account_affiliate_partner" %> <%= render "account_session_detail" %> <%= render "account_session_properties" %> <%= render "account_payment_history" %> @@ -209,6 +210,9 @@ var accountSessionPropertiesScreen = new JK.AccountSessionProperties(JK.app); accountSessionPropertiesScreen.initialize(); + var accountAffiliateScreen = new JK.AccountAffiliateScreen(JK.app); + accountAffiliateScreen.initialize(); + var affiliateReportScreen = new JK.AffiliateReportScreen(JK.app); affiliateReportScreen.initialize(); diff --git a/web/app/views/landings/affiliate_program.html.slim b/web/app/views/landings/affiliate_program.html.slim new file mode 100644 index 000000000..34859ff76 --- /dev/null +++ b/web/app/views/landings/affiliate_program.html.slim @@ -0,0 +1,56 @@ +- provide(:page_name, 'landing_page full landing_product affiliate_program') +- provide(:description, 'Signup for JamKazam Affiliate Program') + +.row + .column + h1.product-headline JamKazam Affiliate Program + p Do you have a following of musicians on Facebook, YouTube, Twitter or an email list? Generate income simply by letting them know about JamKazam. + p Let's say you make YouTube tutorial videos. You can link directly from a video on how to play "Back in Black" to our JamTrack for that song. Video watchers can get this first JamTrack free, and can buy others if they like. You get paid every time they buy something from us for 2 years. + p Or let's say you have a Facebook group for guitarist with 5,000 members. You can let them know they can play together free on JamKazam. For everyone who signs up, you get paid every time they buy something from us for 2 years. + p You don't have to sell anything. Just let your followers know about cool new stuff they'll like! To get started, simply review the affiliate agreement below, accept it (at the end of the agreement), and then start sharing links with your affiliate code. When referred users buy JamTracks, JamBlasters, JamLessons, and so on, you get paid! + .column + h1 Learn How to Make Money by Referring Users + .video-wrapper + .video-container + iframe src="//www.youtube.com/embed/ylYcvTY9CVo" frameborder="0" allowfullscreen + br clear="all" +.row + h1 JamKazam Affiliate Agreement + = render "legal/partner_agreement_v1" + + p.agreement-notice By clicking the "I Agree" button below, I certify that I have the authority to enter into this Agreement on behalf of myself as an individual or on behalf of the entity I have listed below, and I further certify that I have read, understood, and agree to be bound by the terms above. + .entity-options + .field.radio + = radio_button_tag(:entity, 'individual') + label I am entering into this Agreement as an individual + .field.radio + = radio_button_tag(:entity, 'entity') + label I am executing this Agreement on behalf of the company or entity listed below + + .entity-info.hidden + .field.entity.name + label Entity Name + input type="text" name="entity-name" + .field.entity.type + label Entity Type + select name="entity-type" + option value="" Choose Entity Type + option value="Sole Proprietor" Sole Proprietor + option value="Limited Liability Company (LLC)" Limited Liability Company (LLC) + option value="Partnership" Partnership + option value="Trust/Estate" Trust/Estate + option value="S Corporation" S Corporation + option value="C Corporation" C Corporation + option value="Other" Other + + .agree-disagree-buttons + = link_to image_tag("content/agree_button.png", {:width => 213, :height => 50 }), '#', class: "agree-button" + = link_to image_tag("content/disagree_button.png", {:width => 213, :height => 50 }), '#', class: "disagree-button" + p.disagree-text.hidden + | Thank you for your interest in the JamKazam affiliate program. We are sorry, but you cannot join the program without consenting to the terms of this Agreement. + +javascript: + $(document).on('JAMKAZAM_READY', function(e, data) { + var affiliateProgram = new JK.AffiliateProgram(data.app); + affiliateProgram.initialize(); + }) \ No newline at end of file diff --git a/web/app/views/legal/_partner_agreement_v1.html.erb b/web/app/views/legal/_partner_agreement_v1.html.erb new file mode 100644 index 000000000..1dbc81472 --- /dev/null +++ b/web/app/views/legal/_partner_agreement_v1.html.erb @@ -0,0 +1,422 @@ + +
+ +

Updated: April 30, 2015.

+ +

+ +

+ This Affiliate Agreement (this “Agreement”) contains the terms and conditions that govern your participation in the JamKazam affiliate marketing program (the “Program”). “JamKazam”, “we,” “us,” + or “our” + means JamKazam, Inc. “You” + or “your” + means the applicant. A “site” + means a website. “JamKazam Site” means the jamkazam.com website or a JamKazam applicaion or any other site that is owned or operated by or on behalf of us and which is identified as participating in the Program in the Program Advertising Fee Schedule in Section 10, as applicable. “Your Site” + means any site(s), software application(s), or content that you create, own, or operate and link to the JamKazam Site. +

+ +

+ +

1. Description of the Program

+ +

+ +

+ The purpose of the Program is to permit you to advertise Products on Your Site and to earn advertising fees for Qualifying Purchases (defined in Section 7) made by your Qualifying Customers (defined in Section 7). A “Product” + is an item sold on the JamKazam Site and listed in the Program Advertising Fee Schedule in Section 10. In order to facilitate your advertisement of Products, we may make available to you data, images, text, link formats, widgets, links, and other linking tools, and other information in connection with the Program (“Content”). +

+ +

+ +

2. Enrollment, Suitability, and Communications

+ +

+ +

To enroll in the Program, you must execute this Agreement by clicking the “I Agree” + button at the end of this Agreement, after having thoroughly reviewed the Agreement.

+ +

+ +

+ Your Site may be considered unsuitable for participation in the Program resulting in termination of this Agreement by JamKazam if Your Site: +

+ +

+
    +
  • promotes or contains sexually explicit materials;
  • +
  • promotes violence or contains violent materials;
  • +
  • promotes or contains libelous or defamatory materials;
  • +
  • + promotes discrimination, or employs discriminatory practices, based on race, sex, religion, nationality, disability, sexual orientation, or age; +
  • +
  • promotes or undertakes illegal activities;
  • +
  • + is directed toward children under 13 years of age, as defined by the Children’s Online Privacy Protection Act (15 U.S.C. §§ + 6501-6506) and any regulations promulgated thereunder;
  • +
  • + includes any trademark of JamKazam or a variant or misspelling of a trademark of JamKazam in any domain name, subdomain name, or in any username, group name, or other identifier on any social networking site; or +
  • +
  • otherwise violates intellectual property rights.
  • +
+

+ +

+ You will ensure that the information you provide in executing this Agreement and otherwise associated with your account, including your name, email address, mailing address, tax ID, and other information, is at all times complete, accurate, and up-to-date. We may send notifications (if any), reports (if any), and other communications relating to the Program and this Agreement to the email address then-currently associated with your JamKazam account. You will be deemed to have received all notifications, reports, and other communications sent to that email address, even if the email address associated with your account is no longer current. We may mail checks (if any) payable to you for advertising fees earned under this Agreement to the mailing address then-currently associated with your JamKazam account. You will be deemed to have received all checks sent to that mailing address, even if the mailing address associated with your account is no longer current. If we send a check to a mailing address that is no longer valid, we may, in our sole discretion, choose to issue a stop payment order for such a check and send a new check to a new current address that your provide, but in such a case, we will charge a US$50.00 fee for this exception process. +

+ +

+ +

+ If you are a Non-US person participating in the Program, you agree that you will perform all services under the Agreement outside the United States. +

+ +

+ +

3. Links on Your Site

+ +

+ +

+ After you have entered into this Agreement, you may display Special Links on Your Site. “Special Links” + are links to the JamKazam Site that you place on Your Site in accordance with this Agreement, that properly utilize the special “tagged” + link formats we specify or provide. Special Links permit accurate tracking, reporting, and accrual of advertising fees. +

+ +

+ +

+ You may earn advertising fees only as described in Section 7 and only with respect to activity on the JamKazam Site occurring directly through Special Links. We will have no obligation to pay you advertising fees if you fail to properly format the links on Your Site to the JamKazam Site as Special Links, including to the extent that such failure may result in any reduction of advertising fee amounts that would otherwise be paid to you under this Agreement. +

+ +

+ +

4. Program Requirements

+ +

+ +

You hereby consent to us:

+ +

+
    +
  • sending you emails relating to the Program from time to time; and
  • +
  • + monitoring, recording, using, and disclosing information about Your Site and visitors to Your Site that we obtain in connection with your display of Special Links in accordance with the JamKazam Privacy Policy. +
  • +
+

+ +

5. Responsibility for Your Site

+ +

+ +

+ You will be solely responsible for Your Site including its development, operation, and maintenance, and all materials that appear on or within it. For example, you will be solely responsible for: +

+ +

+
    +
  • the technical operation of Your Site and all related equipment;
  • +
  • + displaying Special Links and Content on Your Site in compliance with this Agreement and any agreement between you and any other person or entity (including any restrictions or requirements placed on you by any person or entity that hosts Your Site); +
  • +
  • + creating and posting, and ensuring the accuracy, completeness, and appropriateness of, materials posted on Your Site (including all Product descriptions and other Product-related materials and any information you include within or associate with Special Links); +
  • +
  • + using the Content, Your Site, and the materials on or within Your Site in a manner that does not infringe, violate, or misappropriate any of our rights or those of any other person or entity (including copyrights, trademarks, privacy, publicity or other intellectual property or proprietary rights); +
  • +
  • + disclosing on Your Site accurately and adequately, either through a privacy policy or otherwise, how you collect, use, store, and disclose data collected from visitors, including, where applicable, that third parties (including us and other advertisers) may serve content and advertisements, collect information directly from visitors, and place or recognize cookies on visitors’ + browsers; and
  • +
  • + any use that you make of the Content and the JamKazam Marks, whether or not permitted under this Agreement. +
  • +
+

+ +

+ We will have no liability for these matters or for any of your end users’ claims relating to these matters, and you agree to defend, indemnify, and hold us, our affiliates and licensors, and our and their respective employees, officers, directors, and representatives, harmless from and against all claims, damages, losses, liabilities, costs, and expenses (including attorneys’ + fees) relating to (a) Your Site or any materials that appear on Your Site, including the combination of Your Site or those materials with other applications, content, or processes; (b) the use, development, design, manufacture, production, advertising, promotion, or marketing of Your Site or any materials that appear on or within Your Site, and all other matters described in this Section 5; (c) your use of any Content, whether or not such use is authorized by or violates this Agreement or any applicable law; (d) your violation of any term or condition of this Agreement; or (e) your or your employees' negligence or willful misconduct. +

+ +

+ +

6. Order Processing

+ +

+ +

+ We will process Product orders placed by Qualifying Customers (defined in Section 7) on the JamKazam Site. We reserve the right to reject orders that do not comply with any requirements on the JamKazam Site, as they may be updated from time to time. We will track Qualifying Purchases (defined in Section 7) for reporting and advertising fee accrual purposes and will make available to you reports summarizing those Qualifying Purchases. +

+ +

+ +

7. Advertising Fees

+ +

+ +

+ We will pay you advertising fees on Qualifying Purchases in accordance with Section 8 and the Program Advertising Fee Schedule in Section 10. Subject to the exclusions set forth below, a “Qualifying Purchase” + occurs when a Qualifying Customer: (a) purchases a Product within two (2) years of the date on which such Qualifying Customer registered to create his/her JamKazam account; and (b) pays for such Product. A “Qualifying Customer” + is an end user who: (a) clicks through a Special Link on Your Site to the JamKazam Site; and (b) during the single Session created by this click through, registers to create a new JamKazam account. A “Session” + begins when an end user clicks through a Special Link on Your Site to the JamKazam Site and ends when such end user leaves the JamKazam Site. +

+ +

+ +

+ Qualifying Purchases exclude, and we will not pay advertising fees on any of, the following: +

+ +

+
    +
  • + any Product purchase that is not correctly tracked or reported because the links from Your Site to the JamKazam Site are not properly formatted; +
  • +
  • + any Product purchased through a Special Link by you or on your behalf, including Products you purchase through Special Links for yourself, friends, relatives, or associates; +
  • +
  • + any Product purchased through a Special Link that violates the terms of this Agreement; +
  • +
  • any Product order that is canceled or returned;
  • +
  • any Product purchase that becomes classified as bad debt; or
  • +
  • + any Product purchase for which we process a promotional discount against the transaction that makes such Product free. +
  • +
+

+ +

8. Advertising Fee Payment

+ +

+ +

+ We will pay you advertising fees on a quarterly basis for Qualifying Purchases downloaded, shipped, or otherwise fulfilled (as applicable) in a given calendar quarter, subject to any applicable withholding or deduction described below. We will pay you approximately 30 days following the end of each calendar quarter by mailing a check in the amount of the advertising fees you earn to the mailing address then-currently associated with your JamKazam account, but we may accrue and withhold payment of advertising fees until the total amount due to you is at least US$50.00. If you do not have a valid mailing address associated with your JamKazam account within 30 days of the end of a calendar quarter, we will withhold any unpaid accrued advertising fees until you have associated a valid mailing address and notified us that you have done so. +

+ +

+ +

+ Further, any unpaid accrued advertising fees in your account may be subject to escheatment under state law. We may be obligated by law to obtain tax information from you if you are a U.S. citizen, U.S. resident, or U.S. corporation, or if your business is otherwise taxable in the U.S. If we request tax information from you and you do not provide it to us, we may (in addition to any other rights or remedies available to us) withhold your advertising fees until you provide this information or otherwise satisfy us that you are not a person from whom we are required to obtain tax information. +

+ +

+ +

9. Policies and Pricing

+ +

+ +

+ Qualifying Customers who buy Products through this Program are our customers with respect to all activities they undertake in connection with the JamKazam Site. Accordingly, as between you and us, all pricing, terms of sale, rules, policies, and operating procedures concerning customer orders, customer service, and product sales set forth on the JamKazam Site will apply to such Qualifying Customers, and we may change them at any time in our sole discretion. +

+ +

+ +

10. Program Advertising Fee Schedule

+ +

+ +

+ We will determine and calculate amounts payable to you as advertising fees for Qualifying Purchases as set forth in the table below (the “Program Advertising Fee Schedule”). +

+ +

+ + + + + + + + + + + + +

Product

Advertising Fees

JamTracks

+ We will pay advertising fees of US$0.20 per JamTrack sold as a Qualifying Purchase. +

+

+ +

+ From time to time, we may modify this Program Advertising Fee Schedule as part of modifications made to this Agreement. +

+ +

+ +

11. Limited License

+ +

+ +

+ Subject to the terms of this Agreement and solely for the limited purposes of advertising Products on, and directing end users to, the JamKazam Site in connection with the Program, we hereby grant you a limited, revocable, non-transferable, non-sublicensable, non-exclusive, royalty-free license to (a) copy and display the Content solely on Your Site; and (b) use only those of our trademarks and logos that we may make available to you as part of Content (those trademarks and logos, collectively, “JamKazam Marks”) solely on Your Site. +

+ +

+ +

+ The license set forth in this Section 11 will immediately and automatically terminate if at any time you do not timely comply with any obligation under this Agreement, or otherwise upon termination of this Agreement. In addition, we may terminate the license set forth in this Section 11 in whole or in part upon written notice to you. You will promptly remove from Your Site and delete or otherwise destroy all of the Content and JamKazam Marks with respect to which the license set forth in this Section 11 is terminated or as we may otherwise request from time to time. +

+ +

+ +

12. Reservation of Rights; Submissions

+ +

+ +

+ Other than the limited licenses expressly set forth in Section 11, we reserve all right, title and interest (including all intellectual property and proprietary rights) in and to, and you do not, by virtue of this Agreement or otherwise, acquire any ownership interest or rights in or to, the Program, Special Links, Content, Products, any domain name owned or operated by us, our trademarks and logos (including the JamKazam Marks), and any other intellectual property and technology that we provide or use in connection with the Program (including any application program interfaces, software development kits, libraries, sample code, and related materials). If you provide us with suggestions, reviews, modifications, data, images, text, or other information or content about a Product or in connection with this Agreement, any Content, or your participation in the Program, or if you modify any Content in any way, (collectively, “Your Submission”), you hereby irrevocably assign to us all right, title, and interest in and to Your Submission and grant us (even if you have designated Your Submission as confidential) a perpetual, paid-up royalty-free, nonexclusive, worldwide, irrevocable, freely transferable right and license to (a) use, reproduce, perform, display, and distribute Your Submission in any manner; (b) adapt, modify, re-format, and create derivative works of Your Submission for any purpose; (c) use and publish your name in the form of a credit in conjunction with Your Submission (however, we will not have any obligation to do so); and (d) sublicense the foregoing rights to any other person or entity. Additionally, you hereby warrant that: (y) Your Submission is your original work, or you obtained Your Submission in a lawful manner; and (z) our and our sublicensees’ + exercise of rights under the license above will not violate any person’s or entity’s rights, including any copyright rights. You agree to provide us such assistance as we may require to document, perfect, or maintain our rights in and to Your Submission. +

+ +

+ +

13. Compliance with Laws

+ +

+ +

+ In connection with your participation in the Program you will comply with all applicable laws, ordinances, rules, regulations, orders, licenses, permits, judgments, decisions, and other requirements of any governmental authority that has jurisdiction over you, including laws (federal, state, or otherwise) that govern marketing email (e.g., the CAN-SPAM Act of 2003). +

+ +

+ +

14. Term and Termination

+ +

+ +

+ The term of this Agreement will begin upon your execution of this Agreement by clicking the “I Agree” + button at the end of this Agreement, only if such execution is processed and confirmed successfully by the JamKazam Site, and will end when terminated by either you or us. Either you or we may terminate this Agreement at any time, with or without cause, by giving the other party written notice of termination. Upon any termination of this Agreement, any and all licenses you have with respect to Content will automatically terminate, and you will immediately stop using the Content and JamKazam Marks and promptly remove from Your Site and delete or otherwise destroy all links to the JamKazam Site, all JamKazam Marks, all other Content, and any other materials provided or made available by or on behalf of us to you under this Agreement or otherwise in connection with the Program. We may withhold accrued unpaid advertising fees for a reasonable period of time following termination to ensure that the correct amount is paid (e.g., to account for any cancelations or returns). Upon any termination of this Agreement, all rights and obligations of the parties will be extinguished, except that the rights and obligations of the parties under Sections 5, 9, 12, 13, 14, 16, 17, 18, 19, and 20, together with any of our payment obligations that accrue in accordance with Sections 6, 7, 8, and 10 following the termination of this Agreement, will survive the termination of this Agreement. No termination of this Agreement will relieve either party for any liability for any breach of, or liability accruing under, this Agreement prior to termination. +

+ +

+ +

15. Modification

+ +

+ +

+ We may modify any of the terms and conditions contained in this Agreement at any time and in our sole discretion by posting a change notice or revised agreement on the JamKazam Site or by sending notice of such modification to you by email to the email address then-currently associated with your JamKazam account (any such change by email will be effective on the date specified in such email and will in no event be less than two business days after the date the email is sent). Modifications may include, for example, changes to the Program Advertising Fee Schedule, payment procedures, and other Program requirements. IF ANY MODIFICATION IS UNACCEPTABLE TO YOU, YOUR ONLY RECOURSE IS TO TERMINATE THIS AGREEMENT. YOUR CONTINUED PARTICIPATION IN THE PROGRAM FOLLOWING THE EFFECTIVE DATE OF ANY MODIFICATION (E.G., THE DATE OF OUR POSTING OF A CHANGE NOTICE OR REVISED AGREEMENT ON THE JAMKAZAM SITE OR THE DATE SPECIFIED IN ANY EMAIL TO YOU REGARDING SUCH MODIFICATION) WILL CONSTITUTE YOUR BINDING ACCEPTANCE OF THE CHANGE. +

+ +

+ +

16. Relationship of Parties

+ +

+ +

+ You and we are independent contractors, and nothing in this Agreement will create any partnership, joint venture, agency, franchise, sales representative, or employment relationship between you and us or our respective affiliates. You will have no authority to make or accept any offers or representations on our behalf. You will not make any statement, whether on Your Site or otherwise, that contradicts or may contradict anything in this section. If you authorize, assist, encourage, or facilitate another person or entity to take any action related to the subject matter of this Agreement, you will be deemed to have taken the action yourself. +

+ +

+ +

17. Limitation of Liability

+ +

+ +

+ WE WILL NOT BE LIABLE FOR INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL, OR EXEMPLARY DAMAGES (INCLUDING ANY LOSS OF REVENUE, PROFITS, GOODWILL, USE, OR DATA) ARISING IN CONNECTION WITH THIS AGREEMENT, THE PROGRAM, THE JAMKAZAM SITE, OR THE SERVICE OFFERINGS (DEFINED BELOW), EVEN IF WE HAVE BEEN ADVISED OF THE POSSIBILITY OF THOSE DAMAGES. FURTHER, OUR AGGREGATE LIABILITY ARISING IN CONNECTION WITH THIS AGREEMENT, THE PROGRAM, THE JAMKAZAM SITE, AND THE SERVICE OFFERINGS WILL NOT EXCEED THE TOTAL ADVERTISING FEES PAID OR PAYABLE TO YOU UNDER THIS AGREEMENT IN THE TWELVE MONTHS IMMEDIATELY PRECEDING THE DATE ON WHICH THE EVENT GIVING RISE TO THE MOST RECENT CLAIM OF LIABILITY OCCURRED. +

+ +

+ +

18. Disclaimers

+ +

+ +

+ THE PROGRAM, THE JAMKAZAM SITE, ANY PRODUCTS AND SERVICES OFFERED ON THE JAMKAZAM SITE, ANY SPECIAL LINKS, LINK FORMATS, CONTENT, JAMKAZAM.COM DOMAIN NAME, OUR TRADEMARKS AND LOGOS (INCLUDING THE JAMKAZAM MARKS), AND ALL TECHNOLOGY, SOFTWARE, FUNCTIONS, MATERIALS, DATA, IMAGES, TEXT, AND OTHER INFORMATION AND CONTENT PROVIDED OR USED BY OR ON BEHALF OF US OR LICENSORS IN CONNECTION WITH THE PROGRAM (COLLECTIVELY THE “SERVICE OFFERINGS”) ARE PROVIDED “AS IS.” + NEITHER WE NOR ANY OF OUR LICENSORS MAKE ANY REPRESENTATION OR WARRANTY OF ANY KIND, WHETHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO THE SERVICE OFFERINGS. EXCEPT TO THE EXTENT PROHIBITED BY APPLICABLE LAW, WE AND OUR LICENSORS DISCLAIM ALL WARRANTIES WITH RESPECT TO THE SERVICE OFFERINGS, INCLUDING ANY IMPLIED WARRANTIES OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND QUIET ENJOYMENT, AND ANY WARRANTIES ARISING OUT OF ANY COURSE OF DEALING, PERFORMANCE, OR TRADE USAGE. WE MAY DISCONTINUE ANY SERVICE OFFERING, OR MAY CHANGE THE NATURE, FEATURES, FUNCTIONS, SCOPE, OR OPERATION OF ANY SERVICE OFFERING, AT ANY TIME AND FROM TIME TO TIME. NEITHER WE NOR ANY OF OUR LICENSORS WARRANT THAT THE SERVICE OFFERINGS WILL CONTINUE TO BE PROVIDED, WILL FUNCTION AS DESCRIBED, CONSISTENTLY OR IN ANY PARTICULAR MANNER, OR WILL BE UNINTERRUPTED, ACCURATE, ERROR FREE, OR FREE OF HARMFUL COMPONENTS. NEITHER WE NOR ANY OF OUR LICENSORS WILL BE RESPONSIBLE FOR (A) ANY ERRORS, INACCURACIES, OR SERVICE INTERRUPTIONS, INCLUDING POWER OUTAGES OR SYSTEM FAILURES; OR (B) ANY UNAUTHORIZED ACCESS TO OR ALTERATION OF, OR DELETION, DESTRUCTION, DAMAGE, OR LOSS OF, YOUR SITE OR ANY DATA, IMAGES, TEXT, OR OTHER INFORMATION OR CONTENT. NO ADVICE OR INFORMATION OBTAINED BY YOU FROM US OR FROM ANY OTHER PERSON OR ENTITY OR THROUGH THE PROGRAM, CONTENT, OR THE JAMKAZAM SITE WILL CREATE ANY WARRANTY NOT EXPRESSLY STATED IN THIS AGREEMENT. FURTHER, NEITHER WE NOR ANY OF OUR LICENSORS WILL BE RESPONSIBLE FOR ANY COMPENSATION, REIMBURSEMENT, OR DAMAGES ARISING IN CONNECTION WITH (X) ANY LOSS OF PROSPECTIVE PROFITS OR REVENUE, ANTICIPATED SALES, GOODWILL, OR OTHER BENEFITS, (Y) ANY INVESTMENTS, EXPENDITURES, OR COMMITMENTS BY YOU IN CONNECTION WITH THIS AGREEMENT OR YOUR PARTICIPATION IN THE PROGRAM, OR (Z) ANY TERMINATION OF THIS AGREEMENT OR YOUR PARTICIPATION IN THE PROGRAM. +

+ +

+ +

19. Disputes

+ +

+ +

+ Any dispute relating in any way to the Program or this Agreement will be resolved by binding arbitration, rather than in court, except that you may assert claims in small claims court if your claims qualify. The Federal Arbitration Act and federal arbitration law and the laws of the state of Texas, without regard to principles of conflict of laws, will govern this Agreement and any dispute of any sort that might arise between you and us. +

+ +

+ +

+ There is no judge or jury in arbitration, and court review of an arbitration award is limited. However, an arbitrator can award on an individual basis the same damages and relief as a court (including injunctive and declaratory relief or statutory damages), and must follow the terms of this Agreement as a court would. +

+ +

+ +

+ To begin an arbitration proceeding, you must send a letter requesting arbitration and describing your claim to us at: JamKazam, Inc., Attn: Legal Department, 5813 Lookout Mountain Drive, Austin TX 78731. The arbitration will be conducted by the American Arbitration Association (“AAA”) under its rules, including the AAA’s Supplementary Procedures for Consumer-Related Disputes. The AAA’s rules are available at www.adr.org or by calling 1-800-778-7879. Payment of all filing, administration and arbitrator fees will be governed by the AAA’s rules. We will reimburse those fees for claims totaling less than $10,000 unless the arbitrator determines the claims are frivolous. Likewise, we will not seek attorneys’ + fees and costs in arbitration unless the arbitrator determines the claims are frivolous. You may choose to have the arbitration conducted by telephone, based on written submissions, or in person in the county where you live or at another mutually agreed location. +

+ +

+ +

+ We each agree that any dispute resolution proceedings will be conducted only on an individual basis and not in a class, consolidated or representative action. If for any reason a claim proceeds in court rather than in arbitration, we each waive any right to a jury trial. We also both agree that you or we may bring suit in court to enjoin infringement or other misuse of intellectual property rights. +

+ +

+ +

+ Notwithstanding anything to the contrary in this Agreement, we may seek injunctive or other relief in any state, federal, or national court of competent jurisdiction for any actual or alleged infringement of our or any other person or entity’s intellectual property or proprietary rights. You further acknowledge and agree that our rights in the Content are of a special, unique, extraordinary character, giving them peculiar value, the loss of which cannot be readily estimated or adequately compensated for in monetary damages. +

+ +

+ +

20. Miscellaneous

+ +

+ +

+ You acknowledge and agree that we may at any time (directly or indirectly) solicit customer referrals on terms that may differ from those contained in this Agreement or operate sites that are similar to or compete with Your Site. You may not assign this Agreement, by operation of law or otherwise, without our express prior written approval. Subject to that restriction, this Agreement will be binding on, inure to the benefit of, and be enforceable against the parties and their respective successors and assigns. Our failure to enforce your strict performance of any provision of this Agreement will not constitute a waiver of our right to subsequently enforce such provision or any other provision of this Agreement. Whenever used in this Agreement, the terms “include(s),” “including,” “e.g.,” + and “for example” mean, respectively, “include(s), without limitation,” “including, without limitation,” “e.g., without limitation,” + and “for example, without limitation.” Any determinations or updates that may be made by us, any actions that may be taken by us, and any approvals that may be given by us under this Agreement, may be made, taken, or given in our sole discretion. +

+ +

+ +

+ +

+ BY CLICKING THE "I AGREE" BUTTON BELOW, YOU AGREE TO THE TERMS AND CONDITIONS OF THIS AGREEMENT, OR BY CONTINUING TO PARTICIPATE IN THE PROGRAM FOLLOWING OUR POSTING OF A CHANGE NOTICE OR REVISED AGREEMENT ON THE JAMKAZAM.COM SITE, YOU (A) AGREE TO BE BOUND BY THIS AGREEMENT; (B) ACKNOWLEDGE AND AGREE THAT YOU HAVE INDEPENDENTLY EVALUATED THE DESIRABILITY OF PARTICIPATING IN THE PROGRAM AND ARE NOT RELYING ON ANY REPRESENTATION, GUARANTEE, OR STATEMENT OTHER THAN AS EXPRESSLY SET FORTH IN THIS AGREEMENT; AND (C) HEREBY REPRESENT AND WARRANT THAT YOU ARE LAWFULLY ABLE TO ENTER INTO CONTRACTS (E.G., YOU ARE NOT A MINOR) AND THAT YOU ARE AND WILL REMAIN IN COMPLIANCE WITH THIS AGREEMENT. IN ADDITION, IF THIS AGREEMENT IS BEING AGREED TO BY A COMPANY OR OTHER LEGAL ENTITY, THEN THE PERSON AGREEING TO THIS AGREEMENT ON BEHALF OF THAT COMPANY OR ENTITY HEREBY REPRESENTS AND WARRANTS THAT HE OR SHE IS AUTHORIZED AND LAWFULLY ABLE TO BIND THAT COMPANY OR ENTITY TO THIS AGREEMENT. +

+ + + +

+ JamKazam Confidential                4/17/2015 +

+
\ No newline at end of file diff --git a/web/app/views/legal/partner_agreement_full.html.erb b/web/app/views/legal/partner_agreement_full.html.erb new file mode 100644 index 000000000..1c6203aef --- /dev/null +++ b/web/app/views/legal/partner_agreement_full.html.erb @@ -0,0 +1,5062 @@ + +2015-04 JamKazam Affiliate Agreement v2.docx + + + + +

        

+

JamKazam Affiliate Agreement

+ +

Updated: April 30, 2015.

+ +

+ +

+ This Affiliate Agreement (this “Agreement”) contains the terms and conditions that govern your participation in the JamKazam affiliate marketing program (the “Program”). “JamKazam”, “we,” “us,” + or “our” + means JamKazam, Inc. “You” + or “your” + means the applicant. A “site” + means a website. “JamKazam Site” means the jamkazam.com website or a JamKazam applicaion or any other site that is owned or operated by or on behalf of us and which is identified as participating in the Program in the Program Advertising Fee Schedule in Section 10, as applicable. “Your Site” + means any site(s), software application(s), or content that you create, own, or operate and link to the JamKazam Site. +

+ +

+ +

1. Description of the Program

+ +

+ +

+ The purpose of the Program is to permit you to advertise Products on Your Site and to earn advertising fees for Qualifying Purchases (defined in Section 7) made by your Qualifying Customers (defined in Section 7). A “Product” + is an item sold on the JamKazam Site and listed in the Program Advertising Fee Schedule in Section 10. In order to facilitate your advertisement of Products, we may make available to you data, images, text, link formats, widgets, links, and other linking tools, and other information in connection with the Program (“Content”). +

+ +

+ +

2. Enrollment, Suitability, and Communications

+ +

+ +

To enroll in the Program, you must execute this Agreement by clicking the “I Agree” + button at the end of this Agreement, after having thoroughly reviewed the Agreement.

+ +

+ +

+ Your Site may be considered unsuitable for participation in the Program resulting in termination of this Agreement by JamKazam if Your Site: +

+ +

+
    +
  • promotes or contains sexually explicit materials;
  • +
  • promotes violence or contains violent materials;
  • +
  • promotes or contains libelous or defamatory materials;
  • +
  • + promotes discrimination, or employs discriminatory practices, based on race, sex, religion, nationality, disability, sexual orientation, or age; +
  • +
  • promotes or undertakes illegal activities;
  • +
  • + is directed toward children under 13 years of age, as defined by the Children’s Online Privacy Protection Act (15 U.S.C. §§ + 6501-6506) and any regulations promulgated thereunder;
  • +
  • + includes any trademark of JamKazam or a variant or misspelling of a trademark of JamKazam in any domain name, subdomain name, or in any username, group name, or other identifier on any social networking site; or +
  • +
  • otherwise violates intellectual property rights.
  • +
+

+ +

+ You will ensure that the information you provide in executing this Agreement and otherwise associated with your account, including your name, email address, mailing address, tax ID, and other information, is at all times complete, accurate, and up-to-date. We may send notifications (if any), reports (if any), and other communications relating to the Program and this Agreement to the email address then-currently associated with your JamKazam account. You will be deemed to have received all notifications, reports, and other communications sent to that email address, even if the email address associated with your account is no longer current. We may mail checks (if any) payable to you for advertising fees earned under this Agreement to the mailing address then-currently associated with your JamKazam account. You will be deemed to have received all checks sent to that mailing address, even if the mailing address associated with your account is no longer current. If we send a check to a mailing address that is no longer valid, we may, in our sole discretion, choose to issue a stop payment order for such a check and send a new check to a new current address that your provide, but in such a case, we will charge a US$50.00 fee for this exception process. +

+ +

+ +

+ If you are a Non-US person participating in the Program, you agree that you will perform all services under the Agreement outside the United States. +

+ +

+ +

3. Links on Your Site

+ +

+ +

+ After you have entered into this Agreement, you may display Special Links on Your Site. “Special Links” + are links to the JamKazam Site that you place on Your Site in accordance with this Agreement, that properly utilize the special “tagged” + link formats we specify or provide. Special Links permit accurate tracking, reporting, and accrual of advertising fees. +

+ +

+ +

+ You may earn advertising fees only as described in Section 7 and only with respect to activity on the JamKazam Site occurring directly through Special Links. We will have no obligation to pay you advertising fees if you fail to properly format the links on Your Site to the JamKazam Site as Special Links, including to the extent that such failure may result in any reduction of advertising fee amounts that would otherwise be paid to you under this Agreement. +

+ +

+ +

4. Program Requirements

+ +

+ +

You hereby consent to us:

+ +

+
    +
  • sending you emails relating to the Program from time to time; and
  • +
  • + monitoring, recording, using, and disclosing information about Your Site and visitors to Your Site that we obtain in connection with your display of Special Links in accordance with the JamKazam Privacy Policy. +
  • +
+

+ +

5. Responsibility for Your Site

+ +

+ +

+ You will be solely responsible for Your Site including its development, operation, and maintenance, and all materials that appear on or within it. For example, you will be solely responsible for: +

+ +

+
    +
  • the technical operation of Your Site and all related equipment;
  • +
  • + displaying Special Links and Content on Your Site in compliance with this Agreement and any agreement between you and any other person or entity (including any restrictions or requirements placed on you by any person or entity that hosts Your Site); +
  • +
  • + creating and posting, and ensuring the accuracy, completeness, and appropriateness of, materials posted on Your Site (including all Product descriptions and other Product-related materials and any information you include within or associate with Special Links); +
  • +
  • + using the Content, Your Site, and the materials on or within Your Site in a manner that does not infringe, violate, or misappropriate any of our rights or those of any other person or entity (including copyrights, trademarks, privacy, publicity or other intellectual property or proprietary rights); +
  • +
  • + disclosing on Your Site accurately and adequately, either through a privacy policy or otherwise, how you collect, use, store, and disclose data collected from visitors, including, where applicable, that third parties (including us and other advertisers) may serve content and advertisements, collect information directly from visitors, and place or recognize cookies on visitors’ + browsers; and
  • +
  • + any use that you make of the Content and the JamKazam Marks, whether or not permitted under this Agreement. +
  • +
+

+ +

+ We will have no liability for these matters or for any of your end users’ claims relating to these matters, and you agree to defend, indemnify, and hold us, our affiliates and licensors, and our and their respective employees, officers, directors, and representatives, harmless from and against all claims, damages, losses, liabilities, costs, and expenses (including attorneys’ + fees) relating to (a) Your Site or any materials that appear on Your Site, including the combination of Your Site or those materials with other applications, content, or processes; (b) the use, development, design, manufacture, production, advertising, promotion, or marketing of Your Site or any materials that appear on or within Your Site, and all other matters described in this Section 5; (c) your use of any Content, whether or not such use is authorized by or violates this Agreement or any applicable law; (d) your violation of any term or condition of this Agreement; or (e) your or your employees' negligence or willful misconduct. +

+ +

+ +

6. Order Processing

+ +

+ +

+ We will process Product orders placed by Qualifying Customers (defined in Section 7) on the JamKazam Site. We reserve the right to reject orders that do not comply with any requirements on the JamKazam Site, as they may be updated from time to time. We will track Qualifying Purchases (defined in Section 7) for reporting and advertising fee accrual purposes and will make available to you reports summarizing those Qualifying Purchases. +

+ +

+ +

7. Advertising Fees

+ +

+ +

+ We will pay you advertising fees on Qualifying Purchases in accordance with Section 8 and the Program Advertising Fee Schedule in Section 10. Subject to the exclusions set forth below, a “Qualifying Purchase” + occurs when a Qualifying Customer: (a) purchases a Product within two (2) years of the date on which such Qualifying Customer registered to create his/her JamKazam account; and (b) pays for such Product. A “Qualifying Customer” + is an end user who: (a) clicks through a Special Link on Your Site to the JamKazam Site; and (b) during the single Session created by this click through, registers to create a new JamKazam account. A “Session” + begins when an end user clicks through a Special Link on Your Site to the JamKazam Site and ends when such end user leaves the JamKazam Site. +

+ +

+ +

+ Qualifying Purchases exclude, and we will not pay advertising fees on any of, the following: +

+ +

+
    +
  • + any Product purchase that is not correctly tracked or reported because the links from Your Site to the JamKazam Site are not properly formatted; +
  • +
  • + any Product purchased through a Special Link by you or on your behalf, including Products you purchase through Special Links for yourself, friends, relatives, or associates; +
  • +
  • + any Product purchased through a Special Link that violates the terms of this Agreement; +
  • +
  • any Product order that is canceled or returned;
  • +
  • any Product purchase that becomes classified as bad debt; or
  • +
  • + any Product purchase for which we process a promotional discount against the transaction that makes such Product free. +
  • +
+

+ +

8. Advertising Fee Payment

+ +

+ +

+ We will pay you advertising fees on a quarterly basis for Qualifying Purchases downloaded, shipped, or otherwise fulfilled (as applicable) in a given calendar quarter, subject to any applicable withholding or deduction described below. We will pay you approximately 30 days following the end of each calendar quarter by mailing a check in the amount of the advertising fees you earn to the mailing address then-currently associated with your JamKazam account, but we may accrue and withhold payment of advertising fees until the total amount due to you is at least US$50.00. If you do not have a valid mailing address associated with your JamKazam account within 30 days of the end of a calendar quarter, we will withhold any unpaid accrued advertising fees until you have associated a valid mailing address and notified us that you have done so. +

+ +

+ +

+ Further, any unpaid accrued advertising fees in your account may be subject to escheatment under state law. We may be obligated by law to obtain tax information from you if you are a U.S. citizen, U.S. resident, or U.S. corporation, or if your business is otherwise taxable in the U.S. If we request tax information from you and you do not provide it to us, we may (in addition to any other rights or remedies available to us) withhold your advertising fees until you provide this information or otherwise satisfy us that you are not a person from whom we are required to obtain tax information. +

+ +

+ +

9. Policies and Pricing

+ +

+ +

+ Qualifying Customers who buy Products through this Program are our customers with respect to all activities they undertake in connection with the JamKazam Site. Accordingly, as between you and us, all pricing, terms of sale, rules, policies, and operating procedures concerning customer orders, customer service, and product sales set forth on the JamKazam Site will apply to such Qualifying Customers, and we may change them at any time in our sole discretion. +

+ +

+ +

10. Program Advertising Fee Schedule

+ +

+ +

+ We will determine and calculate amounts payable to you as advertising fees for Qualifying Purchases as set forth in the table below (the “Program Advertising Fee Schedule”). +

+ +

+ + + + + + + + + + + + +

Product

Advertising Fees

JamTracks

+ We will pay advertising fees of US$0.20 per JamTrack sold as a Qualifying Purchase. +

+

+ +

+ From time to time, we may modify this Program Advertising Fee Schedule as part of modifications made to this Agreement. +

+ +

+ +

11. Limited License

+ +

+ +

+ Subject to the terms of this Agreement and solely for the limited purposes of advertising Products on, and directing end users to, the JamKazam Site in connection with the Program, we hereby grant you a limited, revocable, non-transferable, non-sublicensable, non-exclusive, royalty-free license to (a) copy and display the Content solely on Your Site; and (b) use only those of our trademarks and logos that we may make available to you as part of Content (those trademarks and logos, collectively, “JamKazam Marks”) solely on Your Site. +

+ +

+ +

+ The license set forth in this Section 11 will immediately and automatically terminate if at any time you do not timely comply with any obligation under this Agreement, or otherwise upon termination of this Agreement. In addition, we may terminate the license set forth in this Section 11 in whole or in part upon written notice to you. You will promptly remove from Your Site and delete or otherwise destroy all of the Content and JamKazam Marks with respect to which the license set forth in this Section 11 is terminated or as we may otherwise request from time to time. +

+ +

+ +

12. Reservation of Rights; Submissions

+ +

+ +

+ Other than the limited licenses expressly set forth in Section 11, we reserve all right, title and interest (including all intellectual property and proprietary rights) in and to, and you do not, by virtue of this Agreement or otherwise, acquire any ownership interest or rights in or to, the Program, Special Links, Content, Products, any domain name owned or operated by us, our trademarks and logos (including the JamKazam Marks), and any other intellectual property and technology that we provide or use in connection with the Program (including any application program interfaces, software development kits, libraries, sample code, and related materials). If you provide us with suggestions, reviews, modifications, data, images, text, or other information or content about a Product or in connection with this Agreement, any Content, or your participation in the Program, or if you modify any Content in any way, (collectively, “Your Submission”), you hereby irrevocably assign to us all right, title, and interest in and to Your Submission and grant us (even if you have designated Your Submission as confidential) a perpetual, paid-up royalty-free, nonexclusive, worldwide, irrevocable, freely transferable right and license to (a) use, reproduce, perform, display, and distribute Your Submission in any manner; (b) adapt, modify, re-format, and create derivative works of Your Submission for any purpose; (c) use and publish your name in the form of a credit in conjunction with Your Submission (however, we will not have any obligation to do so); and (d) sublicense the foregoing rights to any other person or entity. Additionally, you hereby warrant that: (y) Your Submission is your original work, or you obtained Your Submission in a lawful manner; and (z) our and our sublicensees’ + exercise of rights under the license above will not violate any person’s or entity’s rights, including any copyright rights. You agree to provide us such assistance as we may require to document, perfect, or maintain our rights in and to Your Submission. +

+ +

+ +

13. Compliance with Laws

+ +

+ +

+ In connection with your participation in the Program you will comply with all applicable laws, ordinances, rules, regulations, orders, licenses, permits, judgments, decisions, and other requirements of any governmental authority that has jurisdiction over you, including laws (federal, state, or otherwise) that govern marketing email (e.g., the CAN-SPAM Act of 2003). +

+ +

+ +

14. Term and Termination

+ +

+ +

+ The term of this Agreement will begin upon your execution of this Agreement by clicking the “I Agree” + button at the end of this Agreement, only if such execution is processed and confirmed successfully by the JamKazam Site, and will end when terminated by either you or us. Either you or we may terminate this Agreement at any time, with or without cause, by giving the other party written notice of termination. Upon any termination of this Agreement, any and all licenses you have with respect to Content will automatically terminate, and you will immediately stop using the Content and JamKazam Marks and promptly remove from Your Site and delete or otherwise destroy all links to the JamKazam Site, all JamKazam Marks, all other Content, and any other materials provided or made available by or on behalf of us to you under this Agreement or otherwise in connection with the Program. We may withhold accrued unpaid advertising fees for a reasonable period of time following termination to ensure that the correct amount is paid (e.g., to account for any cancelations or returns). Upon any termination of this Agreement, all rights and obligations of the parties will be extinguished, except that the rights and obligations of the parties under Sections 5, 9, 12, 13, 14, 16, 17, 18, 19, and 20, together with any of our payment obligations that accrue in accordance with Sections 6, 7, 8, and 10 following the termination of this Agreement, will survive the termination of this Agreement. No termination of this Agreement will relieve either party for any liability for any breach of, or liability accruing under, this Agreement prior to termination. +

+ +

+ +

15. Modification

+ +

+ +

+ We may modify any of the terms and conditions contained in this Agreement at any time and in our sole discretion by posting a change notice or revised agreement on the JamKazam Site or by sending notice of such modification to you by email to the email address then-currently associated with your JamKazam account (any such change by email will be effective on the date specified in such email and will in no event be less than two business days after the date the email is sent). Modifications may include, for example, changes to the Program Advertising Fee Schedule, payment procedures, and other Program requirements. IF ANY MODIFICATION IS UNACCEPTABLE TO YOU, YOUR ONLY RECOURSE IS TO TERMINATE THIS AGREEMENT. YOUR CONTINUED PARTICIPATION IN THE PROGRAM FOLLOWING THE EFFECTIVE DATE OF ANY MODIFICATION (E.G., THE DATE OF OUR POSTING OF A CHANGE NOTICE OR REVISED AGREEMENT ON THE JAMKAZAM SITE OR THE DATE SPECIFIED IN ANY EMAIL TO YOU REGARDING SUCH MODIFICATION) WILL CONSTITUTE YOUR BINDING ACCEPTANCE OF THE CHANGE. +

+ +

+ +

16. Relationship of Parties

+ +

+ +

+ You and we are independent contractors, and nothing in this Agreement will create any partnership, joint venture, agency, franchise, sales representative, or employment relationship between you and us or our respective affiliates. You will have no authority to make or accept any offers or representations on our behalf. You will not make any statement, whether on Your Site or otherwise, that contradicts or may contradict anything in this section. If you authorize, assist, encourage, or facilitate another person or entity to take any action related to the subject matter of this Agreement, you will be deemed to have taken the action yourself. +

+ +

+ +

17. Limitation of Liability

+ +

+ +

+ WE WILL NOT BE LIABLE FOR INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL, OR EXEMPLARY DAMAGES (INCLUDING ANY LOSS OF REVENUE, PROFITS, GOODWILL, USE, OR DATA) ARISING IN CONNECTION WITH THIS AGREEMENT, THE PROGRAM, THE JAMKAZAM SITE, OR THE SERVICE OFFERINGS (DEFINED BELOW), EVEN IF WE HAVE BEEN ADVISED OF THE POSSIBILITY OF THOSE DAMAGES. FURTHER, OUR AGGREGATE LIABILITY ARISING IN CONNECTION WITH THIS AGREEMENT, THE PROGRAM, THE JAMKAZAM SITE, AND THE SERVICE OFFERINGS WILL NOT EXCEED THE TOTAL ADVERTISING FEES PAID OR PAYABLE TO YOU UNDER THIS AGREEMENT IN THE TWELVE MONTHS IMMEDIATELY PRECEDING THE DATE ON WHICH THE EVENT GIVING RISE TO THE MOST RECENT CLAIM OF LIABILITY OCCURRED. +

+ +

+ +

18. Disclaimers

+ +

+ +

+ THE PROGRAM, THE JAMKAZAM SITE, ANY PRODUCTS AND SERVICES OFFERED ON THE JAMKAZAM SITE, ANY SPECIAL LINKS, LINK FORMATS, CONTENT, JAMKAZAM.COM DOMAIN NAME, OUR TRADEMARKS AND LOGOS (INCLUDING THE JAMKAZAM MARKS), AND ALL TECHNOLOGY, SOFTWARE, FUNCTIONS, MATERIALS, DATA, IMAGES, TEXT, AND OTHER INFORMATION AND CONTENT PROVIDED OR USED BY OR ON BEHALF OF US OR LICENSORS IN CONNECTION WITH THE PROGRAM (COLLECTIVELY THE “SERVICE OFFERINGS”) ARE PROVIDED “AS IS.” + NEITHER WE NOR ANY OF OUR LICENSORS MAKE ANY REPRESENTATION OR WARRANTY OF ANY KIND, WHETHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO THE SERVICE OFFERINGS. EXCEPT TO THE EXTENT PROHIBITED BY APPLICABLE LAW, WE AND OUR LICENSORS DISCLAIM ALL WARRANTIES WITH RESPECT TO THE SERVICE OFFERINGS, INCLUDING ANY IMPLIED WARRANTIES OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND QUIET ENJOYMENT, AND ANY WARRANTIES ARISING OUT OF ANY COURSE OF DEALING, PERFORMANCE, OR TRADE USAGE. WE MAY DISCONTINUE ANY SERVICE OFFERING, OR MAY CHANGE THE NATURE, FEATURES, FUNCTIONS, SCOPE, OR OPERATION OF ANY SERVICE OFFERING, AT ANY TIME AND FROM TIME TO TIME. NEITHER WE NOR ANY OF OUR LICENSORS WARRANT THAT THE SERVICE OFFERINGS WILL CONTINUE TO BE PROVIDED, WILL FUNCTION AS DESCRIBED, CONSISTENTLY OR IN ANY PARTICULAR MANNER, OR WILL BE UNINTERRUPTED, ACCURATE, ERROR FREE, OR FREE OF HARMFUL COMPONENTS. NEITHER WE NOR ANY OF OUR LICENSORS WILL BE RESPONSIBLE FOR (A) ANY ERRORS, INACCURACIES, OR SERVICE INTERRUPTIONS, INCLUDING POWER OUTAGES OR SYSTEM FAILURES; OR (B) ANY UNAUTHORIZED ACCESS TO OR ALTERATION OF, OR DELETION, DESTRUCTION, DAMAGE, OR LOSS OF, YOUR SITE OR ANY DATA, IMAGES, TEXT, OR OTHER INFORMATION OR CONTENT. NO ADVICE OR INFORMATION OBTAINED BY YOU FROM US OR FROM ANY OTHER PERSON OR ENTITY OR THROUGH THE PROGRAM, CONTENT, OR THE JAMKAZAM SITE WILL CREATE ANY WARRANTY NOT EXPRESSLY STATED IN THIS AGREEMENT. FURTHER, NEITHER WE NOR ANY OF OUR LICENSORS WILL BE RESPONSIBLE FOR ANY COMPENSATION, REIMBURSEMENT, OR DAMAGES ARISING IN CONNECTION WITH (X) ANY LOSS OF PROSPECTIVE PROFITS OR REVENUE, ANTICIPATED SALES, GOODWILL, OR OTHER BENEFITS, (Y) ANY INVESTMENTS, EXPENDITURES, OR COMMITMENTS BY YOU IN CONNECTION WITH THIS AGREEMENT OR YOUR PARTICIPATION IN THE PROGRAM, OR (Z) ANY TERMINATION OF THIS AGREEMENT OR YOUR PARTICIPATION IN THE PROGRAM. +

+ +

+ +

19. Disputes

+ +

+ +

+ Any dispute relating in any way to the Program or this Agreement will be resolved by binding arbitration, rather than in court, except that you may assert claims in small claims court if your claims qualify. The Federal Arbitration Act and federal arbitration law and the laws of the state of Texas, without regard to principles of conflict of laws, will govern this Agreement and any dispute of any sort that might arise between you and us. +

+ +

+ +

+ There is no judge or jury in arbitration, and court review of an arbitration award is limited. However, an arbitrator can award on an individual basis the same damages and relief as a court (including injunctive and declaratory relief or statutory damages), and must follow the terms of this Agreement as a court would. +

+ +

+ +

+ To begin an arbitration proceeding, you must send a letter requesting arbitration and describing your claim to us at: JamKazam, Inc., Attn: Legal Department, 5813 Lookout Mountain Drive, Austin TX 78731. The arbitration will be conducted by the American Arbitration Association (“AAA”) under its rules, including the AAA’s Supplementary Procedures for Consumer-Related Disputes. The AAA’s rules are available at www.adr.org or by calling 1-800-778-7879. Payment of all filing, administration and arbitrator fees will be governed by the AAA’s rules. We will reimburse those fees for claims totaling less than $10,000 unless the arbitrator determines the claims are frivolous. Likewise, we will not seek attorneys’ + fees and costs in arbitration unless the arbitrator determines the claims are frivolous. You may choose to have the arbitration conducted by telephone, based on written submissions, or in person in the county where you live or at another mutually agreed location. +

+ +

+ +

+ We each agree that any dispute resolution proceedings will be conducted only on an individual basis and not in a class, consolidated or representative action. If for any reason a claim proceeds in court rather than in arbitration, we each waive any right to a jury trial. We also both agree that you or we may bring suit in court to enjoin infringement or other misuse of intellectual property rights. +

+ +

+ +

+ Notwithstanding anything to the contrary in this Agreement, we may seek injunctive or other relief in any state, federal, or national court of competent jurisdiction for any actual or alleged infringement of our or any other person or entity’s intellectual property or proprietary rights. You further acknowledge and agree that our rights in the Content are of a special, unique, extraordinary character, giving them peculiar value, the loss of which cannot be readily estimated or adequately compensated for in monetary damages. +

+ +

+ +

20. Miscellaneous

+ +

+ +

+ You acknowledge and agree that we may at any time (directly or indirectly) solicit customer referrals on terms that may differ from those contained in this Agreement or operate sites that are similar to or compete with Your Site. You may not assign this Agreement, by operation of law or otherwise, without our express prior written approval. Subject to that restriction, this Agreement will be binding on, inure to the benefit of, and be enforceable against the parties and their respective successors and assigns. Our failure to enforce your strict performance of any provision of this Agreement will not constitute a waiver of our right to subsequently enforce such provision or any other provision of this Agreement. Whenever used in this Agreement, the terms “include(s),” “including,” “e.g.,” + and “for example” mean, respectively, “include(s), without limitation,” “including, without limitation,” “e.g., without limitation,” + and “for example, without limitation.” Any determinations or updates that may be made by us, any actions that may be taken by us, and any approvals that may be given by us under this Agreement, may be made, taken, or given in our sole discretion. +

+ +

+ +

+ +

+ BY CLICKING THE "I AGREE" BUTTON BELOW, YOU AGREE TO THE TERMS AND CONDITIONS OF THIS AGREEMENT, OR BY CONTINUING TO PARTICIPATE IN THE PROGRAM FOLLOWING OUR POSTING OF A CHANGE NOTICE OR REVISED AGREEMENT ON THE JAMKAZAM.COM SITE, YOU (A) AGREE TO BE BOUND BY THIS AGREEMENT; (B) ACKNOWLEDGE AND AGREE THAT YOU HAVE INDEPENDENTLY EVALUATED THE DESIRABILITY OF PARTICIPATING IN THE PROGRAM AND ARE NOT RELYING ON ANY REPRESENTATION, GUARANTEE, OR STATEMENT OTHER THAN AS EXPRESSLY SET FORTH IN THIS AGREEMENT; AND (C) HEREBY REPRESENT AND WARRANT THAT YOU ARE LAWFULLY ABLE TO ENTER INTO CONTRACTS (E.G., YOU ARE NOT A MINOR) AND THAT YOU ARE AND WILL REMAIN IN COMPLIANCE WITH THIS AGREEMENT. IN ADDITION, IF THIS AGREEMENT IS BEING AGREED TO BY A COMPANY OR OTHER LEGAL ENTITY, THEN THE PERSON AGREEING TO THIS AGREEMENT ON BEHALF OF THAT COMPANY OR ENTITY HEREBY REPRESENTS AND WARRANTS THAT HE OR SHE IS AUTHORIZED AND LAWFULLY ABLE TO BIND THAT COMPANY OR ENTITY TO THIS AGREEMENT. +

+ +

+ +

Radio buttons for:

+
    +
  • I am entering into this Agreement as an individual
  • +
  • + I am executing this Agreement on behalf of the company or entity listed below
  • +
+

+ +

+ If the user clicks the entity radio button above, we display an Entity Name label and associated text entry box, and an Entity Type label with a drop down list box with the following options: Sole Proprietorship, Limited Liability Company (LLC), S Corporation, C Corporation, Partnership, Trust/Estate, and Other. +

+ +

+ +

+ Green “I Agree” button on the left / centered. Red “I Do Not Agree” button on the right / centered. +

+ +

+ +

+ +

+ +

JamKazam Confidential                4/17/2015 +

+ + \ No newline at end of file diff --git a/web/app/views/users/new.html.erb b/web/app/views/users/new.html.erb index f7b718af5..01fc14c25 100644 --- a/web/app/views/users/new.html.erb +++ b/web/app/views/users/new.html.erb @@ -145,7 +145,7 @@ - +
<% end %> diff --git a/web/config/environments/test.rb b/web/config/environments/test.rb index 920391264..b20761c29 100644 --- a/web/config/environments/test.rb +++ b/web/config/environments/test.rb @@ -108,5 +108,6 @@ SampleApp::Application.configure do config.jam_tracks_available = true config.video_available = "full" config.guard_against_fraud = true + config.error_on_fraud = true end diff --git a/web/config/routes.rb b/web/config/routes.rb index f9a2b8244..7c6c5bd27 100644 --- a/web/config/routes.rb +++ b/web/config/routes.rb @@ -32,6 +32,9 @@ SampleApp::Application.routes.draw do match '/landing/kick4', to: 'landings#watch_overview_kick4', via: :get, as: 'landing_kick4' match '/landing/jamtracks/:plan_code', to: 'landings#individual_jamtrack', via: :get, as: 'individual_jamtrack' match '/landing/jamtracks/band/:plan_code', to: 'landings#individual_jamtrack_band', via: :get, as: 'individual_jamtrack_band' + match '/affiliateProgram', to: 'landings#affiliate_program', via: :get, as: 'affiliate_program' + + match '/affiliate/links/:id', to: 'affiliates#links', via: :get, as: 'affilate_links' # redirect /jamtracks to jamtracks browse page get '/jamtracks', to: redirect('/client#/jamtrackBrowse') @@ -384,6 +387,13 @@ SampleApp::Application.routes.draw do match '/users/:id/plays' => 'api_users#add_play', :via => :post, :as => 'api_users_add_play' match '/users/:id/affiliate' => 'api_users#affiliate_report', :via => :get, :as => 'api_users_affiliate' + match '/users/:id/affiliate_partner' => 'api_users#affiliate_partner', :via => [:get, :post], :as => 'api_users_affiliate_partner' + + match '/affiliate_partners' => 'api_affiliate#create', :via => :post, :as => 'api_affiliates_create' + match '/affiliate_partners/signups' => 'api_affiliate#traffic_index', :via => :get, :as => 'api_affiliates_signups' + match '/affiliate_partners/monthly_earnings' => 'api_affiliate#monthly_index', :via => :get, :as => 'api_affiliates_monthly' + match '/affiliate_partners/quarterly_earnings' => 'api_affiliate#quarterly_index', :via => :get, :as => 'api_affiliates_quarterly' + match '/affiliate_partners/payments' => 'api_affiliate#payment_index', :via => :get, :as => 'api_affiliates_payment' # downloads/uploads match '/users/:id/syncs' => 'api_user_syncs#index', :via => :get @@ -569,5 +579,13 @@ SampleApp::Application.routes.draw do match '/signup_hints/:id' => 'api_signup_hints#show', :via => :get, :as => :api_signup_hint_detail match '/alerts' => 'api_alerts#create', :via => :post + + # links generated to help affiliates share relevant links + match '/links/jamtrack_songs' => 'api_links#jamtrack_song_index' + match '/links/jamtrack_bands' => 'api_links#jamtrack_band_index' + match '/links/jamtrack_general' => 'api_links#jamtrack_general_index' + match '/links/jamkazam' => 'api_links#jamkazam_general_index' + match '/links/sessions' => 'api_links#session_index' + match '/links/recordings' => 'api_links#recording_index' end end diff --git a/web/config/scheduler.yml b/web/config/scheduler.yml index fb899f1bf..1890a41d4 100644 --- a/web/config/scheduler.yml +++ b/web/config/scheduler.yml @@ -74,3 +74,8 @@ StatsMaker: cron: "* * * * *" class: "JamRuby::StatsMaker" description: "Generates interesting stats from the database" + +TallyAffiliates: + cron: "0 0,4,8,12,16,20 * * *" + class: "JamRuby::TallyAffiliates" + description: "Tallies up affiliate totals" diff --git a/web/db/schema.rb b/web/db/schema.rb new file mode 100644 index 000000000..287f828b8 --- /dev/null +++ b/web/db/schema.rb @@ -0,0 +1,1752 @@ +# encoding: UTF-8 +# This file is auto-generated from the current state of the database. Instead +# of editing this file, please use the migrations feature of Active Record to +# incrementally modify your database, and then regenerate this schema definition. +# +# Note that this schema.rb definition is the authoritative source for your +# database schema. If you need to create the application database on another +# system, you should be using db:schema:load, not running all the migrations +# from scratch. The latter is a flawed and unsustainable approach (the more migrations +# you'll amass, the slower it'll run and the greater likelihood for issues). +# +# It's strongly recommended to check this file into your version control system. + +ActiveRecord::Schema.define(:version => 0) do + + add_extension "fuzzystrmatch" + add_extension "postgis" + add_extension "postgis_tiger_geocoder" + add_extension "postgis_topology" + add_extension "tablefunc" + add_extension "uuid-ossp" + + create_table "active_admin_comments", :force => true do |t| + t.string "resource_id", :null => false + t.string "resource_type", :null => false + t.integer "author_id" + t.string "author_type" + t.text "body" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.string "namespace" + end + + add_index "active_admin_comments", ["author_type", "author_id"], :name => "index_active_admin_comments_on_author_type_and_author_id" + add_index "active_admin_comments", ["namespace"], :name => "index_active_admin_comments_on_namespace" + add_index "active_admin_comments", ["resource_type", "resource_id"], :name => "index_admin_comments_on_resource_type_and_resource_id" + + create_table "active_music_sessions", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "user_id", :limit => 64, :null => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.string "claimed_recording_id", :limit => 64 + t.string "claimed_recording_initiator_id", :limit => 64 + t.integer "track_changes_counter", :default => 0 + t.integer "jam_track_id", :limit => 8 + t.string "jam_track_initiator_id", :limit => 64 + t.string "backing_track_path", :limit => 1024 + t.string "backing_track_initiator_id", :limit => 64 + t.boolean "metronome_active", :default => false, :null => false + t.string "metronome_initiator_id", :limit => 64 + end + + create_table "addr", :primary_key => "gid", :force => true do |t| + t.integer "tlid", :limit => 8 + t.string "fromhn", :limit => 12 + t.string "tohn", :limit => 12 + t.string "side", :limit => 1 + t.string "zip", :limit => 5 + t.string "plus4", :limit => 4 + t.string "fromtyp", :limit => 1 + t.string "totyp", :limit => 1 + t.integer "fromarmid" + t.integer "toarmid" + t.string "arid", :limit => 22 + t.string "mtfcc", :limit => 5 + t.string "statefp", :limit => 2 + end + + add_index "addr", ["tlid", "statefp"], :name => "idx_tiger_addr_tlid_statefp" + add_index "addr", ["zip"], :name => "idx_tiger_addr_zip" + +# Could not dump table "addrfeat" because of following StandardError +# Unknown type 'geometry' for column 'the_geom' + + create_table "affiliate_partners", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "partner_name", :limit => 128, :null => false + t.string "partner_code", :limit => 128, :null => false + t.string "partner_user_id", :limit => 64, :null => false + t.string "user_email" + t.integer "referral_user_count", :default => 0, :null => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + add_index "affiliate_partners", ["partner_code"], :name => "affiliate_partners_code_idx" + add_index "affiliate_partners", ["partner_user_id"], :name => "affiliate_partners_user_idx" + + create_table "artifact_updates", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "product", :null => false + t.string "version", :null => false + t.string "uri", :limit => 2000, :null => false + t.string "sha1", :null => false + t.string "environment", :default => "public", :null => false + t.integer "size", :null => false + end + + add_index "artifact_updates", ["product", "version"], :name => "artifact_updates_uniqkey", :unique => true + + create_table "backing_tracks", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "filename", :limit => 1024, :null => false + t.string "connection_id", :limit => 64, :null => false + t.string "client_track_id", :limit => 64, :null => false + t.string "client_resource_id", :limit => 100 + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "band_invitations", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "user_id", :limit => 64 + t.string "band_id", :limit => 64 + t.boolean "accepted" + t.string "creator_id", :limit => 64 + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "bands", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "name", :limit => 1024, :null => false + t.string "website", :limit => 4000 + t.string "biography", :limit => 4000, :null => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.string "city", :limit => 100 + t.string "state", :limit => 100 + t.string "country", :limit => 100 + t.string "photo_url", :limit => 2048 + t.string "logo_url", :limit => 2048 + t.tsvector "name_tsv" + t.string "original_fpfile_photo", :limit => 8000 + t.string "cropped_fpfile_photo", :limit => 8000 + t.string "cropped_s3_path_photo", :limit => 512 + t.string "crop_selection_photo", :limit => 256 + t.decimal "lat", :precision => 15, :scale => 10 + t.decimal "lng", :precision => 15, :scale => 10 + t.string "large_photo_url", :limit => 2048 + t.string "cropped_large_s3_path_photo", :limit => 512 + t.string "cropped_large_fpfile_photo", :limit => 8000 + t.boolean "did_real_session", :default => false + end + + add_index "bands", ["name_tsv"], :name => "bands_name_tsv_index", :using => :gin + + create_table "bands_musicians", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "band_id", :limit => 64, :null => false + t.string "user_id", :limit => 64, :null => false + t.boolean "admin", :default => false, :null => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + add_index "bands_musicians", ["band_id", "user_id"], :name => "band_musician_uniqkey", :unique => true + +# Could not dump table "bg" because of following StandardError +# Unknown type 'geometry' for column 'the_geom' + + create_table "chat_messages", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "user_id", :limit => 64 + t.string "music_session_id", :limit => 64 + t.text "message", :null => false + t.datetime "created_at", :null => false + end + + create_table "cities", :id => false, :force => true do |t| + t.string "city", :null => false + t.string "region", :limit => 2, :null => false + t.string "countrycode", :limit => 2, :null => false + end + + create_table "claimed_recordings", :id => false, :force => true do |t| + t.string "user_id", :limit => 64, :null => false + t.string "recording_id", :limit => 64, :null => false + t.string "id", :limit => 64, :null => false + t.string "name", :limit => 200, :null => false + t.boolean "is_public", :default => true, :null => false + t.string "genre_id", :limit => 64, :null => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.string "description", :limit => 8000 + t.tsvector "description_tsv" + t.tsvector "name_tsv" + t.boolean "discarded", :default => false + t.boolean "upload_to_youtube", :default => false, :null => false + end + + add_index "claimed_recordings", ["description_tsv"], :name => "claimed_recordings_description_tsv_index", :using => :gin + add_index "claimed_recordings", ["name_tsv"], :name => "claimed_recordings_name_tsv_index", :using => :gin + add_index "claimed_recordings", ["user_id", "recording_id"], :name => "musician_recording_uniqkey", :unique => true + +# Could not dump table "cohorts" because of following StandardError +# Unknown type 'json' for column 'data_set' + + create_table "connections", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "user_id", :limit => 64 + t.string "client_id", :limit => 64, :null => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.string "music_session_id", :limit => 64 + t.string "ip_address", :limit => 64, :null => false + t.boolean "as_musician" + t.string "aasm_state", :limit => 64, :default => "idle", :null => false + t.integer "addr", :limit => 8, :null => false + t.integer "locidispid", :limit => 8 + t.datetime "joined_session_at" + t.string "client_type", :limit => 256, :null => false + t.integer "stale_time", :default => 40, :null => false + t.integer "expire_time", :default => 60, :null => false + t.float "last_jam_audio_latency" + t.string "channel_id", :limit => 256, :null => false + t.boolean "udp_reachable", :default => true, :null => false + t.datetime "scoring_timeout", :null => false + t.integer "scoring_failures", :default => 0, :null => false + t.integer "scoring_timeout_occurrences", :default => 0, :null => false + t.integer "scoring_failures_offset", :default => 0, :null => false + t.string "gateway", :limit => nil, :default => "default-1", :null => false + t.boolean "is_network_testing", :default => false, :null => false + end + + add_index "connections", ["client_id"], :name => "connections_client_id_key", :unique => true + add_index "connections", ["locidispid"], :name => "connections_locidispid_ndx" + + create_table "countries", :id => false, :force => true do |t| + t.string "countrycode", :limit => 2, :null => false + t.string "countryname", :limit => 64 + end + +# Could not dump table "county" because of following StandardError +# Unknown type 'geometry' for column 'the_geom' + + create_table "county_lookup", :id => false, :force => true do |t| + t.integer "st_code", :null => false + t.string "state", :limit => 2 + t.integer "co_code", :null => false + t.string "name", :limit => 90 + end + + add_index "county_lookup", ["state"], :name => "county_lookup_state_idx" + + create_table "countysub_lookup", :id => false, :force => true do |t| + t.integer "st_code", :null => false + t.string "state", :limit => 2 + t.integer "co_code", :null => false + t.string "county", :limit => 90 + t.integer "cs_code", :null => false + t.string "name", :limit => 90 + end + + add_index "countysub_lookup", ["state"], :name => "countysub_lookup_state_idx" + +# Could not dump table "cousub" because of following StandardError +# Unknown type 'geometry' for column 'the_geom' + + create_table "crash_dumps", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "client_type", :limit => 64, :null => false + t.string "client_id", :limit => 64 + t.string "user_id", :limit => 64 + t.string "session_id", :limit => 64 + t.datetime "timestamp" + t.string "uri", :limit => 1000 + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.string "client_version", :limit => 100, :null => false + end + + add_index "crash_dumps", ["client_id"], :name => "crash_dumps_client_id_idx" + add_index "crash_dumps", ["timestamp"], :name => "crash_dumps_timestamp_idx" + add_index "crash_dumps", ["user_id"], :name => "crash_dumps_user_id_idx" + + create_table "current_network_scores", :id => false, :force => true do |t| + t.integer "alocidispid", :limit => 8, :null => false + t.integer "blocidispid", :limit => 8, :null => false + t.integer "score", :null => false + t.boolean "limited", :null => false + t.datetime "score_dt", :null => false + end + + add_index "current_network_scores", ["alocidispid", "blocidispid"], :name => "current_network_scores_a_b_ndx", :unique => true + add_index "current_network_scores", ["blocidispid", "alocidispid"], :name => "current_network_scores_b_a_ndx", :unique => true + + create_table "diagnostics", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "user_id", :limit => 64, :null => false + t.string "type", :null => false + t.string "creator", :null => false + t.text "data" + t.datetime "created_at", :null => false + end + + add_index "diagnostics", ["type"], :name => "diagnostics_type_idx" + add_index "diagnostics", ["user_id"], :name => "diagnostics_user_id" + + create_table "direction_lookup", :id => false, :force => true do |t| + t.string "name", :limit => 20, :null => false + t.string "abbrev", :limit => 3 + end + + add_index "direction_lookup", ["abbrev"], :name => "direction_lookup_abbrev_idx" + +# Could not dump table "edges" because of following StandardError +# Unknown type 'geometry' for column 'the_geom' + + create_table "email_batch_sets", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "email_batch_id", :limit => 64 + t.datetime "started_at" + t.text "user_ids", :default => "", :null => false + t.integer "batch_count" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.integer "trigger_index", :default => 0, :null => false + t.string "sub_type", :limit => 64 + t.string "user_id", :limit => 64 + end + + add_index "email_batch_sets", ["email_batch_id", "started_at"], :name => "email_batch_set_uniqkey", :unique => true + add_index "email_batch_sets", ["email_batch_id"], :name => "email_batch_set_fkidx" + add_index "email_batch_sets", ["user_id", "sub_type"], :name => "email_batch_sets_progress_idx" + + create_table "email_batches", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "subject", :limit => 256 + t.text "body" + t.string "from_email", :limit => 64, :default => "JamKazam ", :null => false + t.string "aasm_state", :limit => 32, :default => "pending", :null => false + t.text "test_emails", :default => "test@jamkazam.com", :null => false + t.integer "opt_in_count", :default => 0, :null => false + t.integer "sent_count", :default => 0, :null => false + t.integer "lock_version" + t.datetime "started_at" + t.datetime "completed_at" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.string "type", :limit => 64, :default => "JamRuby::EmailBatch", :null => false + t.string "sub_type", :limit => 64 + end + + create_table "email_errors", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "user_id", :limit => 64 + t.string "error_type", :limit => 32 + t.string "email_address", :limit => 256 + t.string "status", :limit => 32 + t.datetime "email_date" + t.text "reason" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + add_index "email_errors", ["email_address"], :name => "email_error_address_idx" + add_index "email_errors", ["user_id"], :name => "email_error_user_fkidx" + + create_table "event_sessions", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.datetime "starts_at" + t.datetime "ends_at" + t.string "pinned_state" + t.string "img_url", :limit => 1024 + t.integer "img_width" + t.integer "img_height" + t.string "event_id", :limit => 64 + t.string "user_id", :limit => 64 + t.string "band_id", :limit => 64 + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.integer "ordinal" + end + + create_table "events", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "slug", :limit => 512, :null => false + t.text "title" + t.text "description" + t.boolean "show_sponser", :default => false, :null => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.text "social_description" + end + + add_index "events", ["slug"], :name => "events_slug_key", :unique => true + + create_table "facebook_signups", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "lookup_id", :null => false + t.string "last_name", :limit => 100 + t.string "first_name", :limit => 100 + t.string "gender", :limit => 1 + t.string "email", :limit => 1024 + t.string "uid", :limit => 1024 + t.string "token", :limit => 1024 + t.datetime "token_expires_at" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + add_index "facebook_signups", ["lookup_id"], :name => "facebook_signups_lookup_id_key", :unique => true + +# Could not dump table "faces" because of following StandardError +# Unknown type 'geometry' for column 'the_geom' + + create_table "fan_invitations", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "sender_id", :limit => 64 + t.string "receiver_id", :limit => 64 + t.string "music_session_id", :limit => 64 + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "featnames", :primary_key => "gid", :force => true do |t| + t.integer "tlid", :limit => 8 + t.string "fullname", :limit => 100 + t.string "name", :limit => 100 + t.string "predirabrv", :limit => 15 + t.string "pretypabrv", :limit => 50 + t.string "prequalabr", :limit => 15 + t.string "sufdirabrv", :limit => 15 + t.string "suftypabrv", :limit => 50 + t.string "sufqualabr", :limit => 15 + t.string "predir", :limit => 2 + t.string "pretyp", :limit => 3 + t.string "prequal", :limit => 2 + t.string "sufdir", :limit => 2 + t.string "suftyp", :limit => 3 + t.string "sufqual", :limit => 2 + t.string "linearid", :limit => 22 + t.string "mtfcc", :limit => 5 + t.string "paflag", :limit => 1 + t.string "statefp", :limit => 2 + end + + add_index "featnames", ["tlid", "statefp"], :name => "idx_tiger_featnames_tlid_statefp" + + create_table "feeds", :force => true do |t| + t.string "recording_id", :limit => 64 + t.string "music_session_id", :limit => 64 + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.boolean "active", :default => false + end + + add_index "feeds", ["music_session_id"], :name => "feeds_music_session_id_key", :unique => true + add_index "feeds", ["recording_id"], :name => "feeds_recording_id_key", :unique => true + + create_table "follows", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "user_id", :limit => 64, :null => false + t.string "followable_id", :limit => 64, :null => false + t.string "followable_type", :limit => 25, :null => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + add_index "follows", ["user_id", "followable_id"], :name => "follows_user_uniqkey", :unique => true + + create_table "friend_requests", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "user_id", :limit => 64 + t.string "friend_id", :limit => 64 + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.string "status", :limit => 50 + t.string "message", :limit => 4000 + end + + create_table "friendships", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "user_id", :limit => 64 + t.string "friend_id", :limit => 64 + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + add_index "friendships", ["user_id", "friend_id"], :name => "user_friend_uniqkey", :unique => true + + create_table "generic_state", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.datetime "score_history_last_imported_at" + t.string "env", :default => "development", :null => false + end + + create_table "genre_players", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "player_id", :limit => 64, :null => false + t.string "genre_id", :limit => 64, :null => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.string "player_type", :limit => 128 + end + + add_index "genre_players", ["player_id", "player_type", "genre_id"], :name => "genre_player_uniqkey", :unique => true + + create_table "genres", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "description", :limit => 1024, :null => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "genres_music_sessions", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "genre_id", :limit => 64 + t.string "music_session_id", :limit => 64 + end + + create_table "geocode_settings", :id => false, :force => true do |t| + t.text "name", :null => false + t.text "setting" + t.text "unit" + t.text "category" + t.text "short_desc" + end + +# Could not dump table "geoipblocks" because of following StandardError +# Unknown type 'geometry(Polygon)' for column 'geom' + + create_table "geoipisp", :id => false, :force => true do |t| + t.integer "beginip", :limit => 8, :null => false + t.integer "endip", :limit => 8, :null => false + t.string "company", :limit => 50, :null => false + end + + add_index "geoipisp", ["company"], :name => "geoipisp_company_ndx" + + create_table "geoiplocations", :id => false, :force => true do |t| + t.integer "locid", :null => false + t.string "countrycode", :limit => 2 + t.string "region", :limit => 2 + t.string "city" + t.string "postalcode", :limit => 8 + t.float "latitude", :null => false + t.float "longitude", :null => false + t.integer "metrocode" + t.string "areacode", :limit => 3 + t.integer "geog", :limit => 0 + end + + add_index "geoiplocations", ["geog"], :name => "geoiplocations_geog_gix", :using => :gist + + create_table "icecast_admin_authentications", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "source_pass", :limit => 64, :null => false + t.string "relay_user", :limit => 64, :null => false + t.string "relay_pass", :limit => 64, :null => false + t.string "admin_user", :limit => 64, :null => false + t.string "admin_pass", :limit => 64, :null => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "icecast_directories", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.integer "yp_url_timeout", :default => 15, :null => false + t.string "yp_url", :limit => 1024, :null => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "icecast_limits", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.integer "clients", :default => 1000, :null => false + t.integer "sources", :default => 50, :null => false + t.integer "queue_size", :default => 102400, :null => false + t.integer "client_timeout", :default => 30 + t.integer "header_timeout", :default => 15 + t.integer "source_timeout", :default => 10 + t.integer "burst_size", :default => 65536 + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "icecast_listen_sockets", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.integer "port", :default => 8001, :null => false + t.string "bind_address", :limit => 1024 + t.string "shoutcast_mount", :limit => 1024 + t.integer "shoutcast_compat" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "icecast_loggings", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "access_log", :limit => 1024, :default => "access.log", :null => false + t.string "error_log", :limit => 1024, :default => "error.log", :null => false + t.string "playlist_log", :limit => 1024 + t.integer "log_level", :default => 3, :null => false + t.integer "log_archive" + t.integer "log_size", :default => 10000 + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "icecast_master_server_relays", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "master_server", :limit => 1024, :null => false + t.integer "master_server_port", :default => 8001, :null => false + t.integer "master_update_interval", :default => 120, :null => false + t.string "master_username", :limit => 64, :null => false + t.string "master_pass", :limit => 64, :null => false + t.integer "relays_on_demand", :default => 1, :null => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "icecast_mount_templates", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "name", :limit => 256, :null => false + t.string "source_username", :limit => 64 + t.string "source_pass", :limit => 64 + t.integer "max_listeners", :default => 10000 + t.integer "max_listener_duration", :default => 3600 + t.string "dump_file", :limit => 1024 + t.string "intro", :limit => 1024 + t.string "fallback_mount", :limit => 1024 + t.integer "fallback_override", :default => 1 + t.integer "fallback_when_full", :default => 1 + t.string "charset", :limit => 1024, :default => "ISO8859-1" + t.integer "is_public", :default => 0 + t.string "stream_name", :limit => 1024 + t.string "stream_description", :limit => 10000 + t.string "stream_url", :limit => 1024 + t.string "genre", :limit => 256 + t.integer "bitrate" + t.string "mime_type", :limit => 64, :default => "audio/mpeg", :null => false + t.string "subtype", :limit => 64 + t.integer "burst_size" + t.integer "mp3_metadata_interval" + t.integer "hidden", :default => 1 + t.string "on_connect", :limit => 1024 + t.string "on_disconnect", :limit => 1024 + t.string "authentication_id", :limit => 64, :null => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "icecast_mounts", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "name", :limit => 1024, :null => false + t.string "source_username", :limit => 64 + t.string "source_pass", :limit => 64 + t.integer "max_listeners", :default => 10000 + t.integer "max_listener_duration", :default => 3600 + t.string "dump_file", :limit => 1024 + t.string "intro", :limit => 1024 + t.string "fallback_mount", :limit => 1024 + t.integer "fallback_override", :default => 1 + t.integer "fallback_when_full", :default => 1 + t.string "charset", :limit => 1024, :default => "ISO8859-1" + t.integer "is_public", :default => 0 + t.string "stream_name", :limit => 1024 + t.string "stream_description", :limit => 10000 + t.string "stream_url", :limit => 1024 + t.string "genre", :limit => 256 + t.integer "bitrate" + t.string "mime_type", :limit => 64 + t.string "subtype", :limit => 64 + t.integer "burst_size" + t.integer "mp3_metadata_interval" + t.integer "hidden", :default => 1 + t.string "on_connect", :limit => 1024 + t.string "on_disconnect", :limit => 1024 + t.string "authentication_id", :limit => 64 + t.integer "listeners", :default => 0, :null => false + t.boolean "sourced", :default => false, :null => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.string "music_session_id", :limit => 64 + t.string "icecast_server_id", :limit => 64, :null => false + t.string "icecast_mount_template_id", :limit => 64 + t.datetime "sourced_needs_changing_at" + t.boolean "source_direction", :default => false, :null => false + end + + add_index "icecast_mounts", ["name"], :name => "icecast_mounts_name_key", :unique => true + + create_table "icecast_paths", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "base_dir", :limit => 1024, :default => "./", :null => false + t.string "log_dir", :limit => 1024, :default => "./logs", :null => false + t.string "pid_file", :limit => 1024, :default => "./icecast.pid" + t.string "web_root", :limit => 1024, :default => "./web", :null => false + t.string "admin_root", :limit => 1024, :default => "./admin", :null => false + t.string "allow_ip", :limit => 1024 + t.string "deny_ip", :limit => 1024 + t.string "alias_source", :limit => 1024 + t.string "alias_dest", :limit => 1024 + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "icecast_relays", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "server", :limit => 1024, :null => false + t.integer "port", :default => 8001, :null => false + t.string "mount", :limit => 1024, :null => false + t.string "local_mount", :limit => 1024 + t.string "relay_username", :limit => 64 + t.string "relay_pass", :limit => 64 + t.integer "relay_shoutcast_metadata", :default => 0 + t.integer "on_demand", :default => 1 + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "icecast_securities", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.integer "chroot", :default => 0, :null => false + t.string "change_owner_user", :limit => 64 + t.string "change_owner_group", :limit => 64 + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "icecast_server_groups", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "name", :null => false + end + + add_index "icecast_server_groups", ["name"], :name => "icecast_server_groups_name_key", :unique => true + + create_table "icecast_server_mounts", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "icecast_mount_id", :limit => 64 + t.string "icecast_server_id", :limit => 64 + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + add_index "icecast_server_mounts", ["icecast_mount_id", "icecast_server_id"], :name => "server_mount_uniqkey", :unique => true + + create_table "icecast_server_relays", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "icecast_relay_id", :limit => 64 + t.string "icecast_server_id", :limit => 64 + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + add_index "icecast_server_relays", ["icecast_relay_id", "icecast_server_id"], :name => "server_relay_uniqkey", :unique => true + + create_table "icecast_server_sockets", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "icecast_listen_socket_id", :limit => 64 + t.string "icecast_server_id", :limit => 64 + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + add_index "icecast_server_sockets", ["icecast_listen_socket_id", "icecast_server_id"], :name => "server_socket_uniqkey", :unique => true + + create_table "icecast_servers", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.integer "config_changed", :default => 0 + t.string "limit_id", :limit => 64 + t.string "admin_auth_id", :limit => 64 + t.string "directory_id", :limit => 64 + t.string "master_relay_id", :limit => 64 + t.string "path_id", :limit => 64 + t.string "logging_id", :limit => 64 + t.string "security_id", :limit => 64 + t.string "template_id", :limit => 64, :null => false + t.string "hostname", :limit => 1024, :null => false + t.string "server_id", :limit => 1024, :null => false + t.string "location", :limit => 1024 + t.string "admin_email", :limit => 1024 + t.integer "fileserve" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.string "icecast_server_group_id", :limit => 64, :default => "default", :null => false + t.string "mount_template_id", :limit => 64 + t.datetime "config_updated_at" + end + + add_index "icecast_servers", ["server_id"], :name => "icecast_servers_server_id_key", :unique => true + + create_table "icecast_source_changes", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.boolean "source_direction", :null => false + t.string "change_type", :limit => 64, :null => false + t.string "user_id", :limit => 64 + t.string "client_id", :limit => 64 + t.boolean "success", :null => false + t.string "reason", :limit => nil + t.string "detail", :limit => nil + t.datetime "created_at", :null => false + t.string "icecast_mount_id", :limit => 64, :null => false + end + + create_table "icecast_template_sockets", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "icecast_listen_socket_id", :limit => 64 + t.string "icecast_template_id", :limit => 64 + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + add_index "icecast_template_sockets", ["icecast_listen_socket_id", "icecast_template_id"], :name => "template_socket_uniqkey", :unique => true + + create_table "icecast_templates", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "limit_id", :limit => 64 + t.string "admin_auth_id", :limit => 64 + t.string "directory_id", :limit => 64 + t.string "master_relay_id", :limit => 64 + t.string "path_id", :limit => 64 + t.string "logging_id", :limit => 64 + t.string "security_id", :limit => 64 + t.string "location", :limit => 1024, :null => false + t.string "name", :limit => 256, :null => false + t.string "admin_email", :limit => 1024, :default => "admin@jamkazam.com", :null => false + t.integer "fileserve", :default => 1, :null => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "icecast_user_authentications", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "authentication_type", :limit => 16, :default => "url" + t.string "filename", :limit => 1024 + t.integer "allow_duplicate_users" + t.string "mount_add", :limit => 1024 + t.string "mount_remove", :limit => 1024 + t.string "listener_add", :limit => 1024 + t.string "listener_remove", :limit => 1024 + t.string "unused_username", :limit => 64 + t.string "unused_pass", :limit => 64 + t.string "auth_header", :limit => 64, :default => "icecast-auth-user: 1" + t.string "timelimit_header", :limit => 64, :default => "icecast-auth-timelimit:" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "instruments", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "description", :limit => 1024, :null => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.integer "popularity", :default => 0, :null => false + end + + create_table "invitations", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "sender_id", :limit => 64 + t.string "receiver_id", :limit => 64 + t.string "music_session_id", :limit => 64 + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.string "join_request_id", :limit => 64 + end + + create_table "invited_users", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "sender_id", :limit => 64 + t.boolean "autofriend", :null => false + t.string "email", :limit => 256 + t.string "invitation_code", :limit => 256, :null => false + t.boolean "accepted", :default => false + t.text "note" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.string "invite_medium", :limit => 64 + end + + add_index "invited_users", ["invitation_code"], :name => "invited_users_invitation_code_key", :unique => true + + create_table "isp_score_batch", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.text "json_scoring_data", :null => false + t.datetime "created_at", :null => false + end + + create_table "jam_track_licensors", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "name", :limit => nil, :null => false + t.text "description" + t.text "attention" + t.string "address_line_1", :limit => nil + t.string "address_line_2", :limit => nil + t.string "city", :limit => nil + t.string "state", :limit => nil + t.string "zip_code", :limit => nil + t.string "contact", :limit => nil + t.string "email", :limit => nil + t.string "phone", :limit => nil + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + add_index "jam_track_licensors", ["name"], :name => "jam_track_licensors_name_key", :unique => true + + create_table "jam_track_rights", :force => true do |t| + t.string "user_id", :limit => 64, :null => false + t.integer "jam_track_id", :limit => 8, :null => false + t.string "url", :limit => 2048 + t.string "md5", :limit => nil + t.integer "length", :default => 0, :null => false + t.integer "download_count", :default => 0, :null => false + t.boolean "signed", :default => false, :null => false + t.boolean "downloaded_since_sign", :default => false, :null => false + t.datetime "last_signed_at" + t.datetime "last_downloaded_at" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.string "private_key", :limit => nil + t.datetime "signing_queued_at" + t.datetime "signing_started_at" + t.integer "error_count", :default => 0, :null => false + t.string "error_reason", :limit => nil + t.string "error_detail", :limit => nil + t.boolean "should_retry", :default => false, :null => false + t.boolean "redeemed", :default => false, :null => false + end + + add_index "jam_track_rights", ["user_id", "jam_track_id"], :name => "jam_tracks_rights_uniqkey" + + create_table "jam_track_tap_ins", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.integer "offset_time", :null => false + t.integer "jam_track_id", :limit => 8, :null => false + t.decimal "bpm", :null => false + t.integer "tap_in_count", :default => 0, :null => false + end + + create_table "jam_track_tracks", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.integer "position" + t.string "track_type", :limit => nil + t.integer "jam_track_id", :limit => 8, :null => false + t.string "instrument_id", :limit => 64 + t.string "part", :limit => nil + t.string "url", :limit => nil + t.string "md5", :limit => nil + t.integer "length", :limit => 8 + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + add_index "jam_track_tracks", ["position", "jam_track_id"], :name => "jam_track_tracks_position_uniqkey" + + create_table "jam_tracks", :force => true do |t| + t.string "name", :limit => nil, :null => false + t.text "description" + t.string "time_signature", :limit => nil + t.string "status", :limit => nil + t.string "recording_type", :limit => nil + t.text "original_artist" + t.text "songwriter" + t.text "publisher" + t.string "pro", :limit => nil + t.string "sales_region", :limit => nil + t.decimal "price" + t.boolean "reproduction_royalty" + t.boolean "public_performance_royalty" + t.decimal "reproduction_royalty_amount" + t.decimal "licensor_royalty_amount" + t.decimal "pro_royalty_amount" + t.string "url", :limit => nil + t.string "md5", :limit => nil + t.integer "length", :limit => 8 + t.string "licensor_id", :limit => 64 + t.string "genre_id", :limit => 64 + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.string "plan_code", :limit => 50 + t.decimal "initial_play_silence", :default => 5.0, :null => false + t.boolean "available", :default => false, :null => false + end + + add_index "jam_tracks", ["name"], :name => "jam_tracks_name_key", :unique => true + + create_table "jamcompany", :primary_key => "coid", :force => true do |t| + t.string "company", :limit => 50, :null => false + end + + add_index "jamcompany", ["company"], :name => "jamcompany_company_ndx", :unique => true + +# Could not dump table "jamisp" because of following StandardError +# Unknown type 'geometry(Polygon)' for column 'geom' + + create_table "join_requests", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "user_id", :limit => 64 + t.string "music_session_id", :limit => 64 + t.string "text", :limit => 2000 + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + add_index "join_requests", ["user_id", "music_session_id"], :name => "user_music_session_uniqkey", :unique => true + + create_table "latency_testers", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "client_id", :limit => 64, :null => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + add_index "latency_testers", ["client_id"], :name => "latency_testers_client_id_key", :unique => true + + create_table "layer", :id => false, :force => true do |t| + t.integer "topology_id", :null => false + t.integer "layer_id", :null => false + t.string "schema_name", :limit => nil, :null => false + t.string "table_name", :limit => nil, :null => false + t.string "feature_column", :limit => nil, :null => false + t.integer "feature_type", :null => false + t.integer "level", :default => 0, :null => false + t.integer "child_id" + end + + add_index "layer", ["schema_name", "table_name", "feature_column"], :name => "layer_schema_name_table_name_feature_column_key", :unique => true + + create_table "likes", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "user_id", :limit => 64, :null => false + t.string "likable_id", :limit => 64, :null => false + t.string "likable_type", :limit => 25, :null => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + add_index "likes", ["user_id", "likable_id"], :name => "likes_user_uniqkey", :unique => true + + create_table "loader_lookuptables", :id => false, :force => true do |t| + t.integer "process_order", :default => 1000, :null => false + t.text "lookup_name", :null => false + t.text "table_name" + t.boolean "single_mode", :default => true, :null => false + t.boolean "load", :default => true, :null => false + t.boolean "level_county", :default => false, :null => false + t.boolean "level_state", :default => false, :null => false + t.boolean "level_nation", :default => false, :null => false + t.text "post_load_process" + t.boolean "single_geom_mode", :default => false + t.string "insert_mode", :limit => 1, :default => "c", :null => false + t.text "pre_load_process" + t.text "columns_exclude", :array => true + t.text "website_root_override" + end + + create_table "loader_platform", :id => false, :force => true do |t| + t.string "os", :limit => 50, :null => false + t.text "declare_sect" + t.text "pgbin" + t.text "wget" + t.text "unzip_command" + t.text "psql" + t.text "path_sep" + t.text "loader" + t.text "environ_set_command" + t.text "county_process_command" + end + + create_table "loader_variables", :id => false, :force => true do |t| + t.string "tiger_year", :limit => 4, :null => false + t.text "website_root" + t.text "staging_fold" + t.text "data_schema" + t.text "staging_schema" + end + + create_table "max_mind_releases", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.date "released_at", :null => false + t.boolean "imported", :default => false, :null => false + t.date "imported_at" + t.string "geo_ip_124_url", :limit => 2000 + t.string "geo_ip_124_md5" + t.integer "geo_ip_124_size" + t.string "geo_ip_134_url", :limit => 2000 + t.string "geo_ip_134_md5" + t.integer "geo_ip_134_size" + t.string "region_codes_url", :limit => 2000 + t.string "region_codes_md5" + t.integer "region_codes_size" + t.string "iso3166_url", :limit => 2000 + t.string "iso3166_md5" + t.integer "iso3166_size" + t.string "table_dumps_url", :limit => 2000 + t.string "table_dumps_md5" + t.integer "table_dumps_size" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + add_index "max_mind_releases", ["released_at"], :name => "max_mind_releases_released_at_key", :unique => true + + create_table "mixes", :force => true do |t| + t.string "recording_id", :limit => 64, :null => false + t.string "mix_server", :limit => 64 + t.datetime "started_at" + t.datetime "completed_at" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.string "ogg_md5", :limit => 100 + t.integer "ogg_length" + t.string "ogg_url", :limit => 1024 + t.boolean "completed", :default => false, :null => false + t.integer "error_count", :default => 0, :null => false + t.text "error_reason" + t.text "error_detail" + t.boolean "should_retry", :default => false, :null => false + t.string "mp3_md5", :limit => 100 + t.integer "mp3_length" + t.string "mp3_url", :limit => 1024 + t.integer "download_count", :default => 0, :null => false + t.datetime "last_downloaded_at" + end + + add_index "mixes", ["completed_at"], :name => "index_completed_at" + add_index "mixes", ["started_at"], :name => "index_started_at" + + create_table "music_notations", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "user_id", :limit => 64, :null => false + t.string "music_session_id", :limit => 64 + t.string "file_url", :limit => 512 + t.integer "size" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.string "file_name" + end + + create_table "music_session_perf_data", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "music_session_id", :limit => 64 + t.string "client_id", :limit => 64 + t.string "uri", :limit => 1000 + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "music_sessions", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "music_session_id", :limit => 64 + t.string "description", :limit => 8000 + t.string "user_id", :limit => 64, :null => false + t.string "band_id", :limit => 64 + t.datetime "created_at", :null => false + t.datetime "session_removed_at" + t.integer "play_count", :default => 0, :null => false + t.integer "like_count", :default => 0, :null => false + t.boolean "fan_access", :default => true, :null => false + t.datetime "scheduled_start" + t.string "scheduled_duration", :limit => nil + t.boolean "musician_access", :default => true, :null => false + t.boolean "approval_required", :default => false, :null => false + t.boolean "fan_chat", :default => true, :null => false + t.string "genre_id", :limit => 64, :null => false + t.string "legal_policy", :default => "standard", :null => false + t.string "language", :default => "eng", :null => false + t.text "name", :null => false + t.string "recurring_session_id", :limit => 64 + t.string "recurring_mode", :limit => 50, :default => "once", :null => false + t.string "timezone" + t.datetime "started_at" + t.boolean "open_rsvps", :default => false, :null => false + t.boolean "next_session_scheduled", :default => false + t.tsvector "description_tsv" + t.boolean "is_unstructured_rsvp", :default => false + t.boolean "canceled", :default => false + t.string "create_type", :limit => 64 + end + + add_index "music_sessions", ["description_tsv"], :name => "music_sessions_description_tsv_index", :using => :gin + add_index "music_sessions", ["music_session_id"], :name => "music_session_uniqkey", :unique => true + + create_table "music_sessions_comments", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "creator_id", :limit => 64, :null => false + t.string "comment", :limit => 4000, :null => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.inet "ip_address" + t.string "music_session_id", :limit => 64 + end + + create_table "music_sessions_likers", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "liker_id", :limit => 64 + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.inet "ip_address" + t.string "music_session_id", :limit => 64 + end + + create_table "music_sessions_user_history", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "user_id", :limit => 64, :null => false + t.string "client_id", :limit => 64, :null => false + t.datetime "created_at", :null => false + t.datetime "session_removed_at" + t.integer "max_concurrent_connections" + t.integer "rating" + t.string "instruments" + t.text "rating_comment" + t.string "music_session_id", :limit => 64 + end + + add_index "music_sessions_user_history", ["music_session_id"], :name => "msuh_music_session_idx" + + create_table "musicians_instruments", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "user_id", :limit => 64, :null => false + t.string "instrument_id", :limit => 64, :null => false + t.integer "proficiency_level", :limit => 2, :null => false + t.integer "priority", :limit => 2, :default => 1, :null => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + add_index "musicians_instruments", ["user_id", "instrument_id"], :name => "musician_instrument_uniqkey", :unique => true + + create_table "notifications", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "description", :limit => 100, :null => false + t.string "source_user_id", :limit => 64 + t.string "target_user_id", :limit => 64 + t.string "band_id", :limit => 64 + t.string "session_id", :limit => 64 + t.string "recording_id", :limit => 64 + t.string "invitation_id", :limit => 64 + t.string "join_request_id", :limit => 64 + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.string "friend_request_id", :limit => 64 + t.string "band_invitation_id", :limit => 64 + t.text "message" + t.integer "jam_track_right_id", :limit => 8 + end + + create_table "pagc_gaz", :force => true do |t| + t.integer "seq" + t.text "word" + t.text "stdword" + t.integer "token" + t.boolean "is_custom", :default => true, :null => false + end + + create_table "pagc_lex", :force => true do |t| + t.integer "seq" + t.text "word" + t.text "stdword" + t.integer "token" + t.boolean "is_custom", :default => true, :null => false + end + + create_table "pagc_rules", :force => true do |t| + t.text "rule" + t.boolean "is_custom", :default => true + end + + create_table "performance_samples", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "user_id", :limit => 64, :null => false + t.string "url", :limit => 4000 + t.string "type", :limit => 100, :null => false + t.string "claimed_recording_id", :limit => 64 + t.string "service_id", :limit => 100 + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + +# Could not dump table "place" because of following StandardError +# Unknown type 'geometry' for column 'the_geom' + + create_table "place_lookup", :id => false, :force => true do |t| + t.integer "st_code", :null => false + t.string "state", :limit => 2 + t.integer "pl_code", :null => false + t.string "name", :limit => 90 + end + + add_index "place_lookup", ["state"], :name => "place_lookup_state_idx" + + create_table "playable_plays", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "playable_id", :limit => 64, :null => false + t.string "playable_type", :limit => 128, :null => false + t.string "player_id", :limit => 64 + t.string "claimed_recording_id", :limit => 64 + t.inet "ip_address" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "promotionals", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "type", :limit => 128, :default => "JamRuby::PromoBuzz", :null => false + t.string "aasm_state", :limit => 64, :default => "hidden" + t.integer "position", :default => 0, :null => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.string "latest_id", :limit => 64 + t.string "latest_type", :limit => 128 + t.string "image", :limit => 1024 + t.string "text_short", :limit => 512 + t.string "text_long", :limit => 4096 + end + + add_index "promotionals", ["latest_id", "latest_type"], :name => "promo_latest_idx" + + create_table "quick_mixes", :force => true do |t| + t.integer "next_part_to_upload", :default => 0, :null => false + t.boolean "fully_uploaded", :default => false, :null => false + t.string "upload_id", :limit => 1024 + t.integer "file_offset", :limit => 8, :default => 0 + t.boolean "is_part_uploading", :default => false, :null => false + t.integer "upload_failures", :default => 0 + t.integer "part_failures", :default => 0 + t.string "ogg_md5", :limit => 100 + t.integer "ogg_length" + t.string "ogg_url", :limit => 1000 + t.string "mp3_md5", :limit => 100 + t.integer "mp3_length" + t.string "mp3_url", :limit => 1000 + t.integer "error_count", :default => 0, :null => false + t.text "error_reason" + t.text "error_detail" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.datetime "started_at" + t.datetime "completed_at" + t.boolean "completed", :default => false, :null => false + t.boolean "should_retry", :default => false, :null => false + t.boolean "cleaned", :default => false, :null => false + t.string "user_id", :limit => 64 + t.string "recording_id", :limit => 64 + end + + create_table "recorded_backing_tracks", :force => true do |t| + t.string "user_id", :limit => 64 + t.string "backing_track_id", :limit => 64 + t.string "recording_id", :limit => 64, :null => false + t.string "client_track_id", :limit => 64, :null => false + t.boolean "is_part_uploading", :default => false, :null => false + t.integer "next_part_to_upload", :default => 0, :null => false + t.string "upload_id", :limit => 1024 + t.integer "part_failures", :default => 0, :null => false + t.boolean "discard" + t.integer "download_count", :default => 0, :null => false + t.string "md5", :limit => 100 + t.integer "length", :limit => 8 + t.string "client_id", :limit => 64, :null => false + t.integer "file_offset", :limit => 8 + t.string "url", :limit => 1024, :null => false + t.boolean "fully_uploaded", :default => false, :null => false + t.integer "upload_failures", :default => 0, :null => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.string "filename", :limit => nil, :null => false + t.datetime "last_downloaded_at" + end + + create_table "recorded_tracks", :force => true do |t| + t.string "user_id", :limit => 64, :null => false + t.string "instrument_id", :limit => 64, :null => false + t.string "sound", :limit => 64, :null => false + t.integer "next_part_to_upload", :default => 0, :null => false + t.boolean "fully_uploaded", :default => false, :null => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.string "upload_id", :limit => 1024 + t.string "recording_id", :limit => 64, :null => false + t.string "md5", :limit => 100 + t.integer "length", :limit => 8 + t.string "client_id", :limit => 64, :null => false + t.string "track_id", :limit => 64, :null => false + t.string "url", :limit => 1024 + t.integer "file_offset", :limit => 8, :default => 0 + t.string "client_track_id", :limit => 64, :null => false + t.boolean "is_part_uploading", :default => false, :null => false + t.integer "upload_failures", :default => 0, :null => false + t.integer "part_failures", :default => 0, :null => false + t.boolean "discard" + t.integer "download_count", :default => 0, :null => false + t.datetime "last_downloaded_at" + end + + create_table "recorded_videos", :force => true do |t| + t.string "user_id", :limit => 64 + t.boolean "fully_uploaded", :default => false, :null => false + t.string "recording_id", :limit => 64, :null => false + t.integer "length", :limit => 8 + t.string "client_video_source_id", :limit => 64, :null => false + t.string "url", :limit => 1024 + t.integer "file_offset", :limit => 8 + t.integer "upload_failures", :default => 0, :null => false + t.boolean "discard" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "recordings", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.string "owner_id", :limit => 64, :null => false + t.string "music_session_id", :limit => 64 + t.string "band_id", :limit => 64 + t.integer "duration" + t.boolean "is_done", :default => false + t.boolean "all_discarded", :default => false, :null => false + t.string "name", :limit => 1024 + t.integer "play_count", :default => 0, :null => false + t.integer "like_count", :default => 0, :null => false + t.boolean "has_stream_mix", :default => false, :null => false + t.boolean "has_final_mix", :default => false, :null => false + t.integer "first_quick_mix_id", :limit => 8 + t.boolean "deleted", :default => false, :null => false + end + + create_table "recordings_comments", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "recording_id", :limit => 64, :null => false + t.string "creator_id", :limit => 64, :null => false + t.string "comment", :limit => 4000, :null => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.inet "ip_address" + end + + create_table "recordings_downloads", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "recording_id", :limit => 64, :null => false + t.string "downloader_id", :limit => 64, :null => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "recordings_likers", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "recording_id", :limit => 64, :null => false + t.string "liker_id", :limit => 64 + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.inet "ip_address" + t.string "claimed_recording_id", :limit => 64, :null => false + t.boolean "favorite", :default => true, :null => false + end + + add_index "recordings_likers", ["recording_id", "liker_id"], :name => "recording_liker_uniqkey", :unique => true + + create_table "recurring_sessions", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "description", :limit => 8000 + t.datetime "scheduled_start" + t.string "scheduled_duration", :limit => nil + t.boolean "musician_access", :null => false + t.boolean "approval_required", :null => false + t.boolean "fan_chat", :null => false + t.string "genre_id", :limit => 64 + t.string "legal_policy", :default => "standard", :null => false + t.string "language", :default => "en", :null => false + t.text "name" + t.string "user_id", :limit => 64, :null => false + t.string "band_id", :limit => 64 + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "regions", :id => false, :force => true do |t| + t.string "region", :limit => 2, :null => false + t.string "regionname", :limit => 64 + t.string "countrycode", :limit => 2, :null => false + end + + add_index "regions", ["countrycode", "region"], :name => "regions_countrycode_region_ndx", :unique => true + add_index "regions", ["countrycode"], :name => "regions_countrycode_ndx" + + create_table "rsvp_requests", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "user_id", :limit => 64, :null => false + t.boolean "canceled", :default => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.boolean "cancel_all", :default => false + end + + create_table "rsvp_requests_rsvp_slots", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "rsvp_request_id", :limit => 64, :null => false + t.string "rsvp_slot_id", :limit => 64, :null => false + t.boolean "chosen" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "rsvp_slots", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "instrument_id", :limit => 64 + t.integer "proficiency_level", :limit => 2 + t.string "music_session_id", :limit => 64, :null => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.boolean "is_unstructured_rsvp", :default => false + end + + create_table "score_histories", :id => false, :force => true do |t| + t.string "from_client_id", :limit => 64 + t.integer "from_addr", :limit => 8 + t.string "from_isp", :limit => 50 + t.string "from_country", :limit => 64 + t.string "from_region", :limit => 64 + t.string "from_city" + t.string "from_postal", :limit => 25 + t.float "from_latitude" + t.float "from_longitude" + t.string "to_client_id", :limit => 64 + t.integer "to_addr", :limit => 8 + t.string "to_isp", :limit => 50 + t.string "to_country", :limit => 64 + t.string "to_region", :limit => 64 + t.string "to_city" + t.string "to_postal", :limit => 25 + t.float "to_latitude" + t.float "to_longitude" + t.integer "score", :null => false + t.datetime "score_dt", :null => false + t.text "scoring_data" + t.string "from_user_id", :limit => 64 + t.string "to_user_id", :limit => 64 + t.string "from_latency_tester_id", :limit => 64 + t.string "to_latency_tester_id", :limit => 64 + t.integer "from_locidispid", :limit => 8, :null => false + t.integer "to_locidispid", :limit => 8, :null => false + end + + create_table "scores", :id => false, :force => true do |t| + t.integer "alocidispid", :limit => 8, :null => false + t.string "anodeid", :limit => 64, :null => false + t.integer "aaddr", :limit => 8, :null => false + t.integer "blocidispid", :limit => 8, :null => false + t.string "bnodeid", :limit => 64, :null => false + t.integer "baddr", :limit => 8, :null => false + t.integer "score", :null => false + t.integer "scorer", :null => false + t.datetime "score_dt", :null => false + t.string "scoring_data", :limit => 4000 + t.datetime "created_at", :null => false + t.string "auserid", :limit => 64 + t.string "buserid", :limit => 64 + t.string "alatencytestid", :limit => 64 + t.string "blatencytestid", :limit => 64 + end + + add_index "scores", ["alocidispid", "blocidispid", "score_dt"], :name => "scores_alocidispid_blocidispid_score_dt_ndx" + add_index "scores", ["blocidispid", "alocidispid", "score_dt"], :name => "scores_blocidispid_alocidispid_score_dt_ndx" + + create_table "secondary_unit_lookup", :id => false, :force => true do |t| + t.string "name", :limit => 20, :null => false + t.string "abbrev", :limit => 5 + end + + add_index "secondary_unit_lookup", ["abbrev"], :name => "secondary_unit_lookup_abbrev_idx" + + create_table "session_info_comments", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "music_session_id", :limit => 64, :null => false + t.string "creator_id", :limit => 64, :null => false + t.text "comment", :null => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "share_tokens", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "token", :limit => 15, :null => false + t.string "shareable_id", :limit => 64, :null => false + t.string "shareable_type", :limit => 50, :null => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + add_index "share_tokens", ["token"], :name => "token_uniqkey", :unique => true + + create_table "shopping_carts", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.integer "quantity", :default => 1, :null => false + t.string "user_id", :limit => 64, :null => false + t.string "cart_id", :limit => 64, :null => false + t.string "cart_class_name", :limit => 64 + t.string "cart_type", :limit => 64 + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "spatial_ref_sys", :id => false, :force => true do |t| + t.integer "srid", :null => false + t.string "auth_name", :limit => 256 + t.integer "auth_srid" + t.string "srtext", :limit => 2048 + t.string "proj4text", :limit => 2048 + end + +# Could not dump table "state" because of following StandardError +# Unknown type 'geometry' for column 'the_geom' + + create_table "state_lookup", :id => false, :force => true do |t| + t.integer "st_code", :null => false + t.string "name", :limit => 40 + t.string "abbrev", :limit => 3 + t.string "statefp", :limit => 2 + end + + add_index "state_lookup", ["abbrev"], :name => "state_lookup_abbrev_key", :unique => true + add_index "state_lookup", ["name"], :name => "state_lookup_name_key", :unique => true + add_index "state_lookup", ["statefp"], :name => "state_lookup_statefp_key", :unique => true + + create_table "street_type_lookup", :id => false, :force => true do |t| + t.string "name", :limit => 50, :null => false + t.string "abbrev", :limit => 50 + t.boolean "is_hw", :default => false, :null => false + end + + add_index "street_type_lookup", ["abbrev"], :name => "street_type_lookup_abbrev_idx" + +# Could not dump table "tabblock" because of following StandardError +# Unknown type 'geometry' for column 'the_geom' + + create_table "text_messages", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "source_user_id", :limit => 64 + t.string "target_user_id", :limit => 64 + t.text "message", :null => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "topology", :force => true do |t| + t.string "name", :limit => nil, :null => false + t.integer "srid", :null => false + t.float "precision", :null => false + t.boolean "hasz", :default => false, :null => false + end + + add_index "topology", ["name"], :name => "topology_name_key", :unique => true + + create_table "tracks", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "connection_id", :limit => 64, :null => false + t.string "instrument_id", :limit => 64 + t.string "sound", :limit => 64, :null => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.string "client_track_id", :limit => 64, :null => false + t.string "client_resource_id", :limit => 100 + end + +# Could not dump table "tract" because of following StandardError +# Unknown type 'geometry' for column 'the_geom' + + create_table "user_authorizations", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "user_id", :limit => 64 + t.string "uid", :null => false + t.string "provider", :null => false + t.string "token", :limit => 2000 + t.datetime "token_expiration" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.string "secret" + end + + add_index "user_authorizations", ["provider", "uid"], :name => "user_authorizations_uniqkey", :unique => true + add_index "user_authorizations", ["user_id"], :name => "user_authorizations_user_id_idx" + + create_table "user_presences", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "user_id", :limit => 64, :null => false + t.string "type", :limit => 100, :null => false + t.string "username", :limit => 100, :null => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + +# Could not dump table "users" because of following StandardError +# Unknown type 'json' for column 'mods' + + create_table "video_sources", :id => false, :force => true do |t| + t.string "id", :limit => 64, :null => false + t.string "connection_id", :limit => 64, :null => false + t.string "client_video_source_id", :limit => 64, :null => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "wert_snot", :id => false, :force => true do |t| + t.integer "count", :limit => 8 + t.integer "last_jam_locidispid", :limit => 8 + end + +# Could not dump table "zcta5" because of following StandardError +# Unknown type 'geometry' for column 'the_geom' + + create_table "zip_lookup", :id => false, :force => true do |t| + t.integer "zip", :null => false + t.integer "st_code" + t.string "state", :limit => 2 + t.integer "co_code" + t.string "county", :limit => 90 + t.integer "cs_code" + t.string "cousub", :limit => 90 + t.integer "pl_code" + t.string "place", :limit => 90 + t.integer "cnt" + end + + create_table "zip_lookup_all", :id => false, :force => true do |t| + t.integer "zip" + t.integer "st_code" + t.string "state", :limit => 2 + t.integer "co_code" + t.string "county", :limit => 90 + t.integer "cs_code" + t.string "cousub", :limit => 90 + t.integer "pl_code" + t.string "place", :limit => 90 + t.integer "cnt" + end + + create_table "zip_lookup_base", :id => false, :force => true do |t| + t.string "zip", :limit => 5, :null => false + t.string "state", :limit => 40 + t.string "county", :limit => 90 + t.string "city", :limit => 90 + t.string "statefp", :limit => 2 + end + + create_table "zip_state", :id => false, :force => true do |t| + t.string "zip", :limit => 5, :null => false + t.string "stusps", :limit => 2, :null => false + t.string "statefp", :limit => 2 + end + + create_table "zip_state_loc", :id => false, :force => true do |t| + t.string "zip", :limit => 5, :null => false + t.string "stusps", :limit => 2, :null => false + t.string "statefp", :limit => 2 + t.string "place", :limit => 100, :null => false + end + +end diff --git a/web/db/structure.sql b/web/db/structure.sql new file mode 100644 index 000000000..4a3422815 --- /dev/null +++ b/web/db/structure.sql @@ -0,0 +1,3862 @@ +-- +-- PostgreSQL database dump +-- + +SET statement_timeout = 0; +SET lock_timeout = 0; +SET client_encoding = 'UTF8'; +SET standard_conforming_strings = on; +SET check_function_bodies = false; +SET client_min_messages = warning; + +-- +-- Name: pgmigrate; Type: SCHEMA; Schema: -; Owner: - +-- + +CREATE SCHEMA pgmigrate; + + +-- +-- Name: tiger; Type: SCHEMA; Schema: -; Owner: - +-- + +CREATE SCHEMA tiger; + + +-- +-- Name: fuzzystrmatch; Type: EXTENSION; Schema: -; Owner: - +-- + +CREATE EXTENSION IF NOT EXISTS fuzzystrmatch WITH SCHEMA public; + + +-- +-- Name: EXTENSION fuzzystrmatch; Type: COMMENT; Schema: -; Owner: - +-- + +COMMENT ON EXTENSION fuzzystrmatch IS 'determine similarities and distance between strings'; + + +-- +-- Name: postgis; Type: EXTENSION; Schema: -; Owner: - +-- + +CREATE EXTENSION IF NOT EXISTS postgis WITH SCHEMA public; + + +-- +-- Name: EXTENSION postgis; Type: COMMENT; Schema: -; Owner: - +-- + +COMMENT ON EXTENSION postgis IS 'PostGIS geometry, geography, and raster spatial types and functions'; + + +-- +-- Name: postgis_tiger_geocoder; Type: EXTENSION; Schema: -; Owner: - +-- + +CREATE EXTENSION IF NOT EXISTS postgis_tiger_geocoder WITH SCHEMA tiger; + + +-- +-- Name: EXTENSION postgis_tiger_geocoder; Type: COMMENT; Schema: -; Owner: - +-- + +COMMENT ON EXTENSION postgis_tiger_geocoder IS 'PostGIS tiger geocoder and reverse geocoder'; + + +-- +-- Name: topology; Type: SCHEMA; Schema: -; Owner: - +-- + +CREATE SCHEMA topology; + + +-- +-- Name: plpgsql; Type: EXTENSION; Schema: -; Owner: - +-- + +CREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA pg_catalog; + + +-- +-- Name: EXTENSION plpgsql; Type: COMMENT; Schema: -; Owner: - +-- + +COMMENT ON EXTENSION plpgsql IS 'PL/pgSQL procedural language'; + + +-- +-- Name: postgis_topology; Type: EXTENSION; Schema: -; Owner: - +-- + +CREATE EXTENSION IF NOT EXISTS postgis_topology WITH SCHEMA topology; + + +-- +-- Name: EXTENSION postgis_topology; Type: COMMENT; Schema: -; Owner: - +-- + +COMMENT ON EXTENSION postgis_topology IS 'PostGIS topology spatial types and functions'; + + +-- +-- Name: uuid-ossp; Type: EXTENSION; Schema: -; Owner: - +-- + +CREATE EXTENSION IF NOT EXISTS "uuid-ossp" WITH SCHEMA public; + + +-- +-- Name: EXTENSION "uuid-ossp"; Type: COMMENT; Schema: -; Owner: - +-- + +COMMENT ON EXTENSION "uuid-ossp" IS 'generate universally unique identifiers (UUIDs)'; + + +SET search_path = pgmigrate, pg_catalog; + +-- +-- Name: bootstrap_pg_migrate(); Type: FUNCTION; Schema: pgmigrate; Owner: - +-- + +CREATE FUNCTION bootstrap_pg_migrate() RETURNS void + LANGUAGE plpgsql + AS $$ DECLARE found_pg_migrate information_schema.tables; found_pg_migrations information_schema.tables; BEGIN BEGIN SELECT * INTO STRICT found_pg_migrate FROM information_schema.tables WHERE table_name = 'pg_migrate' and table_schema = 'pgmigrate'; EXCEPTION WHEN NO_DATA_FOUND THEN CREATE TABLE pgmigrate.pg_migrate (id BIGSERIAL PRIMARY KEY, template_version VARCHAR(255), builder_version VARCHAR(255), migrator_version VARCHAR(255), database_version VARCHAR(1024)); CREATE INDEX pg_migrate_unique_index ON pgmigrate.pg_migrate (template_version, builder_version, migrator_version, database_version); WHEN TOO_MANY_ROWS THEN RAISE EXCEPTION 'Multiple pg_migrate tables. Unique key on information_schema.tables should have prevented this.'; END; BEGIN SELECT * INTO STRICT found_pg_migrations FROM information_schema.tables WHERE table_name = 'pg_migrations' and table_schema = 'pgmigrate'; EXCEPTION WHEN NO_DATA_FOUND THEN CREATE TABLE pgmigrate.pg_migrations( name VARCHAR(255) PRIMARY KEY, ordinal INTEGER NOT NULL, created TIMESTAMP DEFAULT CURRENT_TIMESTAMP, finalized SMALLINT DEFAULT 1, pg_migrate_id BIGINT NOT NULL REFERENCES pgmigrate.pg_migrate(id)); WHEN TOO_MANY_ROWS THEN RAISE EXCEPTION 'Multiple pg_migrations tables. Unique key on information_schema.tables should have prevented this.'; END; END; $$; + + +-- +-- Name: bypass_existing_migration(character varying); Type: FUNCTION; Schema: pgmigrate; Owner: - +-- + +CREATE FUNCTION bypass_existing_migration(migration character varying) RETURNS void + LANGUAGE plpgsql + AS $_$ DECLARE found_migration pgmigrate.pg_migrations; BEGIN BEGIN EXECUTE 'SELECT * FROM pgmigrate.pg_migrations WHERE name=$1' INTO STRICT found_migration USING migration ; EXCEPTION WHEN NO_DATA_FOUND THEN RETURN; WHEN TOO_MANY_ROWS THEN RAISE EXCEPTION 'pg_migrate: code=pg_migrations_uniqueness_error, migration=%', migration; END; RAISE EXCEPTION 'pg_migrate: code=migration_exists, migration=%', migration; END; $_$; + + +-- +-- Name: record_migration(character varying, integer, character varying, character varying); Type: FUNCTION; Schema: pgmigrate; Owner: - +-- + +CREATE FUNCTION record_migration(migration character varying, ordinal integer, template_version character varying, builder_version character varying) RETURNS void + LANGUAGE plpgsql + AS $_$ DECLARE found_pg_migrate_id BIGINT; migrator_version VARCHAR(255); BEGIN EXECUTE 'SELECT current_setting(''application_name'')' INTO migrator_version; BEGIN EXECUTE 'SELECT id FROM pgmigrate.pg_migrate WHERE template_version=$1 and builder_version=$2 and migrator_version=$3 and database_version=$4' INTO found_pg_migrate_id USING template_version, builder_version, migrator_version, (select version()); EXCEPTION WHEN NO_DATA_FOUND THEN found_pg_migrate_id = NULL; WHEN TOO_MANY_ROWS THEN RAISE EXCEPTION 'pg_migrate: code=pg_migrate_uniqueness_error, migration=%, ordinal=%, template_version=%, builder_version=%, migrator_version=%, database_version', migration, ordinal, template_version, builder_version, migrator_version, (select version()); END; IF found_pg_migrate_id IS NULL THEN INSERT INTO pgmigrate.pg_migrate(id, template_version, builder_version, migrator_version, database_version) VALUES (default, template_version, builder_version, migrator_version, (select version())) RETURNING id INTO found_pg_migrate_id; END IF; EXECUTE 'INSERT INTO pgmigrate.pg_migrations(name, ordinal, created, finalized, pg_migrate_id) VALUES ($1, $2, CURRENT_TIMESTAMP, 1, $3)' USING migration, ordinal, found_pg_migrate_id; END; $_$; + + +-- +-- Name: verify_against_existing_migrations(character varying, integer); Type: FUNCTION; Schema: pgmigrate; Owner: - +-- + +CREATE FUNCTION verify_against_existing_migrations(migration character varying, ordinal integer) RETURNS void + LANGUAGE plpgsql + AS $_$ DECLARE found_migration pgmigrate.pg_migrations; BEGIN BEGIN EXECUTE 'SELECT * FROM pgmigrate.pg_migrations WHERE name=$1' INTO STRICT found_migration USING migration; EXCEPTION WHEN NO_DATA_FOUND THEN IF coalesce((SELECT MAX(p.ordinal) FROM pgmigrate.pg_migrations as p), -1) <> ordinal - 1 THEN RAISE EXCEPTION 'pg_migrate: code=missing_migration, migration=%, ordinal=%, last_ordinal=%', migration, ordinal, (SELECT MAX(p.ordinal) FROM pgmigrate.pg_migrations as p); END IF; RETURN; WHEN TOO_MANY_ROWS THEN RAISE EXCEPTION 'pg_migrate: code=pg_migrations_uniqueness_error, migration=%', migration; END; IF found_migration.ordinal <> ordinal THEN RAISE EXCEPTION 'pg_migrate: code=incorrect_ordinal, migration=%, expected_ordinal=%, actual_ordinal', migration, ordinal, found_migration.ordinal; END IF; END; $_$; + + +-- +-- Name: verify_manifest_is_not_old(integer); Type: FUNCTION; Schema: pgmigrate; Owner: - +-- + +CREATE FUNCTION verify_manifest_is_not_old(manifest_version integer) RETURNS void + LANGUAGE plpgsql + AS $$ DECLARE max_ordinal INTEGER; BEGIN EXECUTE 'SELECT max(ordinal) FROM pgmigrate.pg_migrations' INTO max_ordinal; IF max_ordinal > manifest_version THEN RAISE EXCEPTION 'pg_migrate: code=old_manifest, max_ordinal_in_db=%, manifest_version=%', max_ordinal, manifest_version; END IF; END; $$; + + +SET search_path = public, pg_catalog; + +-- +-- Name: bootstrap_users(); Type: FUNCTION; Schema: public; Owner: - +-- + +CREATE FUNCTION bootstrap_users() RETURNS void + LANGUAGE plpgsql + AS $_$ DECLARE test_user VARCHAR(64); BEGIN SELECT id INTO STRICT test_user FROM users WHERE id = '1'; UPDATE users SET first_name = 'Test', last_name = 'User', email = 'test@jamkazam.com', remember_token = 'NQubl-z16Em94tnSdofObw', password_digest = '$2a$10$QyaNTLVX5DAaJ.JL21kDWeUQqdh3Qh7JQbdRgE82x1Cib7HWNcHXC', email_confirmed=true, musician=true WHERE id = '1'; EXCEPTION WHEN NO_DATA_FOUND THEN INSERT INTO users (id, first_name, last_name, email, remember_token, password_digest, email_confirmed, musician) VALUES ('1', 'Test', 'User', 'test@jamkazam.com', 'NQubl-z16Em94tnSdofObw', '$2a$10$QyaNTLVX5DAaJ.JL21kDWeUQqdh3Qh7JQbdRgE82x1Cib7HWNcHXC', true, true); RETURN; WHEN TOO_MANY_ROWS THEN RAISE EXCEPTION 'user id 1 not unique'; END; $_$; + + +-- +-- Name: get_work(bigint); Type: FUNCTION; Schema: public; Owner: - +-- + +CREATE FUNCTION get_work(mylocidispid bigint) RETURNS TABLE(client_id character varying) + LANGUAGE plpgsql ROWS 5 + AS $$ BEGIN CREATE TEMPORARY TABLE foo (locidispid BIGINT, locid INT); INSERT INTO foo SELECT DISTINCT locidispid, locidispid/1000000 FROM connections where client_type = 'client'; DELETE FROM foo WHERE locidispid IN (SELECT DISTINCT blocidispid FROM current_scores WHERE alocidispid = mylocidispid AND (current_timestamp - score_dt) < interval '24 hours'); DELETE FROM foo WHERE locid NOT IN (SELECT locid FROM geoiplocations WHERE geog && st_buffer((SELECT geog from geoiplocations WHERE locid = mylocidispid/1000000), 806000)); CREATE TEMPORARY TABLE bar (client_id VARCHAR(64), locidispid BIGINT, r DOUBLE PRECISION); INSERT INTO bar SELECT l.client_id, l.locidispid, random() FROM connections l, foo f WHERE l.locidispid = f.locidispid and l.client_type = 'client'; DROP TABLE foo; DELETE FROM bar b WHERE r != (SELECT max(r) FROM bar b0 WHERE b0.locidispid = b.locidispid); RETURN QUERY SELECT b.client_id FROM bar b ORDER BY r LIMIT 5; DROP TABLE bar; RETURN; END; $$; + + +-- +-- Name: truncate_tables(); Type: FUNCTION; Schema: public; Owner: - +-- + +CREATE FUNCTION truncate_tables() RETURNS void + LANGUAGE plpgsql + AS $$ DECLARE statements CURSOR FOR SELECT tablename FROM pg_tables WHERE schemaname = 'public'; BEGIN FOR stmt IN statements LOOP EXECUTE 'TRUNCATE TABLE ' || quote_ident(stmt.tablename) || ' CASCADE;'; END LOOP; END; $$; + + +-- +-- Name: english_stem; Type: TEXT SEARCH DICTIONARY; Schema: public; Owner: - +-- + +CREATE TEXT SEARCH DICTIONARY english_stem ( + TEMPLATE = pg_catalog.snowball, + language = 'english', stopwords = 'english' ); + + +-- +-- Name: jamenglish; Type: TEXT SEARCH CONFIGURATION; Schema: public; Owner: - +-- + +CREATE TEXT SEARCH CONFIGURATION jamenglish ( + PARSER = pg_catalog."default" ); + +ALTER TEXT SEARCH CONFIGURATION jamenglish + ADD MAPPING FOR asciiword WITH pg_catalog.english_stem; + +ALTER TEXT SEARCH CONFIGURATION jamenglish + ADD MAPPING FOR word WITH pg_catalog.english_stem; + +ALTER TEXT SEARCH CONFIGURATION jamenglish + ADD MAPPING FOR numword WITH simple; + +ALTER TEXT SEARCH CONFIGURATION jamenglish + ADD MAPPING FOR host WITH simple; + +ALTER TEXT SEARCH CONFIGURATION jamenglish + ADD MAPPING FOR version WITH simple; + +ALTER TEXT SEARCH CONFIGURATION jamenglish + ADD MAPPING FOR hword_numpart WITH simple; + +ALTER TEXT SEARCH CONFIGURATION jamenglish + ADD MAPPING FOR hword_part WITH pg_catalog.english_stem; + +ALTER TEXT SEARCH CONFIGURATION jamenglish + ADD MAPPING FOR hword_asciipart WITH pg_catalog.english_stem; + +ALTER TEXT SEARCH CONFIGURATION jamenglish + ADD MAPPING FOR numhword WITH simple; + +ALTER TEXT SEARCH CONFIGURATION jamenglish + ADD MAPPING FOR asciihword WITH pg_catalog.english_stem; + +ALTER TEXT SEARCH CONFIGURATION jamenglish + ADD MAPPING FOR hword WITH pg_catalog.english_stem; + +ALTER TEXT SEARCH CONFIGURATION jamenglish + ADD MAPPING FOR file WITH simple; + +ALTER TEXT SEARCH CONFIGURATION jamenglish + ADD MAPPING FOR "int" WITH simple; + +ALTER TEXT SEARCH CONFIGURATION jamenglish + ADD MAPPING FOR uint WITH simple; + + +SET search_path = pgmigrate, pg_catalog; + +SET default_tablespace = ''; + +SET default_with_oids = false; + +-- +-- Name: pg_migrate; Type: TABLE; Schema: pgmigrate; Owner: -; Tablespace: +-- + +CREATE TABLE pg_migrate ( + id bigint NOT NULL, + template_version character varying(255), + builder_version character varying(255), + migrator_version character varying(255), + database_version character varying(1024) +); + + +-- +-- Name: pg_migrate_id_seq; Type: SEQUENCE; Schema: pgmigrate; Owner: - +-- + +CREATE SEQUENCE pg_migrate_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: pg_migrate_id_seq; Type: SEQUENCE OWNED BY; Schema: pgmigrate; Owner: - +-- + +ALTER SEQUENCE pg_migrate_id_seq OWNED BY pg_migrate.id; + + +-- +-- Name: pg_migrations; Type: TABLE; Schema: pgmigrate; Owner: -; Tablespace: +-- + +CREATE TABLE pg_migrations ( + name character varying(255) NOT NULL, + ordinal integer NOT NULL, + created timestamp without time zone DEFAULT now(), + finalized smallint DEFAULT 1, + pg_migrate_id bigint NOT NULL +); + + +SET search_path = public, pg_catalog; + +-- +-- Name: active_admin_comments; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE active_admin_comments ( + id integer NOT NULL, + resource_id character varying(255) NOT NULL, + resource_type character varying(255) NOT NULL, + author_id integer, + author_type character varying(255), + body text, + created_at timestamp without time zone NOT NULL, + updated_at timestamp without time zone NOT NULL, + namespace character varying(255) +); + + +-- +-- Name: active_admin_comments_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE active_admin_comments_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: active_admin_comments_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE active_admin_comments_id_seq OWNED BY active_admin_comments.id; + + +-- +-- Name: active_music_sessions; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE UNLOGGED TABLE active_music_sessions ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + user_id character varying(64) NOT NULL, + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL, + claimed_recording_id character varying(64), + claimed_recording_initiator_id character varying(64), + track_changes_counter integer DEFAULT 0 +); + + +-- +-- Name: affiliate_partners; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE affiliate_partners ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + partner_name character varying(128) NOT NULL, + partner_code character varying(128) NOT NULL, + partner_user_id character varying(64) NOT NULL, + user_email character varying(255), + referral_user_count integer DEFAULT 0 NOT NULL, + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL +); + + +-- +-- Name: artifact_updates; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE artifact_updates ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + product character varying(255) NOT NULL, + version character varying(255) NOT NULL, + uri character varying(2000) NOT NULL, + sha1 character varying(255) NOT NULL, + environment character varying(255) DEFAULT 'public'::character varying NOT NULL, + size integer NOT NULL +); + + +-- +-- Name: band_invitations; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE band_invitations ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + user_id character varying(64), + band_id character varying(64), + accepted boolean, + creator_id character varying(64), + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL +); + + +-- +-- Name: bands; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE bands ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + name character varying(1024) NOT NULL, + website character varying(4000), + biography character varying(4000) NOT NULL, + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL, + city character varying(100), + state character varying(100), + country character varying(100), + photo_url character varying(2048), + logo_url character varying(2048), + name_tsv tsvector, + original_fpfile_photo character varying(8000) DEFAULT NULL::character varying, + cropped_fpfile_photo character varying(8000) DEFAULT NULL::character varying, + cropped_s3_path_photo character varying(512) DEFAULT NULL::character varying, + crop_selection_photo character varying(256) DEFAULT NULL::character varying, + lat numeric(15,10), + lng numeric(15,10), + large_photo_url character varying(2048), + cropped_large_s3_path_photo character varying(512), + cropped_large_fpfile_photo character varying(8000), + did_real_session boolean DEFAULT false +); + + +-- +-- Name: bands_genres; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE bands_genres ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + band_id character varying(64) NOT NULL, + genre_id character varying(64) NOT NULL, + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL +); + + +-- +-- Name: bands_musicians; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE bands_musicians ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + band_id character varying(64) NOT NULL, + user_id character varying(64) NOT NULL, + admin boolean DEFAULT false NOT NULL, + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL +); + + +-- +-- Name: chat_messages; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE chat_messages ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + user_id character varying(64), + music_session_id character varying(64), + message text NOT NULL, + created_at timestamp without time zone DEFAULT now() NOT NULL +); + + +-- +-- Name: cities; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE cities ( + city character varying(255) NOT NULL, + region character varying(2) NOT NULL, + countrycode character varying(2) NOT NULL +); + + +-- +-- Name: claimed_recordings; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE claimed_recordings ( + user_id character varying(64) NOT NULL, + recording_id character varying(64) NOT NULL, + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + name character varying(200) NOT NULL, + is_public boolean DEFAULT true NOT NULL, + genre_id character varying(64) NOT NULL, + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL, + description character varying(8000), + description_tsv tsvector, + name_tsv tsvector +); + + +-- +-- Name: connections; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE UNLOGGED TABLE connections ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + user_id character varying(64) NOT NULL, + client_id character varying(64) NOT NULL, + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL, + music_session_id character varying(64), + ip_address character varying(64) NOT NULL, + as_musician boolean, + aasm_state character varying(64) DEFAULT 'idle'::character varying NOT NULL, + addr bigint NOT NULL, + locidispid bigint NOT NULL, + joined_session_at timestamp without time zone, + client_type character varying(256) NOT NULL, + stale_time integer DEFAULT 40 NOT NULL, + expire_time integer DEFAULT 60 NOT NULL +); + + +-- +-- Name: countries; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE countries ( + countrycode character varying(2) NOT NULL, + countryname character varying(64) +); + + +-- +-- Name: crash_dumps; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE crash_dumps ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + client_type character varying(64) NOT NULL, + client_id character varying(64), + user_id character varying(64), + session_id character varying(64), + "timestamp" timestamp without time zone, + uri character varying(1000), + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL, + client_version character varying(100) NOT NULL +); + + +-- +-- Name: scores; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE scores ( + alocidispid bigint NOT NULL, + anodeid character varying(64) NOT NULL, + aaddr bigint NOT NULL, + blocidispid bigint NOT NULL, + bnodeid character varying(64) NOT NULL, + baddr bigint NOT NULL, + score integer NOT NULL, + scorer integer NOT NULL, + score_dt timestamp without time zone DEFAULT now() NOT NULL +); + + +-- +-- Name: current_scores; Type: VIEW; Schema: public; Owner: - +-- + +CREATE VIEW current_scores AS + SELECT s.alocidispid, + s.anodeid, + s.aaddr, + s.blocidispid, + s.bnodeid, + s.baddr, + s.score, + s.scorer, + s.score_dt + FROM scores s + WHERE (s.score_dt = ( SELECT max(s0.score_dt) AS max + FROM scores s0 + WHERE ((s0.alocidispid = s.alocidispid) AND (s0.blocidispid = s.blocidispid)))); + + +-- +-- Name: diagnostics; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE diagnostics ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + user_id character varying(64) NOT NULL, + type character varying(255) NOT NULL, + creator character varying(255) NOT NULL, + data text, + created_at timestamp without time zone DEFAULT now() NOT NULL +); + + +-- +-- Name: email_batch_sets; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE email_batch_sets ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + email_batch_id character varying(64), + started_at timestamp without time zone, + user_ids text DEFAULT ''::text NOT NULL, + batch_count integer, + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL, + trigger_index integer DEFAULT 0 NOT NULL, + sub_type character varying(64), + user_id character varying(64) +); + + +-- +-- Name: email_batches; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE email_batches ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + subject character varying(256), + body text, + from_email character varying(64) DEFAULT 'noreply@jamkazam.com'::character varying NOT NULL, + aasm_state character varying(32) DEFAULT 'pending'::character varying NOT NULL, + test_emails text DEFAULT 'test@jamkazam.com'::text NOT NULL, + opt_in_count integer DEFAULT 0 NOT NULL, + sent_count integer DEFAULT 0 NOT NULL, + lock_version integer, + started_at timestamp without time zone, + completed_at timestamp without time zone, + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL, + type character varying(64) DEFAULT 'JamRuby::EmailBatch'::character varying NOT NULL, + sub_type character varying(64) +); + + +-- +-- Name: email_errors; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE email_errors ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + user_id character varying(64), + error_type character varying(32), + email_address character varying(256), + status character varying(32), + email_date timestamp without time zone DEFAULT now(), + reason text, + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL +); + + +-- +-- Name: event_sessions; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE event_sessions ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + starts_at timestamp without time zone, + ends_at timestamp without time zone, + pinned_state character varying(255), + img_url character varying(1024), + img_width integer, + img_height integer, + event_id character varying(64), + user_id character varying(64), + band_id character varying(64), + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL, + ordinal integer +); + + +-- +-- Name: events; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE events ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + slug character varying(512) NOT NULL, + title text, + description text, + show_sponser boolean DEFAULT false NOT NULL, + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL, + social_description text +); + + +-- +-- Name: facebook_signups; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE UNLOGGED TABLE facebook_signups ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + lookup_id character varying(255) NOT NULL, + last_name character varying(100), + first_name character varying(100), + gender character varying(1), + email character varying(1024), + uid character varying(1024), + token character varying(1024), + token_expires_at timestamp without time zone, + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL +); + + +-- +-- Name: fan_invitations; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE fan_invitations ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + sender_id character varying(64), + receiver_id character varying(64), + music_session_id character varying(64), + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL +); + + +-- +-- Name: feeds; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE feeds ( + id bigint NOT NULL, + recording_id character varying(64), + music_session_id character varying(64), + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL +); + + +-- +-- Name: feeds_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE feeds_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: feeds_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE feeds_id_seq OWNED BY feeds.id; + + +-- +-- Name: follows; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE follows ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + user_id character varying(64) NOT NULL, + followable_id character varying(64) NOT NULL, + followable_type character varying(25) NOT NULL, + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL +); + + +-- +-- Name: friend_requests; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE friend_requests ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + user_id character varying(64), + friend_id character varying(64), + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL, + status character varying(50), + message character varying(4000) +); + + +-- +-- Name: friendships; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE friendships ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + user_id character varying(64), + friend_id character varying(64), + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL +); + + +-- +-- Name: genres; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE genres ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + description character varying(1024) NOT NULL, + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL +); + + +-- +-- Name: genres_music_sessions; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE UNLOGGED TABLE genres_music_sessions ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + genre_id character varying(64), + music_session_id character varying(64) +); + + +-- +-- Name: geoipblocks; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE geoipblocks ( + beginip bigint NOT NULL, + endip bigint NOT NULL, + locid integer NOT NULL, + geom geometry(Polygon) +); + + +-- +-- Name: geoipisp; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE geoipisp ( + beginip bigint NOT NULL, + endip bigint NOT NULL, + company character varying(50) NOT NULL +); + + +-- +-- Name: geoiplocations; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE geoiplocations ( + locid integer NOT NULL, + countrycode character varying(2), + region character varying(2), + city character varying(255), + postalcode character varying(8), + latitude double precision NOT NULL, + longitude double precision NOT NULL, + metrocode integer, + areacode character(3), + geog geography(Point,4326) +); + + +-- +-- Name: icecast_admin_authentications; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE icecast_admin_authentications ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + source_pass character varying(64) NOT NULL, + relay_user character varying(64) NOT NULL, + relay_pass character varying(64) NOT NULL, + admin_user character varying(64) NOT NULL, + admin_pass character varying(64) NOT NULL, + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL +); + + +-- +-- Name: icecast_directories; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE icecast_directories ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + yp_url_timeout integer DEFAULT 15 NOT NULL, + yp_url character varying(1024) NOT NULL, + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL +); + + +-- +-- Name: icecast_limits; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE icecast_limits ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + clients integer DEFAULT 1000 NOT NULL, + sources integer DEFAULT 50 NOT NULL, + queue_size integer DEFAULT 102400 NOT NULL, + client_timeout integer DEFAULT 30, + header_timeout integer DEFAULT 15, + source_timeout integer DEFAULT 10, + burst_size integer DEFAULT 65536, + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL +); + + +-- +-- Name: icecast_listen_sockets; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE icecast_listen_sockets ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + port integer DEFAULT 8001 NOT NULL, + bind_address character varying(1024), + shoutcast_mount character varying(1024), + shoutcast_compat integer, + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL +); + + +-- +-- Name: icecast_loggings; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE icecast_loggings ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + access_log character varying(1024) DEFAULT 'access.log'::character varying NOT NULL, + error_log character varying(1024) DEFAULT 'error.log'::character varying NOT NULL, + playlist_log character varying(1024), + log_level integer DEFAULT 3 NOT NULL, + log_archive integer, + log_size integer DEFAULT 10000, + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL +); + + +-- +-- Name: icecast_master_server_relays; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE icecast_master_server_relays ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + master_server character varying(1024) NOT NULL, + master_server_port integer DEFAULT 8001 NOT NULL, + master_update_interval integer DEFAULT 120 NOT NULL, + master_username character varying(64) NOT NULL, + master_pass character varying(64) NOT NULL, + relays_on_demand integer DEFAULT 1 NOT NULL, + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL +); + + +-- +-- Name: icecast_mount_templates; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE icecast_mount_templates ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + name character varying(256) NOT NULL, + source_username character varying(64), + source_pass character varying(64), + max_listeners integer DEFAULT 4, + max_listener_duration integer DEFAULT 3600, + dump_file character varying(1024), + intro character varying(1024), + fallback_mount character varying(1024), + fallback_override integer DEFAULT 1, + fallback_when_full integer DEFAULT 1, + charset character varying(1024) DEFAULT 'ISO8859-1'::character varying, + is_public integer DEFAULT 0, + stream_name character varying(1024), + stream_description character varying(10000), + stream_url character varying(1024), + genre character varying(256), + bitrate integer, + mime_type character varying(64) DEFAULT 'audio/mpeg'::character varying NOT NULL, + subtype character varying(64), + burst_size integer, + mp3_metadata_interval integer, + hidden integer DEFAULT 1, + on_connect character varying(1024), + on_disconnect character varying(1024), + authentication_id character varying(64) NOT NULL, + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL +); + + +-- +-- Name: icecast_mounts; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE UNLOGGED TABLE icecast_mounts ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + name character varying(1024) NOT NULL, + source_username character varying(64), + source_pass character varying(64), + max_listeners integer DEFAULT 4, + max_listener_duration integer DEFAULT 3600, + dump_file character varying(1024), + intro character varying(1024), + fallback_mount character varying(1024), + fallback_override integer DEFAULT 1, + fallback_when_full integer DEFAULT 1, + charset character varying(1024) DEFAULT 'ISO8859-1'::character varying, + is_public integer DEFAULT 0, + stream_name character varying(1024), + stream_description character varying(10000), + stream_url character varying(1024), + genre character varying(256), + bitrate integer, + mime_type character varying(64), + subtype character varying(64), + burst_size integer, + mp3_metadata_interval integer, + hidden integer DEFAULT 1, + on_connect character varying(1024), + on_disconnect character varying(1024), + authentication_id character varying(64) DEFAULT NULL::character varying, + listeners integer DEFAULT 0 NOT NULL, + sourced boolean DEFAULT false NOT NULL, + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL, + music_session_id character varying(64), + icecast_server_id character varying(64) NOT NULL, + icecast_mount_template_id character varying(64), + sourced_needs_changing_at timestamp without time zone +); + + +-- +-- Name: icecast_paths; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE icecast_paths ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + base_dir character varying(1024) DEFAULT './'::character varying NOT NULL, + log_dir character varying(1024) DEFAULT './logs'::character varying NOT NULL, + pid_file character varying(1024) DEFAULT './icecast.pid'::character varying, + web_root character varying(1024) DEFAULT './web'::character varying NOT NULL, + admin_root character varying(1024) DEFAULT './admin'::character varying NOT NULL, + allow_ip character varying(1024), + deny_ip character varying(1024), + alias_source character varying(1024), + alias_dest character varying(1024), + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL +); + + +-- +-- Name: icecast_relays; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE icecast_relays ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + server character varying(1024) NOT NULL, + port integer DEFAULT 8001 NOT NULL, + mount character varying(1024) NOT NULL, + local_mount character varying(1024), + relay_username character varying(64), + relay_pass character varying(64), + relay_shoutcast_metadata integer DEFAULT 0, + on_demand integer DEFAULT 1, + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL +); + + +-- +-- Name: icecast_securities; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE icecast_securities ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + chroot integer DEFAULT 0 NOT NULL, + change_owner_user character varying(64), + change_owner_group character varying(64), + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL +); + + +-- +-- Name: icecast_server_groups; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE icecast_server_groups ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + name character varying(255) NOT NULL +); + + +-- +-- Name: icecast_server_mounts; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE icecast_server_mounts ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + icecast_mount_id character varying(64), + icecast_server_id character varying(64), + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL +); + + +-- +-- Name: icecast_server_relays; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE icecast_server_relays ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + icecast_relay_id character varying(64), + icecast_server_id character varying(64), + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL +); + + +-- +-- Name: icecast_server_sockets; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE icecast_server_sockets ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + icecast_listen_socket_id character varying(64), + icecast_server_id character varying(64), + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL +); + + +-- +-- Name: icecast_servers; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE icecast_servers ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + config_changed integer DEFAULT 0, + limit_id character varying(64), + admin_auth_id character varying(64), + directory_id character varying(64), + master_relay_id character varying(64), + path_id character varying(64), + logging_id character varying(64), + security_id character varying(64), + template_id character varying(64) NOT NULL, + hostname character varying(1024) NOT NULL, + server_id character varying(1024) NOT NULL, + location character varying(1024), + admin_email character varying(1024), + fileserve integer, + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL, + icecast_server_group_id character varying(64) DEFAULT 'default'::character varying NOT NULL, + mount_template_id character varying(64), + config_updated_at timestamp without time zone +); + + +-- +-- Name: icecast_template_sockets; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE icecast_template_sockets ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + icecast_listen_socket_id character varying(64), + icecast_template_id character varying(64), + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL +); + + +-- +-- Name: icecast_templates; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE icecast_templates ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + limit_id character varying(64), + admin_auth_id character varying(64), + directory_id character varying(64), + master_relay_id character varying(64), + path_id character varying(64), + logging_id character varying(64), + security_id character varying(64), + location character varying(1024) NOT NULL, + name character varying(256) NOT NULL, + admin_email character varying(1024) DEFAULT 'admin@jamkazam.com'::character varying NOT NULL, + fileserve integer DEFAULT 1 NOT NULL, + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL +); + + +-- +-- Name: icecast_user_authentications; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE UNLOGGED TABLE icecast_user_authentications ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + authentication_type character varying(16) DEFAULT 'url'::character varying, + filename character varying(1024), + allow_duplicate_users integer, + mount_add character varying(1024), + mount_remove character varying(1024), + listener_add character varying(1024), + listener_remove character varying(1024), + unused_username character varying(64), + unused_pass character varying(64), + auth_header character varying(64) DEFAULT 'icecast-auth-user: 1'::character varying, + timelimit_header character varying(64) DEFAULT 'icecast-auth-timelimit:'::character varying, + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL +); + + +-- +-- Name: instruments; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE instruments ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + description character varying(1024) NOT NULL, + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL, + popularity integer DEFAULT 0 NOT NULL +); + + +-- +-- Name: invitations; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE UNLOGGED TABLE invitations ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + sender_id character varying(64), + receiver_id character varying(64), + music_session_id character varying(64), + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL, + join_request_id character varying(64) +); + + +-- +-- Name: invited_users; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE invited_users ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + sender_id character varying(64), + autofriend boolean NOT NULL, + email character varying(256), + invitation_code character varying(256) NOT NULL, + accepted boolean DEFAULT false, + note text, + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL, + invite_medium character varying(64) +); + + +-- +-- Name: isp_score_batch; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE isp_score_batch ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + json_scoring_data text NOT NULL, + created_at timestamp without time zone DEFAULT now() NOT NULL +); + + +-- +-- Name: jamcompany; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE jamcompany ( + coid integer NOT NULL, + company character varying(50) NOT NULL +); + + +-- +-- Name: jamcompany_coid_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE jamcompany_coid_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: jamcompany_coid_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE jamcompany_coid_seq OWNED BY jamcompany.coid; + + +-- +-- Name: jamisp; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE jamisp ( + beginip bigint NOT NULL, + endip bigint NOT NULL, + coid integer NOT NULL, + geom geometry(Polygon) +); + + +-- +-- Name: join_requests; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE UNLOGGED TABLE join_requests ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + user_id character varying(64), + music_session_id character varying(64), + text character varying(2000), + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL +); + + +-- +-- Name: likes; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE likes ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + user_id character varying(64) NOT NULL, + likable_id character varying(64) NOT NULL, + likable_type character varying(25) NOT NULL, + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL +); + + +-- +-- Name: max_mind_geo; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE max_mind_geo ( + country character varying(2) NOT NULL, + region character varying(2) NOT NULL, + city character varying(255) NOT NULL, + lat numeric(15,10) NOT NULL, + lng numeric(15,10) NOT NULL, + ip_start bigint NOT NULL, + ip_end bigint NOT NULL +); + + +-- +-- Name: max_mind_isp; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE max_mind_isp ( + ip_bottom bigint NOT NULL, + ip_top bigint NOT NULL, + isp character varying(64) NOT NULL, + country character varying(2) NOT NULL +); + + +-- +-- Name: tracks_next_tracker_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE tracks_next_tracker_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: mixes; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE mixes ( + id bigint DEFAULT nextval('tracks_next_tracker_seq'::regclass) NOT NULL, + recording_id character varying(64) NOT NULL, + mix_server character varying(64) DEFAULT NULL::character varying, + started_at timestamp without time zone, + completed_at timestamp without time zone, + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL, + ogg_md5 character varying(100), + ogg_length integer, + ogg_url character varying(1024), + completed boolean DEFAULT false NOT NULL, + error_count integer DEFAULT 0 NOT NULL, + error_reason text, + error_detail text, + should_retry boolean DEFAULT false NOT NULL, + mp3_md5 character varying(100), + mp3_length integer, + mp3_url character varying(1024), + download_count integer DEFAULT 0 NOT NULL, + last_downloaded_at timestamp without time zone +); + + +-- +-- Name: music_session_perf_data; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE music_session_perf_data ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + music_session_id character varying(64), + client_id character varying(64), + uri character varying(1000), + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL +); + + +-- +-- Name: music_sessions; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE music_sessions ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + music_session_id character varying(64), + description character varying(8000), + user_id character varying(64) NOT NULL, + band_id character varying(64), + created_at timestamp without time zone DEFAULT now() NOT NULL, + session_removed_at timestamp without time zone DEFAULT now(), + play_count integer DEFAULT 0 NOT NULL, + like_count integer DEFAULT 0 NOT NULL, + fan_access boolean DEFAULT true NOT NULL, + scheduled_start timestamp with time zone, + scheduled_duration interval, + musician_access boolean DEFAULT true NOT NULL, + approval_required boolean DEFAULT false NOT NULL, + fan_chat boolean DEFAULT true NOT NULL, + genre_id character varying(64) NOT NULL, + legal_policy character varying(255) DEFAULT 'standard'::character varying NOT NULL, + language character varying(255) DEFAULT 'en'::character varying NOT NULL, + name text NOT NULL, + recurring_session_id character varying(64) +); + + +-- +-- Name: music_sessions_comments; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE music_sessions_comments ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + creator_id character varying(64) NOT NULL, + comment character varying(4000) NOT NULL, + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL, + ip_address inet, + music_session_id character varying(64) +); + + +-- +-- Name: music_sessions_likers; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE music_sessions_likers ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + liker_id character varying(64), + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL, + ip_address inet, + music_session_id character varying(64) +); + + +-- +-- Name: music_sessions_user_history; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE music_sessions_user_history ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + user_id character varying(64) NOT NULL, + client_id character varying(64) NOT NULL, + created_at timestamp without time zone DEFAULT now() NOT NULL, + session_removed_at timestamp without time zone, + max_concurrent_connections integer, + rating integer, + instruments character varying(255), + rating_comment text, + music_session_id character varying(64) +); + + +-- +-- Name: musicians_instruments; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE musicians_instruments ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + user_id character varying(64) NOT NULL, + instrument_id character varying(64) NOT NULL, + proficiency_level smallint NOT NULL, + priority smallint DEFAULT 1 NOT NULL, + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL +); + + +-- +-- Name: notifications; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE notifications ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + description character varying(32) NOT NULL, + source_user_id character varying(64), + target_user_id character varying(64), + band_id character varying(64), + session_id character varying(64), + recording_id character varying(64), + invitation_id character varying(64), + join_request_id character varying(64), + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL, + friend_request_id character varying(64), + band_invitation_id character varying(64), + message text +); + + +-- +-- Name: playable_plays; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE playable_plays ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + playable_id character varying(64) NOT NULL, + playable_type character varying(128) NOT NULL, + player_id character varying(64), + claimed_recording_id character varying(64), + ip_address inet, + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL +); + + +-- +-- Name: promotionals; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE promotionals ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + type character varying(128) DEFAULT 'JamRuby::PromoBuzz'::character varying NOT NULL, + aasm_state character varying(64) DEFAULT 'hidden'::character varying, + "position" integer DEFAULT 0 NOT NULL, + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL, + latest_id character varying(64) DEFAULT NULL::character varying, + latest_type character varying(128) DEFAULT NULL::character varying, + image character varying(1024) DEFAULT NULL::character varying, + text_short character varying(512) DEFAULT NULL::character varying, + text_long character varying(4096) DEFAULT NULL::character varying +); + + +-- +-- Name: recorded_tracks; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE recorded_tracks ( + id bigint DEFAULT nextval('tracks_next_tracker_seq'::regclass) NOT NULL, + user_id character varying(64) NOT NULL, + instrument_id character varying(64) NOT NULL, + sound character varying(64) NOT NULL, + next_part_to_upload integer DEFAULT 0 NOT NULL, + fully_uploaded boolean DEFAULT false NOT NULL, + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL, + upload_id character varying(1024), + recording_id character varying(64) NOT NULL, + md5 character varying(100), + length bigint, + client_id character varying(64) NOT NULL, + track_id character varying(64) NOT NULL, + url character varying(1024), + file_offset bigint DEFAULT 0, + client_track_id character varying(64) NOT NULL, + is_part_uploading boolean DEFAULT false NOT NULL, + upload_failures integer DEFAULT 0 NOT NULL, + part_failures integer DEFAULT 0 NOT NULL, + discard boolean, + download_count integer DEFAULT 0 NOT NULL, + last_downloaded_at timestamp without time zone +); + + +-- +-- Name: recordings; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE recordings ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL, + owner_id character varying(64) NOT NULL, + music_session_id character varying(64), + band_id character varying(64), + duration integer, + is_done boolean DEFAULT false, + all_discarded boolean DEFAULT false NOT NULL, + name character varying(1024), + play_count integer DEFAULT 0 NOT NULL, + like_count integer DEFAULT 0 NOT NULL +); + + +-- +-- Name: recordings_comments; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE recordings_comments ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + recording_id character varying(64) NOT NULL, + creator_id character varying(64) NOT NULL, + comment character varying(4000) NOT NULL, + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL, + ip_address inet +); + + +-- +-- Name: recordings_downloads; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE recordings_downloads ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + recording_id character varying(64) NOT NULL, + downloader_id character varying(64) NOT NULL, + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL +); + + +-- +-- Name: recordings_likers; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE recordings_likers ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + recording_id character varying(64) NOT NULL, + liker_id character varying(64), + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL, + ip_address inet, + claimed_recording_id character varying(64) NOT NULL, + favorite boolean DEFAULT true NOT NULL +); + + +-- +-- Name: recurring_sessions; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE recurring_sessions ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + description character varying(8000), + scheduled_start timestamp with time zone, + scheduled_duration interval, + musician_access boolean NOT NULL, + approval_required boolean NOT NULL, + fan_chat boolean NOT NULL, + genre_id character varying(64), + legal_policy character varying(255) DEFAULT 'standard'::character varying NOT NULL, + language character varying(255) DEFAULT 'en'::character varying NOT NULL, + name text, + user_id character varying(64) NOT NULL, + band_id character varying(64), + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL +); + + +-- +-- Name: regions; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE regions ( + region character varying(2) NOT NULL, + regionname character varying(64), + countrycode character varying(2) NOT NULL +); + + +-- +-- Name: rsvp_requests; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE rsvp_requests ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + user_id character varying(64) NOT NULL, + rsvp_slot_id character varying(64) NOT NULL, + message text, + chosen boolean DEFAULT false, + canceled boolean DEFAULT false, + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL +); + + +-- +-- Name: rsvp_slots; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE rsvp_slots ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + instrument_id character varying(64), + proficiency_level character varying(255) NOT NULL, + music_session_id character varying(64) NOT NULL, + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL +); + + +-- +-- Name: share_tokens; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE share_tokens ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + token character varying(15) NOT NULL, + shareable_id character varying(64) NOT NULL, + shareable_type character varying(50) NOT NULL, + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL +); + + +-- +-- Name: tracks; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE UNLOGGED TABLE tracks ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + connection_id character varying(64) NOT NULL, + instrument_id character varying(64), + sound character varying(64) NOT NULL, + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL, + client_track_id character varying(64) NOT NULL +); + + +-- +-- Name: user_authorizations; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE user_authorizations ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + user_id character varying(64), + uid character varying(255) NOT NULL, + provider character varying(255) NOT NULL, + token character varying(255), + token_expiration timestamp without time zone, + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL, + secret character varying(255) +); + + +-- +-- Name: users; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE users ( + id character varying(64) DEFAULT uuid_generate_v4() NOT NULL, + email character varying(255) NOT NULL, + remember_token character varying(255), + encrypted_password character varying(255) NOT NULL, + admin boolean DEFAULT false NOT NULL, + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL, + musician boolean DEFAULT false NOT NULL, + city character varying(100), + state character varying(100), + country character varying(100), + first_name character varying(50), + last_name character varying(50), + birth_date date, + gender character(1), + internet_service_provider character varying(50), + signup_token character varying(255), + email_confirmed boolean DEFAULT false, + photo_url character varying(2048), + session_settings character varying(4000), + reset_password_token character varying(64), + reset_password_token_created timestamp without time zone, + can_invite boolean DEFAULT true NOT NULL, + name_tsv tsvector, + environment character varying(255) DEFAULT 'public'::character varying NOT NULL, + subscribe_email boolean DEFAULT true, + update_email character varying(1024), + update_email_token character varying(1024), + original_fpfile character varying(8000) DEFAULT NULL::character varying, + cropped_fpfile character varying(8000) DEFAULT NULL::character varying, + cropped_s3_path character varying(512) DEFAULT NULL::character varying, + crop_selection character varying(256) DEFAULT NULL::character varying, + last_failed_certified_gear_at timestamp without time zone, + last_failed_certified_gear_reason character varying(256), + first_downloaded_client_at timestamp without time zone, + first_ran_client_at timestamp without time zone, + first_certified_gear_at timestamp without time zone, + first_music_session_at timestamp without time zone, + first_real_music_session_at timestamp without time zone, + first_good_music_session_at timestamp without time zone, + first_invited_at timestamp without time zone, + first_friended_at timestamp without time zone, + first_social_promoted_at timestamp without time zone, + show_whats_next boolean DEFAULT true, + biography text, + lat numeric(15,10), + lng numeric(15,10), + icecast_server_group_id character varying(64) DEFAULT 'default'::character varying NOT NULL, + first_recording_at timestamp without time zone, + large_photo_url character varying(2048), + cropped_large_s3_path character varying(512), + cropped_large_fpfile character varying(8000), + addr bigint DEFAULT 0 NOT NULL, + locidispid bigint DEFAULT 0 NOT NULL, + notification_seen_at timestamp without time zone, + affiliate_referral_id character varying(64), + mods json, + audio_latency double precision, + last_jam_addr bigint, + last_jam_locidispid bigint, + last_jam_updated_reason character(1), + last_jam_updated_at timestamp without time zone +); + + +SET search_path = pgmigrate, pg_catalog; + +-- +-- Name: id; Type: DEFAULT; Schema: pgmigrate; Owner: - +-- + +ALTER TABLE ONLY pg_migrate ALTER COLUMN id SET DEFAULT nextval('pg_migrate_id_seq'::regclass); + + +SET search_path = public, pg_catalog; + +-- +-- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY active_admin_comments ALTER COLUMN id SET DEFAULT nextval('active_admin_comments_id_seq'::regclass); + + +-- +-- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY feeds ALTER COLUMN id SET DEFAULT nextval('feeds_id_seq'::regclass); + + +-- +-- Name: coid; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY jamcompany ALTER COLUMN coid SET DEFAULT nextval('jamcompany_coid_seq'::regclass); + + +SET search_path = pgmigrate, pg_catalog; + +-- +-- Name: pg_migrate_pkey; Type: CONSTRAINT; Schema: pgmigrate; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY pg_migrate + ADD CONSTRAINT pg_migrate_pkey PRIMARY KEY (id); + + +-- +-- Name: pg_migrations_pkey; Type: CONSTRAINT; Schema: pgmigrate; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY pg_migrations + ADD CONSTRAINT pg_migrations_pkey PRIMARY KEY (name); + + +SET search_path = public, pg_catalog; + +-- +-- Name: admin_comments_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY active_admin_comments + ADD CONSTRAINT admin_comments_pkey PRIMARY KEY (id); + + +-- +-- Name: affiliate_partners_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY affiliate_partners + ADD CONSTRAINT affiliate_partners_pkey PRIMARY KEY (id); + + +-- +-- Name: artifact_updates_uniqkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY artifact_updates + ADD CONSTRAINT artifact_updates_uniqkey UNIQUE (product, version); + + +-- +-- Name: band_genre_uniqkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY bands_genres + ADD CONSTRAINT band_genre_uniqkey UNIQUE (band_id, genre_id); + + +-- +-- Name: band_invitations_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY band_invitations + ADD CONSTRAINT band_invitations_pkey PRIMARY KEY (id); + + +-- +-- Name: band_musician_uniqkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY bands_musicians + ADD CONSTRAINT band_musician_uniqkey UNIQUE (band_id, user_id); + + +-- +-- Name: bands_genres_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY bands_genres + ADD CONSTRAINT bands_genres_pkey PRIMARY KEY (id); + + +-- +-- Name: bands_musicians_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY bands_musicians + ADD CONSTRAINT bands_musicians_pkey PRIMARY KEY (id); + + +-- +-- Name: bands_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY bands + ADD CONSTRAINT bands_pkey PRIMARY KEY (id); + + +-- +-- Name: claimed_recordings_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY claimed_recordings + ADD CONSTRAINT claimed_recordings_pkey PRIMARY KEY (id); + + +-- +-- Name: connections_client_id_key; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY connections + ADD CONSTRAINT connections_client_id_key UNIQUE (client_id); + + +-- +-- Name: connections_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY connections + ADD CONSTRAINT connections_pkey PRIMARY KEY (id); + + +-- +-- Name: crash_dumps_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY crash_dumps + ADD CONSTRAINT crash_dumps_pkey PRIMARY KEY (id); + + +-- +-- Name: email_batch_set_uniqkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY email_batch_sets + ADD CONSTRAINT email_batch_set_uniqkey UNIQUE (email_batch_id, started_at); + + +-- +-- Name: email_batch_sets_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY email_batch_sets + ADD CONSTRAINT email_batch_sets_pkey PRIMARY KEY (id); + + +-- +-- Name: email_batches_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY email_batches + ADD CONSTRAINT email_batches_pkey PRIMARY KEY (id); + + +-- +-- Name: email_errors_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY email_errors + ADD CONSTRAINT email_errors_pkey PRIMARY KEY (id); + + +-- +-- Name: event_sessions_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY event_sessions + ADD CONSTRAINT event_sessions_pkey PRIMARY KEY (id); + + +-- +-- Name: events_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY events + ADD CONSTRAINT events_pkey PRIMARY KEY (id); + + +-- +-- Name: events_slug_key; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY events + ADD CONSTRAINT events_slug_key UNIQUE (slug); + + +-- +-- Name: facebook_signups_lookup_id_key; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY facebook_signups + ADD CONSTRAINT facebook_signups_lookup_id_key UNIQUE (lookup_id); + + +-- +-- Name: facebook_signups_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY facebook_signups + ADD CONSTRAINT facebook_signups_pkey PRIMARY KEY (id); + + +-- +-- Name: fan_invitations_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY fan_invitations + ADD CONSTRAINT fan_invitations_pkey PRIMARY KEY (id); + + +-- +-- Name: feeds_music_session_id_key; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY feeds + ADD CONSTRAINT feeds_music_session_id_key UNIQUE (music_session_id); + + +-- +-- Name: feeds_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY feeds + ADD CONSTRAINT feeds_pkey PRIMARY KEY (id); + + +-- +-- Name: feeds_recording_id_key; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY feeds + ADD CONSTRAINT feeds_recording_id_key UNIQUE (recording_id); + + +-- +-- Name: follows_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY follows + ADD CONSTRAINT follows_pkey PRIMARY KEY (id); + + +-- +-- Name: follows_user_uniqkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY follows + ADD CONSTRAINT follows_user_uniqkey UNIQUE (user_id, followable_id); + + +-- +-- Name: friend_requests_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY friend_requests + ADD CONSTRAINT friend_requests_pkey PRIMARY KEY (id); + + +-- +-- Name: friendships_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY friendships + ADD CONSTRAINT friendships_pkey PRIMARY KEY (id); + + +-- +-- Name: genres_music_sessions_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY genres_music_sessions + ADD CONSTRAINT genres_music_sessions_pkey PRIMARY KEY (id); + + +-- +-- Name: genres_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY genres + ADD CONSTRAINT genres_pkey PRIMARY KEY (id); + + +-- +-- Name: geoiplocations_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY geoiplocations + ADD CONSTRAINT geoiplocations_pkey PRIMARY KEY (locid); + + +-- +-- Name: icecast_admin_authentications_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY icecast_admin_authentications + ADD CONSTRAINT icecast_admin_authentications_pkey PRIMARY KEY (id); + + +-- +-- Name: icecast_directories_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY icecast_directories + ADD CONSTRAINT icecast_directories_pkey PRIMARY KEY (id); + + +-- +-- Name: icecast_limits_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY icecast_limits + ADD CONSTRAINT icecast_limits_pkey PRIMARY KEY (id); + + +-- +-- Name: icecast_listen_sockets_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY icecast_listen_sockets + ADD CONSTRAINT icecast_listen_sockets_pkey PRIMARY KEY (id); + + +-- +-- Name: icecast_loggings_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY icecast_loggings + ADD CONSTRAINT icecast_loggings_pkey PRIMARY KEY (id); + + +-- +-- Name: icecast_master_server_relays_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY icecast_master_server_relays + ADD CONSTRAINT icecast_master_server_relays_pkey PRIMARY KEY (id); + + +-- +-- Name: icecast_mount_templates_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY icecast_mount_templates + ADD CONSTRAINT icecast_mount_templates_pkey PRIMARY KEY (id); + + +-- +-- Name: icecast_mounts_name_key; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY icecast_mounts + ADD CONSTRAINT icecast_mounts_name_key UNIQUE (name); + + +-- +-- Name: icecast_mounts_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY icecast_mounts + ADD CONSTRAINT icecast_mounts_pkey PRIMARY KEY (id); + + +-- +-- Name: icecast_paths_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY icecast_paths + ADD CONSTRAINT icecast_paths_pkey PRIMARY KEY (id); + + +-- +-- Name: icecast_relays_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY icecast_relays + ADD CONSTRAINT icecast_relays_pkey PRIMARY KEY (id); + + +-- +-- Name: icecast_securities_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY icecast_securities + ADD CONSTRAINT icecast_securities_pkey PRIMARY KEY (id); + + +-- +-- Name: icecast_server_groups_name_key; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY icecast_server_groups + ADD CONSTRAINT icecast_server_groups_name_key UNIQUE (name); + + +-- +-- Name: icecast_server_groups_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY icecast_server_groups + ADD CONSTRAINT icecast_server_groups_pkey PRIMARY KEY (id); + + +-- +-- Name: icecast_server_mounts_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY icecast_server_mounts + ADD CONSTRAINT icecast_server_mounts_pkey PRIMARY KEY (id); + + +-- +-- Name: icecast_server_relays_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY icecast_server_relays + ADD CONSTRAINT icecast_server_relays_pkey PRIMARY KEY (id); + + +-- +-- Name: icecast_server_sockets_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY icecast_server_sockets + ADD CONSTRAINT icecast_server_sockets_pkey PRIMARY KEY (id); + + +-- +-- Name: icecast_servers_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY icecast_servers + ADD CONSTRAINT icecast_servers_pkey PRIMARY KEY (id); + + +-- +-- Name: icecast_servers_server_id_key; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY icecast_servers + ADD CONSTRAINT icecast_servers_server_id_key UNIQUE (server_id); + + +-- +-- Name: icecast_template_sockets_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY icecast_template_sockets + ADD CONSTRAINT icecast_template_sockets_pkey PRIMARY KEY (id); + + +-- +-- Name: icecast_templates_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY icecast_templates + ADD CONSTRAINT icecast_templates_pkey PRIMARY KEY (id); + + +-- +-- Name: icecast_user_authentications_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY icecast_user_authentications + ADD CONSTRAINT icecast_user_authentications_pkey PRIMARY KEY (id); + + +-- +-- Name: instruments_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY instruments + ADD CONSTRAINT instruments_pkey PRIMARY KEY (id); + + +-- +-- Name: invitations_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY invitations + ADD CONSTRAINT invitations_pkey PRIMARY KEY (id); + + +-- +-- Name: invitations_uniqkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY invitations + ADD CONSTRAINT invitations_uniqkey UNIQUE (sender_id, receiver_id, music_session_id); + + +-- +-- Name: invited_users_invitation_code_key; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY invited_users + ADD CONSTRAINT invited_users_invitation_code_key UNIQUE (invitation_code); + + +-- +-- Name: invited_users_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY invited_users + ADD CONSTRAINT invited_users_pkey PRIMARY KEY (id); + + +-- +-- Name: isp_score_batch_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY isp_score_batch + ADD CONSTRAINT isp_score_batch_pkey PRIMARY KEY (id); + + +-- +-- Name: jamcompany_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY jamcompany + ADD CONSTRAINT jamcompany_pkey PRIMARY KEY (coid); + + +-- +-- Name: join_requests_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY join_requests + ADD CONSTRAINT join_requests_pkey PRIMARY KEY (id); + + +-- +-- Name: likes_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY likes + ADD CONSTRAINT likes_pkey PRIMARY KEY (id); + + +-- +-- Name: likes_user_uniqkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY likes + ADD CONSTRAINT likes_user_uniqkey UNIQUE (user_id, likable_id); + + +-- +-- Name: mixes_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY mixes + ADD CONSTRAINT mixes_pkey PRIMARY KEY (id); + + +-- +-- Name: music_session_perf_data_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY music_session_perf_data + ADD CONSTRAINT music_session_perf_data_pkey PRIMARY KEY (id); + + +-- +-- Name: music_session_uniqkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY music_sessions + ADD CONSTRAINT music_session_uniqkey UNIQUE (music_session_id); + + +-- +-- Name: music_sessions_comments_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY music_sessions_comments + ADD CONSTRAINT music_sessions_comments_pkey PRIMARY KEY (id); + + +-- +-- Name: music_sessions_history_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY music_sessions + ADD CONSTRAINT music_sessions_history_pkey PRIMARY KEY (id); + + +-- +-- Name: music_sessions_likers_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY music_sessions_likers + ADD CONSTRAINT music_sessions_likers_pkey PRIMARY KEY (id); + + +-- +-- Name: music_sessions_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY active_music_sessions + ADD CONSTRAINT music_sessions_pkey PRIMARY KEY (id); + + +-- +-- Name: musician_instrument_uniqkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY musicians_instruments + ADD CONSTRAINT musician_instrument_uniqkey UNIQUE (user_id, instrument_id); + + +-- +-- Name: musician_recording_uniqkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY claimed_recordings + ADD CONSTRAINT musician_recording_uniqkey UNIQUE (user_id, recording_id); + + +-- +-- Name: musicians_instruments_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY musicians_instruments + ADD CONSTRAINT musicians_instruments_pkey PRIMARY KEY (id); + + +-- +-- Name: notifications_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY notifications + ADD CONSTRAINT notifications_pkey PRIMARY KEY (id); + + +-- +-- Name: playable_plays_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY playable_plays + ADD CONSTRAINT playable_plays_pkey PRIMARY KEY (id); + + +-- +-- Name: promotionals_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY promotionals + ADD CONSTRAINT promotionals_pkey PRIMARY KEY (id); + + +-- +-- Name: recording_liker_uniqkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY recordings_likers + ADD CONSTRAINT recording_liker_uniqkey UNIQUE (recording_id, liker_id); + + +-- +-- Name: recordings_comments_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY recordings_comments + ADD CONSTRAINT recordings_comments_pkey PRIMARY KEY (id); + + +-- +-- Name: recordings_downloads_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY recordings_downloads + ADD CONSTRAINT recordings_downloads_pkey PRIMARY KEY (id); + + +-- +-- Name: recordings_likers_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY recordings_likers + ADD CONSTRAINT recordings_likers_pkey PRIMARY KEY (id); + + +-- +-- Name: recordings_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY recordings + ADD CONSTRAINT recordings_pkey PRIMARY KEY (id); + + +-- +-- Name: recurring_sessions_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY recurring_sessions + ADD CONSTRAINT recurring_sessions_pkey PRIMARY KEY (id); + + +-- +-- Name: rsvp_requests_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY rsvp_requests + ADD CONSTRAINT rsvp_requests_pkey PRIMARY KEY (id); + + +-- +-- Name: rsvp_slots_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY rsvp_slots + ADD CONSTRAINT rsvp_slots_pkey PRIMARY KEY (id); + + +-- +-- Name: saved_tracks_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY recorded_tracks + ADD CONSTRAINT saved_tracks_pkey PRIMARY KEY (id); + + +-- +-- Name: server_mount_uniqkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY icecast_server_mounts + ADD CONSTRAINT server_mount_uniqkey UNIQUE (icecast_mount_id, icecast_server_id); + + +-- +-- Name: server_relay_uniqkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY icecast_server_relays + ADD CONSTRAINT server_relay_uniqkey UNIQUE (icecast_relay_id, icecast_server_id); + + +-- +-- Name: server_socket_uniqkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY icecast_server_sockets + ADD CONSTRAINT server_socket_uniqkey UNIQUE (icecast_listen_socket_id, icecast_server_id); + + +-- +-- Name: share_tokens_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY share_tokens + ADD CONSTRAINT share_tokens_pkey PRIMARY KEY (id); + + +-- +-- Name: template_socket_uniqkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY icecast_template_sockets + ADD CONSTRAINT template_socket_uniqkey UNIQUE (icecast_listen_socket_id, icecast_template_id); + + +-- +-- Name: token_uniqkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY share_tokens + ADD CONSTRAINT token_uniqkey UNIQUE (token); + + +-- +-- Name: tracks_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY tracks + ADD CONSTRAINT tracks_pkey PRIMARY KEY (id); + + +-- +-- Name: user_authorizations_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY user_authorizations + ADD CONSTRAINT user_authorizations_pkey PRIMARY KEY (id); + + +-- +-- Name: user_authorizations_uniqkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY user_authorizations + ADD CONSTRAINT user_authorizations_uniqkey UNIQUE (provider, uid); + + +-- +-- Name: user_friend_uniqkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY friendships + ADD CONSTRAINT user_friend_uniqkey UNIQUE (user_id, friend_id); + + +-- +-- Name: user_music_session_uniqkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY join_requests + ADD CONSTRAINT user_music_session_uniqkey UNIQUE (user_id, music_session_id); + + +-- +-- Name: users_email_key; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY users + ADD CONSTRAINT users_email_key UNIQUE (email); + + +-- +-- Name: users_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY users + ADD CONSTRAINT users_pkey PRIMARY KEY (id); + + +-- +-- Name: users_remember_token_key; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY users + ADD CONSTRAINT users_remember_token_key UNIQUE (remember_token); + + +-- +-- Name: users_signup_token_key; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY users + ADD CONSTRAINT users_signup_token_key UNIQUE (signup_token); + + +-- +-- Name: users_update_email_token_key; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY users + ADD CONSTRAINT users_update_email_token_key UNIQUE (update_email_token); + + +SET search_path = pgmigrate, pg_catalog; + +-- +-- Name: pg_migrate_unique_index; Type: INDEX; Schema: pgmigrate; Owner: -; Tablespace: +-- + +CREATE INDEX pg_migrate_unique_index ON pg_migrate USING btree (template_version, builder_version, migrator_version, database_version); + + +SET search_path = public, pg_catalog; + +-- +-- Name: affiliate_partners_code_idx; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX affiliate_partners_code_idx ON affiliate_partners USING btree (partner_code); + + +-- +-- Name: affiliate_partners_user_idx; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX affiliate_partners_user_idx ON affiliate_partners USING btree (partner_user_id); + + +-- +-- Name: bands_name_tsv_index; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX bands_name_tsv_index ON bands USING gin (name_tsv); + + +-- +-- Name: claimed_recordings_description_tsv_index; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX claimed_recordings_description_tsv_index ON claimed_recordings USING gin (description_tsv); + + +-- +-- Name: claimed_recordings_name_tsv_index; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX claimed_recordings_name_tsv_index ON claimed_recordings USING gin (name_tsv); + + +-- +-- Name: connections_locidispid_ndx; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX connections_locidispid_ndx ON connections USING btree (locidispid); + + +-- +-- Name: crash_dumps_client_id_idx; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX crash_dumps_client_id_idx ON crash_dumps USING btree (client_id); + + +-- +-- Name: crash_dumps_timestamp_idx; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX crash_dumps_timestamp_idx ON crash_dumps USING btree ("timestamp"); + + +-- +-- Name: crash_dumps_user_id_idx; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX crash_dumps_user_id_idx ON crash_dumps USING btree (user_id); + + +-- +-- Name: diagnostics_type_idx; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX diagnostics_type_idx ON diagnostics USING btree (type); + + +-- +-- Name: email_batch_set_fkidx; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX email_batch_set_fkidx ON email_batch_sets USING btree (email_batch_id); + + +-- +-- Name: email_batch_sets_progress_idx; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX email_batch_sets_progress_idx ON email_batch_sets USING btree (user_id, sub_type); + + +-- +-- Name: email_error_address_idx; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX email_error_address_idx ON email_errors USING btree (email_address); + + +-- +-- Name: email_error_user_fkidx; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX email_error_user_fkidx ON email_errors USING btree (user_id); + + +-- +-- Name: geoipblocks_geom_gix; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX geoipblocks_geom_gix ON geoipblocks USING gist (geom); + + +-- +-- Name: geoipisp_company_ndx; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX geoipisp_company_ndx ON geoipisp USING btree (company); + + +-- +-- Name: geoiplocations_geog_gix; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX geoiplocations_geog_gix ON geoiplocations USING gist (geog); + + +-- +-- Name: index_active_admin_comments_on_author_type_and_author_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_active_admin_comments_on_author_type_and_author_id ON active_admin_comments USING btree (author_type, author_id); + + +-- +-- Name: index_active_admin_comments_on_namespace; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_active_admin_comments_on_namespace ON active_admin_comments USING btree (namespace); + + +-- +-- Name: index_admin_comments_on_resource_type_and_resource_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_admin_comments_on_resource_type_and_resource_id ON active_admin_comments USING btree (resource_type, resource_id); + + +-- +-- Name: index_completed_at; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_completed_at ON mixes USING btree (completed_at); + + +-- +-- Name: index_started_at; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_started_at ON mixes USING btree (started_at); + + +-- +-- Name: jamcompany_company_ndx; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE UNIQUE INDEX jamcompany_company_ndx ON jamcompany USING btree (company); + + +-- +-- Name: jamisp_coid_ndx; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX jamisp_coid_ndx ON jamisp USING btree (coid); + + +-- +-- Name: jamisp_geom_gix; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX jamisp_geom_gix ON jamisp USING gist (geom); + + +-- +-- Name: max_mind_isp_ip_bottom_idx; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX max_mind_isp_ip_bottom_idx ON max_mind_isp USING btree (ip_bottom); + + +-- +-- Name: max_mind_isp_ip_top_idx; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX max_mind_isp_ip_top_idx ON max_mind_isp USING btree (ip_top); + + +-- +-- Name: promo_latest_idx; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX promo_latest_idx ON promotionals USING btree (latest_id, latest_type); + + +-- +-- Name: remember_token_idx; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX remember_token_idx ON users USING btree (remember_token); + + +-- +-- Name: scores_alocidispid_blocidispid_score_dt_ndx; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX scores_alocidispid_blocidispid_score_dt_ndx ON scores USING btree (alocidispid, blocidispid, score_dt); + + +-- +-- Name: scores_blocidispid_alocidispid_score_dt_ndx; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX scores_blocidispid_alocidispid_score_dt_ndx ON scores USING btree (blocidispid, alocidispid, score_dt); + + +-- +-- Name: user_authorizations_user_id_idx; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX user_authorizations_user_id_idx ON user_authorizations USING btree (user_id); + + +-- +-- Name: users_musician_email_idx; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX users_musician_email_idx ON users USING btree (subscribe_email, musician); + + +-- +-- Name: users_name_tsv_index; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX users_name_tsv_index ON users USING gin (name_tsv); + + +-- +-- Name: tsvectorupdate; Type: TRIGGER; Schema: public; Owner: - +-- + +CREATE TRIGGER tsvectorupdate BEFORE INSERT OR UPDATE ON users FOR EACH ROW EXECUTE PROCEDURE tsvector_update_trigger('name_tsv', 'public.jamenglish', 'first_name', 'last_name'); + + +-- +-- Name: tsvectorupdate; Type: TRIGGER; Schema: public; Owner: - +-- + +CREATE TRIGGER tsvectorupdate BEFORE INSERT OR UPDATE ON bands FOR EACH ROW EXECUTE PROCEDURE tsvector_update_trigger('name_tsv', 'public.jamenglish', 'name'); + + +-- +-- Name: tsvectorupdate_description; Type: TRIGGER; Schema: public; Owner: - +-- + +CREATE TRIGGER tsvectorupdate_description BEFORE INSERT OR UPDATE ON claimed_recordings FOR EACH ROW EXECUTE PROCEDURE tsvector_update_trigger('description_tsv', 'public.jamenglish', 'description'); + + +-- +-- Name: tsvectorupdate_name; Type: TRIGGER; Schema: public; Owner: - +-- + +CREATE TRIGGER tsvectorupdate_name BEFORE INSERT OR UPDATE ON claimed_recordings FOR EACH ROW EXECUTE PROCEDURE tsvector_update_trigger('name_tsv', 'public.jamenglish', 'name'); + + +SET search_path = pgmigrate, pg_catalog; + +-- +-- Name: pg_migrations_pg_migrate_id_fkey; Type: FK CONSTRAINT; Schema: pgmigrate; Owner: - +-- + +ALTER TABLE ONLY pg_migrations + ADD CONSTRAINT pg_migrations_pg_migrate_id_fkey FOREIGN KEY (pg_migrate_id) REFERENCES pg_migrate(id); + + +SET search_path = public, pg_catalog; + +-- +-- Name: band_invitations_band_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY band_invitations + ADD CONSTRAINT band_invitations_band_id_fkey FOREIGN KEY (band_id) REFERENCES bands(id) ON DELETE CASCADE; + + +-- +-- Name: band_invitations_creator_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY band_invitations + ADD CONSTRAINT band_invitations_creator_id_fkey FOREIGN KEY (creator_id) REFERENCES users(id) ON DELETE CASCADE; + + +-- +-- Name: band_invitations_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY band_invitations + ADD CONSTRAINT band_invitations_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE; + + +-- +-- Name: bands_genres_band_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY bands_genres + ADD CONSTRAINT bands_genres_band_id_fkey FOREIGN KEY (band_id) REFERENCES bands(id) ON DELETE CASCADE; + + +-- +-- Name: bands_genres_genre_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY bands_genres + ADD CONSTRAINT bands_genres_genre_id_fkey FOREIGN KEY (genre_id) REFERENCES genres(id) ON DELETE CASCADE; + + +-- +-- Name: bands_musicians_band_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY bands_musicians + ADD CONSTRAINT bands_musicians_band_id_fkey FOREIGN KEY (band_id) REFERENCES bands(id) ON DELETE CASCADE; + + +-- +-- Name: bands_musicians_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY bands_musicians + ADD CONSTRAINT bands_musicians_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE; + + +-- +-- Name: chat_messages_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY chat_messages + ADD CONSTRAINT chat_messages_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE; + + +-- +-- Name: claimed_recordings_genre_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY claimed_recordings + ADD CONSTRAINT claimed_recordings_genre_id_fkey FOREIGN KEY (genre_id) REFERENCES genres(id); + + +-- +-- Name: connections_music_session_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY connections + ADD CONSTRAINT connections_music_session_id_fkey FOREIGN KEY (music_session_id) REFERENCES active_music_sessions(id) ON DELETE SET NULL; + + +-- +-- Name: connections_tracks_connection_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY tracks + ADD CONSTRAINT connections_tracks_connection_id_fkey FOREIGN KEY (connection_id) REFERENCES connections(id) ON DELETE CASCADE; + + +-- +-- Name: crash_dumps_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY crash_dumps + ADD CONSTRAINT crash_dumps_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL; + + +-- +-- Name: diagnostics_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY diagnostics + ADD CONSTRAINT diagnostics_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE; + + +-- +-- Name: email_batch_sets_email_batch_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY email_batch_sets + ADD CONSTRAINT email_batch_sets_email_batch_id_fkey FOREIGN KEY (email_batch_id) REFERENCES email_batches(id) ON DELETE CASCADE; + + +-- +-- Name: email_errors_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY email_errors + ADD CONSTRAINT email_errors_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE; + + +-- +-- Name: event_sessions_band_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY event_sessions + ADD CONSTRAINT event_sessions_band_id_fkey FOREIGN KEY (band_id) REFERENCES bands(id) ON DELETE SET NULL; + + +-- +-- Name: event_sessions_event_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY event_sessions + ADD CONSTRAINT event_sessions_event_id_fkey FOREIGN KEY (event_id) REFERENCES events(id) ON DELETE CASCADE; + + +-- +-- Name: event_sessions_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY event_sessions + ADD CONSTRAINT event_sessions_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL; + + +-- +-- Name: fan_invitations_music_session_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY fan_invitations + ADD CONSTRAINT fan_invitations_music_session_id_fkey FOREIGN KEY (music_session_id) REFERENCES music_sessions(id) ON DELETE CASCADE; + + +-- +-- Name: feeds_music_session_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY feeds + ADD CONSTRAINT feeds_music_session_id_fkey FOREIGN KEY (music_session_id) REFERENCES music_sessions(id) ON DELETE CASCADE; + + +-- +-- Name: feeds_recording_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY feeds + ADD CONSTRAINT feeds_recording_id_fkey FOREIGN KEY (recording_id) REFERENCES recordings(id) ON DELETE CASCADE; + + +-- +-- Name: follows_user_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY follows + ADD CONSTRAINT follows_user_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE; + + +-- +-- Name: friend_requests_friend_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY friend_requests + ADD CONSTRAINT friend_requests_friend_id_fkey FOREIGN KEY (friend_id) REFERENCES users(id) ON DELETE CASCADE; + + +-- +-- Name: friend_requests_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY friend_requests + ADD CONSTRAINT friend_requests_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE; + + +-- +-- Name: friendships_friend_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY friendships + ADD CONSTRAINT friendships_friend_id_fkey FOREIGN KEY (friend_id) REFERENCES users(id) ON DELETE CASCADE; + + +-- +-- Name: friendships_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY friendships + ADD CONSTRAINT friendships_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE; + + +-- +-- Name: genres_music_sessions_music_session_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY genres_music_sessions + ADD CONSTRAINT genres_music_sessions_music_session_id_fkey FOREIGN KEY (music_session_id) REFERENCES active_music_sessions(id) ON DELETE CASCADE; + + +-- +-- Name: icecast_mounts_icecast_mount_template_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY icecast_mounts + ADD CONSTRAINT icecast_mounts_icecast_mount_template_id_fkey FOREIGN KEY (icecast_mount_template_id) REFERENCES icecast_mount_templates(id) ON DELETE SET NULL; + + +-- +-- Name: icecast_mounts_icecast_server_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY icecast_mounts + ADD CONSTRAINT icecast_mounts_icecast_server_id_fkey FOREIGN KEY (icecast_server_id) REFERENCES icecast_servers(id) ON DELETE SET NULL; + + +-- +-- Name: icecast_mounts_music_session_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY icecast_mounts + ADD CONSTRAINT icecast_mounts_music_session_id_fkey FOREIGN KEY (music_session_id) REFERENCES active_music_sessions(id) ON DELETE CASCADE; + + +-- +-- Name: icecast_server_mounts_icecast_server_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY icecast_server_mounts + ADD CONSTRAINT icecast_server_mounts_icecast_server_id_fkey FOREIGN KEY (icecast_server_id) REFERENCES icecast_servers(id) ON DELETE CASCADE; + + +-- +-- Name: icecast_server_relays_icecast_relay_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY icecast_server_relays + ADD CONSTRAINT icecast_server_relays_icecast_relay_id_fkey FOREIGN KEY (icecast_relay_id) REFERENCES icecast_relays(id) ON DELETE CASCADE; + + +-- +-- Name: icecast_server_relays_icecast_server_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY icecast_server_relays + ADD CONSTRAINT icecast_server_relays_icecast_server_id_fkey FOREIGN KEY (icecast_server_id) REFERENCES icecast_servers(id) ON DELETE CASCADE; + + +-- +-- Name: icecast_server_sockets_icecast_listen_socket_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY icecast_server_sockets + ADD CONSTRAINT icecast_server_sockets_icecast_listen_socket_id_fkey FOREIGN KEY (icecast_listen_socket_id) REFERENCES icecast_listen_sockets(id) ON DELETE CASCADE; + + +-- +-- Name: icecast_server_sockets_icecast_server_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY icecast_server_sockets + ADD CONSTRAINT icecast_server_sockets_icecast_server_id_fkey FOREIGN KEY (icecast_server_id) REFERENCES icecast_servers(id) ON DELETE CASCADE; + + +-- +-- Name: icecast_servers_admin_auth_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY icecast_servers + ADD CONSTRAINT icecast_servers_admin_auth_id_fkey FOREIGN KEY (admin_auth_id) REFERENCES icecast_admin_authentications(id) ON DELETE SET NULL; + + +-- +-- Name: icecast_servers_directory_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY icecast_servers + ADD CONSTRAINT icecast_servers_directory_id_fkey FOREIGN KEY (directory_id) REFERENCES icecast_directories(id) ON DELETE SET NULL; + + +-- +-- Name: icecast_servers_icecast_server_group_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY icecast_servers + ADD CONSTRAINT icecast_servers_icecast_server_group_id_fkey FOREIGN KEY (icecast_server_group_id) REFERENCES icecast_server_groups(id) ON DELETE SET NULL; + + +-- +-- Name: icecast_servers_limit_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY icecast_servers + ADD CONSTRAINT icecast_servers_limit_id_fkey FOREIGN KEY (limit_id) REFERENCES icecast_limits(id) ON DELETE SET NULL; + + +-- +-- Name: icecast_servers_logging_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY icecast_servers + ADD CONSTRAINT icecast_servers_logging_id_fkey FOREIGN KEY (logging_id) REFERENCES icecast_loggings(id) ON DELETE SET NULL; + + +-- +-- Name: icecast_servers_master_relay_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY icecast_servers + ADD CONSTRAINT icecast_servers_master_relay_id_fkey FOREIGN KEY (master_relay_id) REFERENCES icecast_master_server_relays(id) ON DELETE SET NULL; + + +-- +-- Name: icecast_servers_mount_template_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY icecast_servers + ADD CONSTRAINT icecast_servers_mount_template_id_fkey FOREIGN KEY (mount_template_id) REFERENCES icecast_mount_templates(id) ON DELETE SET NULL; + + +-- +-- Name: icecast_servers_path_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY icecast_servers + ADD CONSTRAINT icecast_servers_path_id_fkey FOREIGN KEY (path_id) REFERENCES icecast_paths(id) ON DELETE SET NULL; + + +-- +-- Name: icecast_servers_security_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY icecast_servers + ADD CONSTRAINT icecast_servers_security_id_fkey FOREIGN KEY (security_id) REFERENCES icecast_securities(id) ON DELETE SET NULL; + + +-- +-- Name: icecast_servers_template_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY icecast_servers + ADD CONSTRAINT icecast_servers_template_id_fkey FOREIGN KEY (template_id) REFERENCES icecast_templates(id) ON DELETE SET NULL; + + +-- +-- Name: icecast_template_sockets_icecast_listen_socket_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY icecast_template_sockets + ADD CONSTRAINT icecast_template_sockets_icecast_listen_socket_id_fkey FOREIGN KEY (icecast_listen_socket_id) REFERENCES icecast_listen_sockets(id) ON DELETE CASCADE; + + +-- +-- Name: icecast_template_sockets_icecast_template_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY icecast_template_sockets + ADD CONSTRAINT icecast_template_sockets_icecast_template_id_fkey FOREIGN KEY (icecast_template_id) REFERENCES icecast_templates(id) ON DELETE CASCADE; + + +-- +-- Name: icecast_templates_admin_auth_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY icecast_templates + ADD CONSTRAINT icecast_templates_admin_auth_id_fkey FOREIGN KEY (admin_auth_id) REFERENCES icecast_admin_authentications(id) ON DELETE SET NULL; + + +-- +-- Name: icecast_templates_directory_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY icecast_templates + ADD CONSTRAINT icecast_templates_directory_id_fkey FOREIGN KEY (directory_id) REFERENCES icecast_directories(id) ON DELETE SET NULL; + + +-- +-- Name: icecast_templates_limit_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY icecast_templates + ADD CONSTRAINT icecast_templates_limit_id_fkey FOREIGN KEY (limit_id) REFERENCES icecast_limits(id) ON DELETE SET NULL; + + +-- +-- Name: icecast_templates_logging_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY icecast_templates + ADD CONSTRAINT icecast_templates_logging_id_fkey FOREIGN KEY (logging_id) REFERENCES icecast_loggings(id) ON DELETE SET NULL; + + +-- +-- Name: icecast_templates_master_relay_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY icecast_templates + ADD CONSTRAINT icecast_templates_master_relay_id_fkey FOREIGN KEY (master_relay_id) REFERENCES icecast_master_server_relays(id) ON DELETE SET NULL; + + +-- +-- Name: icecast_templates_path_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY icecast_templates + ADD CONSTRAINT icecast_templates_path_id_fkey FOREIGN KEY (path_id) REFERENCES icecast_paths(id) ON DELETE SET NULL; + + +-- +-- Name: icecast_templates_security_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY icecast_templates + ADD CONSTRAINT icecast_templates_security_id_fkey FOREIGN KEY (security_id) REFERENCES icecast_securities(id) ON DELETE SET NULL; + + +-- +-- Name: invitations_join_request_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY invitations + ADD CONSTRAINT invitations_join_request_id_fkey FOREIGN KEY (join_request_id) REFERENCES join_requests(id) ON DELETE CASCADE; + + +-- +-- Name: invitations_music_session_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY invitations + ADD CONSTRAINT invitations_music_session_id_fkey FOREIGN KEY (music_session_id) REFERENCES music_sessions(id) ON DELETE CASCADE; + + +-- +-- Name: invited_users_sender_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY invited_users + ADD CONSTRAINT invited_users_sender_id_fkey FOREIGN KEY (sender_id) REFERENCES users(id) ON DELETE CASCADE; + + +-- +-- Name: join_requests_music_session_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY join_requests + ADD CONSTRAINT join_requests_music_session_id_fkey FOREIGN KEY (music_session_id) REFERENCES music_sessions(id) ON DELETE CASCADE; + + +-- +-- Name: likes_user_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY likes + ADD CONSTRAINT likes_user_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE; + + +-- +-- Name: mixes_recording_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY mixes + ADD CONSTRAINT mixes_recording_id_fkey FOREIGN KEY (recording_id) REFERENCES recordings(id) ON DELETE CASCADE; + + +-- +-- Name: music_sessions_comments_creator_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY music_sessions_comments + ADD CONSTRAINT music_sessions_comments_creator_id_fkey FOREIGN KEY (creator_id) REFERENCES users(id) ON DELETE CASCADE; + + +-- +-- Name: music_sessions_comments_music_session_id2_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY music_sessions_comments + ADD CONSTRAINT music_sessions_comments_music_session_id2_fkey FOREIGN KEY (music_session_id) REFERENCES music_sessions(id) ON DELETE CASCADE; + + +-- +-- Name: music_sessions_history_band_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY music_sessions + ADD CONSTRAINT music_sessions_history_band_id_fkey FOREIGN KEY (band_id) REFERENCES bands(id) ON DELETE CASCADE; + + +-- +-- Name: music_sessions_history_genre_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY music_sessions + ADD CONSTRAINT music_sessions_history_genre_id_fkey FOREIGN KEY (genre_id) REFERENCES genres(id); + + +-- +-- Name: music_sessions_history_recurring_session_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY music_sessions + ADD CONSTRAINT music_sessions_history_recurring_session_id_fkey FOREIGN KEY (recurring_session_id) REFERENCES recurring_sessions(id); + + +-- +-- Name: music_sessions_history_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY music_sessions + ADD CONSTRAINT music_sessions_history_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE; + + +-- +-- Name: music_sessions_likers_liker_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY music_sessions_likers + ADD CONSTRAINT music_sessions_likers_liker_id_fkey FOREIGN KEY (liker_id) REFERENCES users(id) ON DELETE CASCADE; + + +-- +-- Name: music_sessions_likers_music_session_id2_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY music_sessions_likers + ADD CONSTRAINT music_sessions_likers_music_session_id2_fkey FOREIGN KEY (music_session_id) REFERENCES music_sessions(id) ON DELETE CASCADE; + + +-- +-- Name: music_sessions_user_history_music_session_id2_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY music_sessions_user_history + ADD CONSTRAINT music_sessions_user_history_music_session_id2_fkey FOREIGN KEY (music_session_id) REFERENCES music_sessions(id) ON DELETE CASCADE; + + +-- +-- Name: music_sessions_user_history_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY music_sessions_user_history + ADD CONSTRAINT music_sessions_user_history_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE; + + +-- +-- Name: musicians_instruments_instrument_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY musicians_instruments + ADD CONSTRAINT musicians_instruments_instrument_id_fkey FOREIGN KEY (instrument_id) REFERENCES instruments(id) ON DELETE CASCADE; + + +-- +-- Name: musicians_instruments_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY musicians_instruments + ADD CONSTRAINT musicians_instruments_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE; + + +-- +-- Name: musicians_recordings_recording_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY claimed_recordings + ADD CONSTRAINT musicians_recordings_recording_id_fkey FOREIGN KEY (recording_id) REFERENCES recordings(id) ON DELETE CASCADE; + + +-- +-- Name: musicians_recordings_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY claimed_recordings + ADD CONSTRAINT musicians_recordings_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE; + + +-- +-- Name: notifications_band_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY notifications + ADD CONSTRAINT notifications_band_id_fkey FOREIGN KEY (band_id) REFERENCES bands(id) ON DELETE CASCADE; + + +-- +-- Name: notifications_band_invitation_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY notifications + ADD CONSTRAINT notifications_band_invitation_id_fkey FOREIGN KEY (band_invitation_id) REFERENCES band_invitations(id) ON DELETE CASCADE; + + +-- +-- Name: notifications_friend_request_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY notifications + ADD CONSTRAINT notifications_friend_request_id_fkey FOREIGN KEY (friend_request_id) REFERENCES friend_requests(id); + + +-- +-- Name: notifications_recording_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY notifications + ADD CONSTRAINT notifications_recording_id_fkey FOREIGN KEY (recording_id) REFERENCES recordings(id) ON DELETE CASCADE; + + +-- +-- Name: notifications_source_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY notifications + ADD CONSTRAINT notifications_source_user_id_fkey FOREIGN KEY (source_user_id) REFERENCES users(id) ON DELETE CASCADE; + + +-- +-- Name: notifications_target_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY notifications + ADD CONSTRAINT notifications_target_user_id_fkey FOREIGN KEY (target_user_id) REFERENCES users(id) ON DELETE CASCADE; + + +-- +-- Name: playable_plays_claimed_recording_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY playable_plays + ADD CONSTRAINT playable_plays_claimed_recording_id_fkey FOREIGN KEY (claimed_recording_id) REFERENCES claimed_recordings(id) ON DELETE CASCADE; + + +-- +-- Name: playable_plays_player_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY playable_plays + ADD CONSTRAINT playable_plays_player_id_fkey FOREIGN KEY (player_id) REFERENCES users(id) ON DELETE CASCADE; + + +-- +-- Name: recorded_tracks_recording_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY recorded_tracks + ADD CONSTRAINT recorded_tracks_recording_id_fkey FOREIGN KEY (recording_id) REFERENCES recordings(id) ON DELETE CASCADE; + + +-- +-- Name: recordings_band_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY recordings + ADD CONSTRAINT recordings_band_id_fkey FOREIGN KEY (band_id) REFERENCES bands(id); + + +-- +-- Name: recordings_comments_creator_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY recordings_comments + ADD CONSTRAINT recordings_comments_creator_id_fkey FOREIGN KEY (creator_id) REFERENCES users(id) ON DELETE CASCADE; + + +-- +-- Name: recordings_comments_recording_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY recordings_comments + ADD CONSTRAINT recordings_comments_recording_id_fkey FOREIGN KEY (recording_id) REFERENCES recordings(id) ON DELETE CASCADE; + + +-- +-- Name: recordings_creator_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY recordings + ADD CONSTRAINT recordings_creator_id_fkey FOREIGN KEY (owner_id) REFERENCES users(id) ON DELETE CASCADE; + + +-- +-- Name: recordings_downloads_downloader_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY recordings_downloads + ADD CONSTRAINT recordings_downloads_downloader_id_fkey FOREIGN KEY (downloader_id) REFERENCES users(id) ON DELETE CASCADE; + + +-- +-- Name: recordings_downloads_recording_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY recordings_downloads + ADD CONSTRAINT recordings_downloads_recording_id_fkey FOREIGN KEY (recording_id) REFERENCES recordings(id) ON DELETE CASCADE; + + +-- +-- Name: recordings_likers_claimed_recording_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY recordings_likers + ADD CONSTRAINT recordings_likers_claimed_recording_id_fkey FOREIGN KEY (claimed_recording_id) REFERENCES claimed_recordings(id); + + +-- +-- Name: recordings_likers_liker_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY recordings_likers + ADD CONSTRAINT recordings_likers_liker_id_fkey FOREIGN KEY (liker_id) REFERENCES users(id) ON DELETE CASCADE; + + +-- +-- Name: recordings_likers_recording_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY recordings_likers + ADD CONSTRAINT recordings_likers_recording_id_fkey FOREIGN KEY (recording_id) REFERENCES recordings(id) ON DELETE CASCADE; + + +-- +-- Name: recurring_sessions_band_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY recurring_sessions + ADD CONSTRAINT recurring_sessions_band_id_fkey FOREIGN KEY (band_id) REFERENCES bands(id) ON DELETE CASCADE; + + +-- +-- Name: recurring_sessions_genre_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY recurring_sessions + ADD CONSTRAINT recurring_sessions_genre_id_fkey FOREIGN KEY (genre_id) REFERENCES genres(id); + + +-- +-- Name: recurring_sessions_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY recurring_sessions + ADD CONSTRAINT recurring_sessions_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE; + + +-- +-- Name: rsvp_requests_rsvp_slot_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY rsvp_requests + ADD CONSTRAINT rsvp_requests_rsvp_slot_id_fkey FOREIGN KEY (rsvp_slot_id) REFERENCES rsvp_slots(id) ON DELETE CASCADE; + + +-- +-- Name: rsvp_requests_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY rsvp_requests + ADD CONSTRAINT rsvp_requests_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE; + + +-- +-- Name: rsvp_slots_instrument_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY rsvp_slots + ADD CONSTRAINT rsvp_slots_instrument_id_fkey FOREIGN KEY (instrument_id) REFERENCES instruments(id); + + +-- +-- Name: rsvp_slots_music_session_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY rsvp_slots + ADD CONSTRAINT rsvp_slots_music_session_id_fkey FOREIGN KEY (music_session_id) REFERENCES music_sessions(id) ON DELETE CASCADE; + + +-- +-- Name: saved_tracks_instrument_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY recorded_tracks + ADD CONSTRAINT saved_tracks_instrument_id_fkey FOREIGN KEY (instrument_id) REFERENCES instruments(id) ON DELETE CASCADE; + + +-- +-- Name: saved_tracks_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY recorded_tracks + ADD CONSTRAINT saved_tracks_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE; + + +-- +-- Name: user_authorizations_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY user_authorizations + ADD CONSTRAINT user_authorizations_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE; + + +-- +-- Name: users_affiliate_referral_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY users + ADD CONSTRAINT users_affiliate_referral_id_fkey FOREIGN KEY (affiliate_referral_id) REFERENCES affiliate_partners(id); + + +-- +-- Name: users_icecast_server_group_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY users + ADD CONSTRAINT users_icecast_server_group_id_fkey FOREIGN KEY (icecast_server_group_id) REFERENCES icecast_server_groups(id); + + +-- +-- PostgreSQL database dump complete +-- + +SET search_path TO "$user", public, topology; + diff --git a/web/lib/tasks/email.rake b/web/lib/tasks/email.rake new file mode 100644 index 000000000..0d2a77977 --- /dev/null +++ b/web/lib/tasks/email.rake @@ -0,0 +1,13 @@ +namespace :emails do + + task :test_progression_email => :environment do |task, args| + user = User.find_by_email('jonathan@jamkazam.com') + EmailBatchProgression::SUBTYPES.each do |stype| + ebatch = EmailBatchProgression.create + ebatch.update_attribute(:sub_type, stype) + ebatch.email_batch_sets << (bset = ebatch.make_set(user, 0)) + ProgressMailer.send_reminder(bset).deliver + end + end + +end diff --git a/web/lib/tasks/google.rake b/web/lib/tasks/google.rake new file mode 100644 index 000000000..c3ef000eb --- /dev/null +++ b/web/lib/tasks/google.rake @@ -0,0 +1,13 @@ +=begin +require 'google/api_client' + +namespace :google do + + task :youtube do |task, args| + client = Google::APIClient.new + yt = client.discovered_api('youtube', 'v3') + # google-api oauth-2-login --client-id='785931784279-gd0g8on6sc0tuesj7cu763pitaiv2la8.apps.googleusercontent.com' --client-secret='UwzIcvtErv9c2-GIsNfIo7bA' --scope="https://www.googleapis.com/auth/plus.me" + end + +end +=end \ No newline at end of file diff --git a/web/lib/tasks/sample_data.rake b/web/lib/tasks/sample_data.rake index c19d46dea..e996d06c4 100644 --- a/web/lib/tasks/sample_data.rake +++ b/web/lib/tasks/sample_data.rake @@ -85,6 +85,17 @@ namespace :db do make_music_sessions_history make_music_sessions_user_history end + + task affiliate_traffic_earnings: :environment do + partner = FactoryGirl.create(:affiliate_partner) + user_partner = FactoryGirl.create(:user, affiliate_partner: partner) + + puts "USER CREATED: u: #{user_partner.email}/p: foobar" + + today = Date.today + quarter1 = FactoryGirl.create(:affiliate_quarterly_payment, affiliate_partner: partner, due_amount_in_cents: 10000, closed:true) + month1 = FactoryGirl.create(:affiliate_monthly_payment, affiliate_partner: partner, due_amount_in_cents: 10000, closed:true) + end end def make_music_sessions_history diff --git a/web/lib/user_manager.rb b/web/lib/user_manager.rb index 0ce291b60..8f231a57b 100644 --- a/web/lib/user_manager.rb +++ b/web/lib/user_manager.rb @@ -28,6 +28,7 @@ class UserManager < BaseManager affiliate_referral_id = options[:affiliate_referral_id] any_user = options[:any_user] signup_hint = options[:signup_hint] + affiliate_partner = options[:affiliate_partner] recaptcha_failed = false unless options[:skip_recaptcha] # allow callers to opt-of recaptcha @@ -70,7 +71,8 @@ class UserManager < BaseManager signup_confirm_url: signup_confirm_url, affiliate_referral_id: affiliate_referral_id, any_user: any_user, - signup_hint: signup_hint) + signup_hint: signup_hint, + affiliate_partner: affiliate_partner) user end diff --git a/web/loop.bash b/web/loop.bash new file mode 100755 index 000000000..1c38b6d12 --- /dev/null +++ b/web/loop.bash @@ -0,0 +1,7 @@ +#!/bin/bash + +for i in {1..100} +do + echo "Loop $i "`date` + bundle exec rspec spec/features/music_sessions_spec.rb +done \ No newline at end of file diff --git a/web/ruby-bt.txt b/web/ruby-bt.txt new file mode 100644 index 000000000..e5351db3a --- /dev/null +++ b/web/ruby-bt.txt @@ -0,0 +1,919 @@ +$ bundle exec rake routes +/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json/common.rb:67: [BUG] Segmentation fault +ruby 2.0.0p247 (2013-06-27 revision 41674) [x86_64-linux] + +-- Control frame information ----------------------------------------------- +c:0056 p:---- s:0192 e:000191 CFUNC :initialize +c:0055 p:---- s:0190 e:000189 CFUNC :new +c:0054 p:0075 s:0187 e:000184 METHOD /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json/common.rb:67 +c:0053 p:0070 s:0176 e:000174 CLASS /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json/ext.rb:17 +c:0052 p:0011 s:0173 e:000172 CLASS /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json/ext.rb:12 +c:0051 p:0057 s:0171 e:000170 TOP /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json/ext.rb:9 [FINISH] +c:0050 p:---- s:0169 e:000168 CFUNC :require +c:0049 p:0010 s:0165 e:000164 BLOCK /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:251 +c:0048 p:0054 s:0163 e:000162 METHOD /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:236 +c:0047 p:0015 s:0158 e:000157 METHOD /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:251 +c:0046 p:0019 s:0153 e:000152 CLASS /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json.rb:58 +c:0045 p:0017 s:0151 e:000150 TOP /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json.rb:54 [FINISH] +c:0044 p:---- s:0149 e:000148 CFUNC :require +c:0043 p:0010 s:0145 e:000144 BLOCK /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:251 +c:0042 p:0054 s:0143 e:000142 METHOD /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:236 +c:0041 p:0015 s:0138 e:000137 METHOD /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:251 +c:0040 p:0009 s:0133 e:000132 TOP /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/object/to_json.rb:3 [FINISH] +c:0039 p:---- s:0131 e:000130 CFUNC :require +c:0038 p:0010 s:0127 e:000126 BLOCK /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:251 +c:0037 p:0054 s:0125 e:000124 METHOD /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:236 +c:0036 p:0015 s:0120 e:000119 METHOD /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:251 +c:0035 p:0007 s:0115 e:000114 TOP /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/json/encoding.rb:1 [FINISH] +c:0034 p:---- s:0113 e:000112 CFUNC :require +c:0033 p:0010 s:0109 e:000108 BLOCK /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:251 +c:0032 p:0054 s:0107 e:000106 METHOD /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:236 +c:0031 p:0015 s:0102 e:000101 METHOD /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:251 +c:0030 p:0015 s:0097 e:000096 TOP /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/json.rb:2 [FINISH] +c:0029 p:---- s:0095 e:000094 CFUNC :require +c:0028 p:0010 s:0091 e:000090 BLOCK /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:251 +c:0027 p:0054 s:0089 e:000088 METHOD /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:236 +c:0026 p:0015 s:0084 e:000083 METHOD /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:251 +c:0025 p:0007 s:0079 e:000078 TOP /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/serializers/json.rb:1 [FINISH] +c:0024 p:0029 s:0077 e:000075 CLASS /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/serialization.rb:5 +c:0023 p:0011 s:0074 e:000073 CLASS /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/serialization.rb:3 +c:0022 p:0009 s:0072 e:000071 TOP /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/serialization.rb:1 [FINISH] +c:0021 p:0770 s:0070 e:000065 CLASS /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/base.rb:715 +c:0020 p:0011 s:0064 e:000063 CLASS /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/base.rb:333 +c:0019 p:0228 s:0062 e:000061 TOP /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/base.rb:33 [FINISH] +c:0018 p:0068 s:0060 e:000059 TOP /home/jam/workspace/jam-cloud/web/config/application.rb:13 [FINISH] +c:0017 p:---- s:0058 e:000057 CFUNC :require +c:0016 p:0018 s:0054 e:000053 TOP /home/jam/workspace/jam-cloud/web/Rakefile:5 [FINISH] +c:0015 p:---- s:0052 e:000051 CFUNC :load +c:0014 p:0009 s:0048 e:000047 METHOD /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/rake_module.rb:25 +c:0013 p:0176 s:0044 e:000043 METHOD /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/application.rb:637 +c:0012 p:0007 s:0039 e:000038 BLOCK /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/application.rb:94 +c:0011 p:0006 s:0037 e:000036 METHOD /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/application.rb:165 +c:0010 p:0007 s:0033 e:000032 METHOD /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/application.rb:93 +c:0009 p:0013 s:0030 e:000029 BLOCK /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/application.rb:77 +c:0008 p:0006 s:0028 e:000027 METHOD /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/application.rb:165 +c:0007 p:0007 s:0024 e:000023 METHOD /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/application.rb:75 +c:0006 p:0040 s:0021 e:000020 TOP /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/bin/rake:33 [FINISH] +c:0005 p:---- s:0019 e:000018 CFUNC :load +c:0004 p:0118 s:0015 E:000da8 EVAL /home/jam/.rvm/gems/ruby-2.0.0-p247@global/bin/rake:23 [FINISH] +c:0003 p:---- s:0011 e:000010 CFUNC :eval +c:0002 p:0118 s:0005 E:001d40 EVAL /home/jam/.rvm/gems/ruby-2.0.0-p247@global/bin/ruby_executable_hooks:15 [FINISH] +c:0001 p:0000 s:0002 E:000338 TOP [FINISH] + +/home/jam/.rvm/gems/ruby-2.0.0-p247@global/bin/ruby_executable_hooks:15:in `
' +/home/jam/.rvm/gems/ruby-2.0.0-p247@global/bin/ruby_executable_hooks:15:in `eval' +/home/jam/.rvm/gems/ruby-2.0.0-p247@global/bin/rake:23:in `
' +/home/jam/.rvm/gems/ruby-2.0.0-p247@global/bin/rake:23:in `load' +/home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/bin/rake:33:in `' +/home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/application.rb:75:in `run' +/home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/application.rb:165:in `standard_exception_handling' +/home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/application.rb:77:in `block in run' +/home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/application.rb:93:in `load_rakefile' +/home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/application.rb:165:in `standard_exception_handling' +/home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/application.rb:94:in `block in load_rakefile' +/home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/application.rb:637:in `raw_load_rakefile' +/home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/rake_module.rb:25:in `load_rakefile' +/home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/rake_module.rb:25:in `load' +/home/jam/workspace/jam-cloud/web/Rakefile:5:in `' +/home/jam/workspace/jam-cloud/web/Rakefile:5:in `require' +/home/jam/workspace/jam-cloud/web/config/application.rb:13:in `' +/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/base.rb:33:in `' +/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/base.rb:333:in `' +/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/base.rb:715:in `' +/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/serialization.rb:1:in `' +/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/serialization.rb:3:in `' +/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/serialization.rb:5:in `' +/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/serializers/json.rb:1:in `' +/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:251:in `require' +/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:236:in `load_dependency' +/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:251:in `block in require' +/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:251:in `require' +/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/json.rb:2:in `' +/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:251:in `require' +/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:236:in `load_dependency' +/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:251:in `block in require' +/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:251:in `require' +/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/json/encoding.rb:1:in `' +/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:251:in `require' +/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:236:in `load_dependency' +/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:251:in `block in require' +/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:251:in `require' +/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/object/to_json.rb:3:in `' +/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:251:in `require' +/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:236:in `load_dependency' +/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:251:in `block in require' +/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:251:in `require' +/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json.rb:54:in `' +/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json.rb:58:in `' +/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:251:in `require' +/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:236:in `load_dependency' +/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:251:in `block in require' +/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:251:in `require' +/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json/ext.rb:9:in `' +/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json/ext.rb:12:in `' +/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json/ext.rb:17:in `' +/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json/common.rb:67:in `generator=' +/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json/common.rb:67:in `new' +/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json/common.rb:67:in `initialize' + +-- C level backtrace information ------------------------------------------- +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x19d7f5) [0x7fd2a8a937f5] vm_dump.c:647 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x64dbc) [0x7fd2a895adbc] error.c:283 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_bug+0xb7) [0x7fd2a895c2c7] error.c:302 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x129cee) [0x7fd2a8a1fcee] signal.c:672 +/lib/x86_64-linux-gnu/libc.so.6(+0x364a0) [0x7fd2a856d4a0] +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_hash_aref+0x11) [0x7fd2a897ce31] hash.c:561 +/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json/ext/generator.so(+0x3294) [0x7fd2a3f99294] generator.c:528 +/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json/ext/generator.so(+0x4d9f) [0x7fd2a3f9ad9f] generator.c:954 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x193440) [0x7fd2a8a89440] vm_eval.c:117 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x1939e3) [0x7fd2a8a899e3] vm_eval.c:49 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_class_new_instance+0x30) [0x7fd2a89b5ae0] object.c:1761 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x187c06) [0x7fd2a8a7dc06] vm_insnhelper.c:1469 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x1965ff) [0x7fd2a8a8c5ff] vm_insnhelper.c:1559 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x18c2d2) [0x7fd2a8a822d2] insns.def:1017 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x192036) [0x7fd2a8a88036] vm.c:1201 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_iseq_eval+0x176) [0x7fd2a8a8e8f6] vm.c:1436 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x6f784) [0x7fd2a8965784] load.c:599 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_require_safe+0x4ff) [0x7fd2a896757f] load.c:959 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x187c06) [0x7fd2a8a7dc06] vm_insnhelper.c:1469 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x1965ff) [0x7fd2a8a8c5ff] vm_insnhelper.c:1559 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x18c45d) [0x7fd2a8a8245d] insns.def:1039 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x192036) [0x7fd2a8a88036] vm.c:1201 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_iseq_eval+0x176) [0x7fd2a8a8e8f6] vm.c:1436 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x6f784) [0x7fd2a8965784] load.c:599 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_require_safe+0x4ff) [0x7fd2a896757f] load.c:959 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x187c06) [0x7fd2a8a7dc06] vm_insnhelper.c:1469 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x1965ff) [0x7fd2a8a8c5ff] vm_insnhelper.c:1559 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x18c45d) [0x7fd2a8a8245d] insns.def:1039 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x192036) [0x7fd2a8a88036] vm.c:1201 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_iseq_eval+0x176) [0x7fd2a8a8e8f6] vm.c:1436 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x6f784) [0x7fd2a8965784] load.c:599 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_require_safe+0x4ff) [0x7fd2a896757f] load.c:959 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x187c06) [0x7fd2a8a7dc06] vm_insnhelper.c:1469 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x1965ff) [0x7fd2a8a8c5ff] vm_insnhelper.c:1559 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x18c45d) [0x7fd2a8a8245d] insns.def:1039 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x192036) [0x7fd2a8a88036] vm.c:1201 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_iseq_eval+0x176) [0x7fd2a8a8e8f6] vm.c:1436 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x6f784) [0x7fd2a8965784] load.c:599 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_require_safe+0x4ff) [0x7fd2a896757f] load.c:959 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x187c06) [0x7fd2a8a7dc06] vm_insnhelper.c:1469 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x1965ff) [0x7fd2a8a8c5ff] vm_insnhelper.c:1559 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x18c45d) [0x7fd2a8a8245d] insns.def:1039 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x192036) [0x7fd2a8a88036] vm.c:1201 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_iseq_eval+0x176) [0x7fd2a8a8e8f6] vm.c:1436 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x6f784) [0x7fd2a8965784] load.c:599 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_require_safe+0x4ff) [0x7fd2a896757f] load.c:959 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x187c06) [0x7fd2a8a7dc06] vm_insnhelper.c:1469 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x1965ff) [0x7fd2a8a8c5ff] vm_insnhelper.c:1559 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x18c45d) [0x7fd2a8a8245d] insns.def:1039 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x192036) [0x7fd2a8a88036] vm.c:1201 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_iseq_eval+0x176) [0x7fd2a8a8e8f6] vm.c:1436 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x6f784) [0x7fd2a8965784] load.c:599 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_require_safe+0x4ff) [0x7fd2a896757f] load.c:959 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_protect+0xd7) [0x7fd2a8963307] eval.c:786 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_autoload_load+0x10c) [0x7fd2a8a614fc] variable.c:1781 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x16b687) [0x7fd2a8a61687] variable.c:1841 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x189e48) [0x7fd2a8a7fe48] vm_insnhelper.c:450 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x192036) [0x7fd2a8a88036] vm.c:1201 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_iseq_eval+0x176) [0x7fd2a8a8e8f6] vm.c:1436 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x6f784) [0x7fd2a8965784] load.c:599 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_require_safe+0x4ff) [0x7fd2a896757f] load.c:959 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_protect+0xd7) [0x7fd2a8963307] eval.c:786 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_autoload_load+0x10c) [0x7fd2a8a614fc] variable.c:1781 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x18784f) [0x7fd2a8a7d84f] vm_insnhelper.c:414 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x18d92f) [0x7fd2a8a8392f] vm_insnhelper.c:383 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x192036) [0x7fd2a8a88036] vm.c:1201 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_iseq_eval+0x176) [0x7fd2a8a8e8f6] vm.c:1436 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x6f784) [0x7fd2a8965784] load.c:599 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_require_safe+0x4ff) [0x7fd2a896757f] load.c:959 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_protect+0xd7) [0x7fd2a8963307] eval.c:786 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_autoload_load+0x10c) [0x7fd2a8a614fc] variable.c:1781 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x16b687) [0x7fd2a8a61687] variable.c:1841 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x189e48) [0x7fd2a8a7fe48] vm_insnhelper.c:450 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x192036) [0x7fd2a8a88036] vm.c:1201 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_iseq_eval+0x176) [0x7fd2a8a8e8f6] vm.c:1436 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x6f784) [0x7fd2a8965784] load.c:599 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_require_safe+0x4ff) [0x7fd2a896757f] load.c:959 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x187c06) [0x7fd2a8a7dc06] vm_insnhelper.c:1469 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x1965ff) [0x7fd2a8a8c5ff] vm_insnhelper.c:1559 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x18c2d2) [0x7fd2a8a822d2] insns.def:1017 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x192036) [0x7fd2a8a88036] vm.c:1201 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_iseq_eval+0x176) [0x7fd2a8a8e8f6] vm.c:1436 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x6f784) [0x7fd2a8965784] load.c:599 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x6f8e8) [0x7fd2a89658e8] load.c:680 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x187c06) [0x7fd2a8a7dc06] vm_insnhelper.c:1469 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x1965ff) [0x7fd2a8a8c5ff] vm_insnhelper.c:1559 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x18c2d2) [0x7fd2a8a822d2] insns.def:1017 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x192036) [0x7fd2a8a88036] vm.c:1201 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_iseq_eval+0x176) [0x7fd2a8a8e8f6] vm.c:1436 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x6f784) [0x7fd2a8965784] load.c:599 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x6f8e8) [0x7fd2a89658e8] load.c:680 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x187c06) [0x7fd2a8a7dc06] vm_insnhelper.c:1469 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x1965ff) [0x7fd2a8a8c5ff] vm_insnhelper.c:1559 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x18c2d2) [0x7fd2a8a822d2] insns.def:1017 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x192036) [0x7fd2a8a88036] vm.c:1201 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x19259c) [0x7fd2a8a8859c] vm_eval.c:1251 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x192a1f) [0x7fd2a8a88a1f] vm_eval.c:1292 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x187c06) [0x7fd2a8a7dc06] vm_insnhelper.c:1469 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x1965ff) [0x7fd2a8a8c5ff] vm_insnhelper.c:1559 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x18c2d2) [0x7fd2a8a822d2] insns.def:1017 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x192036) [0x7fd2a8a88036] vm.c:1201 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_iseq_eval_main+0x8a) [0x7fd2a8a8e9da] vm.c:1449 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x6b8c2) [0x7fd2a89618c2] eval.c:250 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(ruby_exec_node+0x1d) [0x7fd2a8962bad] eval.c:315 +/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(ruby_run_node+0x1e) [0x7fd2a8964dae] eval.c:307 +/home/jam/.rvm/gems/ruby-2.0.0-p247@global/bin/rake() [0x40080b] +/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed) [0x7fd2a855876d] +/home/jam/.rvm/gems/ruby-2.0.0-p247@global/bin/rake() [0x400839] + +-- Other runtime information ----------------------------------------------- + +* Loaded script: /home/jam/.rvm/gems/ruby-2.0.0-p247@global/bin/rake + +* Loaded features: + + 0 enumerator.so + 1 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/encdb.so + 2 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/trans/transdb.so + 3 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/rbconfig.rb + 4 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/compatibility.rb + 5 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/defaults.rb + 6 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/deprecate.rb + 7 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/errors.rb + 8 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/version.rb + 9 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/requirement.rb + 10 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/platform.rb + 11 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/specification.rb + 12 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/exceptions.rb + 13 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/core_ext/kernel_gem.rb + 14 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/core_ext/kernel_require.rb + 15 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems.rb + 16 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/pathname.so + 17 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/pathname.rb + 18 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/user_interaction.rb + 19 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/etc.so + 20 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/config_file.rb + 21 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/rubygems_integration.rb + 22 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/dependency.rb + 23 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/shared_helpers.rb + 24 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/fileutils.rb + 25 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/gem_path_manipulation.rb + 26 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/gem_helpers.rb + 27 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/match_platform.rb + 28 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/rubygems_ext.rb + 29 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/version.rb + 30 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler.rb + 31 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/settings.rb + 32 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/path_support.rb + 33 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/digest.so + 34 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/digest.rb + 35 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/digest/sha1.so + 36 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/set.rb + 37 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/definition.rb + 38 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/dependency.rb + 39 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/ruby_dsl.rb + 40 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/dsl.rb + 41 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/source.rb + 42 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/common.rb + 43 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb + 44 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/ftp.rb + 45 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/http.rb + 46 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/https.rb + 47 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/ldap.rb + 48 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/ldaps.rb + 49 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/mailto.rb + 50 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri.rb + 51 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/socket.so + 52 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/socket.rb + 53 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/fcntl.so + 54 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/timeout.rb + 55 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/thread.rb + 56 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/openssl.so + 57 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/openssl/bn.rb + 58 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/openssl/cipher.rb + 59 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/stringio.so + 60 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/openssl/config.rb + 61 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/openssl/digest.rb + 62 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/openssl/x509.rb + 63 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/openssl/buffering.rb + 64 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/openssl/ssl.rb + 65 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/openssl.rb + 66 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/securerandom.rb + 67 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/resolv.rb + 68 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/remote_fetcher.rb + 69 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/text.rb + 70 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/name_tuple.rb + 71 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/spec_fetcher.rb + 72 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/source/rubygems.rb + 73 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/source/path.rb + 74 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/strscan.so + 75 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/source/git.rb + 76 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/lockfile_parser.rb + 77 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/lazy_specification.rb + 78 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/tsort.rb + 79 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/forwardable.rb + 80 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/spec_set.rb + 81 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/index.rb + 82 /home/jam/workspace/jam-cloud/websocket-gateway/lib/jam_websockets/version.rb + 83 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/environment.rb + 84 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/runtime.rb + 85 /home/jam/workspace/jam-cloud/db/target/ruby_package/lib/jam_db/version.rb + 86 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/remote_specification.rb + 87 /home/jam/workspace/jam-cloud/ruby/lib/jam_ruby/version.rb + 88 /home/jam/workspace/jam-cloud/pb/target/ruby/jampb/lib/jampb/version.rb + 89 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/dep_proxy.rb + 90 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/resolver.rb + 91 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/ui.rb + 92 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/endpoint_specification.rb + 93 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/setup.rb + 94 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/version.rb + 95 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/singleton.rb + 96 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/monitor.rb + 97 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/optparse.rb + 98 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/ostruct.rb + 99 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/ext/module.rb + 100 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/ext/core.rb + 101 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/ext/string.rb + 102 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/early_time.rb + 103 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/ext/time.rb + 104 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/alt_system.rb + 105 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/win32.rb + 106 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/linked_list.rb + 107 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/scope.rb + 108 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/task_argument_error.rb + 109 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/rule_recursion_overflow_error.rb + 110 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/shellwords.rb + 111 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/task_manager.rb + 112 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/cloneable.rb + 113 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/file_utils.rb + 114 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/file_utils_ext.rb + 115 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/pathmap.rb + 116 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/file_list.rb + 117 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/promise.rb + 118 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/thread_pool.rb + 119 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/private_reader.rb + 120 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/thread_history_display.rb + 121 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/trace_output.rb + 122 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/application.rb + 123 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/rake_module.rb + 124 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/pseudo_status.rb + 125 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/task_arguments.rb + 126 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/invocation_chain.rb + 127 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/invocation_exception_mixin.rb + 128 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/task.rb + 129 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/file_task.rb + 130 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/file_creation_task.rb + 131 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/multi_task.rb + 132 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/dsl_definition.rb + 133 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/default_loader.rb + 134 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/name_space.rb + 135 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/backtrace.rb + 136 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake.rb + 137 /home/jam/workspace/jam-cloud/web/config/boot.rb + 138 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/inflector/inflections.rb + 139 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/inflections.rb + 140 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/inflector/methods.rb + 141 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/lazy_load_hooks.rb + 142 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies/autoload.rb + 143 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/version.rb + 144 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support.rb + 145 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/i18n-0.6.5/lib/i18n/version.rb + 146 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/i18n-0.6.5/lib/i18n/exceptions.rb + 147 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/i18n-0.6.5/lib/i18n/interpolate/ruby.rb + 148 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/i18n-0.6.5/lib/i18n.rb + 149 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/i18n-0.6.5/lib/i18n/config.rb + 150 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/i18n.rb + 151 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/version.rb + 152 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model.rb + 153 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/crud.rb + 154 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/factory_methods.rb + 155 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/expressions.rb + 156 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/predications.rb + 157 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/math.rb + 158 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/alias_predication.rb + 159 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/order_predications.rb + 160 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/table.rb + 161 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/attributes/attribute.rb + 162 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/attributes.rb + 163 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/compatibility/wheres.rb + 164 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/relation.rb + 165 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/expression.rb + 166 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/visitors/visitor.rb + 167 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/visitors/depth_first.rb + 168 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/bigdecimal.so + 169 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/date_core.so + 170 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/date/format.rb + 171 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/date.rb + 172 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/visitors/to_sql.rb + 173 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/visitors/sqlite.rb + 174 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/visitors/postgresql.rb + 175 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/visitors/mysql.rb + 176 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/visitors/mssql.rb + 177 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/visitors/oracle.rb + 178 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/visitors/join_sql.rb + 179 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/visitors/where_sql.rb + 180 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/visitors/order_clauses.rb + 181 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/visitors/dot.rb + 182 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/visitors/ibm_db.rb + 183 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/visitors/informix.rb + 184 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/visitors.rb + 185 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/tree_manager.rb + 186 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/insert_manager.rb + 187 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/select_manager.rb + 188 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/update_manager.rb + 189 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/delete_manager.rb + 190 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/node.rb + 191 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/select_statement.rb + 192 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/select_core.rb + 193 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/insert_statement.rb + 194 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/update_statement.rb + 195 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/terminal.rb + 196 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/true.rb + 197 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/false.rb + 198 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/unary.rb + 199 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/ascending.rb + 200 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/descending.rb + 201 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/unqualified_column.rb + 202 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/with.rb + 203 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/binary.rb + 204 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/equality.rb + 205 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/in.rb + 206 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/join_source.rb + 207 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/delete_statement.rb + 208 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/table_alias.rb + 209 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/infix_operation.rb + 210 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/and.rb + 211 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/function.rb + 212 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/count.rb + 213 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/values.rb + 214 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/named_function.rb + 215 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/inner_join.rb + 216 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/outer_join.rb + 217 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/string_join.rb + 218 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/sql_literal.rb + 219 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes.rb + 220 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/deprecated.rb + 221 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/sql/engine.rb + 222 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/sql_literal.rb + 223 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel.rb + 224 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/version.rb + 225 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/syntax_error.rb + 226 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/psych.so + 227 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/nodes/node.rb + 228 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/nodes/stream.rb + 229 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/nodes/document.rb + 230 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/nodes/sequence.rb + 231 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/nodes/scalar.rb + 232 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/nodes/mapping.rb + 233 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/nodes/alias.rb + 234 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/nodes.rb + 235 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/streaming.rb + 236 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/visitors/visitor.rb + 237 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/scalar_scanner.rb + 238 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/visitors/to_ruby.rb + 239 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/visitors/emitter.rb + 240 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/visitors/yaml_tree.rb + 241 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/json/ruby_events.rb + 242 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/visitors/json_tree.rb + 243 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/visitors/depth_first.rb + 244 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/visitors.rb + 245 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/handler.rb + 246 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/tree_builder.rb + 247 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/parser.rb + 248 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/omap.rb + 249 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/set.rb + 250 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/coder.rb + 251 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/core_ext.rb + 252 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/deprecated.rb + 253 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/stream.rb + 254 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/json/yaml_events.rb + 255 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/json/tree_builder.rb + 256 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/json/stream.rb + 257 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/handlers/document_stream.rb + 258 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych.rb + 259 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/yaml.rb + 260 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/ordered_hash.rb + 261 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/enumerable.rb + 262 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/notifications/fanout.rb + 263 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/notifications.rb + 264 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/array/wrap.rb + 265 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/deprecation/behaviors.rb + 266 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/deprecation/reporting.rb + 267 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/module/deprecation.rb + 268 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/module/aliasing.rb + 269 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/array/extract_options.rb + 270 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/deprecation/method_wrappers.rb + 271 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/deprecation/proxy_wrappers.rb + 272 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/deprecation.rb + 273 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/concern.rb + 274 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/hash/keys.rb + 275 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/kernel/singleton_class.rb + 276 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/module/remove_method.rb + 277 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/class/attribute.rb + 278 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/attribute_methods.rb + 279 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/attribute_methods.rb + 280 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/bigdecimal/util.rb + 281 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/benchmark.rb + 282 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/benchmark.rb + 283 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/connection_adapters/schema_cache.rb + 284 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/big_decimal/conversions.rb + 285 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/connection_adapters/abstract/quoting.rb + 286 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/connection_adapters/abstract/database_statements.rb + 287 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/connection_adapters/abstract/schema_statements.rb + 288 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/connection_adapters/abstract/database_limits.rb + 289 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/connection_adapters/abstract/query_cache.rb + 290 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/descendants_tracker.rb + 291 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/kernel/reporting.rb + 292 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/object/inclusion.rb + 293 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/callbacks.rb + 294 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/connection_adapters/abstract_adapter.rb + 295 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/scoping.rb + 296 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record.rb + 297 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/railties-3.2.15/lib/rails/ruby_version_check.rb + 298 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/class/attribute_accessors.rb + 299 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/logger.rb + 300 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/logger.rb + 301 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/hash/reverse_merge.rb + 302 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/railties-3.2.15/lib/rails/initializable.rb + 303 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/ordered_options.rb + 304 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/hash/deep_dup.rb + 305 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/railties-3.2.15/lib/rails/paths.rb + 306 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/railties-3.2.15/lib/rails/rack.rb + 307 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/railties-3.2.15/lib/rails/configuration.rb + 308 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/module/attribute_accessors.rb + 309 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/multibyte/utils.rb + 310 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/multibyte.rb + 311 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/string/multibyte.rb + 312 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/inflector/transliterate.rb + 313 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/string/inflections.rb + 314 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/inflector.rb + 315 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/module/introspection.rb + 316 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/module/delegation.rb + 317 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/railties-3.2.15/lib/rails/railtie.rb + 318 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/railties-3.2.15/lib/rails/engine/railties.rb + 319 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/railties-3.2.15/lib/rails/engine.rb + 320 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/time.rb + 321 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/base64.rb + 322 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/base64.rb + 323 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/string/encoding.rb + 324 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/object/blank.rb + 325 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/xml_mini/rexml.rb + 326 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/xml_mini.rb + 327 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/array/conversions.rb + 328 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/railties-3.2.15/lib/rails/plugin.rb + 329 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/railties-3.2.15/lib/rails/application.rb + 330 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/railties-3.2.15/lib/rails/version.rb + 331 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/file_update_checker.rb + 332 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/railties-3.2.15/lib/rails/railtie/configurable.rb + 333 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/railties-3.2.15/lib/rails/railtie/configuration.rb + 334 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/i18n_railtie.rb + 335 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/railtie.rb + 336 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/actionpack-3.2.15/lib/action_pack/version.rb + 337 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/actionpack-3.2.15/lib/action_pack.rb + 338 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/rack-1.4.5/lib/rack.rb + 339 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/actionpack-3.2.15/lib/action_dispatch.rb + 340 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/actionpack-3.2.15/lib/action_dispatch/railtie.rb + 341 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/railties-3.2.15/lib/rails.rb + 342 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/railtie.rb + 343 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/basic_object.rb + 344 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/object/acts_like.rb + 345 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/duration.rb + 346 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/object/try.rb + 347 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/values/time_zone.rb + 348 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/time_with_zone.rb + 349 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/time/zones.rb + 350 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/date/zones.rb + 351 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/date/calculations.rb + 352 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/time/publicize_conversion_methods.rb + 353 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/time/conversions.rb + 354 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/date_time/calculations.rb + 355 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/date_time/conversions.rb + 356 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/process/daemon.rb + 357 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/time/calculations.rb + 358 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/string/conversions.rb + 359 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/i18n-0.6.5/lib/i18n/core_ext/string/interpolate.rb + 360 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/string/interpolation.rb + 361 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/rexml/rexml.rb + 362 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/rexml.rb + 363 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/file/path.rb + 364 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/module/method_names.rb + 365 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/ruby/shim.rb + 366 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/module/attr_internal.rb + 367 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/module/anonymous.rb + 368 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/actionpack-3.2.15/lib/abstract_controller.rb + 369 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/cgi/util.rb + 370 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/erb.rb + 371 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/string/output_safety.rb + 372 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/actionpack-3.2.15/lib/action_view.rb + 373 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/actionpack-3.2.15/lib/action_controller/vendor/html-scanner.rb + 374 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/load_error.rb + 375 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/name_error.rb + 376 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/uri.rb + 377 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/actionpack-3.2.15/lib/action_controller.rb + 378 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/actionpack-3.2.15/lib/action_view/railtie.rb + 379 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/actionpack-3.2.15/lib/abstract_controller/railties/routes_helpers.rb + 380 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/actionpack-3.2.15/lib/action_controller/railties/paths.rb + 381 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/actionpack-3.2.15/lib/action_controller/railtie.rb + 382 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/railtie.rb + 383 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/actionmailer-3.2.15/lib/action_mailer/version.rb + 384 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/class/delegating_attributes.rb + 385 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/module/reachable.rb + 386 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/class/subclasses.rb + 387 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/class.rb + 388 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/array/uniq_by.rb + 389 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/actionmailer-3.2.15/lib/action_mailer.rb + 390 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/actionmailer-3.2.15/lib/action_mailer/railtie.rb + 391 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activeresource-3.2.15/lib/active_resource/exceptions.rb + 392 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activeresource-3.2.15/lib/active_resource/version.rb + 393 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activeresource-3.2.15/lib/active_resource.rb + 394 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activeresource-3.2.15/lib/active_resource/railtie.rb + 395 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/actionpack-3.2.15/lib/sprockets/railtie.rb + 396 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/benchmarkable.rb + 397 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/module/qualified_const.rb + 398 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/string/starts_ends_with.rb + 399 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb + 400 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/time/marshal.rb + 401 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/time/acts_like.rb + 402 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/date/acts_like.rb + 403 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/date/freeze.rb + 404 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/date/conversions.rb + 405 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/date_time/acts_like.rb + 406 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/date_time/zones.rb + 407 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/integer/time.rb + 408 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/numeric/time.rb + 409 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/time.rb + 410 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/hash/deep_merge.rb + 411 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/hash_with_indifferent_access.rb + 412 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/hash/indifferent_access.rb + 413 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/hash/slice.rb + 414 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/string/behavior.rb + 415 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/object/duplicable.rb + 416 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/errors.rb + 417 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/log_subscriber.rb + 418 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/log_subscriber.rb + 419 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/explain_subscriber.rb + 420 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/persistence.rb + 421 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/hash/except.rb + 422 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/naming.rb + 423 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/query_cache.rb + 424 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/querying.rb + 425 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/readonly_attributes.rb + 426 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/model_schema.rb + 427 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/translation.rb + 428 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/translation.rb + 429 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/inheritance.rb + 430 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/scoping/default.rb + 431 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/array/access.rb + 432 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/array/grouping.rb + 433 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/array/random_access.rb + 434 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/array/prepend_and_append.rb + 435 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/array.rb + 436 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/scoping/named.rb + 437 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/dynamic_matchers.rb + 438 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/sanitization.rb + 439 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/mass_assignment_security/permission_set.rb + 440 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/mass_assignment_security/sanitizer.rb + 441 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/mass_assignment_security.rb + 442 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/attribute_assignment.rb + 443 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/conversion.rb + 444 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/integration.rb + 445 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/errors.rb + 446 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/validations/callbacks.rb + 447 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/validator.rb + 448 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/validations/acceptance.rb + 449 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/validations/confirmation.rb + 450 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/range/blockless_step.rb + 451 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/range/conversions.rb + 452 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/range/include_range.rb + 453 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/range/overlaps.rb + 454 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/range/cover.rb + 455 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/range.rb + 456 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/validations/exclusion.rb + 457 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/validations/format.rb + 458 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/validations/inclusion.rb + 459 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/validations/length.rb + 460 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/validations/numericality.rb + 461 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/validations/presence.rb + 462 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/validations/validates.rb + 463 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/validations/with.rb + 464 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/validations.rb + 465 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/validations/associated.rb + 466 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/validations/uniqueness.rb + 467 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/validations.rb + 468 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/counter_cache.rb + 469 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/locking/optimistic.rb + 470 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/locking/pessimistic.rb + 471 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/attribute_methods/read.rb + 472 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/attribute_methods/write.rb + 473 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/attribute_methods/before_type_cast.rb + 474 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/attribute_methods/query.rb + 475 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/attribute_methods/primary_key.rb + 476 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/attribute_methods/time_zone_conversion.rb + 477 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/dirty.rb + 478 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/attribute_methods/dirty.rb + 479 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/timestamp.rb + 480 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/attribute_methods/serialization.rb + 481 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/attribute_methods/deprecated_underscore_read.rb + 482 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/callbacks.rb + 483 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/observer_array.rb + 484 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/observing.rb + 485 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/callbacks.rb + 486 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/associations.rb + 487 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/identity_map.rb + 488 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/secure_password.rb + 489 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/explain.rb + 490 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/autosave_association.rb + 491 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/nested_attributes.rb + 492 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/associations/builder/association.rb + 493 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/associations/builder/singular_association.rb + 494 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/associations/builder/has_one.rb + 495 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/associations/builder/collection_association.rb + 496 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/associations/builder/has_many.rb + 497 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/associations/builder/belongs_to.rb + 498 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/associations/builder/has_and_belongs_to_many.rb + 499 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/aggregations.rb + 500 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/transactions.rb + 501 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/reflection.rb + 502 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/multi_json-1.8.2/lib/multi_json/options.rb + 503 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/multi_json-1.8.2/lib/multi_json/version.rb + 504 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/multi_json-1.8.2/lib/multi_json/load_error.rb + 505 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/multi_json-1.8.2/lib/multi_json.rb + 506 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/json/decoding.rb + 507 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json/version.rb + 508 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json/generic_object.rb + 509 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json/common.rb + 510 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/utf_16be.so + 511 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/utf_16le.so + 512 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/utf_32be.so + 513 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/utf_32le.so + 514 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json/ext/parser.so + 515 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json/ext/generator.so + +* Process memory map: + +00400000-00401000 r-xp 00000000 fc:00 2230335 /home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/ruby +00600000-00601000 r--p 00000000 fc:00 2230335 /home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/ruby +00601000-00602000 rw-p 00001000 fc:00 2230335 /home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/ruby +00cbb000-02b22000 rw-p 00000000 00:00 0 [heap] +7fd2a3d80000-7fd2a3d95000 r-xp 00000000 fc:00 1572908 /lib/x86_64-linux-gnu/libgcc_s.so.1 +7fd2a3d95000-7fd2a3f94000 ---p 00015000 fc:00 1572908 /lib/x86_64-linux-gnu/libgcc_s.so.1 +7fd2a3f94000-7fd2a3f95000 r--p 00014000 fc:00 1572908 /lib/x86_64-linux-gnu/libgcc_s.so.1 +7fd2a3f95000-7fd2a3f96000 rw-p 00015000 fc:00 1572908 /lib/x86_64-linux-gnu/libgcc_s.so.1 +7fd2a3f96000-7fd2a3f9e000 r-xp 00000000 fc:00 2493168 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json/ext/generator.so +7fd2a3f9e000-7fd2a419d000 ---p 00008000 fc:00 2493168 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json/ext/generator.so +7fd2a419d000-7fd2a419e000 r--p 00007000 fc:00 2493168 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json/ext/generator.so +7fd2a419e000-7fd2a419f000 rw-p 00008000 fc:00 2493168 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json/ext/generator.so +7fd2a419f000-7fd2a41a0000 r-xp 00000000 fc:00 2229480 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/utf_32le.so +7fd2a41a0000-7fd2a439f000 ---p 00001000 fc:00 2229480 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/utf_32le.so +7fd2a439f000-7fd2a43a0000 r--p 00000000 fc:00 2229480 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/utf_32le.so +7fd2a43a0000-7fd2a43a1000 rw-p 00001000 fc:00 2229480 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/utf_32le.so +7fd2a43a1000-7fd2a43a2000 r-xp 00000000 fc:00 2229448 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/utf_32be.so +7fd2a43a2000-7fd2a45a1000 ---p 00001000 fc:00 2229448 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/utf_32be.so +7fd2a45a1000-7fd2a45a2000 r--p 00000000 fc:00 2229448 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/utf_32be.so +7fd2a45a2000-7fd2a45a3000 rw-p 00001000 fc:00 2229448 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/utf_32be.so +7fd2a45a3000-7fd2a45a4000 r-xp 00000000 fc:00 2229439 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/utf_16le.so +7fd2a45a4000-7fd2a47a3000 ---p 00001000 fc:00 2229439 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/utf_16le.so +7fd2a47a3000-7fd2a47a4000 r--p 00000000 fc:00 2229439 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/utf_16le.so +7fd2a47a4000-7fd2a47a5000 rw-p 00001000 fc:00 2229439 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/utf_16le.so +7fd2a47a5000-7fd2a47a6000 r-xp 00000000 fc:00 2229440 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/utf_16be.so +7fd2a47a6000-7fd2a49a5000 ---p 00001000 fc:00 2229440 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/utf_16be.so +7fd2a49a5000-7fd2a49a6000 r--p 00000000 fc:00 2229440 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/utf_16be.so +7fd2a49a6000-7fd2a49a7000 rw-p 00001000 fc:00 2229440 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/utf_16be.so +7fd2a49a7000-7fd2a4b97000 r-xp 00000000 fc:00 938271 /usr/lib/libruby-1.9.1.so.1.9.1 +7fd2a4b97000-7fd2a4d96000 ---p 001f0000 fc:00 938271 /usr/lib/libruby-1.9.1.so.1.9.1 +7fd2a4d96000-7fd2a4d9b000 r--p 001ef000 fc:00 938271 /usr/lib/libruby-1.9.1.so.1.9.1 +7fd2a4d9b000-7fd2a4d9f000 rw-p 001f4000 fc:00 938271 /usr/lib/libruby-1.9.1.so.1.9.1 +7fd2a4d9f000-7fd2a4dbb000 rw-p 00000000 00:00 0 +7fd2a4dbb000-7fd2a4dc1000 r-xp 00000000 fc:00 2493172 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json/ext/parser.so +7fd2a4dc1000-7fd2a4fc0000 ---p 00006000 fc:00 2493172 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json/ext/parser.so +7fd2a4fc0000-7fd2a4fc1000 r--p 00005000 fc:00 2493172 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json/ext/parser.so +7fd2a4fc1000-7fd2a4fc2000 rw-p 00006000 fc:00 2493172 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json/ext/parser.so +7fd2a4fc2000-7fd2a4fe2000 r-xp 00000000 fc:00 938243 /usr/lib/x86_64-linux-gnu/libyaml-0.so.2.0.2 +7fd2a4fe2000-7fd2a51e1000 ---p 00020000 fc:00 938243 /usr/lib/x86_64-linux-gnu/libyaml-0.so.2.0.2 +7fd2a51e1000-7fd2a51e2000 r--p 0001f000 fc:00 938243 /usr/lib/x86_64-linux-gnu/libyaml-0.so.2.0.2 +7fd2a51e2000-7fd2a51e3000 rw-p 00020000 fc:00 938243 /usr/lib/x86_64-linux-gnu/libyaml-0.so.2.0.2 +7fd2a51e3000-7fd2a51e9000 r-xp 00000000 fc:00 2229434 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/psych.so +7fd2a51e9000-7fd2a53e8000 ---p 00006000 fc:00 2229434 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/psych.so +7fd2a53e8000-7fd2a53e9000 r--p 00005000 fc:00 2229434 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/psych.so +7fd2a53e9000-7fd2a53ea000 rw-p 00006000 fc:00 2229434 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/psych.so +7fd2a53ea000-7fd2a541c000 r-xp 00000000 fc:00 2229497 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/date_core.so +7fd2a541c000-7fd2a561c000 ---p 00032000 fc:00 2229497 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/date_core.so +7fd2a561c000-7fd2a561d000 r--p 00032000 fc:00 2229497 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/date_core.so +7fd2a561d000-7fd2a561e000 rw-p 00033000 fc:00 2229497 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/date_core.so +7fd2a561e000-7fd2a5620000 rw-p 00000000 00:00 0 +7fd2a5620000-7fd2a5634000 r-xp 00000000 fc:00 2229399 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/bigdecimal.so +7fd2a5634000-7fd2a5833000 ---p 00014000 fc:00 2229399 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/bigdecimal.so +7fd2a5833000-7fd2a5834000 r--p 00013000 fc:00 2229399 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/bigdecimal.so +7fd2a5834000-7fd2a5835000 rw-p 00014000 fc:00 2229399 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/bigdecimal.so +7fd2a5835000-7fd2a583a000 r-xp 00000000 fc:00 2229498 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/strscan.so +7fd2a583a000-7fd2a5a39000 ---p 00005000 fc:00 2229498 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/strscan.so +7fd2a5a39000-7fd2a5a3a000 r--p 00004000 fc:00 2229498 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/strscan.so +7fd2a5a3a000-7fd2a5a3b000 rw-p 00005000 fc:00 2229498 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/strscan.so +7fd2a5a3b000-7fd2a5a42000 r-xp 00000000 fc:00 2229401 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/stringio.so +7fd2a5a42000-7fd2a5c41000 ---p 00007000 fc:00 2229401 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/stringio.so +7fd2a5c41000-7fd2a5c42000 r--p 00006000 fc:00 2229401 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/stringio.so +7fd2a5c42000-7fd2a5c43000 rw-p 00007000 fc:00 2229401 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/stringio.so +7fd2a5c43000-7fd2a5c95000 r-xp 00000000 fc:00 1572880 /lib/x86_64-linux-gnu/libssl.so.1.0.0 +7fd2a5c95000-7fd2a5e95000 ---p 00052000 fc:00 1572880 /lib/x86_64-linux-gnu/libssl.so.1.0.0 +7fd2a5e95000-7fd2a5e98000 r--p 00052000 fc:00 1572880 /lib/x86_64-linux-gnu/libssl.so.1.0.0 +7fd2a5e98000-7fd2a5e9e000 rw-p 00055000 fc:00 1572880 /lib/x86_64-linux-gnu/libssl.so.1.0.0 +7fd2a5e9e000-7fd2a5e9f000 rw-p 00000000 00:00 0 +7fd2a5e9f000-7fd2a5eed000 r-xp 00000000 fc:00 2229414 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/openssl.so +7fd2a5eed000-7fd2a60ed000 ---p 0004e000 fc:00 2229414 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/openssl.so +7fd2a60ed000-7fd2a60ee000 r--p 0004e000 fc:00 2229414 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/openssl.so +7fd2a60ee000-7fd2a60f0000 rw-p 0004f000 fc:00 2229414 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/openssl.so +7fd2a60f0000-7fd2a60f1000 rw-p 00000000 00:00 0 +7fd2a60f1000-7fd2a60f2000 r-xp 00000000 fc:00 2229402 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/fcntl.so +7fd2a60f2000-7fd2a62f1000 ---p 00001000 fc:00 2229402 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/fcntl.so +7fd2a62f1000-7fd2a62f2000 r--p 00000000 fc:00 2229402 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/fcntl.so +7fd2a62f2000-7fd2a62f3000 rw-p 00001000 fc:00 2229402 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/fcntl.so +7fd2a62f3000-7fd2a6316000 r-xp 00000000 fc:00 2229409 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/socket.so +7fd2a6316000-7fd2a6516000 ---p 00023000 fc:00 2229409 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/socket.so +7fd2a6516000-7fd2a6517000 r--p 00023000 fc:00 2229409 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/socket.so +7fd2a6517000-7fd2a6518000 rw-p 00024000 fc:00 2229409 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/socket.so +7fd2a6518000-7fd2a651b000 r-xp 00000000 fc:00 2229502 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/digest.so +7fd2a651b000-7fd2a671a000 ---p 00003000 fc:00 2229502 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/digest.so +7fd2a671a000-7fd2a671b000 r--p 00002000 fc:00 2229502 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/digest.so +7fd2a671b000-7fd2a671c000 rw-p 00003000 fc:00 2229502 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/digest.so +7fd2a671c000-7fd2a6732000 r-xp 00000000 fc:00 1573092 /lib/x86_64-linux-gnu/libz.so.1.2.3.4 +7fd2a6732000-7fd2a6931000 ---p 00016000 fc:00 1573092 /lib/x86_64-linux-gnu/libz.so.1.2.3.4 +7fd2a6931000-7fd2a6932000 r--p 00015000 fc:00 1573092 /lib/x86_64-linux-gnu/libz.so.1.2.3.4 +7fd2a6932000-7fd2a6933000 rw-p 00016000 fc:00 1573092 /lib/x86_64-linux-gnu/libz.so.1.2.3.4 +7fd2a6933000-7fd2a6ad2000 r-xp 00000000 fc:00 1572883 /lib/x86_64-linux-gnu/libcrypto.so.1.0.0 +7fd2a6ad2000-7fd2a6cd1000 ---p 0019f000 fc:00 1572883 /lib/x86_64-linux-gnu/libcrypto.so.1.0.0 +7fd2a6cd1000-7fd2a6cec000 r--p 0019e000 fc:00 1572883 /lib/x86_64-linux-gnu/libcrypto.so.1.0.0 +7fd2a6cec000-7fd2a6cf7000 rw-p 001b9000 fc:00 1572883 /lib/x86_64-linux-gnu/libcrypto.so.1.0.0 +7fd2a6cf7000-7fd2a6cfb000 rw-p 00000000 00:00 0 +7fd2a6cfb000-7fd2a6cfc000 r-xp 00000000 fc:00 2229423 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/digest/sha1.so +7fd2a6cfc000-7fd2a6efb000 ---p 00001000 fc:00 2229423 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/digest/sha1.so +7fd2a6efb000-7fd2a6efc000 r--p 00000000 fc:00 2229423 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/digest/sha1.so +7fd2a6efc000-7fd2a6efd000 rw-p 00001000 fc:00 2229423 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/digest/sha1.so +7fd2a6efd000-7fd2a6f00000 r-xp 00000000 fc:00 2229429 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/etc.so +7fd2a6f00000-7fd2a70ff000 ---p 00003000 fc:00 2229429 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/etc.so +7fd2a70ff000-7fd2a7100000 r--p 00002000 fc:00 2229429 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/etc.so +7fd2a7100000-7fd2a7101000 rw-p 00003000 fc:00 2229429 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/etc.so +7fd2a7101000-7fd2a7108000 r-xp 00000000 fc:00 2229501 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/pathname.so +7fd2a7108000-7fd2a7307000 ---p 00007000 fc:00 2229501 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/pathname.so +7fd2a7307000-7fd2a7308000 r--p 00006000 fc:00 2229501 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/pathname.so +7fd2a7308000-7fd2a7309000 rw-p 00007000 fc:00 2229501 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/pathname.so +7fd2a7309000-7fd2a730b000 r-xp 00000000 fc:00 2229473 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/trans/transdb.so +7fd2a730b000-7fd2a750b000 ---p 00002000 fc:00 2229473 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/trans/transdb.so +7fd2a750b000-7fd2a750c000 r--p 00002000 fc:00 2229473 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/trans/transdb.so +7fd2a750c000-7fd2a750d000 rw-p 00003000 fc:00 2229473 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/trans/transdb.so +7fd2a750d000-7fd2a750f000 r-xp 00000000 fc:00 2229441 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/encdb.so +7fd2a750f000-7fd2a770e000 ---p 00002000 fc:00 2229441 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/encdb.so +7fd2a770e000-7fd2a770f000 r--p 00001000 fc:00 2229441 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/encdb.so +7fd2a770f000-7fd2a7710000 rw-p 00002000 fc:00 2229441 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/encdb.so +7fd2a7710000-7fd2a79d9000 r--p 00000000 fc:00 923218 /usr/lib/locale/locale-archive +7fd2a79d9000-7fd2a7ad4000 r-xp 00000000 fc:00 1578039 /lib/x86_64-linux-gnu/libm-2.15.so +7fd2a7ad4000-7fd2a7cd3000 ---p 000fb000 fc:00 1578039 /lib/x86_64-linux-gnu/libm-2.15.so +7fd2a7cd3000-7fd2a7cd4000 r--p 000fa000 fc:00 1578039 /lib/x86_64-linux-gnu/libm-2.15.so +7fd2a7cd4000-7fd2a7cd5000 rw-p 000fb000 fc:00 1578039 /lib/x86_64-linux-gnu/libm-2.15.so +7fd2a7cd5000-7fd2a7cde000 r-xp 00000000 fc:00 1578040 /lib/x86_64-linux-gnu/libcrypt-2.15.so +7fd2a7cde000-7fd2a7ede000 ---p 00009000 fc:00 1578040 /lib/x86_64-linux-gnu/libcrypt-2.15.so +7fd2a7ede000-7fd2a7edf000 r--p 00009000 fc:00 1578040 /lib/x86_64-linux-gnu/libcrypt-2.15.so +7fd2a7edf000-7fd2a7ee0000 rw-p 0000a000 fc:00 1578040 /lib/x86_64-linux-gnu/libcrypt-2.15.so +7fd2a7ee0000-7fd2a7f0e000 rw-p 00000000 00:00 0 +7fd2a7f0e000-7fd2a7f10000 r-xp 00000000 fc:00 1578030 /lib/x86_64-linux-gnu/libdl-2.15.so +7fd2a7f10000-7fd2a8110000 ---p 00002000 fc:00 1578030 /lib/x86_64-linux-gnu/libdl-2.15.so +7fd2a8110000-7fd2a8111000 r--p 00002000 fc:00 1578030 /lib/x86_64-linux-gnu/libdl-2.15.so +7fd2a8111000-7fd2a8112000 rw-p 00003000 fc:00 1578030 /lib/x86_64-linux-gnu/libdl-2.15.so +7fd2a8112000-7fd2a8119000 r-xp 00000000 fc:00 1578035 /lib/x86_64-linux-gnu/librt-2.15.so +7fd2a8119000-7fd2a8318000 ---p 00007000 fc:00 1578035 /lib/x86_64-linux-gnu/librt-2.15.so +7fd2a8318000-7fd2a8319000 r--p 00006000 fc:00 1578035 /lib/x86_64-linux-gnu/librt-2.15.so +7fd2a8319000-7fd2a831a000 rw-p 00007000 fc:00 1578035 /lib/x86_64-linux-gnu/librt-2.15.so +7fd2a831a000-7fd2a8332000 r-xp 00000000 fc:00 1578033 /lib/x86_64-linux-gnu/libpthread-2.15.so +7fd2a8332000-7fd2a8531000 ---p 00018000 fc:00 1578033 /lib/x86_64-linux-gnu/libpthread-2.15.so +7fd2a8531000-7fd2a8532000 r--p 00017000 fc:00 1578033 /lib/x86_64-linux-gnu/libpthread-2.15.so +7fd2a8532000-7fd2a8533000 rw-p 00018000 fc:00 1578033 /lib/x86_64-linux-gnu/libpthread-2.15.so +7fd2a8533000-7fd2a8537000 rw-p 00000000 00:00 0 +7fd2a8537000-7fd2a86ec000 r-xp 00000000 fc:00 1578031 /lib/x86_64-linux-gnu/libc-2.15.so +7fd2a86ec000-7fd2a88eb000 ---p 001b5000 fc:00 1578031 /lib/x86_64-linux-gnu/libc-2.15.so +7fd2a88eb000-7fd2a88ef000 r--p 001b4000 fc:00 1578031 /lib/x86_64-linux-gnu/libc-2.15.so +7fd2a88ef000-7fd2a88f1000 rw-p 001b8000 fc:00 1578031 /lib/x86_64-linux-gnu/libc-2.15.so +7fd2a88f1000-7fd2a88f6000 rw-p 00000000 00:00 0 +7fd2a88f6000-7fd2a8b4a000 r-xp 00000000 fc:00 2229274 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/libruby.so.2.0.0 +7fd2a8b4a000-7fd2a8d49000 ---p 00254000 fc:00 2229274 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/libruby.so.2.0.0 +7fd2a8d49000-7fd2a8d4e000 r--p 00253000 fc:00 2229274 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/libruby.so.2.0.0 +7fd2a8d4e000-7fd2a8d51000 rw-p 00258000 fc:00 2229274 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/libruby.so.2.0.0 +7fd2a8d51000-7fd2a8d72000 rw-p 00000000 00:00 0 +7fd2a8d72000-7fd2a8d94000 r-xp 00000000 fc:00 1578045 /lib/x86_64-linux-gnu/ld-2.15.so +7fd2a8e6c000-7fd2a8e6d000 r--s 00000000 fc:00 2231868 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/gems/2.0.0/bin/rake +7fd2a8e7f000-7fd2a8f86000 rw-p 00000000 00:00 0 +7fd2a8f86000-7fd2a8f87000 r--s 00000000 fc:00 2231868 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/gems/2.0.0/bin/rake +7fd2a8f87000-7fd2a8f8e000 r--s 00000000 fc:00 929597 /usr/lib/x86_64-linux-gnu/gconv/gconv-modules.cache +7fd2a8f8e000-7fd2a8f8f000 ---p 00000000 00:00 0 +7fd2a8f8f000-7fd2a8f94000 rw-p 00000000 00:00 0 +7fd2a8f94000-7fd2a8f95000 r--p 00022000 fc:00 1578045 /lib/x86_64-linux-gnu/ld-2.15.so +7fd2a8f95000-7fd2a8f97000 rw-p 00023000 fc:00 1578045 /lib/x86_64-linux-gnu/ld-2.15.so +7fff9c15f000-7fff9c1e3000 rw-p 00000000 00:00 0 [stack] +7fff9c1ff000-7fff9c200000 r-xp 00000000 00:00 0 [vdso] +ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall] + + +[NOTE] +You may have encountered a bug in the Ruby interpreter or extension libraries. +Bug reports are welcome. +For details: http://www.ruby-lang.org/bugreport.html + +Aborted (core dumped) diff --git a/web/spec/controllers/api_affiliate_controller_spec.rb b/web/spec/controllers/api_affiliate_controller_spec.rb new file mode 100644 index 000000000..93306844d --- /dev/null +++ b/web/spec/controllers/api_affiliate_controller_spec.rb @@ -0,0 +1,82 @@ +require 'spec_helper' + +describe ApiAffiliateController do + render_views + + let(:partner1) {FactoryGirl.create(:affiliate_partner)} + let(:user_partner1) { partner1.partner_user } + let(:partner2) {FactoryGirl.create(:affiliate_partner)} + let(:user_partner2) { partner2.partner_user } + + before(:each) do + controller.current_user = user_partner1 + end + + describe "traffic_index" do + it "empty" do + get :traffic_index + response.should be_success + JSON.parse(response.body)['traffics'].should eq([]) + end + + it "single item" do + traffic_total = FactoryGirl.create(:affiliate_traffic_total, affiliate_partner: partner1, visits: 5, signups: 0, day:Date.today) + + get :traffic_index + response.should be_success + JSON.parse(response.body)['traffics'].should eq([{"day" => Date.today.to_s, "visits" => 5, "signups" => 0, "affiliate_partner_id" => partner1.id}]) + end + end + + describe "monthly_index" do + it "empty" do + get :monthly_index + response.should be_success + JSON.parse(response.body)['monthlies'].should eq([]) + end + + it "single item" do + monthly = FactoryGirl.create(:affiliate_monthly_payment, affiliate_partner: partner1, closed: true, due_amount_in_cents: 20, month: 1, year: 2015) + + get :monthly_index + response.should be_success + JSON.parse(response.body)['monthlies'].should eq([{"closed" => true, "month" => 1, "year" => 2015, "due_amount_in_cents" => 20, "affiliate_partner_id" => partner1.id}]) + end + end + + + describe "quarterly_index" do + it "empty" do + get :quarterly_index + response.should be_success + JSON.parse(response.body)['quarterlies'].should eq([]) + end + + it "single item" do + quarterly = FactoryGirl.create(:affiliate_quarterly_payment, affiliate_partner: partner1, paid: true, closed: true, due_amount_in_cents: 20, quarter: 1, year: 2015) + + get :quarterly_index + response.should be_success + JSON.parse(response.body)['quarterlies'].should eq([{"closed" => true, "paid" => true, "quarter" => 1, "year" => 2015, "due_amount_in_cents" => 20, "affiliate_partner_id" => partner1.id}]) + end + + + it "not paid is excluded" do + quarterly = FactoryGirl.create(:affiliate_quarterly_payment, affiliate_partner: partner1, paid: false, closed: true, due_amount_in_cents: 20, quarter: 1, year: 2015) + + get :quarterly_index + response.should be_success + JSON.parse(response.body)['quarterlies'].should eq([]) + end + + + it "not closed is excluded" do + quarterly = FactoryGirl.create(:affiliate_quarterly_payment, affiliate_partner: partner1, paid: true, closed: false, due_amount_in_cents: 20, quarter: 1, year: 2015) + + get :quarterly_index + response.should be_success + JSON.parse(response.body)['quarterlies'].should eq([]) + end + end + +end diff --git a/web/spec/controllers/api_links_controller_spec.rb b/web/spec/controllers/api_links_controller_spec.rb new file mode 100644 index 000000000..297789693 --- /dev/null +++ b/web/spec/controllers/api_links_controller_spec.rb @@ -0,0 +1,106 @@ +require 'spec_helper' + +describe ApiLinksController do + render_views + + let(:partner1) {FactoryGirl.create(:affiliate_partner)} + let(:user_partner1) { partner1.partner_user } + + before(:each) do + ClaimedRecording.delete_all + Recording.delete_all + MusicSession.delete_all + JamTrackRight.delete_all + JamTrack.delete_all + controller.current_user = nil + end + + describe "jamtrack_song_index" do + it "succeeds with empty data" do + get :jamtrack_song_index, format:'json', affiliate_id: partner1.id + response.status.should eq(200) + body = JSON.parse(response.body) + body.length.should eq(0) + end + + it "succeeds with data" do + jam_track = FactoryGirl.create(:jam_track) + get :jamtrack_song_index, format:'json', affiliate_id: partner1.id + response.status.should eq(200) + body = JSON.parse(response.body) + body.length.should eq(1) + body[0]['url'].should_not be_nil + body[0]['target'].should_not be_nil + end + end + + describe "jamkazam_general_index" do + it "succeeds" do + get :jamkazam_general_index, format:'json', affiliate_id: partner1.id + response.status.should eq(200) + body = JSON.parse(response.body) + body.length.should eq(3) + end + end + + + describe "session_index" do + let(:open_params) { + { + name: "session 1", + description: "my session", + genres: ['ambient'], + musician_access: true, + fan_access: true, + approval_required: true, + fan_chat: true, + legal_policy: 'Standard', + language: 'eng', + start: "Thu Jul 10 2020 10:00 PM", + duration: 30, + timezone: "Central Time (US & Canada),America/Chicago", + open_rsvps: true, + legal_terms: true, + recurring_mode: 'once', + isUnstructuredRsvp: true, + rsvp_slots: [{ instrument_id: "other", proficiency_level: 1, approve: true}] + } + } + + it "succeeds with no data" do + get :session_index, format:'json', affiliate_id: partner1.id + response.status.should eq(200) + body = JSON.parse(response.body) + body.length.should eq(0) + end + + + it "succeeds with one scheduled session" do + session = MusicSession.create(user_partner1, open_params) + get :session_index, format:'json', affiliate_id: partner1.id + response.status.should eq(200) + body = JSON.parse(response.body) + body.length.should eq(1) + end + end + + describe "recording_index" do + + it "succeeds with no data" do + get :recording_index, format:'json', affiliate_id: partner1.id + response.status.should eq(200) + body = JSON.parse(response.body) + body.length.should eq(0) + end + + it "succeeds with one recording" do + claimed_recording1 = FactoryGirl.create(:claimed_recording, user: user_partner1) + puts claimed_recording1.inspect + get :recording_index, format:'json', affiliate_id: partner1.id + response.status.should eq(200) + body = JSON.parse(response.body) + body.length.should eq(1) + end + end + +end diff --git a/web/spec/factories.rb b/web/spec/factories.rb index ca49f36eb..f41205583 100644 --- a/web/spec/factories.rb +++ b/web/spec/factories.rb @@ -777,4 +777,37 @@ FactoryGirl.define do transaction_type JamRuby::RecurlyTransactionWebHook::FAILED_PAYMENT end end + + factory :affiliate_partner, class: 'JamRuby::AffiliatePartner' do + sequence(:partner_name) { |n| "partner-#{n}" } + entity_type 'Individual' + signed_at Time.now + association :partner_user, factory: :user + end + + factory :affiliate_quarterly_payment, class: 'JamRuby::AffiliateQuarterlyPayment' do + year 2015 + quarter 0 + association :affiliate_partner, factory: :affiliate_partner + end + + factory :affiliate_monthly_payment, class: 'JamRuby::AffiliateMonthlyPayment' do + year 2015 + month 1 + association :affiliate_partner, factory: :affiliate_partner + end + + factory :affiliate_referral_visit, class: 'JamRuby::AffiliateReferralVisit' do + ip_address '1.1.1.1' + association :affiliate_partner, factory: :affiliate_partner + end + + factory :affiliate_traffic_total, class: 'JamRuby::AffiliateTrafficTotal' do + day Date.today + association :affiliate_partner, factory: :affiliate_partner + end + + factory :affiliate_legalese, class: 'JamRuby::AffiliateLegalese' do + legalese Faker::Lorem.paragraphs(6).join("\n\n") + end end diff --git a/web/spec/features/account_affiliate_spec.rb b/web/spec/features/account_affiliate_spec.rb new file mode 100644 index 000000000..9747a373b --- /dev/null +++ b/web/spec/features/account_affiliate_spec.rb @@ -0,0 +1,152 @@ +require 'spec_helper' + +describe "Account Affiliate", :js => true, :type => :feature, :capybara_feature => true do + + subject { page } + + let(:user) {FactoryGirl.create(:user)} + let(:partner) { FactoryGirl.create(:affiliate_partner) } + let(:jam_track) {FactoryGirl.create(:jam_track)} + + before(:each) do + JamTrackRight.delete_all + JamTrack.delete_all + AffiliateQuarterlyPayment.delete_all + AffiliateMonthlyPayment.delete_all + AffiliateTrafficTotal.delete_all + UserMailer.deliveries.clear + emulate_client + end + + describe "account overview" do + it "shows correct values for partner" do + partner.referral_user_count = 3 + partner.cumulative_earnings_in_cents = 10000 + partner.save! + + sign_in_poltergeist partner.partner_user + visit "/client#/account" + find('.account-mid.affiliate .user-referrals', text: 'You have referred 3 users to date.') + find('.account-mid.affiliate .affiliate-earnings', text: 'You have earned $100.00 to date.') + end + + it "shows correct values for unaffiliated user" do + sign_in_poltergeist user + visit "/client#/account" + find('.account-mid.affiliate .not-affiliated', text: 'You are not currently a JamKazam affiliate.') + find('.account-mid.affiliate .learn-affiliate') + end + end + + describe "account affiliate page" do + before(:each) do + sign_in_poltergeist partner.partner_user + end + + it "works on no data" do + jam_track.touch + + visit "/client#/account/affiliatePartner" + find('.tab-account', text: 'So please provide this data, and be sure to keep it current!') + + # take a look at the links tab + find('a#affiliate-partner-links-link').trigger(:click) + + find('#account-affiliate-partner tr td.target') + + # can't find this on the page for some reason: + #jk_select('Custom Link', '#account-affiliate-partner select.link_type') + #find('.link-type-prompt[data-type="custom_links"]') + + find('a#affiliate-partner-signups-link').trigger(:click) + find('table.traffic-table') + + find('a#affiliate-partner-earnings-link').trigger(:click) + find('table.payment-table') + + find('a#affiliate-partner-agreement-link').trigger(:click) + find('h2', text: 'JamKazam Affiliate Agreement') + find('span.c0', text: 'Updated: April 30, 2015') + end + + it "shows data" do + visit "/client#/account/affiliatePartner" + find('.tab-account', text: 'So please provide this data, and be sure to keep it current!') + + # verify traffic data shows correctly + day1 = Date.parse('2015-04-05') + FactoryGirl.create(:affiliate_traffic_total, affiliate_partner: partner, day: day1, signups: 1, visits:2) + + find('a#affiliate-partner-signups-link').trigger(:click) + find('table.traffic-table tr td.day', text: "April 5") + find('table.traffic-table tr td.signups', text: '1') + find('table.traffic-table tr td.visits', text: '2') + + + find('a#affiliate-partner-earnings-link').trigger(:click) + find('table.payment-table') + + day2 = Date.parse('2015-04-07') + FactoryGirl.create(:affiliate_traffic_total, affiliate_partner: partner, day: day2, signups: 3, visits:4) + find('a#affiliate-partner-signups-link').trigger(:click) + find('table.traffic-table tr td.day', text: "April 7") + find('table.traffic-table tr td.signups', text: '3') + find('table.traffic-table tr td.visits', text: '4') + + # verify earnings data correctly + FactoryGirl.create(:affiliate_monthly_payment, affiliate_partner:partner, year:2015, month:1, due_amount_in_cents:20, jamtracks_sold: 1, closed:true) + + find('a#affiliate-partner-earnings-link').trigger(:click) + find('table.payment-table tr td.month', text: "January 2015") + find('table.payment-table tr td.sales', text: 'JamTracks: 1 unit sold') + find('table.payment-table tr td.earnings', text: '$0.20') + + + find('a#affiliate-partner-signups-link').trigger(:click) + find('table.traffic-table') + + FactoryGirl.create(:affiliate_monthly_payment, affiliate_partner:partner, year:2015, month:2, due_amount_in_cents:40, jamtracks_sold: 2, closed:true) + FactoryGirl.create(:affiliate_monthly_payment, affiliate_partner:partner, year:2015, month:3, due_amount_in_cents:60, jamtracks_sold: 3, closed:true) + quarter1 = FactoryGirl.create(:affiliate_quarterly_payment, affiliate_partner:partner, year:2015, quarter:0, due_amount_in_cents:120, jamtracks_sold: 6, closed:true, paid:false) + FactoryGirl.create(:affiliate_monthly_payment, affiliate_partner:partner, year:2015, month:4, due_amount_in_cents:2000, jamtracks_sold: 100, closed:true) + + find('a#affiliate-partner-earnings-link').trigger(:click) + find('table.payment-table tr td.month', text: "January 2015") + find('table.payment-table tr td.sales', text: 'JamTracks: 1 unit sold') + find('table.payment-table tr td.earnings', text: '$0.20') + find('table.payment-table tr td.month', text: "February 2015") + find('table.payment-table tr td.sales', text: 'JamTracks: 2 units sold') + find('table.payment-table tr td.earnings', text: '$0.40') + find('table.payment-table tr td.month', text: "March 2015") + find('table.payment-table tr td.sales', text: 'JamTracks: 3 units sold') + find('table.payment-table tr td.earnings', text: '$0.60') + find('table.payment-table tr td.month', text: "1st Quarter 2015") + find('table.payment-table tr td.earnings', text: 'No earning were paid, as the $10 minimum threshold was not reached.') + + + + find('a#affiliate-partner-signups-link').trigger(:click) + find('table.traffic-table') + + quarter1.paid = true + quarter1.save! + FactoryGirl.create(:affiliate_quarterly_payment, affiliate_partner:partner, year:2015, quarter:1, due_amount_in_cents:2000, jamtracks_sold: 100, closed:true, paid:true) + + find('a#affiliate-partner-earnings-link').trigger(:click) + find('table.payment-table tr td.month', text: "January 2015") + find('table.payment-table tr td.sales', text: 'JamTracks: 1 unit sold') + find('table.payment-table tr td.earnings', text: '$0.20') + find('table.payment-table tr td.month', text: "February 2015") + find('table.payment-table tr td.sales', text: 'JamTracks: 2 units sold') + find('table.payment-table tr td.earnings', text: '$0.40') + find('table.payment-table tr td.month', text: "March 2015") + find('table.payment-table tr td.sales', text: 'JamTracks: 3 units sold') + find('table.payment-table tr td.earnings', text: '$0.60') + + find('table.payment-table tr td.month', text: "1st Quarter 2015") + find('table.payment-table tr td.earnings', text: 'PAID $1.20') + find('table.payment-table tr td.month', text: "2nd Quarter 2015") + find('table.payment-table tr td.earnings', text: 'PAID $20.00') + end + end +end diff --git a/web/spec/features/affiliate_program_spec.rb b/web/spec/features/affiliate_program_spec.rb new file mode 100644 index 000000000..26378cd92 --- /dev/null +++ b/web/spec/features/affiliate_program_spec.rb @@ -0,0 +1,90 @@ +require 'spec_helper' + +describe "Affiliate Program", :js => true, :type => :feature, :capybara_feature => true do + + subject { page } + + let(:user) { FactoryGirl.create(:user) } + + before(:each) do + User.delete_all + AffiliateQuarterlyPayment.delete_all + AffiliateMonthlyPayment.delete_all + AffiliateTrafficTotal.delete_all + AffiliatePartner.delete_all + end + + before(:all) do + @old_recaptcha=Rails.application.config.recaptcha_enable + Rails.application.config.recaptcha_enable=false + end + + after(:all) do + Rails.application.config.recaptcha_enable=@old_recaptcha + end + + describe "Affiliate Program signup page" do + it "logged in user creates affiliate" do + fast_signin user, '/affiliateProgram' + + find('input#entity_individual').trigger(:click) + + find('.agree-button').trigger(:click) + + find('h1', text: 'congratulations') + find('.button-orange', text: 'GO TO AFFILIATE PAGE').trigger(:click) + + find('.tab-account', text: 'So please provide this data, and be sure to keep it current!') + + partner = AffiliatePartner.first + partner.partner_user.should eq(user) + partner.entity_type.should eq('Individual') + end + + it "logged in user creates entity affiliate" do + fast_signin user, '/affiliateProgram' + + find('input#entity_entity').trigger(:click) + fill_in('entity-name', with: 'Mr. Bubbles') + select('Sole Proprietor', from:'entity-type') + + find('.agree-button').trigger(:click) + + find('h1', text: 'congratulations') + find('.button-orange', text: 'GO TO AFFILIATE PAGE').trigger(:click) + + find('.tab-account', text: 'So please provide this data, and be sure to keep it current!') + + partner = AffiliatePartner.first + partner.partner_user.should eq(user) + partner.entity_type.should eq('Sole Proprietor') + end + + it "new user creates individual affiliate" do + visit '/affiliateProgram' + + find('input#entity_individual').trigger(:click) + + find('.agree-button').trigger(:click) + + find('h1', text: 'congratulations') + find('.button-orange', text: 'GO SIGNUP').trigger(:click) + + fill_in "jam_ruby_user[first_name]", with: "Affiliate1" + fill_in "jam_ruby_user[last_name]", with: "Someone" + fill_in "jam_ruby_user[email]", with: "affiliate1@jamkazam.com" + fill_in "jam_ruby_user[password]", with: "jam123" + fill_in "jam_ruby_user[password_confirmation]", with: "jam123" + check("jam_ruby_user[instruments][drums][selected]") + check("jam_ruby_user[terms_of_service]") + click_button "CREATE ACCOUNT" + + should have_title("JamKazam | Congratulations") + + found_user = User.first + partner = AffiliatePartner.first + partner.partner_user.should eq(found_user) + partner.entity_type.should eq('Individual') + end + end +end diff --git a/web/spec/features/affiliate_referral_spec.rb b/web/spec/features/affiliate_referral_spec.rb new file mode 100644 index 000000000..ed4f24f49 --- /dev/null +++ b/web/spec/features/affiliate_referral_spec.rb @@ -0,0 +1,59 @@ +require 'spec_helper' + +describe "affiliate visit tracking", :js => true, :type => :feature, :capybara_feature => true do + + subject { page } + + let(:user) { FactoryGirl.create(:user) } + let(:partner) { FactoryGirl.create(:affiliate_partner) } + let(:affiliate_params) { partner.affiliate_query_params } + + before(:each) do + AffiliateTrafficTotal.delete_all + AffiliateReferralVisit.delete_all + end + + before(:all) do + @old_recaptcha=Rails.application.config.recaptcha_enable + Rails.application.config.recaptcha_enable=false + end + + after(:all) do + Rails.application.config.recaptcha_enable=@old_recaptcha + end + + # the ways that a user might signup: + # on free jamtrack redemption flow - this is verified in checkout_spec.rb + # via facebook + # /signup + it "verifies that a signup via /signup page, when coming from a referral, attributes partner" do + visit '/?' + affiliate_params + + should_be_at_root + AffiliateReferralVisit.count.should eq(1) + + visit '/signup' + fill_in "jam_ruby_user[first_name]", with: "Affiliate" + fill_in "jam_ruby_user[last_name]", with: "Referral" + fill_in "jam_ruby_user[email]", with: "referral1@jamkazam.com" + fill_in "jam_ruby_user[password]", with: "jam123" + fill_in "jam_ruby_user[password_confirmation]", with: "jam123" + check("jam_ruby_user[instruments][drums][selected]") + check("jam_ruby_user[terms_of_service]") + click_button "CREATE ACCOUNT" + + should have_title("JamKazam | Congratulations") + + referral = User.find_by_email('referral1@jamkazam.com') + referral.affiliate_referral.should eq(partner) + AffiliatePartner.tally_up(referral.created_at.to_date + 1) + + partner.reload + partner.referral_user_count.should eq(1) + + total = AffiliateTrafficTotal.first + total.signups.should eq(1) + end + + +end diff --git a/web/spec/features/affiliate_visit_tracking.rb b/web/spec/features/affiliate_visit_tracking.rb new file mode 100644 index 000000000..09ee9dcd5 --- /dev/null +++ b/web/spec/features/affiliate_visit_tracking.rb @@ -0,0 +1,36 @@ +require 'spec_helper' + +describe "affiliate visit tracking" do + + subject { page } + + let(:user) { FactoryGirl.create(:user) } + let(:partner) { FactoryGirl.create(:affiliate_partner) } + let(:affiliate_params) { partner.affiliate_query_params } + + before(:each) do + AffiliateReferralVisit.delete_all + end + + it "tracks" do + visit '/?' + affiliate_params + + should_be_at_root + AffiliateReferralVisit.count.should eq(1) + visit = AffiliateReferralVisit.first + visit.visited_url.should eq('/?' + affiliate_params) + visit.affiliate_partner_id.should eq(partner.id) + visit.first_visit.should be_true + + download_url = '/downloads?' + affiliate_params + visit download_url + find('h2.create-account-header') + + + AffiliateReferralVisit.count.should eq(2) + visit = AffiliateReferralVisit.find_by_visited_url(download_url) + visit.affiliate_partner_id.should eq(partner.id) + visit.first_visit.should be_false + end + +end diff --git a/web/spec/features/checkout_spec.rb b/web/spec/features/checkout_spec.rb index d0a3a9b0c..bebe03a02 100644 --- a/web/spec/features/checkout_spec.rb +++ b/web/spec/features/checkout_spec.rb @@ -827,6 +827,123 @@ describe "Checkout", :js => true, :type => :feature, :capybara_feature => true d end + it "for anonymous user with referral" do + + partner = FactoryGirl.create(:affiliate_partner) + affiliate_params = partner.affiliate_query_params + + visit '/landing/jamtracks/acdc-backinblack?' + affiliate_params + find('a.browse-jamtracks').trigger(:click) + + find('h1', text: 'jamtracks') + #find('a', text: 'What is a JamTrack?') + + find("a.jamtrack-add-cart[data-jamtrack-id=\"#{jamtrack_acdc_backinblack.id}\"]", text: 'GET IT FREE!').trigger(:click) + find('h3', text: 'OR SIGN UP USING YOUR EMAIL') + shopping_carts = ShoppingCart.all + shopping_carts.count.should eq(1) + shopping_cart = shopping_carts[0] + shopping_cart.anonymous_user_id.should_not be_nil + shopping_cart.user_id.should be_nil + + fill_in 'first_name', with: 'Seth' + fill_in 'last_name', with: 'Call' + fill_in 'email', with: 'guy_referral@jamkazam.com' + fill_in 'password', with: 'jam123' + find('.right-side .terms_of_service input').trigger(:click) # accept TOS + + # try to submit, and see order page + find('.signup-submit').trigger(:click) + + find('.jam-tracks-in-browser') + + guy = User.find_by_email('guy_referral@jamkazam.com') + guy.affiliate_referral.should eq(partner) + guy.reload + + # verify sales data + guy.sales.length.should eq(1) + sale = guy.sales.first + sale.sale_line_items.length.should eq(1) + acdc_sale = sale.sale_line_items[0] + acdc_sale.affiliate_referral.should eq(partner) + acdc_sale.affiliate_refunded.should be_false + acdc_sale.affiliate_refunded_at.should be_nil + acdc_sale.affiliate_referral_fee_in_cents.should eq(0) + + # this is a little cheat to make the billing info dropdown already say US + guy.country = 'US' + guy.save! + + # now, go back to checkout flow again, and make sure we are told there are no free jam tracks + + visit "/client#/jamtrackBrowse" + + find("a.jamtrack-add-cart[data-jamtrack-id=\"#{jamtrack_pearljam_evenflow.id}\"]", text: 'ADD TO CART').trigger(:click) + find('h1', text: 'shopping cart') + find('.cart-item-caption', text: "JamTrack: #{jamtrack_pearljam_evenflow.name}") + find('.cart-item-price', text: "$ #{jamtrack_pearljam_evenflow.price}") + find('.shopping-sub-total', text:"Subtotal:$ #{jamtrack_pearljam_evenflow.price}") + + # attempt to checkout + find('a.button-orange', text: 'PROCEED TO CHECKOUT').trigger(:click) + + # should be at payment page + + # this should take us to the payment screen + find('p.payment-prompt') + + # fill out all billing info and account info + fill_in 'billing-first-name', with: 'Seth' + fill_in 'billing-last-name', with: 'Call' + fill_in 'billing-address1', with: '10704 Buckthorn Drive' + fill_in 'billing-city', with: 'Austin' + fill_in 'billing-state', with: 'Texas' + fill_in 'billing-zip', with: '78759' + fill_in 'card-number', with: '4111111111111111' + fill_in 'card-verify', with: '012' + #jk_select('US', '#checkoutPaymentScreen #divBillingCountry #billing-country') + + find('#payment-info-next').trigger(:click) + + # should be taken straight to order page + + # now see order page, and everything should no longer appear free + find('p.order-prompt') + find('.order-items-value.order-total', text:'$1.99') + find('.order-items-value.shipping-handling', text:'$0.00') + find('.order-items-value.sub-total', text:'$1.99') + find('.order-items-value.taxes', text:'$0.16') + find('.order-items-value.grand-total', text:'$2.15') + + # click the ORDER button + find('.place-order-center a.button-orange.place-order').trigger(:click) + + # and now we should see confirmation, and a notice that we are in a normal browser + find('.thanks-detail.jam-tracks-in-browser') + + guy.reload + + sleep 3 # challenge to all comers! WHY DO I HAVE TO SLEEP FOR THIS ASSERTION TO BE TRUE! GAH . and 1 second won't do it + + jam_track_right = jamtrack_pearljam_evenflow.right_for_user(guy) + # make sure it appears the user actually bought the jamtrack! + jam_track_right.should_not be_nil + jam_track_right.redeemed.should be_false + guy.has_redeemable_jamtrack.should be_false + + # verify sales data + guy.sales.length.should eq(2) + sale = guy.sales.last + sale.sale_line_items.length.should eq(1) + acdc_sale = SaleLineItem.find_by_recurly_adjustment_uuid(jam_track_right.recurly_adjustment_uuid) + acdc_sale.affiliate_referral.should eq(partner) + acdc_sale.affiliate_refunded.should be_false + acdc_sale.affiliate_refunded_at.should be_nil + acdc_sale.affiliate_referral_fee_in_cents.should eq(20) + + end + it "for existing user with a freebie available (already logged in)" do diff --git a/web/spec/managers/user_manager_spec.rb b/web/spec/managers/user_manager_spec.rb index 275d90b69..f6d464226 100644 --- a/web/spec/managers/user_manager_spec.rb +++ b/web/spec/managers/user_manager_spec.rb @@ -182,9 +182,7 @@ describe UserManager do describe "signup" do let!(:user) { FactoryGirl.create(:user) } let!(:partner) { - AffiliatePartner.create_with_params({:partner_name => Faker::Company.name, - :partner_code => Faker::Lorem.words(1)[0], - :user_email => user.email}) + AffiliatePartner.create_with_web_params(user, {:partner_name => Faker::Company.name, entity_type:'Individual'}) } it "signup successfully" do @@ -200,7 +198,7 @@ describe UserManager do instruments: @instruments, musician:true, signup_confirm_url: "http://localhost:3000/confirm", - affiliate_referral_id: AffiliatePartner.coded_id(partner.partner_code)) + affiliate_referral_id: partner.id) user.errors.any?.should be_false user.first_name.should == "bob" diff --git a/web/spec/requests/affilate_referral_spec.rb b/web/spec/requests/affilate_referral_spec.rb index 7a61f8ec4..c3d0f457d 100644 --- a/web/spec/requests/affilate_referral_spec.rb +++ b/web/spec/requests/affilate_referral_spec.rb @@ -6,9 +6,7 @@ describe "Affiliate Reports", :type => :api do let!(:user) { FactoryGirl.create(:user) } let!(:partner) { - AffiliatePartner.create_with_params({:partner_name => Faker::Company.name, - :partner_code => Faker::Lorem.words[0], - :user_email => user.email}) + AffiliatePartner.create_with_web_params(user, {:partner_name => Faker::Company.name, entity_type:'Individual'}) } it "valid score" do From 31a08030196cbcdf41293cd525a7bfc0589daa8a Mon Sep 17 00:00:00 2001 From: Seth Call Date: Thu, 28 May 2015 08:53:24 -0500 Subject: [PATCH 04/45] * VRFS-3226 - default WDM to 48000 on selection. fix bad filter logic for monthly payments (VRFS-3030) --- ruby/lib/jam_ruby/models/affiliate_payment.rb | 2 +- web/app/assets/javascripts/wizard/gear/step_select_gear.js | 6 +++++- web/app/assets/javascripts/wizard/gear_utils.js | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/ruby/lib/jam_ruby/models/affiliate_payment.rb b/ruby/lib/jam_ruby/models/affiliate_payment.rb index 81c36a977..1aa29f1c8 100644 --- a/ruby/lib/jam_ruby/models/affiliate_payment.rb +++ b/ruby/lib/jam_ruby/models/affiliate_payment.rb @@ -31,7 +31,7 @@ module JamRuby query = AffiliatePayment .includes(affiliate_quarterly_payment: [], affiliate_monthly_payment:[]) .where(affiliate_partner_id: affiliate_partner_id) - .where("payment_type='quarterly' AND closed = true") + .where("(payment_type='quarterly' AND closed = true) OR payment_type='monthly'") .where('(paid = TRUE or due_amount_in_cents < 10000 or paid is NULL)') .paginate(:page => page, :per_page => limit) .order('year ASC, time_sort ASC, payment_type ASC') diff --git a/web/app/assets/javascripts/wizard/gear/step_select_gear.js b/web/app/assets/javascripts/wizard/gear/step_select_gear.js index eda4bbe9b..88f07f295 100644 --- a/web/app/assets/javascripts/wizard/gear/step_select_gear.js +++ b/web/app/assets/javascripts/wizard/gear/step_select_gear.js @@ -884,7 +884,11 @@ // deal with sample rate if(selectedDeviceInfo && context.jamClient.FTUESetPreferredMixerSampleRate) { // get the preferred sample rate for the device, and set that as the initial value of the sample rate dropdown - if (selectedDeviceInfo.input.info.port_audio_name != 'Default Input') { + // except for WKS; we just default to 48 + if (selectedDeviceInfo.input.info.type == 'Win32_wdm') { + var inputSampleRate = 48000; + } + else if (selectedDeviceInfo.input.info.port_audio_name != 'Default Input') { var inputSampleRate = context.jamClient.FTUEgetInputDeviceSampleRate(selectedDeviceInfo.input.info.port_audio_name); } else { diff --git a/web/app/assets/javascripts/wizard/gear_utils.js b/web/app/assets/javascripts/wizard/gear_utils.js index 193bc05ed..d50238724 100644 --- a/web/app/assets/javascripts/wizard/gear_utils.js +++ b/web/app/assets/javascripts/wizard/gear_utils.js @@ -197,7 +197,7 @@ } var devices = context.jamClient.FTUEGetAudioDevices(); - logger.debug("FTUEGetAudioDevices: " + JSON.stringify(devices)); + //logger.debug("FTUEGetAudioDevices: " + JSON.stringify(devices)); var loadedDevices = {}; From e9504b1fc6aed52d9ca49e31e8f99d1a1364718b Mon Sep 17 00:00:00 2001 From: Seth Call Date: Thu, 28 May 2015 10:34:07 -0500 Subject: [PATCH 05/45] * performance API and color changes on affilate page --- .../javascripts/everywhere/everywhere.js | 62 +++++++++++++++++++ .../landings/affiliate_program.css.scss | 7 +++ .../landings/partner_agreement_v1.css.scss | 6 +- 3 files changed, 74 insertions(+), 1 deletion(-) diff --git a/web/app/assets/javascripts/everywhere/everywhere.js b/web/app/assets/javascripts/everywhere/everywhere.js index 1b27ba754..f79494f42 100644 --- a/web/app/assets/javascripts/everywhere/everywhere.js +++ b/web/app/assets/javascripts/everywhere/everywhere.js @@ -20,6 +20,8 @@ var stun = null; var rest = context.JK.Rest(); + $(window).on('load', sendTimingResults) + $(window).on('pagehide', setNavigationStart) $(document).on('JAMKAZAM_CONSTRUCTED', function(e, data) { @@ -245,4 +247,64 @@ } } + function setNavigationStart() { + if(!window.performance || !window.performance.timing) { + try { + window.sessionStorage.setItem('navigationStart', Date.now()) + } + catch(e) { + logger.debug("unable to accesss sessionStorage") + } + } + + } + + + // http://githubengineering.com/browser-monitoring-for-github-com/ + function sendTimingResults() { + setTimeout(function() { + var timing; + var hasTimingApi; + + if(window.performance && window.performance.timing) { + timing = window.performance.timing + hasTimingApi = true; + } + else { + timing = {} + hasTimingApi = false; + } + + // Merge in simulated cross-browser load event + timing['crossBrowserLoadEvent'] = Date.now() + + var chromeFirstPaintTime; + if(window.chrome && window.chrome.loadTimes) { + var loadTimes = window.chrome.loadTimes() + if(loadTimes) { + chromeFirstPaintTime = true; + } + } + + // firstPaintTime is in seconds; convert to milliseconds to match performance.timing. + timing['chromeFirstPaintTime'] = Math.round(chromeFirstPaintTime * 1000); + + // Merge in simulated navigation start, if no navigation timing + if (!hasTimingApi) { + try { + var navStart = window.sessionStorage.getItem('navigationStart') + if(navStart) { + timing['simulatedNavigationStart'] = parseInt(navStart, 10) + } + } + catch(e) { } + } + + + //GitHub.reportStats timing + logger.debug("timing", timing) + }, 0) + + } + })(window, jQuery); diff --git a/web/app/assets/stylesheets/landings/affiliate_program.css.scss b/web/app/assets/stylesheets/landings/affiliate_program.css.scss index 2bfdeeccd..f695f5da7 100644 --- a/web/app/assets/stylesheets/landings/affiliate_program.css.scss +++ b/web/app/assets/stylesheets/landings/affiliate_program.css.scss @@ -3,6 +3,11 @@ body.web.landing_page.full { &.affiliate_program { + .video-container { + width:100%; + padding-bottom:53.33%; + + } .agree-disagree-buttons { margin-top:30px; } @@ -28,7 +33,9 @@ body.web.landing_page.full { h1 { display: inline-block; + margin-bottom:20px; } + .column { @include border_box_sizing; width:50% ! important; diff --git a/web/app/assets/stylesheets/landings/partner_agreement_v1.css.scss b/web/app/assets/stylesheets/landings/partner_agreement_v1.css.scss index 6f1756204..4adb0e548 100644 --- a/web/app/assets/stylesheets/landings/partner_agreement_v1.css.scss +++ b/web/app/assets/stylesheets/landings/partner_agreement_v1.css.scss @@ -1,7 +1,11 @@ #partner-agreement-v1 { + background-color:#eee; * { - color:#CCCCCC ! important; + color:black! important; + background-color:#eee; + font-family: Raleway, Arial, Helvetica, sans-serif ! important; + font-weight: 300 ! important; } .c1, .c20 { From 54a7cb40c9340c4365ba5907955969fbdf8b1122 Mon Sep 17 00:00:00 2001 From: Seth Call Date: Thu, 28 May 2015 11:10:50 -0500 Subject: [PATCH 06/45] * turn timing off, and track with GA --- .../javascripts/everywhere/everywhere.js | 14 +++++---- web/app/assets/javascripts/ga.js | 31 +++++++++++++++++++ web/config/application.rb | 1 + web/config/initializers/gon.rb | 1 + 4 files changed, 41 insertions(+), 6 deletions(-) diff --git a/web/app/assets/javascripts/everywhere/everywhere.js b/web/app/assets/javascripts/everywhere/everywhere.js index f79494f42..43a844a32 100644 --- a/web/app/assets/javascripts/everywhere/everywhere.js +++ b/web/app/assets/javascripts/everywhere/everywhere.js @@ -20,8 +20,11 @@ var stun = null; var rest = context.JK.Rest(); - $(window).on('load', sendTimingResults) - $(window).on('pagehide', setNavigationStart) + if(gon.global.web_performance_timing_enabled) { + $(window).on('load', sendTimingResults) + $(window).on('pagehide', setNavigationStart) + } + $(document).on('JAMKAZAM_CONSTRUCTED', function(e, data) { @@ -262,6 +265,7 @@ // http://githubengineering.com/browser-monitoring-for-github-com/ function sendTimingResults() { + setTimeout(function() { var timing; var hasTimingApi; @@ -294,15 +298,13 @@ try { var navStart = window.sessionStorage.getItem('navigationStart') if(navStart) { - timing['simulatedNavigationStart'] = parseInt(navStart, 10) + timing['navigationStart'] = parseInt(navStart, 10) } } catch(e) { } } - - //GitHub.reportStats timing - logger.debug("timing", timing) + context.JK.GA.trackTiming(timing); }, 0) } diff --git a/web/app/assets/javascripts/ga.js b/web/app/assets/javascripts/ga.js index 8e51a081e..3ff2c28b8 100644 --- a/web/app/assets/javascripts/ga.js +++ b/web/app/assets/javascripts/ga.js @@ -284,6 +284,36 @@ logger.debug("Tracked Jam Track Play") } + function trackTiming(timing) { + + if(!timing) {return} + + try { + var computed = { + dns: timing.domainLookupEnd - timing.domainLookupStart, + connect: timing.connectEnd - timing.connectStart, + ttfb: timing.responseStart - timing.connectEnd, + basePage: timing.responseEnd - timing.responseStart, + frontEnd: timing.loadEventStart - timing.responseEnd, + domContentLoadedEvent: timing.domContentLoadedEventEnd - timing.domContentLoadedEventStart, + windowLoadEvent: timing.loadEventEnd - timing.loadEventStart, + domInteractive: timing.domInteractive - timing.domLoading, + domComplete: timing.domComplete - timing.domLoading, + domCompleteToOnload: timing.loadEventStart - timing.domComplete + }; + + logger.debug("page load time: " + computed.frontEnd) + context._.each(computed, function (key, value) { + if (value > 0 && value < 60000) { + context.ga("send", "timing", "NavigationTiming", key, value); + } + }) + } + catch(e) { + logger.error("loading times failed in ga.js", e) + } + } + // if you want to pass in no title, either omit it from the arg list when u invoke virtualPageView, or pass in undefined, NOT null function virtualPageView(page, title) { @@ -445,6 +475,7 @@ GA.trackBand = trackBand; GA.trackJKSocial = trackJKSocial; GA.virtualPageView = virtualPageView; + GA.trackTiming = trackTiming; context.JK.GA = GA; diff --git a/web/config/application.rb b/web/config/application.rb index 44b5ce2ff..60c645415 100644 --- a/web/config/application.rb +++ b/web/config/application.rb @@ -345,5 +345,6 @@ if defined?(Bundler) config.error_on_fraud = false config.expire_fingerprint_days = 14 config.found_conflict_count = 1 + config.web_performance_timing_enabled = true end end diff --git a/web/config/initializers/gon.rb b/web/config/initializers/gon.rb index 2201a6833..71c0a7493 100644 --- a/web/config/initializers/gon.rb +++ b/web/config/initializers/gon.rb @@ -16,4 +16,5 @@ Gon.global.video_available = Rails.application.config.video_available Gon.global.gear_check_ignore_high_latency = Rails.application.config.gear_check_ignore_high_latency Gon.global.purchases_enabled = Rails.application.config.purchases_enabled Gon.global.estimate_taxes = Rails.application.config.estimate_taxes +Gon.global.web_performance_timing_enabled = Rails.application.config.web_performance_timing_enabled Gon.global.env = Rails.env From de4411fbddc1df134e1c6d7d8f40a3ada97459c5 Mon Sep 17 00:00:00 2001 From: Seth Call Date: Thu, 28 May 2015 13:52:20 -0500 Subject: [PATCH 07/45] * add preview text and preload master on landing page --- ruby/lib/jam_ruby/models/jam_track_right.rb | 2 +- .../javascripts/jam_track_preview.js.coffee | 21 +++++++++++++++++-- .../javascripts/web/individual_jamtrack.js | 2 +- .../web/individual_jamtrack_band.js | 2 +- .../client/jamTrackPreview.css.scss | 13 ++++++++++++ .../stylesheets/client/jamtrack.css.scss | 5 +++++ .../clients/_jam_track_preview.html.slim | 3 ++- 7 files changed, 42 insertions(+), 6 deletions(-) diff --git a/ruby/lib/jam_ruby/models/jam_track_right.rb b/ruby/lib/jam_ruby/models/jam_track_right.rb index f28410e02..f0749dc94 100644 --- a/ruby/lib/jam_ruby/models/jam_track_right.rb +++ b/ruby/lib/jam_ruby/models/jam_track_right.rb @@ -344,7 +344,7 @@ module JamRuby stats['count'] = result['total'].to_i stats['signing_count'] = result['signing_count'].to_i stats['redeemed_count'] = result['redeem_count'].to_i - stats['redeemed_and_dl_count'] = result['redeem_and_dl_count'].to_i + stats['redeemed_and_dl_count'] = result['redeemed_and_dl_count'].to_i stats['purchased_count'] = stats['count'] - stats['redeemed_count'] stats end diff --git a/web/app/assets/javascripts/jam_track_preview.js.coffee b/web/app/assets/javascripts/jam_track_preview.js.coffee index a02a45896..585b500dd 100644 --- a/web/app/assets/javascripts/jam_track_preview.js.coffee +++ b/web/app/assets/javascripts/jam_track_preview.js.coffee @@ -9,7 +9,7 @@ context.JK.JamTrackPreview = class JamTrackPreview @EVENTS = context.JK.EVENTS @rest = context.JK.Rest() @logger = context.JK.logger - @options = options || {master_shows_duration: false, color:'gray', add_line_break: false} + @options = options || {master_shows_duration: false, color:'gray', add_line_break: false, preload_master:false} @app = app @jamTrack = jamTrack @jamTrackTrack = jamTrackTrack @@ -19,7 +19,9 @@ context.JK.JamTrackPreview = class JamTrackPreview @instrumentIcon = null @instrumentName = null @part = null + @loaded = false @loading = null + @loadingText = null template = $('#template-jam-track-preview') throw "no jam track preview template" if not template.exists() @@ -31,6 +33,7 @@ context.JK.JamTrackPreview = class JamTrackPreview @instrumentName = @root.find('.instrument-name') @part = @root.find('.part') @loading = @root.find('.loading') + @loadingText = @root.find('.loading-text') @playButton.on('click', @play) @stopButton.on('click', @stop) @@ -91,6 +94,16 @@ context.JK.JamTrackPreview = class JamTrackPreview if @no_audio @playButton.addClass('disabled') @stopButton.addClass('disabled') + else + if @options.preload_master && @jamTrackTrack.track_type == 'Master' + @sound = new Howl({ + src: @urls, + autoplay: false, + loop: false, + volume: 1.0, + preload: true, + onload: @onHowlerLoad + onend: @onHowlerEnd}) onDestroyed: () => @sound.unload() @@ -108,7 +121,9 @@ context.JK.JamTrackPreview = class JamTrackPreview @removeNowPlaying() onHowlerLoad: () => - @loading.addClass('hidden') + @loaded = true + @loading.fadeOut(); + @loadingText.fadeOut(); #addClass('hidden') play: (e) => if e? @@ -129,7 +144,9 @@ context.JK.JamTrackPreview = class JamTrackPreview onload: @onHowlerLoad onend: @onHowlerEnd}) + unless @loaded @loading.removeClass('hidden') + @loadingText.removeClass('hidden') @logger.debug("play issued for jam track preview") diff --git a/web/app/assets/javascripts/web/individual_jamtrack.js b/web/app/assets/javascripts/web/individual_jamtrack.js index 9eff40023..82863ad74 100644 --- a/web/app/assets/javascripts/web/individual_jamtrack.js +++ b/web/app/assets/javascripts/web/individual_jamtrack.js @@ -44,7 +44,7 @@ $previews.append($element); - new context.JK.JamTrackPreview(app, $element, jam_track, track, {master_shows_duration: false, color:'black', master_adds_line_break: true}) + new context.JK.JamTrackPreview(app, $element, jam_track, track, {master_shows_duration: false, color:'black', master_adds_line_break: true, preload_master:true}) }) $previews.append('
') diff --git a/web/app/assets/javascripts/web/individual_jamtrack_band.js b/web/app/assets/javascripts/web/individual_jamtrack_band.js index c05f58772..aaac3ca8c 100644 --- a/web/app/assets/javascripts/web/individual_jamtrack_band.js +++ b/web/app/assets/javascripts/web/individual_jamtrack_band.js @@ -34,7 +34,7 @@ $previews.append($element); - new context.JK.JamTrackPreview(app, $element, jam_track, track, {master_shows_duration: false, color:'black', master_adds_line_break:true}) + new context.JK.JamTrackPreview(app, $element, jam_track, track, {master_shows_duration: false, color:'black', master_adds_line_break:true, preload_master:true}) }) $previews.append('
') diff --git a/web/app/assets/stylesheets/client/jamTrackPreview.css.scss b/web/app/assets/stylesheets/client/jamTrackPreview.css.scss index 37b871e77..c3cae6e81 100644 --- a/web/app/assets/stylesheets/client/jamTrackPreview.css.scss +++ b/web/app/assets/stylesheets/client/jamTrackPreview.css.scss @@ -69,6 +69,19 @@ } } + .loading-text { + position:absolute; + right:-135px; + top:0; + padding:0 3px; + font-style:italic; + z-index:1; + -webkit-border-radius:10px; + -moz-border-radius:10px; + border-radius:10px; + border:0 solid black; + } + .adds-line-break { display:block; margin-left:66px; diff --git a/web/app/assets/stylesheets/client/jamtrack.css.scss b/web/app/assets/stylesheets/client/jamtrack.css.scss index 0bbce8be2..238465fdd 100644 --- a/web/app/assets/stylesheets/client/jamtrack.css.scss +++ b/web/app/assets/stylesheets/client/jamtrack.css.scss @@ -198,6 +198,11 @@ .jam-track-preview { font-size:11px; white-space:nowrap; + + .loading-text { + right:-115px; + background-color:#262626; + } } .jamtrack-action { diff --git a/web/app/views/clients/_jam_track_preview.html.slim b/web/app/views/clients/_jam_track_preview.html.slim index 1fe91fb33..bf6f22d40 100644 --- a/web/app/views/clients/_jam_track_preview.html.slim +++ b/web/app/views/clients/_jam_track_preview.html.slim @@ -6,4 +6,5 @@ script type="text/template" id='template-jam-track-preview' img.instrument-icon hoveraction="instrument" data-instrument-id="" width="24" height="24" .instrument-name .part - .loading.spinner-small.hidden \ No newline at end of file + .loading.spinner-small.hidden + .loading-text.hidden preview loading \ No newline at end of file From 90dbb395bd3db22d07b3c5a12594b6fa0a4ac04d Mon Sep 17 00:00:00 2001 From: Seth Call Date: Thu, 28 May 2015 13:57:07 -0500 Subject: [PATCH 08/45] * fix navigation timings --- web/app/assets/javascripts/ga.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/web/app/assets/javascripts/ga.js b/web/app/assets/javascripts/ga.js index 3ff2c28b8..68a6c629a 100644 --- a/web/app/assets/javascripts/ga.js +++ b/web/app/assets/javascripts/ga.js @@ -303,11 +303,13 @@ }; logger.debug("page load time: " + computed.frontEnd) - context._.each(computed, function (key, value) { + context._.each(computed, function (value, key) { if (value > 0 && value < 60000) { + console.log("key, value", key, value) context.ga("send", "timing", "NavigationTiming", key, value); } }) + context.stats.write('web.timing.navigation', computed) } catch(e) { logger.error("loading times failed in ga.js", e) From 6ba4c4d28056921ead9ac5d42bfe6a2204b0b8ea Mon Sep 17 00:00:00 2001 From: Seth Call Date: Thu, 28 May 2015 14:06:08 -0500 Subject: [PATCH 09/45] * remove debugging print --- web/app/assets/javascripts/ga.js | 1 - 1 file changed, 1 deletion(-) diff --git a/web/app/assets/javascripts/ga.js b/web/app/assets/javascripts/ga.js index 68a6c629a..76c197c9c 100644 --- a/web/app/assets/javascripts/ga.js +++ b/web/app/assets/javascripts/ga.js @@ -305,7 +305,6 @@ logger.debug("page load time: " + computed.frontEnd) context._.each(computed, function (value, key) { if (value > 0 && value < 60000) { - console.log("key, value", key, value) context.ga("send", "timing", "NavigationTiming", key, value); } }) From 07e83971876005c307e47064caefc22f0aa2343c Mon Sep 17 00:00:00 2001 From: Seth Call Date: Thu, 28 May 2015 15:04:20 -0500 Subject: [PATCH 10/45] * add in page name --- web/app/assets/javascripts/ga.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/app/assets/javascripts/ga.js b/web/app/assets/javascripts/ga.js index 76c197c9c..6bb87c480 100644 --- a/web/app/assets/javascripts/ga.js +++ b/web/app/assets/javascripts/ga.js @@ -305,7 +305,7 @@ logger.debug("page load time: " + computed.frontEnd) context._.each(computed, function (value, key) { if (value > 0 && value < 60000) { - context.ga("send", "timing", "NavigationTiming", key, value); + context.ga("send", "timing", "NavigationTiming", key, value, null, {'page' : '/' + window.location.pathname}); } }) context.stats.write('web.timing.navigation', computed) From dd8b45cc28b6d16dae52aa13f1deace8e29b8855 Mon Sep 17 00:00:00 2001 From: Seth Call Date: Thu, 28 May 2015 15:20:28 -0500 Subject: [PATCH 11/45] * update how we track with GA (add more options) --- web/app/views/shared/_ga.html.erb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/app/views/shared/_ga.html.erb b/web/app/views/shared/_ga.html.erb index c4fb4d6a1..6317b2f06 100644 --- a/web/app/views/shared/_ga.html.erb +++ b/web/app/views/shared/_ga.html.erb @@ -16,9 +16,9 @@ m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); <% if Rails.env == "development" %> - ga('create', '<%= Rails.application.config.ga_ua %>', { 'cookieDomain': 'none' }); + ga('create', {'trackingId': '<%= Rails.application.config.ga_ua %>', 'siteSpeedSampleRate': 100, 'cookieDomain': 'auto'}); <% else %> - ga('create', '<%= Rails.application.config.ga_ua %>', 'jamkazam.com'); + ga('create', {'trackingId': '<%= Rails.application.config.ga_ua %>', 'siteSpeedSampleRate': 50, 'cookieDomain': 'jamkazam.com'}); <% end %> ga('require', 'displayfeatures'); ga('send', 'pageview', { From 6e2145abeaf3e30593fb97c426923432e0573b05 Mon Sep 17 00:00:00 2001 From: Seth Call Date: Thu, 28 May 2015 15:31:11 -0500 Subject: [PATCH 12/45] * up the sample rate --- web/app/views/shared/_ga.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/app/views/shared/_ga.html.erb b/web/app/views/shared/_ga.html.erb index 6317b2f06..fd648c627 100644 --- a/web/app/views/shared/_ga.html.erb +++ b/web/app/views/shared/_ga.html.erb @@ -16,7 +16,7 @@ m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); <% if Rails.env == "development" %> - ga('create', {'trackingId': '<%= Rails.application.config.ga_ua %>', 'siteSpeedSampleRate': 100, 'cookieDomain': 'auto'}); + ga('create', {'trackingId': '<%= Rails.application.config.ga_ua %>', 'siteSpeedSampleRate': 100, 'cookieDomain': 'none'}); <% else %> ga('create', {'trackingId': '<%= Rails.application.config.ga_ua %>', 'siteSpeedSampleRate': 50, 'cookieDomain': 'jamkazam.com'}); <% end %> From 43b92d4a177a5ff139e67aa17a52b1ff33738b32 Mon Sep 17 00:00:00 2001 From: Seth Call Date: Fri, 29 May 2015 15:30:23 -0500 Subject: [PATCH 13/45] * VRFS-3264 - help bubbles on jamtrack browse screen when not logged in, VRFS-3267 help IE11 visualize jamtrack browse page correctly --- ruby/lib/jam_ruby/models/affiliate_partner.rb | 3 +- .../jam_ruby/models/affiliate_partner_spec.rb | 110 +++++++++++++++++ web/app/assets/javascripts/application.js | 1 + web/app/assets/javascripts/globals.js | 3 +- .../assets/javascripts/helpBubbleHelper.js | 47 +++++++ .../javascripts/jam_track_preview.js.coffee | 2 + .../javascripts/jam_track_screen.js.coffee | 115 +++++++++++++++++- .../javascripts/jamtrack_landing.js.coffee | 3 +- .../javascripts/web/individual_jamtrack.js | 6 +- .../web/individual_jamtrack_band.js | 4 + web/app/assets/javascripts/web/web.js | 1 + .../assets/stylesheets/client/help.css.scss | 2 + .../stylesheets/client/jamtrack.css.scss | 8 +- web/app/views/clients/_help.html.slim | 26 +++- .../landings/individual_jamtrack.html.slim | 1 + .../individual_jamtrack_band.html.slim | 1 + web/config/application.rb | 2 + web/config/environments/test.rb | 2 +- web/config/initializers/gon.rb | 2 + .../assets/javascripts/jquery.visible.js | 68 +++++++++++ 20 files changed, 391 insertions(+), 16 deletions(-) create mode 100644 web/vendor/assets/javascripts/jquery.visible.js diff --git a/ruby/lib/jam_ruby/models/affiliate_partner.rb b/ruby/lib/jam_ruby/models/affiliate_partner.rb index 58c4a1b8b..4408ffa42 100644 --- a/ruby/lib/jam_ruby/models/affiliate_partner.rb +++ b/ruby/lib/jam_ruby/models/affiliate_partner.rb @@ -418,12 +418,13 @@ class JamRuby::AffiliatePartner < ActiveRecord::Base elsif quarter == 2 [Date.new(year, 7, 1), Date.new(year, 9, 30)] elsif quarter == 3 - [Date.new(year, 7, 1), Date.new(year, 9, 30)] + [Date.new(year, 10, 1), Date.new(year, 12, 31)] else raise "invalid quarter #{quarter}" end end + # 1-based month def self.boundary_dates_for_month(year, month) [Date.new(year, month, 1), Date.civil(year, month, -1)] end diff --git a/ruby/spec/jam_ruby/models/affiliate_partner_spec.rb b/ruby/spec/jam_ruby/models/affiliate_partner_spec.rb index 26c660daf..822a1f527 100644 --- a/ruby/spec/jam_ruby/models/affiliate_partner_spec.rb +++ b/ruby/spec/jam_ruby/models/affiliate_partner_spec.rb @@ -722,6 +722,116 @@ describe AffiliatePartner do traffic_total_day2.signups.should eq(1) end end + + describe "boundary_dates" do + it "1st quarter" do + start_date, end_date = AffiliatePartner.boundary_dates(2015, 0) + start_date.should eq(Date.new(2015, 1, 1)) + end_date.should eq(Date.new(2015, 3, 31)) + end + + it "2nd quarter" do + start_date, end_date = AffiliatePartner.boundary_dates(2015, 1) + start_date.should eq(Date.new(2015, 4, 1)) + end_date.should eq(Date.new(2015, 6, 30)) + end + + it "3rd quarter" do + start_date, end_date = AffiliatePartner.boundary_dates(2015, 2) + start_date.should eq(Date.new(2015, 7, 1)) + end_date.should eq(Date.new(2015, 9, 30)) + end + + it "4th quarter" do + start_date, end_date = AffiliatePartner.boundary_dates(2015, 3) + start_date.should eq(Date.new(2015, 10, 1)) + end_date.should eq(Date.new(2015, 12, 31)) + end + end + + describe "boundary_dates_for_month" do + it "invalid month" do + expect{AffiliatePartner.boundary_dates_for_month(2015, 0)}.to raise_error + end + + it "January" do + start_date, end_date = AffiliatePartner.boundary_dates_for_month(2015, 1) + start_date.should eq(Date.new(2015, 1, 1)) + end_date.should eq(Date.new(2015, 1, 31)) + end + + it "February" do + start_date, end_date = AffiliatePartner.boundary_dates_for_month(2015, 2) + start_date.should eq(Date.new(2015, 2, 1)) + end_date.should eq(Date.new(2015, 2, 28)) + end + + it "March" do + start_date, end_date = AffiliatePartner.boundary_dates_for_month(2015, 3) + start_date.should eq(Date.new(2015, 3, 1)) + end_date.should eq(Date.new(2015, 3, 31)) + end + + it "April" do + start_date, end_date = AffiliatePartner.boundary_dates_for_month(2015, 4) + start_date.should eq(Date.new(2015, 4, 1)) + end_date.should eq(Date.new(2015, 4, 30)) + end + + it "May" do + start_date, end_date = AffiliatePartner.boundary_dates_for_month(2015, 5) + start_date.should eq(Date.new(2015, 5, 1)) + end_date.should eq(Date.new(2015, 5, 31)) + end + + it "June" do + start_date, end_date = AffiliatePartner.boundary_dates_for_month(2015, 6) + start_date.should eq(Date.new(2015, 6, 1)) + end_date.should eq(Date.new(2015, 6, 30)) + end + + it "July" do + start_date, end_date = AffiliatePartner.boundary_dates_for_month(2015, 7) + start_date.should eq(Date.new(2015, 7, 1)) + end_date.should eq(Date.new(2015, 7, 31)) + end + + it "August" do + start_date, end_date = AffiliatePartner.boundary_dates_for_month(2015, 8) + start_date.should eq(Date.new(2015, 8, 1)) + end_date.should eq(Date.new(2015, 8, 31)) + end + + it "September" do + start_date, end_date = AffiliatePartner.boundary_dates_for_month(2015, 9) + start_date.should eq(Date.new(2015, 9, 1)) + end_date.should eq(Date.new(2015, 9, 30)) + end + + it "October" do + start_date, end_date = AffiliatePartner.boundary_dates_for_month(2015, 10) + start_date.should eq(Date.new(2015, 10, 1)) + end_date.should eq(Date.new(2015, 10, 31)) + end + + it "November" do + start_date, end_date = AffiliatePartner.boundary_dates_for_month(2015, 11) + start_date.should eq(Date.new(2015, 11, 1)) + end_date.should eq(Date.new(2015, 11, 30)) + end + + it "December" do + start_date, end_date = AffiliatePartner.boundary_dates_for_month(2015, 12) + start_date.should eq(Date.new(2015, 12, 1)) + end_date.should eq(Date.new(2015, 12, 31)) + end + + it "February in a leap year" do + start_date, end_date = AffiliatePartner.boundary_dates_for_month(2016, 2) + start_date.should eq(Date.new(2016, 2, 1)) + end_date.should eq(Date.new(2016, 2, 29)) + end + end end end diff --git a/web/app/assets/javascripts/application.js b/web/app/assets/javascripts/application.js index 474503da2..03ccbd2a7 100644 --- a/web/app/assets/javascripts/application.js +++ b/web/app/assets/javascripts/application.js @@ -36,6 +36,7 @@ //= require jquery.custom-protocol //= require jquery.exists //= require jquery.payment +//= require jquery.visible //= require howler.core.js //= require jstz //= require class diff --git a/web/app/assets/javascripts/globals.js b/web/app/assets/javascripts/globals.js index 175a96fd6..85ebcc250 100644 --- a/web/app/assets/javascripts/globals.js +++ b/web/app/assets/javascripts/globals.js @@ -52,7 +52,8 @@ JAMTRACK_DOWNLOADER_STATE_CHANGED: 'jamtrack_downloader_state', METRONOME_PLAYBACK_MODE_SELECTED: 'metronome_playback_mode_selected', CHECKOUT_SIGNED_IN: 'checkout_signed_in', - CHECKOUT_SKIP_SIGN_IN: 'checkout_skip_sign_in' + CHECKOUT_SKIP_SIGN_IN: 'checkout_skip_sign_in', + PREVIEW_PLAYED: 'preview_played' }; context.JK.PLAYBACK_MONITOR_MODE = { diff --git a/web/app/assets/javascripts/helpBubbleHelper.js b/web/app/assets/javascripts/helpBubbleHelper.js index eb68a4a6c..c8ccdc4cf 100644 --- a/web/app/assets/javascripts/helpBubbleHelper.js +++ b/web/app/assets/javascripts/helpBubbleHelper.js @@ -62,6 +62,24 @@ } } + helpBubble.rotateJamTrackLandingBubbles = function($preview, $video, $ctaButton, $alternativeCta) { + $(window).on('load', function() { + setTimeout(function() { + helpBubble.jamtrackLandingPreview($preview, $preview.offsetParent()) + + setTimeout(function() { + helpBubble.jamtrackLandingVideo($video, $video.offsetParent()) + + setTimeout(function() { + helpBubble.jamtrackLandingCta($ctaButton, $alternativeCta) + }, 11000); // 5 seconds on top of 6 second show time of bubbles + }, 11000); // 5 seconds on top of 6 second show time of bubbles + }, 1500) + + + }) + } + helpBubble.clearJamTrackGuide = clearJamTrackGuideTimeout; helpBubble.jamtrackGuideTile = function ($element, $offsetParent) { @@ -82,4 +100,33 @@ }) } + helpBubble.jamtrackLandingPreview = function($element, $offsetParent) { + context.JK.prodBubble($element, 'jamtrack-landing-preview', {}, bigHelpOptions({positions:['right'], offsetParent: $offsetParent})) + } + + helpBubble.jamtrackLandingVideo = function($element, $offsetParent) { + context.JK.prodBubble($element, 'jamtrack-landing-video', {}, bigHelpOptions({positions:['left'], offsetParent: $offsetParent})) + } + + helpBubble.jamtrackLandingCta = function($element, $alternativeElement) { + if ($element.visible()) { + context.JK.prodBubble($element, 'jamtrack-landing-cta', {}, bigHelpOptions({positions:['left']})) + } + else { + context.JK.prodBubble($alternativeElement, 'jamtrack-landing-cta', {}, bigHelpOptions({positions:['right']})) + } + } + + helpBubble.jamtrackBrowseBand = function($element, $offsetParent) { + return context.JK.prodBubble($element, 'jamtrack-browse-band', {}, bigHelpOptions({positions:['top'], offsetParent: $offsetParent})) + } + + helpBubble.jamtrackBrowseMasterMix = function($element, $offsetParent) { + return context.JK.prodBubble($element, 'jamtrack-browse-master-mix', {}, bigHelpOptions({positions:['top'], offsetParent: $offsetParent})) + } + + helpBubble.jamtrackBrowseCta = function($element, $offsetParent) { + return context.JK.prodBubble($element, 'jamtrack-browse-cta', {}, bigHelpOptions({positions:['top'], offsetParent: $offsetParent})) + } + })(window, jQuery); \ No newline at end of file diff --git a/web/app/assets/javascripts/jam_track_preview.js.coffee b/web/app/assets/javascripts/jam_track_preview.js.coffee index 585b500dd..f78a25d05 100644 --- a/web/app/assets/javascripts/jam_track_preview.js.coffee +++ b/web/app/assets/javascripts/jam_track_preview.js.coffee @@ -129,6 +129,8 @@ context.JK.JamTrackPreview = class JamTrackPreview if e? e.stopPropagation() + $(this).triggerHandler(@EVENTS.PREVIEW_PLAYED) + if @no_audio context.JK.prodBubble(@playButton, 'There is no preview available for this track.', {}, {duration:2000}) else diff --git a/web/app/assets/javascripts/jam_track_screen.js.coffee b/web/app/assets/javascripts/jam_track_screen.js.coffee index 43411b93b..ac25cc4c8 100644 --- a/web/app/assets/javascripts/jam_track_screen.js.coffee +++ b/web/app/assets/javascripts/jam_track_screen.js.coffee @@ -6,7 +6,8 @@ context.JK.JamTrackScreen=class JamTrackScreen LIMIT = 10 instrument_logo_map = context.JK.getInstrumentIconMap24() - constructor: (@app) -> + constructor: (@app) -> + @EVENTS = context.JK.EVENTS @logger = context.JK.logger @screen = null @content = null @@ -21,6 +22,7 @@ context.JK.JamTrackScreen=class JamTrackScreen @next = null @currentQuery = this.defaultQuery() @expanded = null + @shownHelperBubbles = false beforeShow:(data) => this.setFilterFromURL() @@ -38,11 +40,17 @@ context.JK.JamTrackScreen=class JamTrackScreen ) else this.refresh() + unless @shownHelperBubbles + @shownHelperBubbles = true + @startHelperBubbles() afterShow:(data) => context.JK.Tracking.jamtrackBrowseTrack(@app) beforeHide: () => + this.clearCtaHelpTimeout() + this.clearBandFilterHelpTimeout() + this.clearMasterHelpTimeout() this.clearResults(); events:() => @@ -57,6 +65,104 @@ context.JK.JamTrackScreen=class JamTrackScreen @noMoreJamtracks.hide() @next = null + startHelperBubbles: () => + @showBandFilterHelpTimeout = setTimeout(@showBandFilterHelp, 3500) + + showBandFilterHelp: () => + context.JK.HelpBubbleHelper.jamtrackBrowseBand(@artist.closest('.easydropdown-wrapper'), $('body')) + + @showMasterHelpDueTime = new Date().getTime() + 11000 # 6000 ms for band tooltip to display, and 5 seconds of quiet time + @scroller.on('scroll', @masterHelpScrollWatch) + @scroller.on('scroll', @clearBubbles) + @showMasterHelpTimeout = setTimeout(@showMasterHelp, @masterHelpDueTime()) + + clearBubbles: () => + if @helpBubble? + @helpBubble.btOff() + @helpBubble = null + + # computes when we should show the master help bubble + masterHelpDueTime: () => + dueTime = @showMasterHelpDueTime - new Date().getTime() + if dueTime <= 0 + dueTime = 2000 + dueTime + + + # computes when we should show the master help bubble + ctaHelpDueTime: () => + dueTime = @showCtaHelpDueTime - new Date().getTime() + if dueTime <= 0 + dueTime = 2000 + dueTime + + # if the user scrolls, reset the master help due time + masterHelpScrollWatch: () => + @clearMasterHelpTimeout() + @showMasterHelpTimeout = setTimeout(@showMasterHelp, @masterHelpDueTime() + 2000) + + # if the user scrolls, reset the master help due time + ctaHelpScrollWatch: () => + @clearCtaHelpTimeout() + @showCtaHelpTimeout = setTimeout(@showCtaHelp, @ctaHelpDueTime() + 2000) + + + showCtaHelp: () => + @scroller.off('scroll', @ctaHelpScrollWatch) + @clearCtaHelpTimeout() + + cutoff = @scroller.offset().top; + + @screen.find('.jamtrack-actions').each((i, element) => + $element = $(element) + + if ($element.offset().top >= cutoff) + @helpBubble = context.JK.HelpBubbleHelper.jamtrackBrowseCta($element, $('body')) + return false + else + return true + ) + + showMasterHelp: () => + @scroller.off('scroll', @masterHelpScrollWatch) + @clearMasterHelpTimeout() + + # don't show the help if the user has already clicked a preview + unless @userPreviewed + cutoff = @scroller.offset().top; + + @screen.find('.jamtrack-preview[data-track-type="Master"]').each((i, element) => + $element = $(element) + + if ($element.offset().top >= cutoff) + @helpBubble = context.JK.HelpBubbleHelper.jamtrackBrowseMasterMix($element.find('.play-button'), $('body')) + return false + else + return true + ) + + @showCtaHelpDueTime = new Date().getTime() + 11000 + @scroller.on('scroll', @ctaHelpScrollWatch) + @showCtaHelpTimeout = setTimeout(@showCtaHelp, @ctaHelpDueTime()) # 6000 ms for bubble show time, and 5000ms for delay + + previewPlayed: () => + @userPreviewed = true + + clearCtaHelpTimeout:() => + if @showCtaHelpTimeout? + clearTimeout(@showCtaHelpTimeout) + @showCtaHelpTimeout = null + + clearBandFilterHelpTimeout: () => + if @showBandFilterHelpTimeout? + clearTimeout(@showBandFilterHelpTimeout) + @showBandFilterHelpTimeout = null + + clearMasterHelpTimeout: () => + if @showMasterHelpTimeout? + clearTimeout(@showMasterHelpTimeout) + @showMasterHelpTimeout = null + setFilterFromURL:() => # Grab parms from URL for artist, instrument, and availability parms=this.getParams() @@ -73,7 +179,9 @@ context.JK.JamTrackScreen=class JamTrackScreen @availability.val(parms.availability) else @availability.val('') - window.history.replaceState({}, "", "/client#/jamtrackBrowse") + + if window.history.replaceState #ie9 proofing + window.history.replaceState({}, "", "/client#/jamtrackBrowse") getParams:() => params = {} @@ -320,7 +428,8 @@ context.JK.JamTrackScreen=class JamTrackScreen for track in jamTrack.tracks trackRow = jamtrackElement.find("[jamtrack-track-id='#{track.id}']") previewElement = trackRow.find(".jamtrack-preview") - new JK.JamTrackPreview(@app, previewElement, jamTrack, track, {master_shows_duration: true, color:'gray'}) + preview = new JK.JamTrackPreview(@app, previewElement, jamTrack, track, {master_shows_duration: true, color:'gray'}) + $(preview).on(@EVENTS.PREVIEW_PLAYED, @previewPlayed) this.handleExpanded(jamtrackElement, false) diff --git a/web/app/assets/javascripts/jamtrack_landing.js.coffee b/web/app/assets/javascripts/jamtrack_landing.js.coffee index 2fb470923..5198a1f64 100644 --- a/web/app/assets/javascripts/jamtrack_landing.js.coffee +++ b/web/app/assets/javascripts/jamtrack_landing.js.coffee @@ -72,7 +72,8 @@ context.JK.JamTrackLanding = class JamTrackLanding that=this @bandList.on "click", "a.artist-link", (event)-> context.location="client#/jamtrackBrowse" - window.history.replaceState({}, "", this.href) + if window.history.replaceState # ie9 proofing + window.history.replaceState({}, "", this.href) event.preventDefault() handleFailure:(error) => diff --git a/web/app/assets/javascripts/web/individual_jamtrack.js b/web/app/assets/javascripts/web/individual_jamtrack.js index 82863ad74..ebb720f2c 100644 --- a/web/app/assets/javascripts/web/individual_jamtrack.js +++ b/web/app/assets/javascripts/web/individual_jamtrack.js @@ -45,11 +45,13 @@ $previews.append($element); new context.JK.JamTrackPreview(app, $element, jam_track, track, {master_shows_duration: false, color:'black', master_adds_line_break: true, preload_master:true}) + + if(track.track_type =='Master') { + context.JK.HelpBubbleHelper.rotateJamTrackLandingBubbles($element.find('.jam-track-preview'), $page.find('.video-wrapper'), $page.find('.cta-free-jamtrack a'), $page.find('a.browse-jamtracks')); + } }) $previews.append('
') - - }) .fail(function () { app.notify({title: 'Unable to fetch JamTrack', text: "Please refresh the page or try again later."}) diff --git a/web/app/assets/javascripts/web/individual_jamtrack_band.js b/web/app/assets/javascripts/web/individual_jamtrack_band.js index aaac3ca8c..22ceb52a3 100644 --- a/web/app/assets/javascripts/web/individual_jamtrack_band.js +++ b/web/app/assets/javascripts/web/individual_jamtrack_band.js @@ -35,6 +35,10 @@ $previews.append($element); new context.JK.JamTrackPreview(app, $element, jam_track, track, {master_shows_duration: false, color:'black', master_adds_line_break:true, preload_master:true}) + + if(track.track_type =='Master') { + context.JK.HelpBubbleHelper.rotateJamTrackLandingBubbles($element.find('.jam-track-preview'), $page.find('.video-wrapper'), $page.find('.cta-free-jamtrack a'), $page.find('a.browse-jamtracks')); + } }) $previews.append('
') diff --git a/web/app/assets/javascripts/web/web.js b/web/app/assets/javascripts/web/web.js index 99dc9de2d..a2a2c58d2 100644 --- a/web/app/assets/javascripts/web/web.js +++ b/web/app/assets/javascripts/web/web.js @@ -20,6 +20,7 @@ //= require jquery.icheck //= require jquery.bt //= require jquery.exists +//= require jquery.visible //= require howler.core.js //= require AAA_Log //= require AAC_underscore diff --git a/web/app/assets/stylesheets/client/help.css.scss b/web/app/assets/stylesheets/client/help.css.scss index b5c3cf17b..1bd085fa4 100644 --- a/web/app/assets/stylesheets/client/help.css.scss +++ b/web/app/assets/stylesheets/client/help.css.scss @@ -50,6 +50,8 @@ body.jam, body.web, .dialog{ .big-help { font-size:20px; + color: #ed3618; + p {color:#ed3618} } .help-hover-recorded-tracks, .help-hover-stream-mix, .help-hover-recorded-backing-tracks { diff --git a/web/app/assets/stylesheets/client/jamtrack.css.scss b/web/app/assets/stylesheets/client/jamtrack.css.scss index 238465fdd..7b3a27aaf 100644 --- a/web/app/assets/stylesheets/client/jamtrack.css.scss +++ b/web/app/assets/stylesheets/client/jamtrack.css.scss @@ -209,14 +209,10 @@ @include border_box_sizing; width: 20%; text-align: center; + vertical-align: middle; .jamtrack-action-container { - display: flex; - align-items: center; - justify-content: center; - position:absolute; - height:100%; - width:100%; + display:inline-block; } .play-button { diff --git a/web/app/views/clients/_help.html.slim b/web/app/views/clients/_help.html.slim index 2ec8bf719..9af12062e 100644 --- a/web/app/views/clients/_help.html.slim +++ b/web/app/views/clients/_help.html.slim @@ -261,4 +261,28 @@ script type="text/template" id="template-help-jamtrack-guide-private" script type="text/template" id="template-help-jamtrack-guide-session" .jamtrack-guide-open.big-help - p To try out your JamTrack, click here to open it. \ No newline at end of file + p To try out your JamTrack, click here to open it. + +script type="text/template" id="template-help-jamtrack-landing-preview" + .jamtrack-landing-preview.big-help + p click a play button to preview the master mix and individual tracks of the JamTrack + +script type="text/template" id="template-help-jamtrack-landing-video" + .jamtrack-landing-video.big-help + p click to watch JamTracks video + +script type="text/template" id="template-help-jamtrack-landing-cta" + .jamtrack-landing-cta.big-help + p click to browse through our JamTracks collection and get your first one free! + +script type="text/template" id="template-help-jamtrack-browse-band" + .jamtrack-browse-band.big-help + p List JamTracks of a specified band + +script type="text/template" id="template-help-jamtrack-browse-master-mix" + .jamtrack-browse-master-mix.big-help + p Listen to master mix and individual tracks + +script type="text/template" id="template-help-jamtrack-browse-cta" + .jamtrack-browse-cta.big-help + p Click to select your first free JamTrack! \ No newline at end of file diff --git a/web/app/views/landings/individual_jamtrack.html.slim b/web/app/views/landings/individual_jamtrack.html.slim index c3b6e9daa..cb1cfc771 100644 --- a/web/app/views/landings/individual_jamtrack.html.slim +++ b/web/app/views/landings/individual_jamtrack.html.slim @@ -1,5 +1,6 @@ - provide(:page_name, 'landing_page full landing_jamtrack individual_jamtrack') - provide(:description, @jam_track.nil? ? nil : "Preview multi-track JamTrack recording: #{@jam_track.name} by #{@jam_track.original_artist}. Way better than a backing track.") +- provide(:title, @jam_track.nil? ? nil : "Preview JamTrack: #{@jam_track.name} by #{@jam_track.original_artist}") .one_by_two .row diff --git a/web/app/views/landings/individual_jamtrack_band.html.slim b/web/app/views/landings/individual_jamtrack_band.html.slim index 88237cd56..9b2b72b19 100644 --- a/web/app/views/landings/individual_jamtrack_band.html.slim +++ b/web/app/views/landings/individual_jamtrack_band.html.slim @@ -1,5 +1,6 @@ - provide(:page_name, 'landing_page full landing_jamtrack individual_jamtrack_band') - provide(:description, @jam_track.nil? ? nil : "Preview multi-track JamTrack recording: #{@jam_track.name} by #{@jam_track.original_artist}. Way better than a backing track.") +- provide(:title, @jam_track.nil? ? nil : "Preview JamTrack: #{@jam_track.name} by #{@jam_track.original_artist}") .one_by_two .row diff --git a/web/config/application.rb b/web/config/application.rb index 60c645415..1e61dc1ab 100644 --- a/web/config/application.rb +++ b/web/config/application.rb @@ -346,5 +346,7 @@ if defined?(Bundler) config.expire_fingerprint_days = 14 config.found_conflict_count = 1 config.web_performance_timing_enabled = true + config.jamtrack_landing_bubbles_enabled = true + config.jamtrack_browser_bubbles_enabled = true end end diff --git a/web/config/environments/test.rb b/web/config/environments/test.rb index b20761c29..a5b075118 100644 --- a/web/config/environments/test.rb +++ b/web/config/environments/test.rb @@ -108,6 +108,6 @@ SampleApp::Application.configure do config.jam_tracks_available = true config.video_available = "full" config.guard_against_fraud = true - config.error_on_fraud = true + config.error_on_fraud = false end diff --git a/web/config/initializers/gon.rb b/web/config/initializers/gon.rb index 71c0a7493..f82a4a1d7 100644 --- a/web/config/initializers/gon.rb +++ b/web/config/initializers/gon.rb @@ -17,4 +17,6 @@ Gon.global.gear_check_ignore_high_latency = Rails.application.config.gear_check_ Gon.global.purchases_enabled = Rails.application.config.purchases_enabled Gon.global.estimate_taxes = Rails.application.config.estimate_taxes Gon.global.web_performance_timing_enabled = Rails.application.config.web_performance_timing_enabled +Gon.global.jamtrack_landing_bubbles_enabled = Rails.application.config.jamtrack_landing_bubbles_enabled +Gon.global.jamtrack_browser_bubbles_enabled = Rails.application.config.jamtrack_browser_bubbles_enabled Gon.global.env = Rails.env diff --git a/web/vendor/assets/javascripts/jquery.visible.js b/web/vendor/assets/javascripts/jquery.visible.js new file mode 100644 index 000000000..1e340099b --- /dev/null +++ b/web/vendor/assets/javascripts/jquery.visible.js @@ -0,0 +1,68 @@ +(function($){ + + /** + * Copyright 2012, Digital Fusion + * Licensed under the MIT license. + * http://teamdf.com/jquery-plugins/license/ + * + * @author Sam Sehnert + * @desc A small plugin that checks whether elements are within + * the user visible viewport of a web browser. + * only accounts for vertical position, not horizontal. + */ + var $w = $(window); + $.fn.visible = function(partial,hidden,direction){ + + if (this.length < 1) + return; + + var $t = this.length > 1 ? this.eq(0) : this, + t = $t.get(0), + vpWidth = $w.width(), + vpHeight = $w.height(), + direction = (direction) ? direction : 'both', + clientSize = hidden === true ? t.offsetWidth * t.offsetHeight : true; + + if (typeof t.getBoundingClientRect === 'function'){ + + // Use this native browser method, if available. + var rec = t.getBoundingClientRect(), + tViz = rec.top >= 0 && rec.top < vpHeight, + bViz = rec.bottom > 0 && rec.bottom <= vpHeight, + lViz = rec.left >= 0 && rec.left < vpWidth, + rViz = rec.right > 0 && rec.right <= vpWidth, + vVisible = partial ? tViz || bViz : tViz && bViz, + hVisible = partial ? lViz || rViz : lViz && rViz; + + if(direction === 'both') + return clientSize && vVisible && hVisible; + else if(direction === 'vertical') + return clientSize && vVisible; + else if(direction === 'horizontal') + return clientSize && hVisible; + } else { + + var viewTop = $w.scrollTop(), + viewBottom = viewTop + vpHeight, + viewLeft = $w.scrollLeft(), + viewRight = viewLeft + vpWidth, + offset = $t.offset(), + _top = offset.top, + _bottom = _top + $t.height(), + _left = offset.left, + _right = _left + $t.width(), + compareTop = partial === true ? _bottom : _top, + compareBottom = partial === true ? _top : _bottom, + compareLeft = partial === true ? _right : _left, + compareRight = partial === true ? _left : _right; + + if(direction === 'both') + return !!clientSize && ((compareBottom <= viewBottom) && (compareTop >= viewTop)) && ((compareRight <= viewRight) && (compareLeft >= viewLeft)); + else if(direction === 'vertical') + return !!clientSize && ((compareBottom <= viewBottom) && (compareTop >= viewTop)); + else if(direction === 'horizontal') + return !!clientSize && ((compareRight <= viewRight) && (compareLeft >= viewLeft)); + } + }; + +})(jQuery); \ No newline at end of file From 666fbfff2a823b406e424b4e2d064799cc3c3498 Mon Sep 17 00:00:00 2001 From: Seth Call Date: Fri, 29 May 2015 16:22:32 -0500 Subject: [PATCH 14/45] * remove stats write for now, until stats server is hTTPs --- web/app/assets/javascripts/ga.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/app/assets/javascripts/ga.js b/web/app/assets/javascripts/ga.js index 6bb87c480..b26cf777a 100644 --- a/web/app/assets/javascripts/ga.js +++ b/web/app/assets/javascripts/ga.js @@ -308,7 +308,7 @@ context.ga("send", "timing", "NavigationTiming", key, value, null, {'page' : '/' + window.location.pathname}); } }) - context.stats.write('web.timing.navigation', computed) + //context.stats.write('web.timing.navigation', computed) } catch(e) { logger.error("loading times failed in ga.js", e) From 8e75465ccd8c531ddb0e56a8179b77cb2644bba3 Mon Sep 17 00:00:00 2001 From: Seth Call Date: Fri, 29 May 2015 17:09:52 -0500 Subject: [PATCH 15/45] * VRFS-3268 - use our own webfont --- web/app/assets/fonts/Raleway/Raleway-Bold.ttf | Bin 0 -> 62224 bytes .../assets/fonts/Raleway/Raleway-Bold.woff | Bin 0 -> 31568 bytes .../assets/fonts/Raleway/Raleway-Bold.woff2 | Bin 0 -> 22592 bytes .../assets/fonts/Raleway/Raleway-Heavy.ttf | Bin 0 -> 63056 bytes .../assets/fonts/Raleway/Raleway-Heavy.woff | Bin 0 -> 29440 bytes .../assets/fonts/Raleway/Raleway-Heavy.woff2 | Bin 0 -> 24156 bytes .../assets/fonts/Raleway/Raleway-Light.ttf | Bin 0 -> 64528 bytes .../assets/fonts/Raleway/Raleway-Light.woff | Bin 0 -> 31592 bytes .../assets/fonts/Raleway/Raleway-Light.woff2 | Bin 0 -> 22628 bytes web/app/assets/fonts/Raleway/Raleway-Thin.ttf | Bin 0 -> 60944 bytes .../assets/fonts/Raleway/Raleway-Thin.woff | Bin 0 -> 27828 bytes .../assets/fonts/Raleway/Raleway-Thin.woff2 | Bin 0 -> 22740 bytes web/app/assets/fonts/Raleway/Raleway.eot | Bin 0 -> 30373 bytes web/app/assets/fonts/Raleway/Raleway.svg | 2168 +++++++++++++++++ web/app/assets/fonts/Raleway/Raleway.ttf | Bin 0 -> 63796 bytes web/app/assets/fonts/Raleway/Raleway.woff | Bin 0 -> 31836 bytes web/app/assets/fonts/Raleway/Raleway.woff2 | Bin 0 -> 22784 bytes web/app/assets/stylesheets/client/client.css | 1 + .../stylesheets/client/jamkazam.css.scss | 12 +- .../metronomePlaybackModeSelect.css.scss | 2 +- .../stylesheets/client/muteSelect.css.scss | 2 +- .../stylesheets/corp/corporate.css.scss.erb | 1 + .../assets/stylesheets/landing/landing.css | 1 + .../landings/partner_agreement_v1.css.scss | 2 +- .../stylesheets/minimal/minimal.css.scss | 1 + web/app/assets/stylesheets/web/Raleway.css | 36 + web/app/assets/stylesheets/web/web.css | 2 + web/app/views/layouts/application.html.erb | 9 - web/app/views/layouts/client.html.erb | 11 - web/app/views/layouts/corporate.html.erb | 11 - web/app/views/layouts/landing.html.erb | 11 - web/app/views/layouts/minimal.html.erb | 11 - web/app/views/layouts/web.html.erb | 11 - web/public/maintenance.html | 2 +- 34 files changed, 2220 insertions(+), 74 deletions(-) create mode 100644 web/app/assets/fonts/Raleway/Raleway-Bold.ttf create mode 100644 web/app/assets/fonts/Raleway/Raleway-Bold.woff create mode 100644 web/app/assets/fonts/Raleway/Raleway-Bold.woff2 create mode 100644 web/app/assets/fonts/Raleway/Raleway-Heavy.ttf create mode 100644 web/app/assets/fonts/Raleway/Raleway-Heavy.woff create mode 100644 web/app/assets/fonts/Raleway/Raleway-Heavy.woff2 create mode 100644 web/app/assets/fonts/Raleway/Raleway-Light.ttf create mode 100644 web/app/assets/fonts/Raleway/Raleway-Light.woff create mode 100644 web/app/assets/fonts/Raleway/Raleway-Light.woff2 create mode 100644 web/app/assets/fonts/Raleway/Raleway-Thin.ttf create mode 100644 web/app/assets/fonts/Raleway/Raleway-Thin.woff create mode 100644 web/app/assets/fonts/Raleway/Raleway-Thin.woff2 create mode 100644 web/app/assets/fonts/Raleway/Raleway.eot create mode 100644 web/app/assets/fonts/Raleway/Raleway.svg create mode 100644 web/app/assets/fonts/Raleway/Raleway.ttf create mode 100644 web/app/assets/fonts/Raleway/Raleway.woff create mode 100644 web/app/assets/fonts/Raleway/Raleway.woff2 create mode 100644 web/app/assets/stylesheets/web/Raleway.css diff --git a/web/app/assets/fonts/Raleway/Raleway-Bold.ttf b/web/app/assets/fonts/Raleway/Raleway-Bold.ttf new file mode 100644 index 0000000000000000000000000000000000000000..adc44af0b26250094fc8936f1778910969a0ab33 GIT binary patch literal 62224 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 literal 0 HcmV?d00001 diff --git a/web/app/assets/fonts/Raleway/Raleway-Bold.woff b/web/app/assets/fonts/Raleway/Raleway-Bold.woff new file mode 100644 index 0000000000000000000000000000000000000000..f4e18af9ebbf2fdaccbff652095b78dcd4c9278d GIT binary patch literal 31568 zcmYg#b8sfl_w^Gy+1R#i+qV70wl~Yh5?eW$vn zd+u!yMF|N22;kd%lmN*8J@0;e`~PG9^ZtL6R8mw006=~M0Lb|O03nIQ#rdnGs=5dO zfJ*kQ)B1+%Cf+u&qADZHH|P89>wLo~8r%xj)Xv!Pn_KyAp9}zi%Hj8Y{xfxVB?17@ zzj*-NH<;ij!1jQS7IxoU761U22LM1x3wwQ~S{S>0Yp{jBHPHVLKP+s$fZv=H03cxx z03`m5jLKHGG&eQ_01R8cH5~upt;NvU@|*nTuD^Z4Z;(N0gLPWkxq5zw_2WAZtnYCg zmoW+PZOom&`!S&c0MOh30Gc6m57bjz2h;Di?ti{xZu<{rZvsMg#-87?c_Jh91AzpRFmUVPC|8DDj{;m7&7hvpb zm+a&TLKY4-g9d^&91x{A{BX(K4!PQ7xBkDYJ#@8+8-9KAerp^0XBby2a$EDscA}aY zU|AdxVvqky!STEuj|>vH0DeUZmi;TcPq(hRMR$zmAvJWY^)Thu?4|CV#maK-%8d5K zUZy|klR7}vr^H@PubDi=v=M@Sv1L_en*=T)dcgL=%t6rVEdP7tBtvt9t zl1H7t(m<2YTD@^(3ISg$?bKhdWOFtngJ832}F;Ks9{!^Ks%zlVq#@2 za8FDB&w80CqlZCw|4?a|Wegy%q|g=2^g*)Ac6Q%Q@#E4@6Pmj{RkS_5b-}4WY@9w# z9Vwl%)Rb_iP1V<1n{SOV(+*eRHLy4wM%+&v>3Pe#aQKB6#c@P2F$Q~!zou{do7*-& zE&;O_(-(l}*Xs-g4cbS>6mFbw9Z4!R+$DD^GDwyhbEX+C9qgW&yLO??I1Z|6`s2FU z%{&h1TT3_Y{+<Iz@ z#pevl$g-w-z0%PdvUVB2Pdv$9cTC(>O=?H7dk#*wU5BeiEPD@G@e7FOjL}W?^O%3$VFe8b|DE}N0gKNBd+vYU zXa7a1W^RF;CtPVKqwn+OjFvQ_Gwnp4f>b+Pn9U0GV7Zns`?zTIhsdTp;gdN=#vv@S zgDBT7wT=j_RI8$coHx-4l|}b&Sov{ASK&Vxhn1<%Y{Ldzt!aDrL{0a4(tF&06+FV+WsqDdax}R{u>-ZIkm^s-!kY!WVIkj^1 zM$gwgTR~bCYL&sz>AD){WOy3<1zHL@FUZ*qzbLdY<}kmXNlDf5t1lq`nsHt>qdV_5 z`A0HQMqnxEEE=0>Jl=6<5(h^>E(d!+YW1xxEiUJ?Z^3qxmpd)FPM)1AaZ=!(0#%dn zY)Z;V77P8Gx%lct5ImM5K9C=)$&|(pv57b`nYsyO2sXO8hYPT;fW>RHk)pl|SLqM4 z&S=N6V^?w@BEt~m1A19@-vtDD)C>J+uvJF=B)M|KD|TFo6QxAg+*K|-Adz9{J4W<% zFT{66gJE$AcTpr!G zc&-__Q!(kCc%$9H$XxyK!c&kuh*;rc>75h4RAsAFW%7WcRdQg0z9sAlWpokNKo#kw zHEe`mh*L?|OOx;BDZZF-#W}uE(dYYnxG3LxyH~$E*0)?KTIVPm{S6pgf~UycGTtG7 z&4K$-!&D<#l{a)k?VU7XKk!+G(tuA)n9McRFU_33YtDD38TTU&1ok6+SoazaJyE~D zU~FF9x{^3>)N<_CY=>>U+<`$?;8vAjtnIV1g1C(4>;R8Z+? zrIXZBv z<0W5(zSC#vfW698ez3etY#6QQ3blwgTuR)ivvD)De8dbk$pWLuqh#c12njoScCCKl zW0V?VzAiBiT6%$!Tlj=@0yh;4<;?|ZIt=u5@HI1u3q{DAI1qY_R}83PreTq=N+ZHq zI5>;{6h5UURzk(|NNAcG?rySp*la8L)SP-H@NuL3^-CQ}f3p``T6XAa zo>7y|Aw!=%vwLFirTe*e(5Cyjf{_P!J8$qN$hkxvFIU{=ew~Yb{pIoABd!0}PCCQS zP5Kr3UVG`e z@=g&ZzeMireh|P^WE~SK>xlqF(x@r2(iRoB|=c zM?q`mL~G8TBW zYZ<|woA#sfzUZQ>xfp6#fY-R0H>|O2K~|Vj*R!5g055Lvk^1zg%=*Ntg>Q3YYGm(? zc+040q+98L_=J~_t3lP2rEx4#VY5(n$bCGxh;GX4Ime_(mq^b8s)Cs6BAKmxpv*f% zfxLln2sjjpudz{m_NeV9Kj&se-ks6;&S}LiTah2jOO6Dz(kRlVJcH8OP8Ea7spGnU zGA$TBHn29%!kBl27)o^28@sd5q4cyrZbi5==WDL>B#+WG<1Dh(lrE7JgVeehUf5#P z@ynrib}^L69Q>=D+$Gyuq^38pWRjaIrk}GvYIR=u_txLa*s^n_lKjhjNgG&oE6t%? z3TeZy(4yI^6X?cS*=}01Em5RRb6Dmo^4B_FJ-J^2O?zvplufpXPhrsOX;fRUyd{Zx zp{M9T;a1-tbCBORGEVvtYCvb=50#HfBv&&3;iiWVy{ubGc_kau3mdSG#2gUvrJS40S@!p7}Zz_EId`bNr*X53ieVeF)bO3fY&? zDqCyVKb~^34w{>fd9?uKE^cQ^; z?&DZGaqek!v>WQJ5C0_p^18|itvau-C*v^Z+E|&~Oj8%t_LX5u%C|tvZ!017DOOz~ zpEN}CXh^J#tzW57P^b7B9Oy3b;p5*q0TCzxv&*iL$O4D+WqVEw*Gb0(_Z3Sj3Q*sDCV2sdpIeSw-ze zCpEqL2iL9DeEt5MEYZxkv)+dj2$;-pz}ik7#jRQ~8zg5rEjKF?@C$Y-=+Lrx5M6nv z#L%d7RPb)RF>ZZ?pzR)75l`%Qy44vS77@TO=YGTJ5G=H}ENa@2wS1+;vB#K~Wr|uiTJRw~6KkWrf}8B> zDG6|2o4B0gYS+BxL2KRYw<$@BElxRy7Z}$iy|g9YD(_JDvMG#Na$sTT^{$8>s~=kd z+SC5En{gFcOwM)=t&iovc2I~kNiXR6$~Igl?RJ*-ALOSPR?Nwr3mB(&W7x0f;ao^l z|2V1Q+n+A!f)sv~V6$f5`XkI_dXcgsx>o7%YljF|bI3pt%g2v&-1*Jd^%cZY0%b|L zra(zO-(dLgSZl$Cx~jm-0Ff?^^>_8ONy^J!FQ@zX6#>EPiazd}4efwexI^$WhNXj%wuIT@r#Ox;LZ5>$7hXb5y?b~gL5laT z>wNJ?_&-h)!HPn}T+I)9e2po_;OE2>oq!rv`-Dc!a1(8`&h_Hk58qHW_x=y#h_0de zXXho;vdRn~5#!+cqVsEp#Wqt{rU8xvSC)MJ6f3I3!uVh6;r1|PG}D6@ zZ)zIFS}*Qetz6j{SA#Vs=1{ck8XR?VM&|L!ewD5k8UmAF7MaWS8qjiQ*`cs>Ic7Jy zz235G#&(2g7PWi|`w|@iXJ#)-9Z~{VIiSy#-HOQtGtNUG^0_PMKTDmGJCpxC5L`Q#>t z(I6!>;8)ygiS5~&OBlK`b4JT0Z(b`5y}dh&)#Ks+Wx2YrWak?A+Qb^y;>GxqWUb6e zZCDy!bK)nl5a)mG4L$GNy7BrNpK(|+vTih)>_EMh&$DjU&Ysn!9&31#h*u*ndv8{~ zOJ^~n+LG8*_+`q*H?_7&ht5KtbJXq^*=RM(2=rN$-E|nHp$~gvnnL9|u7BSyl+`!6 zFuz~Dbf{S0UG0DmNj>vAiPH(!ON4nkT2tPN4Q=Lgu<6rHXolH}9ggMdUFUL$+ShkQ za+vS981vSdo$`Pk*Po4mLtZqkOwrcIT?)P2G>tJdZ{Mu9W#orD+8x>AZn=VXgDl9r zkayAye1RVCT=feS*;1Jp()|Kuoc|KfD^n`TP4!LjtJwS83V*eXyL1n7TjRWfl{HU+ zrAyXQneVEJ^%&-Eq0u0SR3A2?(OOMZ7m51E4RMF-MgDk6|Akn_sqkNA2ZVft9JCLB z2DyW@EY(kKc_cu~h4v0^!+ZPQxvf6KUZ>g$Q4`k0LlyzM>Mj7emL#v=dF?*rw~OEh zMhZtu$j+GOu$$0ao@!W}7f_ra^H_s60s(*R31Vsl^d0yc7ML6uXoaMT2?i#L6awrR zHyXHxqZ*s+nV1+E8S3fy8E6~;025^cLqk);Kxd_5qIw6K8r&I12L^f}^wa*iHjBqY zMVegzuJ=iWqnFa+3Hl< z<>b037P1)zvIub25rPa>?8825vMWR;^ml*R?(uG_@DY(kJZCrp4TM_|a&OK`be(pW zudq>Y)waQ0O)B*W!NKPvO|jRrN~|KgVDgI^q^ItQT|x8V_U8j|<@@S?@9 zLh8!Zk4k9b-#2f+Gh_>X90$ock5RPap$tT#GNzKqP*;c4%jo3)#VIc@Zfm2#t%-od zky(;rjd9};GW@vbT!&|!WLa=NtE^w+u(_{a#OK^}UPn#kSD(-cMsS{hk;HS`*sX~s z_gDNb`hCy25M(yIxX=a!SyWmqGZWLM$)2&%b4|bN>z6|@rCk13_s22_pm`epuO~>d znuYg<1Uz|j*%QMUj7In=;)#7l%WqwQN9sEu~cM#b!~@R>`FKoOq;Fh9s^t5||N-e$^CgOXtO}P76B?(A5Z&{yfotkIOiDR$dun7_?8mJ=| zb@f|e`eaf#aQN&M_t2A8lmCwRCut7im^M%lzFnno9us%y}Wu$GiC z8Y@Te%3>D|>6(dAA}P08@;t4e*gP3MCrWGfspVBiyt+$|BQTDUt8iQdT=e5sIM#fI&Z3WkJvOzX{APm5>9m@8#j2w!0Aqh zH|F+2nedjpUvpi02ytSxWZF;S^f!$RWQFz95scI#f>pQ_i6n!L7~?{M+C^pvdT~8H znal6r$ZUbRp>3sc73#tAL8i*b%GSg^IKjuF5I*(JSVKMNxb@L0k|`tkapIskdu>EP z(d4sJi7h;ns%fyrWd?^*L)MDqPA7pO5PnlR_bO+R^Cqt0elj=Z1B)BOEtmWO^DgBH^9iml`LhD|h2>ouDmpWhX|DG%sYm5JWQg5xf< z5zwj6w}5NZ;&pw4-{Lz>$oPr+q_o-HlV?36)|8@`JXou<+m4QEfpURun)36dAA2JA z*bu&I>wzeXZ?yirFf&e3lt1FQx%hDrZ&!-CK9`m+qBE%kvF0 z>;LRdKdHvYTPy;f^6j5{Zmz|atfuBiq`$hU5EhBcwcoAVpC8O*GBZmKEkB^iKza~( zye`B7h*aq}+kNgeSTNg>0aQN#w|uWer8@x52^@cbM_B*Vmb&S9{bx@yWi&1^Yn5bj&%vQo>>Zjxb6KXuWb90 z_DuoI_Pm}85qa@dD;FgQGYBG&(7;D@_{yXp^2d4L?sjhdJ~jQ3G-v(S&mIhCm@Sbm z0Gb*VmcKM;yjsKw2pW~}FRQ)OGBIQjBGDf`F@1Vxzv=ZZ$>p>vt_ZAS2vhGWpPfAT zs-LNUt#>|t=$5zZ+P0kyVfCat#TgCplV3PZiy_?18#YhL{TAnw5r9Es>jxpKEZLX` z|8=3)&~~EZhyrKkw9K%(o#KfgjPr=4pTHzkPn#867!0DQ`^l9)@%x&71Q9Zjf(40ykqDAYyMgS!LPo+`MJfd1MPx=!20jxqAn!Ux ztSy{-uT8`EQ5iKo_QI!UU8tw&NbI{FYZ&%X|WH>sRE~U4OucTod`9srs96$3h8-3Er^Bog}kR? zfO=2dA$qXIOnZqk=hA|ToZfGbqP%dmcbRZ`&&}4Bh$fH~H{{5z*mbDb{IondRs&H!wy?){su=RWIK zH;#d+_oP;U!dYyHrvY;aXZKR0Urk*e7h0S&%7u_Nj(C#35WqqiL>o+7BpzyFCO$rl zqbLMd1ez6ANccC1_ziU%&i4D7J;iyx3tXaEWmYPi=_UjWsM7O|ZIoC!?b{=B=^>d; zmm;mTTfBxw=vMIjN+~(^f*$FO77H>WVk<0e^*XmFVu|NigW|uaQh`hXmIe*niw=D^ zuXq2r?8^iTr0p(ua>+i0I>5gp$|4p%B}UgIGh~7FjrmU6#aFoEMM4fCl$7+ z!4xG=S2Fg>BD8scZ?_{f@p|p7L8$lRmvKMBk5l;PmCQtvD<~&RSCEDuL_R4qmGvk! z_4&}(-anXZe#ZHD5{%}wKVgJ2wz|Awwn;R{Y`Cgg=@v!#dY(t}9=mV&S-~KsxGR>} z{K`q+1pF*UR4)!j1#+btbz^7NHabQa{2>}u+dB{c0bap$Lj$2yBgaxBC#;bYv=^XK z1#unLh-n&dAsZES&>vOfdAbhhsc#*7{Q-ew%gjSAeJe$<1Y4y`U025&Hp`~J55?t? zfG!Q0AZ;|%Nn4el4{gpxK*P8j{Q;@t+G861kz;!*EPXx{@VTN=ERPBCUc32EO?|P3 zrAtdQjA*%tF6|#gh3Txi?d(7Fpte16dKrWaw#S8tVuOXbvl9vn_*#SPrd2M7zYw;8 z#okqPzdg=SgdJ6&#IfUPOM)h=*PaveNAy^=-HY@sn`Pg{fAf&(Tjix!jdW%xPkqqy zgmS&{xjnG>`$A{+#rXzV#^KM$5pW7auq!E*F%U{x>*AGJ3?N$+R@EHnzFez!^Q&RB?IdDM(3GA=SVWPh`RAj|0nZhs;G~cuR=} z1v;HI{2^q8H_sc^BL`U<&I6$)`1Gs-aJD(3iB@VALapYDLC<0^y5`0};x6NdA3A(+9 z3$L`Cv+U*ea4Vpi;dR6X*95otm+`X*^_Txmr>}OB-X&CXTP|e4-zDNpATR>n=<^3N zf`1G3upnoU3hPJ^RBDVifcA67ZI^e#nl=(PXnBsS+89DHdG!d6m>!_cz$tQebn<)a z$db47eBdiYQXpZO#pItq{783Yr2`365g?FOYs#O?*Z<_X*rUb=Y%vY##8T4|swTx^ zj19$>zj=z$;{5~44gqDWHSQyi=B2l%P|qCJG->c#yylZ-UlUdWt&R7kG@V_m9T%G{ zNDLbMjBjW7agQ%MoZt6i6icHYCNCLc&zZez@VM1{Y6CC6GTb`;`r^mwhy|5RkVL9z zW)Mwt3kUeMDVhqx8xg*2zu8Wi0UEX90~5zDuo$`0PzG(iOn{@`LsX%9^lTKTcJ$Ya{&1$~_ET zyPADO&Pn!6K{!5MQYF+R(=}$Ce~RPw9BL2oBNOs84%NT80VgN0fFjFPh+{$kWzrFsFb)^) zol1gS0Yz}O%f1PL> zZz&LZQ+sQL7)m!LZGLt=QD&&XmUh?uAdA~LW@QD9&gQ%{h_0-@wO$!dOeAw4XFWP; zJzCGJ-zYuciu>qE!_v~|P&+5B^AN1E8JwuUl}AL82g7NN_$Ns3BDGx;NbfrNEI*f? zbHOK^L|}GGj(Hwm&W7)Jm&r*Fy-TLUsxI9{chTdUr5Tpv z=a!qJ$9ZKk<9{^*=d?&C7quw(R&H(S)?);g~(buUYu{dmodlI$t`4n2++ z7LA%sdqa+TdVCsL)%~3OuC6!aQ4UGYXC9c4m^c7nAS_{~n*jU=lc}dU^?K_0t*ewV zH=Q%@yg)jeeB(P~fmO80B&jQVx8Ru0wWgLiQVtv zM-4T})(_`Zpg!|{m7wB`9#X!Ve(}%&Yc@2rG=v@j!l z??+N5|c&m(5-{A8CL*0BdtvtOh=l@3`IB{8dk zy6ZL1LqC>SNf+g)`PSC_Bet4r7EWIR-}BnLmB+GM+Gp11yrX8TPlDyYs=K|O4<2R* z6B>1Oe6yzjDj#Q^@k8e%bVWMYBL7|k5$`D(af2`)R;pR$$Mi)R%c3N(h z*t95e%5@xc6Zo%HJTL!n(0l3@YjNuzwY*U52F5;k9FxxaHX{LueP3(LQ19%pbIiCT zBH!DCNTl83j>e!DHs*(Zz$^lKUcpU7Hq1Dk-}%1mpxst04SlT&91HuUX<)Sti!%y~ zknN?5TX%=ID>{=;7M``3c$4WF3r!@B02DAQ5|&a-{+O+8|;gD6w7yE_#NrWv#Ddu!s&gZWkLl3Z4YoR0;ovwvBGgllL%*_!F`)zM*`E zoS5-?&W<;S(lJcdC22CDlkXT<#O>usESa!ctWy1eXY<7y=qGXTfER4~dvCjY;JO3i ztZeTdsM+Vp_jU{DXFk}wyrQEt$XU0G2A z9|&JvZ_B~@PAP(xk!r?YE|)pCYh8ASyzE9(Gdl%r&S`dT)<|7E^q4uE4)JlH?|K+W z!Gs1jDX!#txGb_0YPZi^rC_*;wMv%8c*vRMNl3)!-q$Fek8WSzc}>$ja*7g1X}Y`f zP2@Y#qn?GMmKUZ?F2&1{}kN$7;fOI$hNx8$;kzzynmz)h8vuOXp2s%zl3zyDm-zyMBWRn4_iJq$8$1 zuJi!#n>sUiyDk&tf1gX`zb#R<6}{H{yGT&M->uOT?q6g$ z!~?9rF?&rwi$;65dxo?>_hog=`@_|<^gM(J!#Fo?i&3=Am2>@Z=%ZCwHUJ&-hkQN5 zpT92`($=jdsmUQj`kqPZflF|dFYXOf%FPj-zHhN*k`h8fGU1SbC43-q6KwZGYhff# z=6piTiT?BX+81eOqwe)r?(2f``|RGVjxX|0q5Jz>=?rjUICU=Tfm`m7ImhaZno}JX zWSBZ{i!eGM{`pc=kd!4Q$%znpn3Bp{8w^!FBwd2KbQu5?Oh|l${cDdXt*IbC4K*PK z5He6w=y*mV>{~Y(U7rf>9@;0&c^WL&h097>usBPNC)ThZDzM6_8*PKi8}{H<7s38= z@v@P3rnq%_0dHB|RVnun9C)9^h=v`NY%w1Dug6UBN{;x{nPS{@bfB-T1kXo!CT>{@ zt+9H*=%!q%gpte21M#5{3Q+p1e_0-nVuz<7ij=ty$W7YnIgelOUS4~7Uz3qmSTPpt& ziC?3~*?|ZYM_F111B~{a!D+}%_RL4W9~`V;N!mFBoq^ugwkEbFUhf_7-J8eR4g@8c zYZn|l1^ekg+!u&lVW2PK2t_I$44^~XwM4s^0OVU0;vItuU+DsJLA8)geV`k_d%JZG z?!a0*3LyBsk2i`E(NG&gVbOLcvL?UXF?_Tql~8o48E98gRXef9^cftebs z<7^r$N=n1E%f3p2>S0Xm_`(ruamUS17D)Pne$pcCwtZY3bx6_|Oc6ktoAaSq8`S2j zP2ZSH#u!EJc~$@RD5;PTncdqq*z}a<=r}=Pd!cj3mHj3#y#45$DU73A%$87G8#&(ySCa= zv;Y%0G-vpNxZl%4h+{@QE-^|01V%s_!%Id{MCVTaS*8k4U&NSNZddOK`EWj^5o_u@ zR#Yi9UegVzI!jaNLiHrFGxdO(n3eYj>0#Z&l7*bT9c# znEM4hyH=aarh4NyE+JOQWh}J7ty>*3bsq+c5AUdVF)9D7Hk(Sv!h4{sACx1@!Brd^ zt=s%HAjN)lZ=ou!32Zy}uo!MIrA?>YZLmZR;hQdB*2@ zq!(?=t*Y|Uhz8Y->imX;;0AL%o?2;#mth@pGkV(_tUI>yUTJwUJbS8b=mw#{1rmYp zExO#svb#Sl3(io%=#Pbv^c^Rb)uutyyr0YbMx40f1~)0FJKw84n_nm>F`wkjQ`x@X zO@@lxQkB1)SAYNN-@(jPrPla6ZxMH=(G;xFFf6g*eZ-ZJA_wd!^VMDwO9d!&*x(b8 zr=FiSfFzHKUJoL9!6>X}4qdPxm{(^a>q?d;kOlt9u#U%gA3#P8 z{#{n!!aSGOthH*n5}(>UUmywbLof*ve%UF3&DnKP+ZSJGtqTShZ?qJYf%;lK7Gx z*fW>@XfoE5zA>fLN3D*?U(e)mXjJsq!L5rW)g28nHPz75-SxGEz=!RqLEfxlIilk{W#1;HEL9~OK&5cF#B;zz|XwY``=h~ zwx)(Pf#l|eeYW5G&hD@x;heJ;P`6l?lk{nq9k-=*XOcP z;WmkKePjZmdyIsLJ!V_Rfc+b0mi`E);z|i*K1`##>%Q!1BD~G>c}nJuPY3C;ZshkN zHAAvLa$rW7ym+G0v>9$?*=pDkmuJ@jPHnqxO)6x*ed4&aBWz8{vcP_d9mnd&gDl1| zQjpbW$lwM0SK_#@w3kfasL3iFobGfs5EZJ8P8bfd9;K!4riUGT6Y+ZwkdmCvqtmsQ zK>V?la7MqFT$C59z;VRKVMI7U!e$-g-M|i=sN~tX!={xD^jIM7>N+$z!|!w-J%6Qa zShnNtEeRHM)M4<`Pe#br5;|J$2Ej`dCy|^9E;5Y*PcloB-lI(FM9oOz#y^cv%Tm%k zK`WQIEDNfgvK%VWAQ>c7Ru{f`oBr}{&)%m?wf8MwkKHEP?&@!Vsfe(gUiz`IX|W$% zc5AzolYwD9P4U`*OC!+2#Q$N_D*M;#gc6>3Byx&1`x9Nfgq&qD_be3!%@Qjz`B>T6 zXnH4a9a88T8>b8A>vQb%lm?4OG3=~1RuCQABk?PU>Ydmr!BrQpHiA!F77VUnvjGHV zD2l~aNSD1`gZn#;!e(3>jCEYvpA3Q83E@P=#tN_fQm-jDjGuI2J|%`Z_!8@<%W+tG z7VPbjew$CY6V*JUjj40(CQWtr8z9g5?^$eCB!XlyW1Ym z-EI1UwAh*(WoVxA3U;Q>QtZ0YpYAw$)Qgz>ucCdUrl2>v&rkYIxqCEI6c*mxlw6c$ z?3MJO&EHm1XIT7@BN9o{RV2)^227Qsq5lZ-mZT-88}*zy@$^UqQg9$BDyoEm!6B&g ziJ3}(kWbXRDfHI)aKR_>*y4Gf(at;D-d_J3*sy+oY3em9HTDeb6j(&;TEvih@jdzT za4PyfGk0Ts@w`{NyBl_L?#h5woIMTAY{;N3%R>+%2^O3l4$e)SMJR#ojv^u;A#Se6 z`4)FpD-asd*{+MR5HG=*72;o&jl_2i;QKIVJktwU9fwxta##Ev_d6AtmAVmo15@4< z@l4fA>a>f$Au#%Tb_Jh9(+|~DCw5!Ve3|sH9_wIUAsnKC9}?zcG*w^mQ8u1~=FYHA zqy(JttN5l9)4z467>7wND=91XBxc50I0Tn%nezU?9f@8f%JryP(fSUQ&Z;8(0fl{G%kP zT$gJhO4TzTL&@gQ8a2GJsRwzrwy>Fqk^+1i^)4H#{C0!qZ^*!MK7hem?b#4VvdB9s zB`gUgn>_E9KU>mSYIi_sPmJ#e` z+EjSi*v(&-^oNf?+~U5u)!A8A*|^lHIr6qlQy)DdVQ5hqwPA+LvvbeKzlR`~F$x@o;oa@ArH;d#VL!1*`3%sx2|y zPPfrZ7;L^2L(iF&$|UCf2HJ=7@1vOsED(svP+XVy=B2Kf_*f3A_9f)>W&wq31bv@( z!+7yM$vf^^r!U^SkNK~j81+@QI9ort_^$>^w-Hy zGhXxISJla9NRh=pfzTx4LJuS#c8F2!az}#IrfLL@v3ZB}F*#S%<8+Xn&Bl}emIRgu z@1Pixwp&FWrYWCUK@v$*CFJ-ZrNxB!$g)=5lA|c98@Tqya znmvDhm1-y|M;$zJwID^ojubXpa0wCmN|l-sFoOpZe2P*)n5(R>N8VvheW##dRYG7_ zJ3BXpwmwkyRFu%f-Lmu_trU+{dWjM2)~&tKOyw(dyrp4cPFprUrp!cjw$U#VX~$cm z5>9CO;mp)wqDciZuTUb~f#uP)m(OR1U!HFu2j2SEI2lSor);dcEO40X7k777f3jt> z1XU5rV;{HJ#OvoC$Lo8> z#al;!h4Itl*CW!zqsnH%f6>gO_$0IyDdCAwVlmlu!t2c!n!s}kDY8QZaI+alH?_!wk&zHvW)0JJD2^v%#$vN&MK$dE#bX1K^K@IEhuQBe`C>TUXHm17 zay^V5K8|}y*SY`aALXeM4dY9cYc$<7{wzwTGocExK!6f^H;)<)p{8eTd)jDWJ8M%V9mK(gO7Qh5vRmMx6_-Voobz3vOm$WnT9JA45M)J)Z zv(;lpip_xC=n(}An!T)%LUryb9%10z|n_n%Xtx96&_C}s{I(p7&sDo{c@o=l> zyOrCy23qHEwm7X)4XvwMHAUieQRQUALa?ayKOw zaRbP>p0lJnj@502R2X!jf+@SQv}Ky3#z-f(+@RSh!rp)58X5v!_4&>*=?c><*+T-` zvrR@0!>0Bnqdzfb{$z>8BK!bTV!Uoi7cL?6A1jDyZXN$6&*Zk*WNK5FWLKBV9#Y|O z15`cp^(n7)H8#0FHz8(q@oaHovt=k$G(#MEf)B9d>TbT{%~^0H(~AD zGd$-oU7(EoR9RIOi0$9Zy75n%Y`_E}Ioab+rZouqL+{Av&b0-dr(1oY zYzKkOa4{xo@7g6REt}uV!-v9bn)fK@O|Ru@Zz6qh#Vhz_U}JFV3_33|;6CP@-%N!R zlUYO66gtRqodZ5<`9+a7^N9-0rAz++B70&mn=14Mt6^U#(ZRtum zDj_ucTMbuFe>O4y)qU+sLLLgm5|>drTSqBzrOK5ox69w}qSdCM;q!J%#F^qWw+cuh zN}TzQB(+pqa(+4UbGOyijVvaJcs^wmhw*|S0!gc&e%;rAMR0&uZ=x6-3N#{+ZPx7A zlfoy1ZKTzmFL9KOCFbSgYOg3qS;W>`%czM|$5qGSTu7^49hq}e3KAI5k=*7@ zND`S&dh`PmFJOTUfFbQa8X2`e(@C?^*&uBztH=VKj~Mv3LN1J0>Nx6j*gI><#J8rX zMZx(skTsTn8(`Ks0;f#uf3PlTt(VT$cjClEUoF?L*e;d6R%Ja$SPHa>#*WWkC? z@$IDG+63zmE-i8v%XF}>?LtggZBjkfEN`ot;J|p~vhip_4utjt;tJQo*3T4-`njfA z*%mf7b9mR!z)uy8i9=U*IwM%*?B&dw@%T<*ZYjxumImLepLd3i2sU<#E;=(ON86QV z_cPoUBOnGN!{hD37ZQUq#D>}vT91-#NOz5oh(K)GgXrzB(N|Lav?<6FhS#br#$bJ< zFZPzP_J+w}y>6xxR?2H*LW}9{8})OO$sX`QkLZd#5naVSo6YGDOTT=d7+f4DIfZv| z_zC9InVX}x;rD71=U)1GE4v^!EFFty(;m3viwS!=tGN(*0`CakfN(Q1zB}`O0jN4x z#VSN^ua#hK z=Na+ckpt!Cu9@M)sN;&kVlz0saNU&iG#J~;c0ot=-t`DnP$Bm4RYDZa*zd_lc z3D2f~qR7_nE1N17BsicDXHUbJFU8@GQ=f*Pwsnc8a-&uA;8U};#=rmh_nMQFfB8yi z9^3QdAMZK#{x@JA(e(tKq#lwYEvU0yavDgboNi@W5o9-@Pcj85W4A>o(YshIP(e%r z5dwaUVJ38_Mvqrf!uCq)3#)@uGMj~-awV>tD=D!`W>_Wkrb;Na>psrgR)i6fslIja zgu~l%x38=_8T5KgF=p30XfRUS$8Tz^uS_LV?ITSFk-SpebN}?pmBM25SUomc3sjl$yec z>HKZ))+R`u+@iRWTN`XC7WvhAeQciW@!@M*6X|=gddB056})a&DnH;0Tl{gi;W^3i zeU-vOJ!2RH~cxf z*Gi0S(O?0AT8plhPS+hF*f4A@xTKYAN=@?dLfjIvO3P` zbyy4n(C#y>RCzKz*ZIL)-U5cspR3ou{P=?xA9&z5X4DG-d=DsL9r(^5fc6gh)3v9n zd)h&m!Fz9#Z)Q{NMD=%4nawRe(rPomI&Kk=sxIK3)egX$fZ%qL<7|lj;6cgZBuR9+h_ICH6}w6+#GJ5g(=Y>=56ABg1qozF3x#}{iYd2A`$-Gjq@ z|GhnUMcadGep~ciN~GR@Zx_TZOE>PGRNT3}Y3;OKzI}e5h{TDTeSAD`Pa0Gc z5g*!x$D>RE=C}KkHO(paF3ktNzOMGcopStWjo&ZF&&1mAF;5uQhY5VK&KIvwD0MoB zhg@yDolYQ5kCW|REM|j99Nfk=0Z z4Jr9|hkJQpJSQl5oFodo(lP+r+wvUU@Hiy0l7g&i)g%|Z<8=#bYhQZu_rLVb`8Tma zwCf-LqVr|-8RP3efNAy&8#&N6SWJl7;<_tzL;}S%1aw24bXp%Dy3O|(0aqeVOllqZ z-xyzOnIl$bXdyDai~h-tuS^<*OIF*?DJ8D_ZTLePyLq09!+XB@&CXGXuRrm`OJ4IM zh5JhGr&)Lz5y-@<_u5Pq7cfVr0 zJk)kFuf89*x|pe1 zYCIda3P<#LP?Q`!A8MW{=;2Us_pg;Q**W`KF_WFQuU(6rpV={Qj-Q#XP9?37nI4-Q z>U#z68%AoYJ-g+g9-vz6zWy`Uhlgy+jXD3rUcl zZx1Bmp#T%yVl<#GNZkl>4*NRB)>j_ggcQ015odNpXt|PVl2{?6WzUd+)9)wfM&zKO zmLoS8!#&jPN+@>%Xm)~EDe1KIQr2BaMDhF4{=)Rm)$DHnUFDs7se4bYadbxpI2Qcyc;sp*RFyrRR0U@1 zM|WmQ2e0iu{p$1evF5={;r`R9LaM#;%bxU5h~4dWrz)Y)P|Az4_Si1u?d@>DkC{mr z9zDtYovlDi?oj70 zdj0*k0U7tv2)JctF^VP?{RoR8g-DEf4Km?yI2LA(8r?m(*2ka8J$vtc` zS&}y7z8VS1TFumGv?m2UqbbM|+iFU3OZnTVDSvB{@>gL0Nk8)P#0%ayc)4=5e0lI` zFG)Q5^2+7vRrc>kJKu~yl7RO;cJ9~MuXB%`_-*#IY z_@O(>(v6C5t50}Mo-c3Y_1bsmyk1503HDmXdS)+AZ)Pv==FG-->MM+WzxIyeX>sp6 zOQ-e~_ZQTIx<(d2YA4(6atTO#p}jCS+iH}i%hTC3n;U%t=));O(b~nUwya>3@`*Ty zSO*Ij3CA1J=V<^*(p@lSk*W}G!K7i!n2}(^&_TDj*ex#hD-NQlmrjyRb)oO&?pstt z3Md&yCOCCojKv?Ce6G0_|L; z{>*TsFmHXxJ~X|Yo4&6+cy=;6%+|8ha1^_ZUFj_6V{6vPGH=Q+oE;xOw~(J6e>A&r zZh|pZBSR^7As&wpr(6?b6Jx9X!f29pq~Bj0OD0*z{$X?|UDo!1g zbip|4=;mDS%%8?Ot$_}-nghPtx&H}cW^mZ$tPf}S$F5zw1{F)dYkQV29y4~P)aS=x z7(Db(*>flQKR>BHfAgcUB%wKMRW%DVcx3(I>=Ssty+`nd!WMfX?7SPEyJrswl4HPp zx5MLv&b!q$pvdsBuVv4cNs~;FEA411MM$cdV$Ls?fV-T_X433CIhkMvuLbj{?Hy&W zG?u4q`v641LpoZ(Q6Vvb6hn!KASno0P~36sli5fG!c&1KRHq;#Q(j$z4QP3wgMNzZ zQlgaX+=_?IhPlPJip42@cDiJZRAf&n0Y5lVO=q0{D! zBIN~xcIu4IkFZc>UuXHB)ZxTB+B^Fd@0+{92qM-Z-c*Yk1kvq)t&}}w2bk$Y*n3;B zm~eV?&BTzL&P3{w=&rl>917a}#+rfpcNpDSv&}9$;)MhpaKsA!V2N2Pu0-1Ho~+!p zbYB<_Q3^#@Jh5Q6SZrBQWb}=QvUieMKfIRpgNww-UbHI_H_^2#vF*DIB0^CbeX6x^ zG8gLqm6Ls?%h>}|*O164@}HM>RRe+Qu99|r{!ltSJe*Ds!GTz9Hl3NRMWeOZOnSB! z`_=L&qLxQ{Y%>oDkqoJlPqdwpaJd-HL^2^I2c}Wl@a$J@W-5>Zqwn*)5FnHyyH8Jh z=}C$`S$Dm3WA|U*QjXhN4s-Ez3+o)P5iABboSHbQs|s zm*iV+5bwNDf8sX##ceF$wcF&soLDc?W7Km;E^0{QqSACq=b{QiSJ&*D>7+OjJ3!^4 zZYhKJ_Ht4Cl+(GW+77!PD@5`{0j^9Q53XH_9G_?$ok=Gr51r6>2{Fb~2uaQ*Q>)VX zJpJpVgN@?i+1BW}rNU~k#K4N91wZl=o>3l09g){RM$aj^#)2fu_C{_5It2VZ+hzqT zo$-MI;yh4}ju3+Y95tYeMH1C;hIRm*ps^Ja8&DM1@hz2J1ZgIZ{His`&aKu~>jx*| zPjj)Etu+aOS`9vN?M3Hq?16aauOOb9IW{ggGhPaV-2OwIFKOq0d>SJ3zlckT2iehY zSXU3?@VJ#@I+DIzGj?&Hm<`W1Psf{i9~`Tlzi_cp^dC6?P;K8w?j0IDd*Omomygxu z?AB#R|1O{&a`I3+2X*(STl#UUAS;|aOmET?5jO={(!&OxOm|_ z5lDuOv45vuKt3TECG%uA%g~h^AIoNtF*GwhHa|W;RLP8HM0yO|`KUD`7Yj$Z1Z^#UrHfd77=~$gvHsY~2ecjyn)+;EB|EH4^na?E$yB5W$~jcMx8doG1l@CH?DYp%_ta=~OoC19-bX--^dZa(;hqBo=Sw{X1>G zm_r`2`JxVI%xCR5{kc{gzwqbrn)B}*PRhgTO(xxl0D>#Rd&$fCoO7th&Ni3}%CQ1S z1OrkfzYdR36ETxU|MNRSqM-11fg>siMmxvHuBF{%29nHdC9D%3xp?)y`>w+4FF*V+ z`=iVg<0K4kre)>arG4!n?zA_byrjM<=3lEAB`WZ+fxu?ph<)&~1}z9EXhA?%&l`-x zX}EIr%9X3(%a`F5m!9(+_DA)LMwoB>6!nk@llZ+15grA?d@(b@w? zNG7NthJXleq%z~~0AT=)TcHxv{ilQJS4c%7+^YPoF$8)YhJG-Du2Xzcvxyq|A!|T~ z4^Ac-t-e0N00aYWN5P&Oi5xdFey$iw6+AHoms>X#72efip;bP1VBTYID(W??Sc|Q8GP5+Ewudu* zcP`<%{LtSG?THwD@nYB$_nPg#h;<@XO*p*O<$8Q57q?ryAvy4O*RK=G=Ds5Q9{fm= z;aYzgv_3~c2vr0@l_ZUxm$$2weVW}^pYmJpX1B2`uPUs5ua;HUEuwf^4kB!5`?411 zOuV!WvB9xf?y&79xsyRv?ok?o#sA6qucND_RT}zb_DhQ^JPGF&zNn8h+cqD=6I(4R zZxri_D=79B2O4vf(^A$7(3d;fx|v4$i(BcWC%Yg15BaK;48p&{bG5Tkt0Gz zDp$~LpcK?@)@*wwDIjfMTSc(?DAauV$KUkT3gHK7K>FS82l!W`KO24FC6D=J_X8n- z&nCaAJUfFjNunx~*8uoPLW#DS==Z$eyt!^go)VMiS(-exo8^fxd4K{!LMf;~HnhaB z`!&>plFCL#Y*I`ASn59Qce)?wpY#!l06w4my7K&duS@}h3Kqhrc8?eA_sr7G^%FJ! z5>1fz(J$Zr9N!)lZm!bA&;IO2Oc;KKx`~aPZJSj4RLLc+qC}GhAQZ;|P1u0OSP9)Y zC2DT(P&>oE;<`6>tx-ZYWk%_absO|Xe&J^(PkGj!5n8F5%>uj*%H_`QQOnbsJMgXf zO?>GVX_NaImTLsN|;OJoap*?;PvjgKtqU86@qt4fhy$f-M<@K>;HVA>e3Oq=3LP;1W8xS?Q6Uz>lEG zn{8>^?(CM71?X7Nc&T8H@7gipYo5EeP#xV_TPV5Xqr1x^4^>;GJ=xSyWnyG+%@-Tl zXEHg11IHMUKO7pc1e2v`u3h%a(F5T?I2Q8TZQ)cUk(ny`v>aORgMVQCJWcj9Ep+a= zYj!8wNe&fq;gEB{C?Q67u`);n{_X^ogk4Mo(WWFzA|ND)C{anI4MIVpQ0uXB0o!O( zng*w8;HGtcPZxNoCU6Hey-K&^w@5FhamS$=^QvbYJ~7}b?bwsd&9?HEd!myGM?7H1 zrRUrwn_vqi#_lQ=XKQKeMO!18sxp_%?y0P`^B=KdWx!w>2t=%om_agr-8P(Q?yh>h z@sw?UJY;kR9Bd=XgLGndL^jz*v)NtsXdqp54h2K$c-jx(%(e$3#WRtRi4zS0i!)#s zMNaZ5u}iiV`~npfn{ouR*4S-EgTU)6Tbyu+$HfLCJUV4^!e;t)mrSj%4)YH_sjUx6 znuM$RA^{}Lu*Ktao(Q=1pkdrydnlnJL`$YZZpx*C$%#Q`xcJ|o-p*TJ3!i=T#+bV1 zuzgR9=>o>+clVFc*PKAX#Y6~zz@cIjgbTsuWB<@HxiyndS8Yk%32!~gh_-GSov$C; zk?Gvn5}p62?FZ-S`o9yxeM~u5!Ab6E`v(RFoCD6S5oNUcn~v^krvdtnIDzr%1lG&* z;(396);J52(!QRJ-wj!k!NI{t;D_pAOmI&p`K_N~C!4Xu3Gv*eYajnO$7sSSG>m;J6S7~63m^;-*45B0& zq+8ayxk3$nGYDH|M4Sqk1Kh1Dkhdp?j_Rjv$Ri6*IX<#noO~cX7ucOnSIh%0<1fEG zJLpL}(lbe?>`nNmBEIrq#UI=ik6tnG8Adj>Me4d^&XsM3+3m_f~h^QcI)I$KM!m8A^Sp;Zz zfP^;RO}WK4m--AFm+Ys7`6h>ML^)ukD(YBmL6QXNB5fQj;>I< zx}}gn2;gn`n~P%+RUXh>sUF=wCUtYPX`2%|Sy(vP92_w}_Ly~~K6Y|P>bfIdiR7D3 zcP#5-j7=Aik@LF;la7Do-uO*ddU)UYAxzR%k>6%xG6##}M9q`*05#G!sgjkpEvIBK z_PPgbMoC20VG?*Dp&V*TIST+aE6bdoq*0H=_0KLPYAf7UI!X~5IxnSXZwb$u-kqL3 zHNN{w=C0s;b8=>BIUJjuZIuTXeFyEs(@WXf!HI-3S@}ov>AA{XjmS{tWFl1^u8*8+ z74x}5=7cXDvIhrea?xffs>lZgcsl)4Cg1+H6G$?SIWUo1NUBi98GIzlWQ;Hw^GwDr z*i=aLN+yCL4KCgqo}kOoP-NmZ%cPAuJsYzs|L;t%*oxELz^_m zY|@t~vW=4|GRyMRCWnTAOim1q53zjSBdsQTqsmPWpOlV6fkWup%&-tR~s`6q^P%#qf;OXN1pev$d#A z3+>(bqVBERUJG`<)(!i0{-Gz#hhh>!&2$&Ljv@}2UGq7`2ce+tUHYlC>gE{>Xc_2q za&t|O<=*T+krJM~Ej3ZeO&7h@vOgzBEcaNeGkeRmyIYZ9uHtp(a|t8F%8OIYpf?eY zxS~a?H)KC+OGI3O@^o5m7Gf5YKazA^BS2y>1kYi5kW^2EVAo_K?sZ$u_`b;jAYfPC zS5K;^`+jU1U%LCc{UXmX8^cWaD{23s(v)*pidQBx`wj$igYMz{mtjbWC7Ya{kh>Lk zjCMoGF_&m(p=6@+IKD^csD*^c({K!W-RP4rN&-(p5ZXYz%4VPt@H;s|Rje<<{wc+o zUQlyiB0{rZ27co%!fpVbHq^Vx=9{~S@P?y5UKRdq-@&z&TodKU|};x zl}kj5%_bpKlLK*LF|yWn3p_(Dqbz2&rHctMjvBhMlmTDH4jheyy&Q0yinu~~RMZ{% zokWQOc$IByUAtez*EYyTdCM95TJA3wh(aPBVUkpzt=~enUjYq&Cw-$UbK*x9A_=6Gpn)Z!L zs^3f`ga)W(^Vv*V4s{N?M{C=Yy=Px@c(gS4N56CZMQhLg9ct;EhPN_u5a14kTcnom zxl9(bdT#Z`xlC4O)r){}1fJu1GHqd{tU^2-iL1F<*&1R3eDssg{nH1J9(nLjpYx{n z@yo4|%g3gXH1wVCuqUp5;G1uM`!_#8RIaU!J=3n9$HcBUzL;JK*j_f1NcHoWHa*Z4 zgK5AcnJQoh*~LBiG^6op*MIdluK%>r_|w;a^Vg{5T~6n_IzR0E_?-^NJ3#9m*Pw9E9ctGC%_+CC*V;(B$re<# zkx?nLJDpLp)$MYbzi|D@XFvPTJ;x{I)CGYz`inAai~HbpH(ok1qxev%_I`+I@R7@H zi_hDAN1^+Ud5@a{zwsKJiYe^#w&)Vwa0__{*vDT3 zuUOd`U3tL^R^l@&P{-rD@ZAE00Amgf<$6Pol8`owXTL!1rz#qcS9l#m15K5WWq)Gyue*34D3nPvX2k(0Z!>^jn7*B3hz z&<#8w7I$n*ad-2>=2B00000 z0C)joU}RumUh`j!fq`YpfAjxlEX6<(RB#6Xg{}r20C)jykpqlfQ5b~h|4(iEd2R2$ z+O}=GQEe-zZAZ1+sJ7dnwr$)_*1E};nd8Y^r2pO%3*ovEszgS>o~UQhM5*AKY((Y6 zxm<83>OMGh8ye~wICU*tQWqul633mh;TjyK0MAvTKM9w5qp#M$yUZOsMD@RSZs2O=i4x>V%AA*L7;|uQFdpW-z zUhsWFtS96-vB*pf<$4uV;#nuVt!CCUXA$NYkGgV?*?C@@z?rBw;K#fb(qq0LQRNMS zB?wM)9KmKI`#FjLIRa1W-cdY14<3nuo0K+X;fDvzxeXC=2bH*PlUMMO$6TMn`3-P_ zUCLgBvDYx!j}Uwz_YfyjQQ5F#`GcZb62bVzTvg$#-4JGOTA$Q|D4Bp#?67Ix+=%dR5-1CD{LfOr8N z*#~f&M}GJ5|Bae^?^S%?6kiagnJGk=f-+><73u;HuH zx0qda-3zwKDs&zL8pNQ6Fr-r$b|WfdR7HGF3z*Ubc4-{bo+hIa%zECuhV5F)T*H7C zFsMlkX$r$0j(B`j=do57F|G|vsEiF-#1^{@TkQ&L^QTF-+e_}z1x#xRd)+>NI^brs zf?1Exsf2kgV}V@PQLAOF)GAi%A_i5)kd`p)MzoGm&0@V>i*e7Ja2q^t3;$n74ev&3 zh)I9i?RnFlrq^Sr6=vPM%2>b~?RKpr?T-PCVwEPb+MfnBfgz1ySR)wG5Jq(ZYgNKJ ztzt~`NZqhe8@R{a>$Z7(yB4v-(|3A&m&(}fPt#r|^~9{3(=z7$X#sDd#TKzzD_Exu zjB5cCZiCyTb!^re(mvQ~w_}?wV$#!ed$`Bb^lBLgyv&S;vz{i;8{OgG^iJEPajek8 z7|<(NsRgXkYgnyWtkZi~Z&%|E&-H1oV_d`dSxsU>MQl(BzpiEchWkx-x5qc?G=4`H zut_WUfL5{D(>&Y~LmJ1h#xSb07}F{yw1Ev;N4_lfY7H}5L|PT|gtyaH zYZ%umCbWd~XJo8lQY%Ow#$J!lYXb|ES;1GB$AD(BO3PU1#fydA%k>A1&m9g9NrZtAWTE_uTlk=wqVt&o;vu*Yp^oJ5w*k-I$5%1LkR@qHh zt!1p!1!Ux6%r3*7b_IUauEfu{yEKn+4Prt=*q~`_w41R>i}-;5O0&k183|kMk8q#e zh)JEr$Gx0(&-J{Q{DOPL<6rbT_i6_F?P?s*9A;F&tlq=Ciddv&ev`Kw#(VUAtke)P zM`2L^g*7^lAw7X%J%UmF9P9O;7}Fu#rDcq32@_hy2F+rVCb3!PFzIOy>VNPt{Wl)= zl%4)7DUa#$r$;F|JwsvZqgI9%&P7^k3v#W3&4MUBIM2J*fBaF=epbuEN8f=6Nsq1-DZ#V@iG4 zhSnDOwK3J~}jA<5G9k5YlWNhMIk7;w;wSXO3K~@J$xm{XE)(A}NJ!Fl* zteev!=5-MZq`8+`tzcNo7||j|HHXa17_)8IPA{tB?K&}_UaZt4R$W|0))x%fRT#Fb zF=E$X)UL%kox`{a_+_nPLMM?u1Mc>4qh7#PpAq)i7Hrcv9?&2rRltWdf!#WVM>U6O zJ%W82#ePpe;At}cH0!b^B5M;CJf^4<%m<8Ftk6>!&>L8#V;Iy$3~3R=ZbVZ^n_#Wh zkogni{xqR6+^rR4B|>^8HoGl$IkwtOm{bYdwS*n&!EVo$_Bv#28)ofN%-I&qGyDB9 zHC)Dk*09R1#)y`1r)|ZL+BW=*+i2HfyZgMyyx^u)!hX9H*&EoO&{vT%%gCMzt86O< zHH$S`!;pqCtRal*6xL}GV_LwtCNbe@8nl9qwheiA+~egpYXkRsX+Q8ZZ5~c)0^2=( z%2TqtK=u{LD8r0aG3zmT@>WyZ1!UKUAECS3Lm$f&`+Zi`)mt#&iA zq9Nl552}ppQIRcj771)KCbKAGhoutRA)q9yFs|6-5k z@Tk@>?J?|*uutRIuSp!xuP~!`Fze=&#k?|D(92k)U;Qb)v5XZuivbN|m4=X+6N5U5 zAq`^K(?pcRs0OfBGg#*->otcl&%0AA_)#q*{SezVg&ms2!=AoVqsYk!yL1lIdKj-G-35A+tKxsf4W8$X*)RK_PQB?(tlEU1k7mwHxpU9@C~3OnTl9&)e;$ zl|@b;IG|NzAB6?dhv;Lcko6ZU^b7{{DzX-1m0rebO=F#2!w+Z{>+KfY;dwuzvlz20 zk<}JI?P*wTF|K3yS-po});uQEgAE$S-JZ8m{rDYCV3SVZ10HTx5g+t&TI?=twQAgF zw_=-@c|aqW^m;y|8Em(!k=})!wi#2l1zC%+Td(6$%_4mad$ovtp10o}PysVqz^p%I z2ab6U7c`7TR^+hJdPwUbt%m{iW2J_%N@=Xt6w-S5H#&>7A=cYXxI-tAHpG}+jXP~K ze$=+$r!|ALB*yg;epY#;B{89HY|we!tuxrDSCE#(CLPBIG>*+WfwUyjlGtiBxX*6K zHs$evhA^o#KIAEx^RYuOVyA7zluJuuw_ZhB5?O1ImPA?-``rPr11*VJl`!XFS`rK5 z7riATv}748J$$c9SY?+XvmCNAV!hprF}ntL+7|q%ZN*($z_^O|Sx?VS02?%kjdlfo zN9)+6Ic(M_KIkc1>;|MYkk&xP5his4AJ+u7+jZD!+c4!G(E|3m{k93&Az()5Fsrke z*Lf`RrcvImfbE93qPXM7_)0}r)|TJ zx}Vk%?sDUL7C)gU)Cfh^b9umFYeZHY}BvtI~v3$Pyc|5*zDm4HHIyA8@Ae? z<376!+x+PPFCnQz_+S1j%}5(yWF_u@w3{%gi6?;Ic!oHxr@LSyB@iVz&5R7 z(sLd064C`tVWRCf_;GV@6{Nv?Rc-nfqBhhfiGK6PdN#XTfb}|!F%_^u!h_nt$Fzv;n#B%}IjlA8R0dNzj$L{O>0OxCB=&k5S{P|z%(;0H z3o05xWed9!}{HcIg@9h7FIpX}cNeOPJ9R za_YpKU5a@PVv&^ham%s|TWkxq+EuupFZmCA+07WSEf}?}$SjJjb_edan=sAy`bTQM z3F!|Qwk;U3tr&I5h2+Bhb{nSol}{KW3jH?GNoU#yk+vw;ueAEWkrSZkY+dmF5`D=}s_;Z864qjo9Ay&TR6*rX+FRta0| z9&EK*+-KV{=_%XoPVCTmWG90uH?4QEz^e3ha&5A2;8yzwHb#U&>~i99oc_kP{UZG5{7gN!)`>Q7*!T)wT$&%PRvW-1|C@>u+!sHo~FxXEx@!& z$ZU+P1<0tuoQGL$u|PRZ)L{%mn!vEeF{%Q$(#)1vp+yY1LA{P49mlX6(H!#bSgQ-z zpfYkw#V(bw+hfw2M&=^ScsQ#u%(;1wDNz4CMw?@`8`L4J(ISTQIx;h3L~9t;FR@mu zSg%ox=?p%mGP2vjPLD}x5W937dvy^ro{JkB%oA?rO^1;;#h_lokct@A3FM0)Z;E_n zWRHQ3p7$XwBQ1|TTEMjCu-9YybO!r9%&revmyvfzW-u&}YcKC!M*17pXdP?a7P|sD zmD_`i+^raMIZ0usZNU__@bvw7pNDta4fs*_J07#guE4$S59~@jXj}0yyB6E+QatS8 zPP-9PZWrUUm6CrSWA>YPpIwDJ?GF5?`_Fa>e#frFJ$3``b$?(t;X(H?y9?VbfQRjF z?DUwF+r^06&%eKB|4uv1BX{)})H_(C3mDQIhBb>(okmV@$ZUo?Z4-XfHX|b);~K++ z&LiIon>?mj!KjyaECD^G6Ou1d|5icQa zo3K|U%xDy|8pJ&H`3Ze>2KkE#_Gl6NXy-O##9_6|h(kskGUAXChm1Iksv8+`Snqim zamWo7c6v-o3&>oAj5TDeA!7~mgb(m5$C0@j!!C0j#&inr*9g+)*hBySxv$qrV@5@0 zRAj%60nK8ymN2L%u*Sn7^>>Kb0tW1I3@VQ`Dq~0mWLCk5U4l`)i!mL?`!#`I z^OW=f{E24p=e8A}_HdV`ki8kE8Cj28JuUMTtIk#o*wx4g!h7vf4BBQ4*|ivUBX%7| z?Rt!B7FqF;TS08`T&)(seV%^5-GE8WA-jD{+pRdDGGqU$zh3q=8K^L%7-^G;nV3%63N25sJMou@F(MilIk9pejY2)S@8#RUx zsf_IFuurSlPs|~spChv?vYI2SIWkU>)f`#Pk$E1O=kYUk8Sb}l;qxAT!F`eO{w#fR z1-EM*D>R7#kEwL4-Jsq>ehc~f7rd;ngmEon!ov+7zsFPV6;hKO_ydn` z^O&Tk@AmX*k73=%0XL&5%xWBSTEo1jERga!+r$@n-p>>-xShu78v}X`IejBHA;|d} z6DlHeDe~89Y_(gEzJVRuhphORR=cGre-bGZxdBGX#43ME$+$xk7}qIGsDPA@O`1n; zq_Nd*#H41iL#@cKAUA~8#jlKGg$`pteaJ2gtMnLh-;O&pjB&k#3FVMq!QGm}Mm>*B zDk1NMt#&;g@R+0~utP0KJ7Zc;V4uoZ>Ke@n#22T6MoHOc55CRmBD6>;ZHoKL&xxGPt#-D_&-f) zM=5y$IsIYC!(lh7X-sPtnGLL$HrYT%C4BF1zM@7FwXLPX|yOfv)bllL5k zG>&17VN|CureRD|&VaE>B5#L5{Sx`s7*Yy$3!`y<8*=B542|IKWyFHxN8h22^} zMyM62)dn&{B6AT2bqrYvJD^&f({Z6G7iEI1P`VU@(^+m zm=NX>BoS~C!V(%1W)hAP%o6?+DidTAmJ}KktQABRuLk{f-bQ9d+(!OJ{zo83G)G!Tlt;`+ z97ujh@JT*Na7n-b00031007(odjJOj000000stfcF919M004gnNdN!<0C)j)jstE) z0Te|~?S@4>L2WClZQB_8D^9wKE~6{#%}d?R$Hg;H!3iZ4l~z$iJ-q8;D&vB1A;#-zUD4#L(>1Ip08&xHh ziIcMam@q?F*&UMHnSPX7Ag`_jfmMaM6HgNQxmEssujK~mXFyn}=D@DW5|&R`eJ}mi zGbNYP`=E}zILQ-X5>g@Bap+g&I3035EWU5*H#=20I-sOdN-LwRFUoo1seYa*uY!sy`J}R1 z`WtAFjRuG@M0MRIk;`DURn=7&-BeM{dvnw=)J$0+PT6$-t3t}`dPY%26cHRXICD+I(V~jOgV@))b%~s8Pv&MJLWj0Qv z7RH-sl0zm)?T6p~SZBRWCTnS~IPs#TkkksTPx# literal 0 HcmV?d00001 diff --git a/web/app/assets/fonts/Raleway/Raleway-Bold.woff2 b/web/app/assets/fonts/Raleway/Raleway-Bold.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..a7f14579160bf176b070887de8b9c006c2d57b87 GIT binary patch literal 22592 zcmV)0K+eB+Pew8T0RR9109Zf(5dZ)H0P_$409V}r0suk)00000000000000000000 z0000Rz9JlS24Db$Ob9Ruj!6*+3WBEqf`fAbHUcCAhHw+rMhk;F00bZfgER+(Aq-&~ zo8I||rz^BZ)_*Mf|NsC0|NsBrl}uu6+xXpn z4?OY!U|^N1RaQli%*ZIZr8-5{w2|eG5<9r}WYmKCQdr|Cg3-{81mtNZcgkbu(lVJi zLuw&5(W)mDq0}N`>L!$_HfxGgS?xG_%=Bbg@EH4rdqanf$CM@WeeF$J2;4YWGy!a) zmKJ#kQPYVfz8iNA%9QxrLVSi-E>$P$K_>>jaX1`cAV7fZW}&()0&)X+fSf~b`d{?F zvN!17^zZu5`e*$Y{a5`r{dfIW{VT1vYBzbWju2O|)_>Q}LGP-;KXiYd3Hra3KWc*V z?*}dj(rXxt^boHnk;C{cm$(wys#B`W>sbp%RBP1#;c!L?wR4Bhs_xdv{ zy}(?_PzJC{%AC|#11<>sqGwb9V7HZ8o4X)>#@-MB(AV$W{C4Qk2!g2OS9hsW6ru*y z+7ehdI77NsO?O3Cze&-Y`?@3Rh=u?mrX!j0EQNClWjh+inLvLeod)${jt0^M_ZF4w zPT#=dhKJzBg31-*HqNcV$z8}dNgN<)ccSwxP8lDIwA-=;DzOj};=3O3_}$|*7N{~2 zAmkBpf4a)6H_87z0Qmp(&DlWFg(MeOyrJ?)r1VMJ%@t&csK2Qz)Ky1o`X2yFXSdAI z*f3L_%_S3SY+98m`eCO1X{XdJ4SVuc|DBl=cJ~HAAV4sH>0VF-AnCn~PyLMVluN7Z z-4!m~6>d7$t{om!r`I!u8rCZ&C@1S=rE+vCNT`O0^2n$O#>U3jh8AUEX=)iBR-+@T zV@CKx$CIC_tZ2;{sg9B#3?g^_KnZYbes@a}4mQTlK9Yewtz3*esjIDr_ov$WpKLyI z4&5HbTM75jF%9G0FzLbn(g(@@UzGnPCkB+_#)80i()54n$NiECPIZCFk{z%EwZkr_ zJ?5$H0n$di-Z0)Yb{Ma>-7qg#c;3{~b{~jQN{(%aov!E(YAfD9Dh&R8g*+Neri5i{5b*;MpN zkSz94M0mmziieJ+Q*HC#?{EL!S4ugA5JW_VVGs$s4d?%*8}p|#qY5F=KnvZz$&YOM zEtHDx?oW*bDH0%J4-#lE*_1psr&FaNO{p39M`s*$Xx;$>z;bw8!0TtOUnD=?0Mrj_ z#ovdnJ4A1<^qbpjL0Lcb<2@_apD;KCM3g`XYRP z1E+%6qg26+WN32q9>2^k6v3oQyg5_&%@HEes>iLfyUz`W*Te=7LqgYGF;Vjj-*o_u+`}{_y4D@8NOqrSKv6MT9TH zhDb&v$rFl3+O%AII_F?SO`ZPvs7ysTw%-BhwXgpr5onti_`PIstW}$Kox1c+o8C90f50oH~8RdBZNc?2fzcxo^z45c3#|W@A}o4#lK1J%(Z#w?R#$3ys}O2fQI?%#A?f zSdc8HB((Pq1G4Otil>W|09UiA<*-J}*em@lyiFR)j(r#UKji=&Do4;5nUG;v1dk=E z$P}fdnamKZJd+ns7RNXNtL9T{eh@MUL$N~+@I%TmHA%fsG+{vL6U9am5#ZsB9;Ki( z#sNc0kzO*(xu#U$hPx`QQ?1objE1#G$e3Jb8b3Uoh^A>CEC#`sNfJIkQ7YgqRU3zV z7#$!(a15BO`{@q?3ejF;)$t(FRiZp?kjX7ezfJJm_r2PND5+s^_LzdA+ zOhPJ_^3Z>STghonEOYCG5~$&-W!6Rw?>bZ$?J4`RS&z6%S;h|Jb}}WT1*|!T73~Fy zePst9s93U#ZPGaZ2U_|pfr>KfFP%81J)IPU2C#A>lFs|_Xb~20&mLRNs+QLU|KyOI z_y(REbcj9~)TE~~I~n33KnMlGGmg)S5Rw?7GKl?LHn|+~IlYtbS^#)fkt0aO!piVs zAW4{wTOPAgaMFAmPzt+~(_Mc1CU8GQN7l=&uNW8)4aSTq9RuXX`wh>@N&oX?HsvGj z%@{oHc*a>Om_Z4fH7|=L3mMt;a?6XGK@QKg_WJvWHIX)DWYZCuGVMTpXm9KcCZZRZ z_4=x9s4MA_M*vyTDm?Fal%Si4ksT(nL$hkI_7e6>y#!^{vlOS65AaT)f|Qqk3KfC5 zqnOi3FGVjnIBmXZu%)BqaudE2=q__r=b8)sw{J>YbX&O#bhy1>edT~PWRA_Iz`ST2 z5%WC)eCIOEz{(8G$uZ%SlfaCsh6*R<55QR!5EP?mgn?N_mS^WeDB0|XwuyCy7Zd;g z0hQUQT7~XXGJz-xoPz+Px z4A3s7MzitjL;HetLsT2hih^lHMlyFw;b{a{K?%jp5&tGtv#S*%LyA%yK@a{i2rwk&mm#9pBS-lfZ-WC^>yf5#&`E(MN zn${`B={#~q|7>Wk?cy7>?0QikIjca7aEHdrUqoOIaIhIR+4%M7cEP59hJubgY$}IHs~*NkqSTp%A30TJergkp714Pj z2Jz}8vAKM&Eb{~#&*X&Q4R6cuS$p5$)5%3g0=Hx?YJB6eY_wRvl*Fh=tIesEu+oe* zgLR(lye?C6yRuRZqy>SozTTBP112M53^Yu0uy?tV{rEyO#5R9ImZay+mm=gQ7$0w;+yszQZE3#EIw{N zW>4V+pt0S2V$Y56Si`m`NZc{?UbZ1XaBx^@*FM(z6nFfbc2qJH9el$ot1U95`mPm0 zwTN0zS!vFi+Pa}^>1VCH6Zk2%)U32@nw*xOy8^@Wj@Bt;aNvb(6|sJ3Ec3Gg{ANbcC^k zbbGUd{7hD#$>}f(=6$JmZU|ZoGa`GPBcf{ z|7zA02R#T;4N}WxH8untxCYR<;7t12?YIylCo2qKGtf)He?Y{$?s3sHmcWy8%QB2B zyW;%*y;SbQAjjs3B3_mWiELZkq}B30jH~1=dVoVwk0oZSxqua%yq&QeyI(8uC>ikx zDub19wml$+cnzKoR+5T-u8Znq7he(Xk&M(;GFM{?4Dt{;*xs*3gBmXH$O)pc#o9i2 zlTZbk+q%?{5U~I)nI(=Z595oGAmw7b6O#x)>QaAf8|@;I$t0d+F(a}p)0v+*^CTUc znNNg}$%0blwWw}#?R7jHEABzL3B8#qu7o}1(tzr zImZ-|%Oan(9cja|Qc@=3q%_u$tX0~l!6rc4(4MG9EAS?R-wk0GPhxD|SYnk%+FDBF zmHELtu#uIS$nl6f_$DmKOljI46h>T&JnO>0qQDOWUD?{)pPwz>=;0>Ptb3+b@zu~o zOp>uEn!>{P{J)7fnVSstPWYp`DI|k(WnBe6HmazG=qYevDA{tB;4Bq@JVRuGfQazs zaX_Wf@aRBx4a0iKC??G%fs(+8T5@e^PDn#AiXYEnpP6OswW zrLE+p28mzOEzi}D_dK8=mW;PwqtAdUMM~zy+V`nC8DXv0 zLUU)Tu6aVnH_Ftecq=QFEL2gTau=Jl?ExVC${O=vW?5?jR?rYW>u9*GBHpg7xt*&jPnb?LN$!XD^X+jF@BR@E+PZ%R563#nURlt)Xhdho33l~`> zbd1EsitLAAJC$@vD^-S=WsdF)6b$1I&c5TU z8-S?1=v-v-Ig`IdI#S|_9&j#ZC9l;2hfC?b&FH5eG=ST)sceMI%T`W+9CN7KSXUwG z{KB90ziqzja3=KQ7%tf>MM0fnSzx{6)w|%j@ttf|JKLS|cQfjKkeFyR)@u_R6N8?c(Rlx@1vCYmIMBavv96U@96<~M~obv3)v zw7A=}dp6yC>Rz)`!~e)#`PB<3{->-NiN5}0H!I?q#lT6z4HRz;Hh-z%zXQ^jP$$mv zwhM%R4+@u7*6WrOqO~%IWuD---YaEM!@mpnf9z6IaxdW2SP#J_9XGK~;{~$GK17Od zWZA_*?Xb*W#07a5Do8`SHL4BGkj|KJua;yx8Kh;mS39mIDD^HXfuLv>wZj8rMLiSZ z$$mfYhu_7^u_i>fB#40<-%>0D_@etufT$x0u8eL&ZHH{@h~7$?gFs-F8uAFA2-d1Z zW&n(-7*bzxvM%4Ki$>u&%$iZ-^B>vUsFobF_A>*2d-k@$Su6;ONfc9*9juC(+jwx)QZ4FFBh2*-Ag_ty6sx-+yQd%%Jo6Mr#gw8)6i#Wj6_%6% zyzh`oEz$4a3Zy^{lU7xRn`nbq3}DO592|++{1$VY4+1(5nA8?DB=rdf_0YZ#g0wJB+I7-C);MNt|xiRK~?8Hq?iHw<=NmUSY(o1yX z?-7S8EH}o?MlIdCs=KLdSPg90V!PcP0tG=N&xyKw;{jN#Xg2wWuEjvCehMOID!?a{ zNGY!@+(K)!9e=~?SL)#ckbmsm_CXv1X6+YuI)Kn}XHI1oI@KQb>@{n-bMl4EuhE2n zF){Z+OkyTX9$hy&emdqaGR+kLU;z;5>)0QdKHqe#r;XnJ>NSdq{R7|59+_;D-!plf ziMi5igvnmOXD+69>_+kC^Sc9_QB3xU0l~g*v;SG{V%Fw(PWEm@Dl!p9L$sEl1{O>I z9}bd#Yx|SD^Rf*HB7I(i(a?mHdirOA@uhCoKGJ6EwX4LVJqv7-m`L(8`8*~BNG-@kwOIi<^x=%&f?oii%i zNqxRoi~+Kp4!ue)Gh03W_W`3Wv%A3bPDC=qDLD5x;F!~}#Q zi7b>*ixo#jFGd#|6SEW+4pw=pl&er_=5q}us=88*9WB;OoqJ@0d!7V(0>V9u46eU1A+RB50Yu=XtZ*I5v ze@UgEDEpPYdDm{m>BsC@El$K^N&J-vZ{v=>m6amK#@tvb^&h5#+FzlNuesjwZ7=9( znW1JXYUwHm^rmT{PzhjGiDYfT^hm-_8N>4r1s`|MEb zNhVdZ)>*X#(@Ge*Cet=@pCJoFij7k>wMN&u!RlO<0167nbq#n3u2R8YfjjU@z!<7W zNODQ+?ksk{X@=3H71F3dl%)1YbYTsWy*F5$9ZnUl@ikkh*ag9P7M0&3P8;cPew#vq z!;uZm%rIclk=xgNq6({v(Dm-pUc2e2yXzL^2CubL^vG)yN=*!wHo$T7r)(N7RYu`| z=De@c6oA)pUHd=^(n2=fKpS6}+Etctu8A{k+ZZg8+QaaG(4288o_sS|=qW4%Ih>RZ zYY|Yr=v0IFAMYymt-a`39~`3c>>zCLu(04TGEa zne~HlJXK@PfVB&@?yJ!Xw52l8V8}^ta`np+ zw4Mofuo0%nnw>v}8yZUN!58O&CfQscQ#991T)w0QAf$kFM4wk*jpX~iGp%{*Hgx#n zDuuJs4q}Ar8Mv%2h4q7qHn&k!Kz<3bFf=2fT6u3GF}@d}MtM+7b%JzF?n1Yjq=f6n zMU)}?(BKva8_e1c_xNIk)QMCO={RxSyqUII`aIqQ?Xr!Xr6YW1ikdehdO{79R~vJK z7b1pqUyemm;jm<$!@NjtKY?&?{9HC|v!9fp10#_!baQU4hE=-Z1d} z5dwYy2*e>aj?ou4-}C+XRSg8cui`1V|J{iEpEdPgg}46~c=`YLLp%U~^Y29_?1TIl zC)#U{NS^w!(Q^^^O)_}1O=3H-{3Wyy~| z54V&0l>)wMS|DGPKd)Y|C)wOO!{3&h;i2#N)MzRE7Pb;9Ngq=BwB9V_9U9cW+-#Wt z!$nxwr>E8F>%EqDy>e*zXm)`P%(Ad}tiFux?)yh?JwIh+wIy2?;ou6D}7 zXsfH8PFl?%tR2-}Cx`X8YSfog*>{}K#kK(l(UF@J@M&xoCi9NaHT$X4G%^W9%sUMv zM2Z%+o{nRafjKz)V9xlWY?|MA;t;fS(spx^0_4vBR0!efswT9}Y~ijh7)`e(O|VA@f|1{wTGcJW7_6?j9Lu^0m1<8Mm`SpvdM8}lB{uJK zbALXIorG!-tPS1C%mxg#Ld%Ez8)BePLTmP3HznPGzf$GsU#>S=4_t{c%4C;?EDX@ci ziMTuzjz?yRF^!}vccUrkJuY;}gpa!#-it6LnB4{ZK?(oF+|TRCr(CFDRCdaQ`{i&MO^Ij(T1iZTWJ9BUjOdn=VFz z!4lH-o$S8Ro!z;ir9rc32u)ITE1Z_I=U^N%b5<3ZoJH4F4-cD#r$$RzWJ||Lc;dj0 zIy`}^6Yi(6l=@7=%wQBRciZlSVSpfKqzgOn^N4RJ#cJp?C)WQ&q}JY_h4p+5L4dXj z>mfc~)ab8t$IlxbYTa^$)tz&J(PiO1Xr*9wuPd3$w>GhSQY?i%?Al9bV?{=5nhU_! z-!`4nH;+|&=4FRMFuMQ569^1cRmRet4gu?C{;-GX!>uYz#oSun4+nrRt=8W;BWKNOtg6W8TvK^KAZcb{g~BeTQf-AK zhFww{uS}RPj;E)&m&`HL3=YN7=>n|Olas`tJ&cYpR+UPkyI}2usT%dz0+y6*me3h; zdTNgfnJwe40AJ?Jysow5Ko#?vN==NPEI2y8_u#4dHiMR;2*0*Vy|5v}w44nz6+V<# zcScW@T-3v$?2g@eCir-vKBuf8JJFG3I{V5^m4LrQ$puUDX%!YUg4b|tTFt@jh@*53H%NGS>pck%j$y;I zpMB%M&MjKWw@&gRIEmjhq8jp4&LjS}48_Qeos%4f@MyT+E!|tjQnbguUCPUr6);`0 zEmt7bqQ3iwer$6l-pZGSP!M^grsOmaR|k~A;*?LPUpAG^!gLUh%!4wgcZlYTZ|Nl) ztnJTDh1n(HntRRe;r~7IhhD`-+g1^#U@~bi=ZT=Y4NHTcgxy~i2aXl>bP2Gq)u~&} z!m~@FJN!Glyq4+C?1Q+u6E8vtfxz4-z8v!gw<$}E2zpk?FqDfkU7dlFniu2UX|}Wi z93foLm^E>cIjepOChY4nnViGhWUN;EI43?)1by}nhv(%kCG8X{h_1gr^Tw;CefqXN zCg&-Z!$`(`xCe#EJb#JHDT$tGN_BmFY;2eluAx9e6X24C9q0pPag6;?f&ip4&c>e(#Z z_Wm$mv`)X!^(>5raQ0lA%j)Y`YEN&3^7>Z>09_^FGbv8)m)lN_B&jJIO>-d%b(=p4 z6Dv3N9CMP?J83$G{>>9FS0&BS8Kmp%idxmvu+gDo*+~myUmgVOn0f7T@iLtYA=0Lc+pt=RL?Nl^^5kUPlaK%NW4=*wQ@==L^0aqI83S z-=ER9z@LR$D&?{Pt81%Tie`!Cl-HjsN)G5kYdpC#`3_c=SZi+7(JI_Ppu^4^eC|ay z4Lb>om(IB}?{B)FREqH{+$h^Jje#&&Vt7;yQ@O&Z3Eyw;pBvftWfq`QI`0o=GL}$$rP)@Y)StxvoNAk&I+3K+A5&l{F}D(z?U5I!Bm-t zW4Fu^m)^wPT;oq9MoMu^WOTX$O_{4T?zrxV0sQ94I&Cik!S{W-UU$!6M{pK<0!y>+Dsip~gm}$8Lmll^zX(XdyDThP>L@GmKJ^@3))-D@ z3gyQ^;>m?%^C#HNt#_N)3Zl_4_lVae4tvz1Em_kla4=mBNR-3uX^vKE)y@P!t3eCh ziYP*;fRKQ5002E$E#C)!i@WI(+;BBNbDbelixlYEoC#Mg8H%T2FJ7M^HQUKBmHZof zp1Ep}51PGmVzp1F;oTsKlfTo2!ewcL>Z@jWUhgVb-c$_7xa^$8p$M!J5)RQAlR?P+ zj;r-lY3!T9Ta8UKwl`cnc4}z1J7W7S@j6b0P%DOR z4HN=`@5Xi(#zC9PtebScA!+^CS~AbHYam;EDKQ#Jc6jP5@^mHsi7s`h28nKaqRd!( z&lO2fn8}j%pIl>l#90DkaU{qDzD$MpzmI9Aw1~*24wM&ixE3+IK)v^`dPej~p&Nfm z^+`H!ZPUM)a#x`$9U(O?>3UqlRccJdu)jc4YNjNuD^qRR$JE>kV?6C?mo=qDX!)c2 zD~^h3PT{7IURF6Tp&7YcBW?Q?RbYY?K|)=Su--68y^}Oco|>)qh;Iv(n&fORFlQL^w5)*m($pK|g{*uOs2FhdAjv@5!1Z zH?LEp@0y^Eut-B;nNT zoNjUA?P3WgE!RO3H{WfRI4BNGnn>2%@?qq8OV$ofE$65TG3b>t>0lUIb~<~&e*Vh5 zFuy)A;29z=dS|Z8OU~8m2iT2~an;%rBtn-^U{%YZnXZ|~EPF8ej{Tcu#VNL0o<2O^ z3iOL(f6f8nOrHtVcR2H*=^0vO(El4Kis*@&7$>kCXI3zv3I)`eMeIoCiFX)tL*F)lsdMCBGa3dD2Wz)AJ9 zR}YU22($vvh=-shNG!viVFGL3s0PVlV^@GPlx3c>q_AnS+)_zK)<3)=x0l3|_@Yk; z$bX#h)*E~$Xk6^2KPY8kcu>_n&k|?N4UHyx7CcqvmE7lBMm+Y47G~6!CDlvVv+p0u zwT^H3`<{`7w+8PF4vxt0j9l=HRMy?P6KQU? zv^*{+l*g*A?MkOhsAqGU(%6u)`z`h@$QI;*6i{Q322yhvSR2tE*cUO`f2XRSWT{0b zPz7%Y{;BE%gP|?b2A}V|Q`LV12C0V=LhdqpN6#9n1H-mSL;P-)^_r98srd^nl|%ea zz1}Ub%`jlWff5 zz5A$YJ9+$gYB+5fi8k^nq}SDM-5juT;fMZ@rMqCj&QVmvU%QFWEvhepB}T(zqN0V4 zur;1-iA^Q!A!tPkcA`;~kB}y=5R5CE`rrR+hq3C-s5O7Y!^U3vt;j8vl1V6WjnzFRMPZ|6? zAL^2|b-Ql1+VB01keE|Z%o{$9I*FPeKHPv9X2zZGN_d;myPLI{6BikaiNg)8tlEPH z!tkO?4CjPs{_tM#9`K@nOTXtX+VbDl{}ylS`I7MG5AROfm$nFa?azU~0rtS$^%LWp zf5wi&l+JtJ*Fr1neLkZ_BD>;G*P#C0L8XQ4NJ5Dy+Q8*_>6U1A0&XQU)unB$Yp*Wf z0RJMar+5V=)>^r|Vga;}d;ydQS2nkzr5Zk!tSnP^m3+3WryKP2PQ&(TPfyY2O#V)< zZ~s+IYT{^%Uo^unt3nj-WbD^-Z^tWa3Z)=sO1=8UH;xH9kTQ=Nm*^3(rE? zoMo9ID#=&Q&Ov|^@QzU#hHqSn`T}Su#tD>_r*Oq9V14 z5eqhv3y_R8A}GcWRgKW`8&lJpgeF6SASIRGppWM?B&OGijRJkR8Z_vH@vObFqM|5I zYDS!=EU#bG0{Hla#@{_n7fvv7H5|l)FRe9{sX#072{Pa9ugs0yo!vOr$3C4URZ3Dh zN;9!ouAmlbOqr~VI-;rENF*w(5qO>H=D<&GJ-nEIE2Yep=6p7SnBzsQyDwjtWJ5lT%(0v6#3M# z|14r9Z^+@R&E#BZ`pcPKZnF4l1_AH-pMY-FNYaIIW^%Srg3nf(oT3?Z$~rx;F8==> z#_0Hb=|)G>RK`>BtaoWatljc?3PhIu}yga@lh6m9z6R#0w4E(EgTm++Cx9u z*=vLsg!{{~SQ<06NTDDX#+uVu5=D-DCA&|}O6qj9dajLfwookTd)AITUDOe1Q?T(Y zrGh|mmKzr{YuWug-cq)3*{$}t6GKxWp=qK2?h-`GA70;G*IirRQ`ZALUpZLW@o!){ z=$FKEyQZ7_g>t%m?U)k+^l)DTDfg2m*hVn{71H3uRHXBBP~*qgJ~(1~auVG8l|p#P3S_ zf>xU23t}ubgB&vSLHmBE0yoE=7{W$PuzlI#F^2iz+6Y7_F!ZW6>$77Y$!B(7!Ri%XR&r_qVBbDTi6fO>+smQPK7gS@BPPf zY|x;At}?~$PBE~m&2~3asVJhF)T|7th~`wQoHTJ{CVOZPE7P1SNlD@VW0ytjjF{%& z#XZ70#4sG58lQm0+BHxd9;S6@?E&Zd&P@+k(zir*=fvyY$}7{A>NG`pb%|;<9_@PN zff(`(-KE`S26-LJNHcg!J!O4m-FFb@R~eCuv|Z2=*kpC+gN}HzkbZtU+I64(w%Qxu z+ZX;SGBkY8pS5AM?$X>+%pE9tsa-eW}5*DUaWu&LAr4D=RY^19W@Q!Tu8O z{Xj@1z!?u+zc29tf&{Qv-$NK;D)T3)LetT3u=X+sNutQ3u81sNtjAD!6#)^{psX7V zOEuyMf>3ZEqco$?CHBI}C8b4KQUT==_X9CboJM>{PLaqMPJLWHIm*$h`O}s#lFZ}D zbZVJYtrC-F`!|A`P6S(;AldM`yw?9Pt4}=6zQ~U-fzpOy8vh({ROce<6#K56T^Y?8 zizq?6CN_VG%zo(j@we=sSVwI3qpgF>)qY;mbXKg1lrK|I3RUI|mMkt?b}gszTQob{ zt|}*~oDETfCd1tnnCtblDqC?3$!kDK1Z)ey7Wq~IsoC2mx0 z+k;1&{#raSV`BE4P5*rR#vSnsrKDVR)bH;s;X5@;JyCEkCwgqZT*!eflqvE zJ06s=)v@ zBQgzdUcY3*XjpmXckc09@8+I=c#A8J9_{1C$^$R_0;$+(492N++PD+~VblL}CT35} zSiI>kFnun)es@!|xT24)I!b5gl}|)3)VBNB5c5Rb7t~UC&Lz`m4XWKg3ZqoQI}t%< zdQB{(a$zM{AK1rf$)cI~HTu4K>oJ4)FF}+&Hgu2A9vC|OUE*D)pZAOd+jgWTm;Bc% zDaGY3EIRhWWiMid+UfwRqm1x1Hh7NE*-3J}DDQW8J|SMp$kb``XmVu%Cq9MRY%ioQ zG`QRnReYVoZA)pivUu^1a$teP&XPoCQZy=By4PXMbEz7GaZtWpCEqBHv#6H5NG)I} zTcPgJM%V4yGN0Jr>srA(R>eQo%)PDOjn%sPiT$m4^ZBQ%1gD#Mtg^LYUlRJK5c{+F z{ve*R#LDEfLW9MvpW(+sxeVwhxfnt*nGrY~!fd9H%`X(vA+k-w-uWzLvT8T%sd?$k zwYy`uGUB(8rmsH-MMFIW!QOXx9a?fthNDt@ih9J{Z)tKa^Z(!I&IhRJx6(dG+G3YhoaH^5-L@0 zrdvU~b+V1Hn|o|>Z6muRhJLH6xn|hJUfaKw>q&4EcMiPsDOjo4I`r-ty(N3#Vh0T6 zf>^#L%xdtD&6cee^*wFOx|S_fxP1GW}f>f+Dr?PVE@T?fe_S;TZB++fJ>kS zPRYeSBDk;&emEG)UmMP{{&m%Q0ttzc+t}Cl5dl)-%M^#}JV18v|S94e6 zjXDYFFHT`A%_L`?49Z54Dzjx*vm4cj&!+CRAe33pymu~J>{rM6=@!#ADc8UWEStH0 za~sX_Ep4ww1UvTip*5GW@SltJK@oBHbK28muJ0-MOs1RRd#DyE@yX%*&X~pkZA9g3 zPmRY|5tjVL$nJQI1|8WFg+5Y$gnOqO*YrM^_b$$e=L1_#qsyc-iIOGJU1miRhw6t&lb4*y=h|ZXg4${~rE7$NYt_XYe3J%buEAA_D}Uhm zlRTq(WQjsuBQHHkRIjVjy0nx=i=jkNt0}2VO?|}AhMy;}%<&i&#~53(sWN*|y)ggS zi-?5M{6Rpiq*O7|FBq(Hk4zG*cXFm{+#sy$&0Ec|0hd6Zbvbw zfdtH}QymTrrJ6+l(3*%)U%3Ati7w;VGy*%E%#4TE^qx#hdVHA#`LpLW1p2&U|IK3G zid;MHw)x>!27{;@wBop&cofxgwnR8;AydB-X<(w-2Dx9u$6XF8#J$}%@ng!;An2cS zhJzt5>Pz~H4UPQOd(MoO|C|+7dNsZkQ82uOD|>HVUrcFMy?xj4U$YP&{OK)^_B}7# zJ9v-jwHlZ%Z#TioRyK{G?y_Jwu~l-lK543rO{0CJK-PVw_8uu&$EPPgHs~NUbr>1S za1x6<9^;S~$6lk*y1>71c@-ID?w|3C-r+!Uu)&T*3eSao6o>77+iOZ|0N7LOZ zQRDteDWxSQ$L{%^%<;YkQM+yI$g0R%ySp-k>(6ld^v!cjhTxrt>76y`f(+rM8>>re zOXsS4X7>yGz|QJ{>Bj$vUSv~6F9csW6X=@qV7u7Z8t`)OY z+p;IBWNYPXtFk8Iwu$Bh)@6gEBK152JUwJXK4?k12=qeTW;LQ?sZlt)>M9a7 z$=s4Kc$wC#=w`g>sw*a&gkYeNI65WJf_)d-+cyJ6J@EFiZ|gGEoc5oFPga02w~gso zkzx8qv@$5r;$^NroJZ{LQ>8PqOUE;xJ-g#7xKeNsN03Gwf@TX^Q^9xLv~}y)iz+g| zq(@sgLpdkRcG6tLDH%cH0CJdN#>hRwXa@3iE;2f%dqb7o7{9tW_mGt$u4a&IS!cGk zPRz#sPTyb8d*9}%-yr4v_Rr7gxARSLQSq$H0r9}a|riUl56eAeaXn~wsKXj)F;VH5*I?F7~45o8GF?osOxAl)M-8> zznN=7^wt>z#AabZ#nqQdGXppvVweZE=G!{=(S_&&M8G)E4L7=sF2pKfD_!=a|^?aQj9oMnvD|LWCCzbmR}$4Zf~xStu>j+ zsaD!kO0Va1XMUCVx+fW$hF=JsevbEmby~bWw!zgKtp{&)|(*YVS*a> z&p}FAd{gW^jYHoxwGwe}R36}Z7aK+udZsxDvk3vWpjHl@R~oE239OgtyGx&B0W&>w z)P9g`aOE4jI}~*Q(W)6T8)mU@Qk%8nsk#XgAd4cuSIe%sei_dIf>#tYX_A<^()Uv0c!jR?vH{W)sat0AN&jz?&E9MRE1V7=}!HrAkgO}(TxS+1steqc5+sK)1TiG_Z^fvvJ=KryG&nH9>kYVLnpbnYddiP{bhxOXjUzQ zzXa_8RxPcZICSJ$J48AS;&kjU+?2BOLFi}Z^!L8Y4U7c75*vVf+~4SU=&FvKI4@AH z)6ty57rhW$(kOqL*4~J&f;rg(*TXI_Kq=WN`qo%Pj$}IR7)R9+uH+Hp=o?|~8{)5* z)6ch;hx_Zx_DA?fjlqzj;_v)EQPbz_w!i}JZaBpPi?KJmvVQ|*q|e=n5kg(yXiI#N z&tqNXSH)G9CWC7V{N2kSD0O%=F&~#9|@s&dU{G&^bp*(4DD11bi%XgT2QZ@m^ zmB(e!$lq|p4i9VzPtdB6hyHFP1Z3R=6H+Y;j?Jm%MwmFP;R8R^?Ji)4KsbUp6*?#w z&kxk0J9846*sPPGB<^?@Dw;oWpU-JWJ!?hd+J1W@SlIbvJSva5eg#+ll_bHnZ8S5k zS9bSWCS!T2FKT06j3xA-Ow`YQk30|^zowE=k#+7_%3N-evMdQVd7lWu`O!8c{*D&9p}sUxvs#zSo3oa zUn$E=iwjY2gY3n{7>lh~TuJHjQd}@l0>HW_oxTrgHe{r87C3m`=BIO07Pm6}Bw=xZ zIJvqey*S(7T{u=AODBd0dwW`&$LW#5VV?7p@@*O`LdY@`o3~KlHnm%u85>oJ*6l#J zpdLj%n7`RZ#NYt%=cR$E!722kzq_km)zT_@ z0LNO686ouWrLVos#XTb^YqvQ90749~?J%^TV3w=2M+8cM zNyyL^y&OQoRU8FW6kT`Or9)UsT0pv%5|-}n4(Sr4OJZpdLAtwPkw!v5mXL;}k&q4r zNdZAn6n^yk^z*;x&7C{*Zr}UPnK@_XT}(e}a+?JQVu~dUk}$A?k`aLm-RfN@Ero!A zJzfzMo}(M)h8?TE{;ww+tMNKR1IQi1Q^5L!*7Z63HPuUA+xb~H&b~*9c9<*@B9H7; zWf?UjDNasH=e^>n(&e36!I>w@36@t`zM1t=+Cdso7QV}4vP1XF`wJj5A;j^k!ygs_ zyHBW&x4ekKAtdsqC* zIJzFR#h*O#ac)o2%afvpn6?2;%k*K9FIGmV6jNWRg(d|aZd)5PZbR(D7%3qIYy;2gMJ=?1Ad)K-AUT z*>p^8VugSp!%~$jDh$j-U!0C2h3Q=mA$;wMtySxr9;DUyKBA_lt7|Xs`CMYMd!G3t z=M+!f%LE%5yPHrnaS=I&sN8xU&^Rn+pFBjGT63iGz|o>Tr9F3?j&TCH(N^vGW(7*` zJzAUbh3*&|A?xqb4S9YkDINAwVZpi>aA69y z^z}--b|(a*pDDf;4R3Qbrn|NiLM7aCx{0_kl&|rp7BA_|?v;48lA@O!O8VS@xU8fq zws=K6qit6E3Aq5e`=z~0c8;ow)ZM^d(7o*Ac+)}EqeoVLU35|g)kvquD{Sjezr)2L z*xY`Zz`nGXu}#o&VyL0*lU|cfwNCOo)`XwQ_d^UK1LkN*4lTyTDKcPdro58LL2oVh z_2kTkqZN;@*2Ki}6O=#!0L#dYG251v^Ck0xccvbiqpp~Z4&m!Kn8!G%g6HuA<-nyH zc2JMhiDT|ih{cx~w1S67=NMmcSt=MNZlAbDK&6(0DR}0)8)m~KeECXo-@wNS#9gxi zUF^J}8WJY2;wUSb;K?zT7nzm0{d|ncC7X?Cn_PAvGEx64LDIofpcJNHBqYXQwbR^= zabP#QfnfB9p+sb9Ua!_g{ihuh(CX{>0roo*sD7ZjayG_`)kVrK&6sst-Z6y6-PSKOnHW{8NB@Gi)@Exx zCZAZVf-^5$vb6(~xud8`V_xQF+=n|+I%h~(<%lL!mmVn5okp8C3}D_ zw&umAu%W%@u1xQ;-YjTmP5AO!{`+nL-$2k(updI=(`R25CL-E6`jR`r@9!D3NK!pH zyuY-jxmAmMfH$}Govs2-*bro#cu30o`Y1Qwy}Crt`P;NViWHWG>R>>FMg3~zb*y+x zn0Y=9XvvO)&`$QN=b-gR@o^O?Z?9|Pv1)7w*HISQk$W5P63K}uvMuQ8%HgaZg>g35 z2mTJ6HJ8~(4-ET-Dhg-!rubg!tFsSjyjZ&v?b-6;=~q!Gxzl;9a`F`t*gW(8NZVSc z(_$Q@IddH#^*qYrt(l$>w(J>OE~iL%KT8`^>#)fq)LKhy2J$`?6@DY{GZ; zj8_EM@pswuio=^MWj{he5V(B=f9NJ`8s&yi_x-G8gW5u9biB#v^$$nU7b@|fEw6P> z9{^efEU-j?U>663=@=2Pc04jar~3F5 zPc`UTmi`g_kxO)MxmyT&vZ*{B_qcy|bAzMX>y{A;hMdP^Pg%iZyX} zZxZ^U3~+(B#YexjB6L$!^7Lz*9!ndR$J1C|K2FO13YtWtqHjG!2WR+u17gRRe-WXQ_&i;BFVyBDU+=!a)axSN{V zVDDj~(o`<2XXeuKytbb1+upnix>I3xuRc{4x26}(atopP!Mhnx0%`~^N(>InSFZ*> z93^?xXoqiAobqQxwo~9noaDkmeM9x+0|SPo>E}@k@WOCh5Lhh)E6Ruq{T&k(s@*JZWV(u=F1$Lu@k{sl; z;%YCD8lyG)i#8%vA~>`0-i&fxJ<^zxkDb|x@Iee4>!8hN&-)L?D@e>%tRA*27?+H7L&#wj`I&|2|eB!gR6LE*ea5Is< zLCU=GCes(Z^UbjRteV*1on18dcg(#{R$#BcoBXKeBT^*yWTg=Q{F#ic>Eghiy}UxC z&4FUUVigyvXErVakfK%n>d`Uf7n2$s!~_CG@=NUGsAAsx^ev07pi$c=14iob;=vKq zQ2dkkaprZNR-KuCJyfBDWW%jMjpDe&MI+n|E9Ta(BGTQ&X}C2hO^T}7&(13tEXJs- zwvJUgjMa$N&jrB+G>|V&fz35YT$rV2!LE(r^1X~DfXa`RXd5H&N$9Chw$(S#A`x~n zV<8LCLiagnHwRejW^a`oHi;EiR_WFNAce&6FcT^=#JVpV@qfu(x3u0jn=gHpWb{Nr zRL!gJEb=-cazsCRW}%8!k5E{s1I3Ga9lY*0Ov$V{k9M+kf!zAG(9(Q|SV)ZPdMH7L z$-TPRwJ-Z^cMs&OA(-Jf6P}pv$eQ3E*n!uE{w|ItX8K_*I-**UXadF_m(`0%p)|zLr-dRE{n5nL*awYid=lZo zS&qY(`zH`j%R*OnoSaG}J`G3I#-vFBlD>1L?S3y0Kd`YC@8VqT%F{=~W3zUR^dnh< z>GT8JT!2SzJ=}HvLV*E{G{ZRD%1EKE4|cQ$v1gZqlnNT>F~etsw}`>bT+gR)R2EofBlWTCCpb ze-%Cx9Pc_1yb}2N?b{d15t?ak8BGmS*wo)5IW&b?o`_{fM&XsISNr8Dc}g>dMOyoJ znFB8vHMk_3sknJ*SwmdKwAQlS(5(_4ug4#!%PXkOK`2 zMMDce;8^cxtL>l~(+@A9^^Cq0MSratj`c|2l2z!-ZvBIDT-FRVVb%B<$MMJqo$s<= z@?SGHKs}zZS5i|NFHi0Tslr0?N}6FOQ-+yk;;L8uQY z+8b+5#DwG$)V$tXFhwNf2@t0+zB?1on-7^U2wO92j6IgPIXU+^USfAp#J`ASq|jm% z#u-x?WwYGmHQphQ*Y5zAzv1R$Y{2WdeJ><^GL1|zdibDo=i)t1yDUjIjdl~Qy^ac7 zzNqv0GU3?wo1JqujUhK5CvV0~^S!T-Bf2i8jhiWTVa`# ztHca-Z*3Iaa@ZW#aJ&m?())KtOLCh6nVRXlhnHVeTSx}^^-JrR@}g|hVUt7N>cgj} z0Y08W+wLE!B0{Z$N}F!(cLInNq`PS52P#i+RL+N^k_>}69TN7c*9OqT@Qy3|qY`#gF65j7sR z><+O_?ZjACKnshi=NZKK8VPw4l@BA!o-@`YQnzt%`>XO}*n%p8FlH)Jr@YBQ#$2&# z9Lu?>(jHp+ctP(I>aT;sX%hG)wB~^G%RZyNT&*}kGZa#|_O*C19 zrT8$4PSsf~u0=^fUPtU;N;2)rfbdK~*tZ5grmzPMCgQKUltH_8bL`cI~cDXrN z*Rh1qa?VD!xF%9Esr_5k~xdM>$6cga2(z17rS z3;x)mu*MR>wmeYD(hkAN*g`8kGrn=QU2Lm_0!gw$c7^Tr(1*<(#f>pw8ZqSC=h+h} zaM!{(dq0c8j=T7rD)Xd<065QYKW#Pj zE=0#=&U%>Rs$$FSj=;{{&>YT*?}l`5pHHS>MOrX!#*c)Y>}I;#6GBO8Ya=dJQGk*OJgaO z{K!x;?p{$MT43nrBSV%k>N=cc52{S1i`;)IImD93IsXb9Dcq$4pbb%Kzd&itEk1RP zYMloJbTxnJEI>GqX;_k~o7DpoB_QG5fR6;Rt;b5ZjFcz@h;ICM*T6&s9-`K9koxk9 zIml9>KnJNM?!a?;CQjFsW?L)ogg1@5ZW_Fz6<^gE=O#7OPjJqy?P`dge<^{5$T$gP zetYj3SlGN#6_&|NY;ZYxEi=hqbOjPu@Hb`<3(2^)uAjJ8;;4IfUi+H3fsO7nL+tnb zJ%5>f0O`@*qq1BkdnsqT_;>snvm;k}lY7q9{KAF8)IPf;;1pxi#h`(Vyr z?86mo_MfJIioJj^K;yfnVr1Cw-5i~JYe&svZ3OJI5p_GWE+6))hBkX+>ZO26@xFaU zt-tf6s^PiPdiy%dr?&L@WgNg(VCdRIa2nxZQV#UYJVfP*D;glZ?go>987X5#aHBK% z_zDFT6_en0XF~uA5EV1AljiRo9u?_-LUDN1Ehx+W4W(nF{{nr$uk9lL5}SYpm?*5tn%f#<#V)H)|{}GzM_5G2&C5qAi zW4NW#{+|0yV~c}-L(*^V$v+<7{xtaqD0;bZd;dxQpAd_0L;e>WIFWl)gYH!27oroN zMJJF9e*}LLlSFJcpX41=_yFIX)5$;!kJom7qrL8fALR(`-o= zIrZu8AKAiY4rD`h{@@ntZ#zHF(I+W?S6){3ZA*)}HCg1Xuq9d1@BB#e{i?ar|FL%L z_%Z%*pB!XZ&v84t8#n-TzisL!fA_v^5;;t|2m{VzJA=1{ zL@C&U{?R)9v)5)Y{xAZ7|CAww4GiYtBf34nMBpR=zJCD6|JKQWTkx-9177F1KXrZ4 z4>T_tB$V-4W*ovm+V*4c<_e-GmNQ2=gopF5t;GK#)%_DAJw4%H zZ7`YqbKyiqiF3Zq^Biycw|q$%YO=uGUrS{7w$*>Hh(G=ikp79L@VAY{->dECxw41+ zpJe~a_%8%^--_iMhyI1!3dnqBC7Mt`7R7{`z}A+&0}_xaeG+c>QzY$EfG7qe$WrPE zkQLe5OF42X67ZhPzx(dvrkTjZcrK$NHWwY@$3=ReE7OC{4Ube)p2o*6=Pmcm_YBqW{1`9tMOuIw5}-}L5U zEUqn^e$Ts)ABeIC3kS^pxTH8&#$w>Ee}{vR38WWjJp*+sJH15tss?FW7nIvRcrFNE zkZD(#nrsu@<6B~BiQ#JB9D{l{bZo9~db5j}_}q^I?qqa3=`!|xS@lw>5ZRVF+;z^8 zkGz&?{Zb1XS^nhr(3e@@vfd-DvbtuyE?d5&UWF$*UpeSz$u6$s%OY+##f+Qu82_H! zdZl^R+uAfc>ewGL8}Jr{Gk1b(d$#R~A#b|0P-w1142pKkR`7^Uc}>p(zdf(qeUWFV zsFXy34euKn495bfop*PZARTpjt&q+u%h^3|YV9)&>`e^%J`1*nbMeR@)4eUe$MvdG z^%3T9e0E(2_S~ikeYcfD_SklfYjqt; z+WU-4llD`jYd_oM{fNA3Y_Vjp%{aQ#}1%{x02F_E8jSjgM46Bzc)BdQF(1`^M z)bU}_J&gKeXILol$_RGx+oPxZ(S04GVaem!j@Pi3^I`d^LwrnBKld*fQZ6xtihA3L af<)CCa~ZTlKykp&zWpDy%=pXz literal 0 HcmV?d00001 diff --git a/web/app/assets/fonts/Raleway/Raleway-Heavy.ttf b/web/app/assets/fonts/Raleway/Raleway-Heavy.ttf new file mode 100644 index 0000000000000000000000000000000000000000..b32bcf64cfeb7d2407881d0367f936292a980c44 GIT binary patch literal 63056 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�%)*cp|h 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

Vs+{DX`UZ|SIm*!eIEIc7 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%0D44!S)fm=1 zEdw=$Yxb#U-g;aTxd6xmaUpg%%csr2V{wu2Z^LqR3uNNRy+%m@jX)m2juM6}j4D-2 zaa^`dqmMJOiL{>fAoQ_r)nlpB-opHMP|^N20iJ*$h!|i^7`YWn70?7^04@qK!rAL4 z?SgIwo#J*T5wOuUEZw~n!@J~N@-Cel@umjK4=xZ=H=G+T8`u4ktvJ5Ho8Hk5r~tT7 zlNI#V%x5W2{#^^c4l!jWLheQ-0L?)(Fb2^#>re?afq7I1Ek`5AS=&Ns0o+m#b|QW1 zu8s4VATW^XB0|sJzF_`(N-?1T@2~u3ieGo6_^L+_m5bum2qne6(Ss zkQ{m(z!&ZGlpYExw)K{t(n9IUOj46T6SD#-uPf7wWa9S^c7C2|lo6NBc&e5WEt3kF zI%F%ru7kP(?&h!Lc>4ZpN*Re}5;qB$1ff$@+{W}IRgYj>r9P!0tmFTw6Z&PQkY68j z7URUgivXcU5cx}*(r+u#mEw#Z@Dils$U&e0#0M9IFwr?A~wfIad6BAeru_dcU)u?4@h;2kV zj7`6jH*^bVvbL+84HIncJG&q_5U>_;Z>^tu_(+gDY%RSv6KXPtv!uC_rgWqBin-sd z+Fv)hr;^$gGn1)_G`X|w%>>zD42|W^llud3f1w=v+^n5-%k@?{Xp^CdYhs%ecDq{s zvSRrgd6h#tffhWd)PvC;2b5seTe-vJSMz)9f2f7h8n!ta0_7YP>bZ8iTTnLd>1}r+ z_rK(OfV^vpFN8QYk1gWA0}YEha5cr4mz-$+X@Vwck|t@ACTWtU({!3n(`k~X)BMwf z9KP~hp(V9njNu63Xtq0`m6h(Qcvs*YIpH4!z@P@C+XB z3-}KqHslac1QJ469Qq-&xZKp~L(MaI)4;WZuZPh2cC;EvP!Ywnid8(Vf6l?Rf$zT+ z=-fD?L#HDT6cC_pX*avDh(oQP%! zo#Ku!Hqkxxs~ed~YQjvOO!g)tXiD?B=+rK_(F%4`(nuGJofmiuLyiHJAO*NF2p5fi zUm*4H9puF3cF*4Cw0A_=KXtla{cJX&gaKp)af3>(_H+X$r&~!ibW``NLUEPe%p)Z! zNtcE6eBSN>6)JeDcBc+k3d=5&Nxf?8}uo8~>wUw+Fpq0JUnR0PiTzr!v zbcI-ll(`f0sVljOG!Z5)iP&t49D>@c8c!ZT=d-))vX|HKL9h@z9@sw@&E?#gU%Y%_6WLKa{u@(hpGx_=g%``!2 zqq7t5WLBeCeY=|3_^b*Ps#43WTHT3h6|{QgJHmFgiUKY5@kULG)tD2Zl`FEB7KL(= z=@bih$dW6B@^4AT&{NR%N3N807orj#BIN(7&&0#l1o>rZ^T(Qfpxavc3ACz7@pP=em?IvL(T*$&t za2`rX95P{2sasYGc5vW&^phQa+Z|=@4q=b}X#INSHQtstqykh8tpWk)su{#!HM#Ps zX}q_DQLQe-_hF02>NL#TJtlS6Oyn$hM;)=FKJu`GxqP4Hd$%cV>0o^ilP`;9sP=Lh zbw->Z@ftO2(Ii1)9o8%DWcArvKeHid?YG6l=6m-aHV4u#e)osXw%BIAWJ~$+=K~IA zKnj}eJdL^Nm=%xrq=Zv-OM6H79>)pcZjp4;(0=nLlwW07piR4lz~WcNGD9YZEZJTa zmA^&~#HZb+!RcYRxxUsT@#Oe;_mXo63yn;?;h<#EFN{TA@yTzv@oL94&fuRFBBKzV$R@=N~Dtf4kl r`>W9pI{Fi(q1f`x0dMQhV|1qJXB1GVtPJxU42i*1!bz=?>o1uyE;q&cK`o@>RaL76Th4e zg5 z^Tn55bL2$u!S*lk`2&neTQ7aljS=JbrKcJD@O$xl<+2l(U$g0^rMEHmcYk0^yKwoD z7o5QN{b>KCxauyy`lic%@VlS?17keE*xOGYKX&BkpWkuOuNnJW`n_=+UuY-gkE8tr zJ|~V}bK^@s_ucFf{Qe2X}aYU%Smcs_FNk!y~{r16Ux`!43gKYil57u@*06W%S1J%%|;(GxcuJMq$M-g-US zYvKMQjI#mhh3o^;V@zhAmP(emF5fb7Cb1BHH?z2O-)P>RZr1k1$48_W_V2~FGP9wr zyXChsEi>SrsTMw)`wV(~)@sz$h!(A6Oh$>RbzFshnVPAa*Z_&EBqn9ih$*JQeY}sy z)##zdYdoHgYPlSh(V2~xa=g^MwEf{rdEYzv@Y|{LhfaQ~aM+OL%YVi;@2VP&&4 zjy}`capbN27PAopc-BMV&6-=A)~+2*`*#;7kA(K_?HN&J*DmYiB&Nk#QF;ltV?8y@ z-%??QSP2U)3YMUENtLFHot9qReO}dB+qZPq*2eaxHY9iU97p?9lMtGm^jHK;Y%s8wA~hbA6NHDem5!&R#`>Vv7ZOY}rK7);Y^ z#_D!k`@No?^_up_&Ec*^*yhpMLG7{R>TBcNhPD5Oc3-X|4by`rpvY>hsS8Mg^^=oVFppnkM<-QQwsVnUmc+az1 zlcZ*6dRXIs{{0^~ux58-B`F>=OV0S~rt4k(JpV?}WRQ{m5&tjstYJb3u{VPki@x$2fFnevw#+l#ea$uzm z8WjukFlfKB!f`-`G{jT@PzlrtP^wm&V~hh700FXW1MTlDqK~O0jRYtLjC5{Lb8(04 zZ=Fj!Vlnt>SAa`rn(`}8Gf{!jhXLSMNDqN7hgpGmOe7L1MDp=yz~^=AwHg)ix_m#E zR6I&(D1+#;tcI)A0QfW}V~Sy}m>2TH)?7OdJXpv&dfmSh2K4h7JfZZkfYq;m26m+idh&PdKy8*PPW zj?X6xTaS-LrY9S=yls5z-t59n`v>^()@?^8_sw{c)v&p_|GJ^c8}<$M$La}ZW+LZo zUH%GmUs>8Ky#?dk#4c_*CdY@HgSA{H5^_8HOnR+K(qqIk<&w{h>G8Z=AxVv-(nW#V{Wn>m-nGWa+cQMAt_Nnu(Q zNL^wr1Qe#wh_V!PNf0!;d#CT#_RcW5Ji#GovIKV&8@p(cz{Odip?a7t*zib;1 zr53K7z5o8rSIsA-hlVbG`NFPO9IEl7)7PI@I(1ih52RYOPGe|d3`RCd@*u8|CUiY= zX%gH>1qp>DB#Gn`1xX2GaeD_#NhnP^fsvh;)NH5uBkfE1745f`O4386_Ad+V?-B14 z{XrI%u_xPF4wXt}QCYwOJH5)14l^IXCSdAOdVu6$wMK=`vLFl+bty@vn3iimD8*o~ z9t4&glCZsJ44h=}H>`|9uJrGH=C4);voaP9sMXGvL#x%=w2&FQ!+~&*u?#BG=(8S< zT@hJ%&xn4ah_Ae7apV~x%0Bbwm2t_PHF^uyNXzW(P%Ea>k=&@W>+CDT>y;wGrCT-Z zjZroLbg-*fD=pLMwLpR_(?Hn7LaEiJn2GE4XekW@?^6ldYVU}dy({-;h@7wLS-3Hh zKA-vB$`F_L@h-rN*hkVNR>O|iM~fLEF7{EwHO-CT2r_sN9ML}Z!jT;!WG^h8fH=7V zPx5gREF~7lpLYR<`&kqm$3;@1-{FQFZJfoxOMV9$Jyc~s);bI-KYwT-X7{*a z)$=El%Ur6o{qmuh$J-ynaES&$Sz>zDXpuUhXUi0a^q~;8v@=y=tpu(_0o7aptwQ>` zgyt~+TKgD3)P4`qn4cHgA0e7nS^BedxAbN3u~)YGGwD<^5s!pijy}*;A#If*hYr}R zl3D`4Mo*+~t7LVT#L*gZj`dXJ5F#^n2qOMg{T!arX!^PjV$^s}OLAutIz&lQIAut} zj_?&>pwX-ou*IdTE`R0xE&Hnj`(8ZP*gG{~%_d*GW%Ag3s<7?&*rpdW-}SZPwJ(^s z?2hTpcN`scXNP0n&6AD&Cq^f)KfgBCdQG4^V|wltVxx*^1RzV6O)(;MTY`idPMPrIWRGt5)L=kc`XswC|N3YJZx~DEr6WB=orOYCWz`Y!oSTpvhzk z0S;LY*Q76=8l|y0mY(FV$8$DTZ0W2PgC6jV{SM+MZsU-CNt6Ps19;FLNRmquoUTb6 z7s5FjBW@QW9O3XkGGsVT+`b*qQ3TFI(%xaK1}3dT;HgW4oQ^>3n01FKM*T`iv4 z3=rD{n>u5&3Qss(d+o)FNrW0#H~{HpLA3vMS)uzzHs11e=)O@0?$}H3iJJML973-J zj0&P4W}#7LK|4t+FL!AB;o6O4M4-+DDW|!BX0pGQ?-D#ltPj9{Wqq{JF3va+(B;Fm zYe~7MR_`J@tl;%c0`{QQqJ78`I*?yUNHZRTUIScXJW4oiioxzBNqve|OM~S#J&$v( z^Kgy7bF}?E-WX~B6hPKKkAJlNukGvkiMM{g+s82aP_qo}0Iq_*(+)Vq8UTba_OuLn zwWswcwfg};^6?Vx!dPe6Q|tskggNI{!>|XxVt|Y!KU`swAqvY9w5Uxi=uF|MW5<*> zK*wYU#$sYkLB~uCVhqVnvP5(&tXDy@q-De(OuSBG0v#izp(DdZt(Y_6o1WLK(vRD} zh_rtJl*{l;O}eZd6Q@E$aY9GcLMA%>L_8JDF$BF z#b-OU4Z+YFe^V{Ze^)C@mr;wS-XNVIl*CiQHib%h^{l>8y!elcGbkS9WA-gd0fwX9?=+}d9Hs(?QcET-h?i_ve5Erwd&3m z{NtH)>z?hAr%tbDOM=IJ2|UgYLJ8dgx=GCEG3uF}+ZEkGCJR!Bktuov(R?r@Vxa0C zZbTXc@2I6hkA_i%zjX2D{gv8*o97m9-iPZ=?R&CYE}v*!zL?2vxqQ5Jd?BNrIC{s- z99YrhWiOwazvI$Teti7;eS?hyCq_C~0bk(7s;e>12peP{YlUJ!hC(hn7#qYlk#Hy| zBsIHLua!6~vs>;X-aP2$Kxz&mM4VZp73Nt;Jwjq5B(lZGZmT85HBHD$b^?EE`v*_phb)ugdN3 ztFVTn<0n?ul6V8jG+z?D$IbH4)%w+{Oez$x^r_rxw?c2ytF@-Cd@BSQnis@hj){>D zOS%#PYIjx}!vNUdp0mP%P^&IG2Vhv4g9h4o34V}%oi?A1hHd>?pU$V)!gK4ituszT z;ivYq&BUOv+jE#qM;-gpIm}1Z*%O6d`&pUoXoX-Bf*4uI#UggA&ae0Pa&59ogHkcQ ztXt92h?0?RCd7AOXc{z4WmgH?5%2Ktv+h(J?ES*C@06m)eeN9Q*4?YS1bq?k1}d9b zp)tf6()k?N57-+BGqk&P^ae8{dPDGbHhM#P-Z{{mhahmAo$m0bg}(?6a7-PAw)RfDRrvA{yA7E}g+_z$mJ#Zq`6+gv`3E zPT~P@#_m&~fn6Pd!*D6AH6@rf*w0#_Y=*Pxsfn@SX02K(WahGSD^MdSJb4qwPs`GcU6#H9Kp7N(>berDs~Nko z%h*rsj#nvjOuN?CNJ{t9;)X#DjBy{l7b{(4fd)yRdI&V1SVI{9daCpUk8g zE1EYf?=WDKa0NO>lu6ONg)H6CygNq6JohSEnXo+`=859gW;j@1C_eRMd?@Yo=7%G{ zl^#k>?#SeKP9)oZ;G@BT$yj`{0?$5VLBY>}n{Lp}m$z(QPdXV4c*@?g+hsPXq-D%3 zhWt(_=K?F$(9z{O@Ug?CZ81VV8YZc*L~8u4fivC@DWGrpA&jGon@KobS1}Qd)*Vk) z8_jghJpn{r;quZMY&k;*h2Bf z@m@ixBNrdWzF2{c!U`J-IBfVNOp(H7(Mp<@Jth3PY$!w96#bpDP3eV^l&1Y_Zlb*k4NOL3lNHiPIZMHAHIBV1 zlMkerhs17|h29azZow7Bcog?R?GSFN7#4X&j3Uc0CszT9NbZmWpfx7#!pVyomgKjOSKFg(>4_c*Qa{@nu{h%c9fXktkt?;nykXv{?LEt@hInLPZ~! z8bGLQe&=}drP4!hY`-uxFd??7{a%{qZper*gu$DTCyl^iH=AJf@NzF{1Wqz>K<&o3 zI@T4qb4aO8_L^285|WiAB=MW)FB)>!!ke!@Z_f?0!J2#Ma1Pd{VScRrH*Fj z_8EFVdSYLl@LBXN69GXWYHt%rbJNF@s^fcok zX>{F~g!K8=(++H9TpAW(V`0XV zaoRD;owZZs$S7OrN|6D-%V9C=qWb7sDKfrViXZ?)eiy#_YfYuazdXkWxH0Pbrs_p32ZBSn;e>cRGg&N{`nE5}UNsJlo zf`;f|QESjF5S!9zn`RL)=;0VpI)G&W*2<=;cRvZ_yS*f#;4b&X%Vfx1)!mg!OdKbh zt8^abLcWMqHnjvG7XJZaqJoJ4v4n9N4t~Xg&~X(tIT(eL!zvKuPqocbxozNoIQ7+> zbZsej>Mvn!l;HRIBmbFXMGH-?Z}~_<9w=v;*=8&ZnFl^;*lp50ZRpy)Hai_al|HWJ zrKF^S+5l%yl=fJKufRl>V+@?6cVL{PK=#49q0!(j__5$gW^ode`ygvCtZfaJw9~gn z4XAYh64!Ej%13Ij^`A5{Ax68G1umDn6HSn&fU6*P)SQ|ag098^7-6~%l65g!$WXj ztX*EUM%}x-Ivs*|PP1c%&W`Do9n*JqZ1;xkf|#A9U9oq-5$s*JWwrRo;(CAUKYg^% zeHST0_S|=J9@u;CyD9AhYOmhU30_t9b7c68`?-5!d~9?`{a>-A=bx_W=ew)_6=Qzx z8!Ib9(z)+#PLZ3Q#r9sc68o#r)$b}e%O?3kD>pVaG(?y?HaRvqF+MapG`jJg_jhUS z`RmcQmpWREW?8RC7zONdXTs#Z4kjZOoM^A1gUJWhw!WJ7o~3nx&nAJ--S*YuBX!XF zFBq87OAvZ z7Ay@nr=b=ru7ji!9H{+TVglT4cxNR(ACj%c9TTa&1^clBQwN>VD_YINvuWP0$%)~` ztiN828w$q!@JwRn+L(24V%j-+#A}v~eSC5@-70yViHdZW9BVG*a*NHVw7keheIYZ{ zB5pWRua4&yFKNmaskm(@V(}$ira(DnZ`H$vU>_Kyz280Lb67)pA2G@QC~Y4KM~1eQ z*3i~vUO7B;M%ub_bmYH=S8mwu^QEf)>7#ufSOtaX+%byuq~*;%tK=hn8j6$5s!M;A zUM2lc_?3p)7DU#&iUr2zHy4JB!}tz(F>bfWH*C zUsM_P4a^o2V}nIkXdsicg_}8#Gf@qO>ZOA7N121Qv1^KVhHLrXII_iBDA7pTByXQD zUI@F=sf;_xcahxp+GdpH?Otr=~lo>&N6rc8?wH!gn_C`2` zj6{Awh&ocfnHvm{QLjNT1fVPmoe#RI3>zM77o7eFSPA!B3Mwpd zG$aeqH34TNY-<3)wopxWpE@tp#LY`bI zZnb(Wy4aI)IOeyz>=wIKlKfGh&26)}kPji|v`KO^c(~z>h_}F!DWAyQ4GX5lf)@&| zDq0?qV%JPJ-RYXP>DE%p*@d|o{j8jnXY@09UoIzQ$6P_r{JbaV8nca$<1vX1E?p~| zqzl=8b}f5ZE5z9~S6zB!=k|rU$?cAatdh~N zb&G^Bm?%ki$bAt?xDql*Yb!GY0&nS^4uOoo;tVqyJ2qB00uiT7Xw10_HWn;j$LOn~ zRTCsJ)pZ04HvG1evCtvOITU4gmLH}UJYYS&RzN&QL@UhqKHka#-yx-!B+k?5q;bbk;XVs)8 zi(aog><%VI7ZR^2)(VsJ!G)I}Zq^Rox@G>h!wtLL?{Ewsd-bk8ufC*l>VFx0!Js84 zISsC4z@7A(DR6ML&bE*Lq?H>Mvi$Dzwr^dSBcI~XzTtfvNg38Ib-i*e;S+6GluGbrBkBmlmZ%?DETRIXx4C^G}_jO3^C2M;Wq}F8Umvr*l zu9RLNe6H_C5L>el^}8LZ#YYw=qE4Ap7p?6{%JB`2d3{KW(LGG_OowHS9+aOa7A?M2hVB6MmxtyFuLe8u!YZ4wP=HL#JsLIKN zP9_^3L@5b?s8$nwhC>9VJqjb}ic#cF>c~;*SSn5KB5Oy*K=@X=hfHXlA(^)(t_&5c z$)i)v1LM)u^o0|`n>4skh>i}V`s8F|!qBQ7mmX_>rZH3AcBI-kvQQ|dCU@ovyCzfa zRMmfP5E)YpPzi6XqzCUhdwc*wi}?Bc?}yu4m%{__{NANo*&VVL&p(SeOE+e>w|IyA z>Sta|V;ElgF?&$@85qC~BF-|zLP5X7PNsOl@jSqeoUI$ut0IqNoub7%OX-Lahgqh< za1y82+)TgI9hu&z5Q9V9&TbVcXHNL%V3Mp`5ui~Qo{Pc8D0luheSg2cxkG2M+6-o$ zY*X)$?r;B_Az?Nr_3aZ@>i%1z$zg5lM4ntn_RK$G#arJx<`EN5Kd1GZhJ`*|O zql}aDTNd-dAju(*`5+O7-irunn$Mb>vDy;dA?DM4sym-LWn__yujVv!ywQ-K$T~>s zYu#Ghp|Z=mKBK+gqTA7=$w~L;4UYCN)z*GfMvBH4=Ckw-5eUu#rEj!P>(=d?I>thwZ>%ZCB=WtK zzUhfh-xQvYSE*hVB5$b zMd*_GTx+;LKM)(+RW9!yPxM2^F#BPY$Zxp>W6Uq@P0mHa^;{R|hBt((R<2 zK2Xyw_w@tT=8FZSIjZCuvVBB;-z3)}%@GO8JVI$68dVV$HSa(678r72mZuAf_5L`ha94z5H!tV#w^(sEYkP5x*(t1wsF*GimrCH3jS$(V0_ z+Tm7Jaq*)1#*6DK!gp0z&Pt@XoL3<)<}X-`71?eIsn2EcJ{FC*L88e2NnERG1k7au zew$UqfvaRWigiTh8O&xG$`r-VB=KS?Wl%4?SE*b|zL~nN%$!2$L!2^U(pHdDk&NUN zD!nf5w*{X1B1t@FSkr(&;ITkRi84@xW1n z3*(?yA`Y8KjN%EWOG4#u1@JpZ9?FJ43&^R$1y-X<1mjv`A>}b^jl1>*kf|WE`qI;K zKVowz{%!}mnBwo84$d~ujE&R=GCQ(6!a+ycnN}jhDFSt5%VMLB0u;O(TTSAy7Qq7& z3=eqQ6UV8?PGV@np-7QZfZ?^VZ@rQSsUXc|y0e^jrf4S07V~#)zw=15dF0ORJ6?H7 zvw6uYx6j>j!C>uzTju9)xuAyYj{JGxX3gEhlb589VHGP zksgJwKghBz1LQax)xDtD0XKf;L^_BV6Wn2w5PVNDN~^3o2qhDw6prEgAQ{o?#YnVR zj7EyZzCKOA!C=+&^_ie8y%OI)uzkR>i60`!2r!A3Fdw%cT;!yu4O z%c%SV%aGrg^f@H}2o?$wF_8MC#Q8&S6xkGKf7S+QTk~wIb*_(fq-=tEr40~%=mI(c zay*r`DnWl*XS|-GxIedb6$g+h2G9!21(|!TNXma^<|QMCH^mcE2b47wIlY@S@3wb6fbxIa>B$^PJ zC5QwP>~c{ZM_#20!B3bN(3NDTj%osusLT|#CCK(g>|=f2$;LBG!{xv8oM%aewoV1k zajHFY)nLqn?1Gjjm(yu;gSo*;Z^onsYR7T`JSs4 z4&$k$L^4Ak*CQcIufcYUVgn#RovKwaI4U}}CG5PGgo(5X6ajLdu0s&1ZkD_(Ac$fv z8^QP2;1%9??h7GmW1V`@Ij_SCtP}1ESSRc)m)7Dh?SFHif-q5m#02XrNUYHS*4JZl zhvTmol{VaUk@j-#*!*I0?w#8_`GcJt7|4ebD&2t3j6y!#)G}{foN5gaE2?;q}-@QH!UuhikofAz2jW={U7X{ac$?CAZ zTXA2$5%3jbj`YO#bb9+l+8HZ*!$Vn5Ej~0Gi_bJ-bdAk6V(q)bmC;~utP&2E$0L!k zQsBYTVm&|#WPGd~)$2p4ia$S9bi0e2@_}+Xq&LPZqoLGT*5%HPB~znx9pyJfDlw}q zHV_F9L~XYC0O`Cl>}h#~!`k+2Y*S5e^cm@oPnRGRC~ffHJf}AJ2bDG?HqRd6FW~zz z4lT02H>?pCho_Y+2@0LX_N*i*6F0$UVMd_ACGnc)`S!PX{*hGbl9bRlSON4s3;Ld7 zBW$W=YSvM6BIIRg9m3a>FEQt`Ro1qvAG*_D`iZ4^Q1Wz383wR6Mq% zW27C*&eg-w;jOv!Of3{?EMRRUb|L=0PWq}?({s@E0O^X+sYlmqLPXYrWL;RTRv+WP zZ}&ZR*=0)GOG{|`E28ZK8}8SZ`&^LPd_8SaOfctADMdb&Q2JInRDQ%yB=RENN?5$e z9Mpu+^g49Uf7kBgzgPMfIa~Y^*u30qvq*Y(Gg8j&{btxfAZ(D_kuyRVHNo2_MbR(l zGKm;K?PV*6LsZb|(}>*^=B>IYEvM9`&;+4w#;unxEbN#K4%uwxtgF_1%Uk%nv)eDe z%4SIz&AYbk$hMKtO>0d#WIHh))W~8-$+uP?EEmB^Jw4@WklRf$uH;*rNN}A#8ITMt z&*5N;8j<^}fl*85Bp#8E4RUQ7J{cG~mwn)rEg-aTAx412C?kwxk?>!=*7cz&Msb>j zR+uzNpTVvC53zE{{NWE*@2xH@*iyskRI}ePS@OnEhs$ONe#2V35%QbV&Y9*_b z9f33-4td?kZ`YAMmN@C81FE*uBpFpD&W%)e3MPM~KX-Si*KED)MnrT!g&$$NX!`aI z=i8a7vLN)=jvWO$D&J!(JJWVfSNx@fSL5p&OU4Jn=B4Uau_`}YUV+{z8~QA&xXB?_ zq+M4Q1dHUSpOAI_Zfi?Hg&2LS#wij zeeWJf|6Cj}`3vD_G1&Kl7gX;9C^|D^=~TJjF0fCvxXcD6Dt1oMc=TaPwP$Byu+9RaFf3W zdlP0eE!#@Iy#kMdQkX#`EL}}KnECeAqW zna5JG4s;ROh#|X7KvSQ+2bzd}V2sEwYhsK=_Ew5L%4cJd6@ck8swANY6Rgy6w~j|e z3bkHWhp7=%LEi-s2w!PPo&XS?4mZMqpk(;@TUZIG?Pq^ZY`yX@Muwf&k@-zz2X3(W zU8(~~wzK7!#$cpa5u02J_T6|Rw%Czt6{t=hZ7$bIruF-o-IZTxgqHVFtVwq1Dt<~D zMV|bHE!gw&xojpHp}auomL*=IotrGcH`Gtk8~8N{KlnBRv0xk!^%6)DMb$Q$1UeX1 zKz+!sq6l_$NeDvPtsn=9PRYsZ#v5p~@d>%vXd$zLcALkx!3$%aH{*9CG=Lg;G_fw9W z#GFen=TBo@3_$jI%IHRph=GaB4Jxcc)g?=Pm@Vclkr)Hf7NU}xvRcV6s8AB5=tJj5 zN=(OEqpnBm0AjE_XA&h@u4})KUlHHGzkM%H-S)`>f3#gHeexIl<Hb1YHJOdl91&NuV@ zvGA2+8Azs)D~r*IT1+-&YNMg@V$Bbmsjj%?;#&QZErq$-^{0MQ-&yxt!$rTlKHx%e z)ElZ3d2gob{ZOce3ZJcASz$T_LEE8dZ0SNeZD|wj!nm{ zgyAIZftYuyONh`eg8FXdzowGdOy1v~@Bt@Cc_*%dQgubm0*&^U$6w^DOlNG?;6TFR zO4b7LdeUAA*5>k5NEMNh?(KWud|O7^b6#qq=qcNxMSq|ev3m1k@wP_d#l?EilN*is ztJ$F1dd1dDuLkBpOk8@Je@8NbVgdJ|bN1zv>UxpG*Zmy`85aNx-~IbPHNW}I#-E8+ zNT7vt{MY;e+~3FaEsYK?J*h8mZ#uPZXL^#0OXC=vmRg@9!gB#g zr``SpU8BBuqkFG1H>Drmpbk21EBC?%$^QtN;%0*_)Pkn4HxxTUnWH?4nHw-1!A1P>A{{O_a)S%gl6JVf%W zbqkhlgStaTR_WG*2gRN-cE7MoiaKtn7b>c!E7^u#0(6Ge5tc_%ub@Lv*)QR$qZ&6@ zk7KYUUR@P7!jxjY1uQN79?yIa?P@^DQOgarKMh)N5v871K(YFrw&_lqiyf`^DTceT zs?;&ay{g-Xj9^8^9_ZA5r~0aA^f3grvIdrWJR+(Y2(ZZ>wGd8$9qHACEiyb2=$O~EcK*dL-vZ@&Y~-;YbJz8M z2dt2I{+sQuppTuPwG#TUpn4$UVF({ZtwJ5P2!2tTX$R;4ft{>ou}hc|N&iZiW~#ok z77ZH1eFkgQma9pRoqAm`rdDUP`Wl6=pr06M;1{|yP@ySFXCHSaW6-wV&kukQTL0Ym z<~N%-w1V#6&0fJz@k<~tRa*pKJ@xNM)MrD$0Bim za@J3A8R^X&heSa@6 z-ME?c;8t^r61q+>)8WbJre+Rs)n6Hzj_=*fW5*75n5piip@F#l#n+LHl3uz@3PC?f zupzdqWlJS1rQ}d*C>nM<`^`%A`=%e|?d&!fyoiW^OsbU_eFUaR1W%{Y*U0*=RFhYd zW@x{) z8xdGcv)Kh)n+trtwtp&>S-g7s#CxwETx|IpQ^kF^?usCZ2FBN?!VPjO(i8L946Za^ zW$#FKY4Umt)Pt%%!R8YS1w2h}b7eP|Yd_6&cL}9I)mkJSAojX@c7(wIimlOf@?H>( zO*^>3j(77b>)p2WS|ip@IYUBup7J$CEiSAmg%YlSLbpET@T!MZ8$5iP-Vqu0pE3zW z;aElAx&TLRGBVt)Kb>L&P`vvL(aalwDL;6+ux0FL2Ag^_{6&6PjNZ^n1pa9mMNCONRO@NgLNie z8#Ge!S*C?-cMkO*$q&C=kWPdqL25x58|*mGqW&W};dh^P{2k}}*(b3whjXp}c-Cob z=wDx7&9viO-+T7CEIZZDKAny~J>8M-ss7`xZsnfS*MH25;*VfS%Tm5p+Yt(|PZ|<4 zMFq%Cv?Phf>%HddXGkvd3(h{huB-g4vy)+W`lI}Rffoa8mhEI8X~i~gu2m6NxO4N) zt&8KM)!Eu?HVqoDy0eE(lc%!BT?u=qQ2D1wa*8{a>m7Xm4IV3zGvDOL=rIg@|S_ zMc_3Gy5cH5NSW8fDv^1eo4;ge_>#q(x3np<`%rf4l~aYS!%>lL9V|!f-f}CQ*;Mov z<74NQ%jb>9f$-(>&av3lsgQ$bB{ zECi_;7(dR4fNc&^52a!>q0F6ZKk#~8x?FX5hbmF2Rw|YF*GvJgwd#+B6&e!MJ;!Zcfb4mF15=aGWEv-wgkT}9_LdU zRJV`!J8Zm7RlTZ9r{oCwO+qG|VAr)mg0eKV5Ec=H0|5~uA|(YuIC{i0!)^|R7wLzcQZpbfI4pufmMQWk z3NPS9H;o#}g>)u_Fzq4Dy5=O6uy-=Du)gyrTVt+D+E;D(GGUk2BfC;ViP_meZonDO zxio(~^^@K?U$|_m-@41K?{`H#k&4Oc(0f%bw{5x-&IN2*Q#cwm$JVV5YNY7AFOaV4R?0S&McJkaNl8sbw65#@-h9Ni zdn(w(sa*AO+vcg6?N*gmcDOnBZV9`J375O(8yLqrSc4gNc~q|t7wg$@X<_=WY;>@Z z)fb7TOb(x=Y0#!4ksRc<64ngW&xG8Dif4RH{d19Ugxi#0;tnM=b%KdO{(B2wr`JTP z{3yMt;`5g`rPEVozppa&0Y|*-hf~wxNZ@lh?&Jr9)lG@yR5ci^P9+nYs=>dfnggyB zeUWs+K2G$eEALn#OQZfU*SBohOs1BtC1QS`axT}h^ox%?Ozh45VWAi2Rc&xw9}p9AEq z?GudpIS*IScqr3M_!wMni0_@M$k1lBaT%46?MldkT{tCDX*tCITXB#?=;Tz;l};4v z6#1Ik6m+Icnb^O%8$ptyzf2-^mOhqJ*R@ETcG|+#)U_>=s2#Q-m+Je&{F;6n*lYU_ zBwW`HgxhbiSXcImY@AfX_*dsx!*~*zzRHONx|O2EdOc`~nvRJx1MkBYkXa&QD084g`QnF;QBMDrDxZA`2N#qsgzrr zM{ccEjcC;$N7WmYYV7n@}mN)En@VF>>Wtl#^gQxpbct0ll=M_I`+=axDe?k*&8|WC3)C z;w)P5$-po*gkpjahEUa#I0`K4ByErYhT~a4x1$wFd$SMiz~_@P}$w>a^#>?u1RZ~rqN=h5-=hpO{skHqifmmhE6Oj1^P=?V6P z^h1mhHbk|BY_K2`lo|#eLLpscXKEmrc9oKznX%-i1%9A*>BSdS9FYS@kC(UKe}U`p zXE8#usXxKK(QT(srgo6Si?Rx$-f%M{e`BGQ8k_N?kf9R5`tSpXKYQ49!TsCI$B!O} zI4T!id@0&dV?2Mv*^iG1xsa@E?TTL)fivJ!`A$+7Gm53 zp?ccwPS-=-E9PsphQO-m8cg$j-5SQJcENNR|I}v zr#lm};_7mzL)Lb*`&0K;y2a&EZV|Wg6>*RJj*Okas>*EbdB9>D6;%-)Dv^BwO?ak2 z$#xu(cArPgh#I!$x{%}7omuFI%0Q|EB4$?tKEMwxTq*C2fQvZ9JJPKAm3NfyxTDNp zl6&3j@IUUSc-+nW4#|vhS=e052b5>4PbtJNXr8boiO4+!U3F7CAZrq$K=6`rtTYft zqp>K7gA|!-?df-(kK9@Qi@zvuMjqi%{*7SRvweZ03#CEu0}#qxWer zppn%NKAW!B@E#@3q9Z)kkpe_Xg{yMWJdJ&mF&MK4$FB^Pkcp;thcd^@(cwzktV+}; zLa1&45MNl%MB6lQ#i^^jyud?lZW%)&T4KQe!Qf!Vlb$>;r$kfGJ|_T7pFrI!(x~TJ zjtp#{nLKK^XYmd4c>2vEs)8)_45fYHRHFcFc+5ffaYyHfI8qzP)!8{uk&5F8b&Kq` zM0B8TDa=(1GDhLV?=`w24retV@Mi0Q;e+l(U$HqENzOJR{(J+a#GS@`;q&RCY|v!# z#s|}hM#4H)afK^UtEW6y&W+@PeR@Z9F#Y*UE}=Or<@qQ0pTrz)I?Wum+!u$Sk;g>H zElRo%z!%~^cC<5ifX(u(zy-n5vTN_g9Pt!+bhE4O6-5#_g^CcF7DZ@8GH-`K(OOUx zGap<#ZF6DWwE6Hk&%1?MKA%D?48MSa?vk*XzdTQXLhPg9H(k@&6Rh(Q+jOml+ZAZ z<%MD_IKI3mC!8p^11p9hbX*D;x-tMedFzK(f4io4WdS?A5h}7F>1uXV;KEuyO14(q z(h=N5CICgW>f6SR%~>HGSxRt zj!cbC;UH8b^X4+Wk`(0%v}!1c!YO@HLkFSO(Gn8Y5dDoj0h}POMhwbYSxVW{?pZM# z7(3VItgldLcRUTr0Q12%=ed)=dxw&(zGKIol&yZ}j=7sJ7_2JU>Q!8~f0lgU{eg_< z`qDKgvkw$Y_1v4a8>FY-vSse312sC#XCCS40N6~;=Pf0@^2a~?;jd5Ri=$tsy@;R& z$ESqNeS|C;(Xh{h`N6hMaV?2pKvaUkjw~l}z$QS{Mu~LpWaa?j6u0o&(={MJ3y&g6 z>Xf{r`Tf|nS#R!w#>{SKZX#RQlyipav+41}zJPCcIao`%EYZQlz}A}o8bc-%OC^SD zo~YY~0Q^8EoE}Npvk`wNWb$PL?tsIhH@PB(*k(AZB-lGYz#m3Uf*Dj>+t=#fyL)16 zu$s@(X)`(v@zlvu5mM9nF>L8pz`6!!ZzE6_@(a!hM#wy*WCV-V@1{Iuc1? z!xWbMt`nRRi7B;MRI=&V7kZ9eS0Kb+AYS8F(ynfW=b(#a^$wd8NFznf$M^35T z?D84!`&*6H|0NL_x1KdPBye#aVHhWOA%l^13oMtd$S(flcX?uJ}&6QotLwnA{2AJj(}Abq!$x{**xp!&aw2T{kCK+bskm zRd{ClU_DqbC;Mu($idd|g_F^0U~s+=9l}@f`lP?Or4iy%*TslNh?5GUCH922Eg^`=ig{Y_8AUWe$h=^$Yg9bGW#+u-=y}yG zH~5l{gVQ?>UbN5S+jYJtHxe7Wz!@`To0}5FEzPh!QTw&==mLy+!PZcyGIZX;!uf@T z@n|h!ZHvGNPy6DzY7Ur$J63EAz5|HmZO(NLlKt z45mnQgeIy$pTa#sE-4WJ*6C%JkW(VCtFC*jXH^9Fu5O@PMox$s5S=z!5T*9Hqhs3t z+~gjOn>%7-Jb}&UGegA)&R0SD$Ro8h*N%Wh0Vq9?Kg{z2NdpsRtD&WXdrfg zAXZS#{ z#E%7MXQutxZ1PoMHmL%F>wUl1|iD)H}9{$B0AZPPImg^FEad`7uE$PPj1Erfww8^ zKshO4_RW?76cgXyO=O4m!L(c(g2IEm0wFP@AQPLk33arWEEX9BSUj1{QANU@UR&xB?DA*?2l7Un3Ef3H+ zj=(*bI!X2-9RWu;_8|(9q}?b?3y?OJE5A{rIGm9VNTjB59xy^y?9xxFKhC}Ih4~*1 z{L3{53iES?{nt>^9Jjas9etKLd*t4GA6cR~Kw#xRK);sGxr`QOK@C+(eV}zW8xRId zy+UMP)2ThoC+Sqkco}C?BDiht{W|^on-4!c^gg}reM1j_S<-#SZ2nIB&+Sv+?(6$D zrxWF=zkcM4tI?l>?P(e8{d8U>Y(gacQfhSwW$w8HZc!_P9F^ARGcO!E@G)7U66#0w$*}N5NVCj{Vn0UjO>q>s}YS?!ZrnpL%+TA4}DI$*+Dj85l_MBXn3O zT8Bo=zX_U)-rcHQ5Z|o)@v+0~1MEvs+gki2e<%O66q7ENeexUSr&L>2-&Lp7$JO_!f3B%& zPHG<3hP3b2enYoYcZcqsx<_?weMx^*|9brc`kxszh6%%Q!#j;L#=A{prg!#f`flv| zw)wdERhGk+_x9)dZ|;8#hm~))zSjC(Th4Ze?Q6ED>|5=3*gsyl>c7;sdZW6gIqe>mhDx^Fl){Dl$M$gf5p96LDnk+E-#{c-$#;}4GiZlW^r z^U3+iFHHWrHP(7b>)zHQn_Qa~Hyz*f_Nmg;UrrBA-!c8cnb6F&v#QzSvkz|`+5F(# zyXT&nKX3lq3pXsf7Qe9N@Rr;0-@CW`ec}>1+6W`3A2?0qt29leXcvZ?TH> z6F}K-*8WL&r5y}#zmjs z!m8qGWhMUaY=)1sO>&bBitjFE+oTj?aK3|xfZw35)o)On=vQnXUM2Q@wvQiS7fLaf zlM*ZsA8&=-kGRnw28!um^Q1%r;9$S(1GPZO!A}wXgG7UA~pgNLBRxDK;!ut|lDUhAlEhQumbMl**7i*H2l587)8vT`6 z39l)B6!SUCrlfIv{{i^m&_7;N>?^2w@D3(Y#*XK)$7ykW7o>olm_yG?WkcWij57*KT+d?iHddA6c>htr*Mk^K_g-4d zd6tBzR>mtPJqUUQc;N3s#^}GIze~}^nCxg6M65)>+Nia z?`7L)jrosR1TimF_OEOb>s*lzv0?cqFcqg=L%Sytqfx_HjI6m4kJeF$QIM+r~mdzWxPit6pa$GGZh zfw{f7_&7wThvDC+mOm}M20y)4x$+-i+(_ofn8+A_>bdtY_PL!5JKyPc+GvdbqTh+Q=3i= zo*Kjl{QJ?!j~0K_{E_~N6F~3}$ z`w*b;e)iwl2iY$6VRnSw$?io>-tV)&WnW@nWG`hmvj^Dc*fs1fb}{=bdjmTG&UYWq z{mes>w=pMFwIJeI!mj`M#aa&Qim z>JYn>9cMRUo&JKolD(F_j=i3}iM^Hm6?;GXDElP)H2Y`vF#9HZ6g2bO>@nc~`S57( zWRI{Hu#4D(?0eX=&wvVFf^~j5dn5Zg`xNl&DEkQD@*(WNo56iE*p++!UuEY4Uv+im z`~S&lPzm9lmz$F%h^LQ(z!N)t>CG2$>dT5BGa@F?HLe+z|9u@jjrL&P)>APS!0ah?(~h$O^g&bI~nwWRK|hZ z=_9wn(E6hDWA239MUVJ0-+D0(&#Q92=KQ7e73b^DSDnA++Zw;+JnTH={H^mH=LgQy z&NEJpQ||o4dC~cq^K<7_`po^#E6xYbd-VGE8O`2tK4t{_C+88q1#O+vNI(3I^IK<) z>tqJ!xWSSKGF<2GS@#!bxd9#o-3@oU3FGf|6Q=#oS?L++sWr2L?%j9KN_X!nP7S(K zl$ugp9CU|GE1ly`)UU&)1>M_}xJ@}W+&wG!K(MB!lq`48D&a}cGAT7#smUd&C0q$e zb)8Ug@j%^F9+&ARWklQ|{5blFxK570wk$2H}00mfLsk%k!~0UxPj3bK?$%njJ%=rlcV$E|hvRvR#$wCWiiOj$xU+d38xJibN$6gZ~%K$_VE2 zYlfSA|Jc;@bPBpU(;XIahuxaxUXvLN7GRS>b7z!J$q3dI&HDVqRK0fXpm>-nZYkncb0p7rsKx@ZHj9Q)~BR1daaElu`g##X&4?zL8=j%!CWL5 z%vFL(OQ&SH$(fUG$jx#`{wJSe$TD(_Vguxiz9l#*SYUn@cgt65Y6>z6GD`1r0~wLk zBe|zKiV9L_<Oz*CgQb$P|z)reg*~$(fV2LO{P7P#SPfTnK^4xFqgr?_oqRF zTsGd2TM*_ed|K)Trj=#f=l9%<0ed1&mOEykvgn{eOEfm2z@W`jGc$sdq1r#9G$8jS4R4l))38A>p8;`DsarGM8!iM|eCYCTK7R|cc1KhZb z*c!epM7#Q+;z%Xx(pv+Ifh+)(_PCDl8 z2J^kMU>WPr5l*>b1vQRf1rra}7%sKvb%xE}MV_~?hZ*6tdS}2k!;M}a>CKj>-JWz9 zc3RFZE3=zV*{zUHcCyHy4CCw^7$#>j5}pDhhEb$SM#AG@AuG6KlQ7vNOm-@eAsGo1 z!5W%2*^z|FjwDQWBw;eLsf0FrBB_$GkFd*7lB77P;#x&SU@eKvB_bu+^_;$jdm8$;-j5vOUpi^ zu}>1X)H@H>S3B&&0a6*b}TTO+V_F-qOp$JG|h?Utu(Ck1Q_zxgITW0xPgvn)5hyr8!R+e&2Aum09Wi zf#+4olZGybz=e2h8XBpVr)k+V+I<*U!wNr*wYF+pYUS6_Bhs9Dt9J$cEDdX~0-L?9 zU<)mnhMoTbl*gu_oyy;YrfK*sJ4!5|S~@Jo;O>bHhV6Q z4Vn+6(+bC(bnDmY*#83Q0!m1yG+{X&m2NVmn+K*l^1yT~76;Z~t8}NT>-Z|T_Q2q?+ZtuLqJhsxQFj$dHc702E#9-kS{Gwm_6ydB^jc-MG#i$lO1hp&t6a8WutFZ7|*UxPf88%LznSLz6UI)b;cw4DX`MYSzwI5P4|(EZ`3Z~+DznkB$@?+sH?6c5EHi;!YCPD6hfhF@lVH2I z8tm}i0K2?jv&*f-t0&URTflltx6m&p;_chPO|)GI9X|n6(JO?G`@lPB-w-XB0On9~ z2z`GG=HlTY^xXtT3}fCp(i(q4a29*OLa!N|frKF}@HTiatrnt{h4&#t2x}Yz=UM)8 z!wUL%h_+UZYU_}VS|Rh#5cX02m#}uodD;6naE0Y`nX^L98Y_9N;X1F0Cyk6tA^Ke- z_@>p^Oy3F7>-T~ith6@TB7_g{x16z_?9k5r)DYI&0m=tL_`osdZ_Nu?HZNq+*Y=Ul zrggHgj0c7pPqMJdelTLFc_9l==mPVpCCmDF7MAHJU4*__c!J)o#1pctZ)VXq&ym*b zkj3oK3$8@+EPS93Y_xZq>|M4eCqvMTW4kcted00D}c#SY>7&9!uAF^r9t>8S% zS?>LjbOm)~JM$Scv(fQ4U=5>mHvKdJF2yF<&NA8}o0i=M)-&2?Gs=AeZb0{Jw0jBM zh&{9MQsv*wNSjR?9S1uMJFS*3OLwCe@hMtuGXA_5O!r;@LtZtnRKK{> zeEv?nU7xNsY(=9x&4=%#-92J!sfHnRnL;~W1hdIG1>KK#JEqX4O4rdwQ;<{n8%+|eE~YR> zT>v+mRP9z~hdt>cor48>6%#~;99ri%7%_~JKL-hqfSN&atk>k&ypUtPCdX#99Oi-q zK2=-f*ocvXJj(x)m8lhA4t@U=*lOuEd#=8dgGU_#J6PA{(1TQCmp#!O7q;;~OiMja zI>ZyBXSHTL#u`sKkkHIGlzt30~cAm87^Sw6Gm5i%l)8EMCu&sr{ z*x?$|S__4-gX&slCDd8%_1?QY(TXUHudWB*G})THpO9{`+BHIkvDH6=ZP+bLPt;qR zn6tvPqx5a}R)QUdo!%PKUCcXSMxGVmR%DxM-Z&NOZ6d9ab1HT_2x{bB2v|U0&ZVVJf#rB+F0G@SmG)$jr577& z1jxnOiC`^~jbrq%Efwppw>~j*y=1}YdoV?p3T2`$g_fU z2#e+6Y5T!!tdxhvj)4W<``~m+&coA&fHRl{^6<1iu!t7Vv)MKeuj?VL*)|Vd-Uc7E zob#-la@Oa0=ye#JkFE01t_7^J{0nG>JXYGf!D{T5$4dJg_zZiiJoFt7{(yZ%9{Q^G zW!NwetyN1sHq5h;DvuUfOL`rimPbrmsJS=~n|uInFfCfW<)qt8{*AP99zLc#o7sis z*=V0ft4SB_9P?tzfB7BjMVzlvSHx@> zF&jp(;m16Y4I^g52qQ2-TeD=uEEzFNMzCZn&t=I7{a0m{)B7S=@(?(mc8p-jw?J7k zLO*Q>7h<0XmQ-4njF=@OSn_((vSh?888J&nu%v2{B_n3Zh*>g%CF6L~XediYu%tAS zB_sIQYoII{p|>6cWyy$HGGdmDm?a}-$%t7pVwQ~1TmQto9?u9C#cq2*t>L509r2*n z@KLOH0hHH8%}P2Cg&#FD~hIv!FH@2MN?sy)v}e@ zJcf4Npw@CR{N$Hlh_!1Beg6n%dvAg{ln_JH6`=eihM(*MrF9HHc^CXTV}8smpnH^Y zq%~8=@RPmZeaIZc4l3b6dRff*j@3So7KzztAHya)NYBR~VtC6MunPOfY*dfoEgzDu zW*r;DK9cqsJS1lJiD93iq?cOB%a|i#SV^bJFIX-0%uO+~RSchbgS0Fb!(zmYu$W|P zw)`8gObnk{25JWp!)LaFo2-P*cwh`mc7YvcpH6$;h3Cic8Rgu{ZYUq?eF_%f)%ob& z3u^t4kM8|oIrDfv`kn+A;0gKYbqrLC=c7>)xD-3*qlMmj(@N0#Hs3rspEgwq?Tq~S zNOBPDGSu#@fYuZS$zOmZ{a_CMP{7Rc9GHtg7cjs4D;P11u_r2EW>KC(TDE{Wr5miU z5?;a^3)o-iEf+}&m`4tRjd(=?^T;t!d+-9}QMv<9E9*pUjtrfoBaEff@yct!7_-uJwBe=~CxP)`qvda6ESk;;#*sy%0Zn5o|}tLe{auPLR`H+H?k*z60jr6*JIL7{l5#&}bXj1kR+T zPJ%%soQcc_zz}wuX=BSwO861!TuPfsId6jzJa8uKf$d<7-ZYa|I|LTu^D}9+t)O-p zGg;&HgD>O5Gi@a>6VKNZ7folR(daO!)|`ojkAfX&I+L+c*kw<; znQ@9NvQb3K#*{y#Iss4-n{RL){y#YJj_~9j>JrAtbC30@ zd&o1C^s|(I549w4wjLr+vH3%>y;aOxaXism#r9UQy;aOxNj%Y8vuUq>Fhswejn+cV z0<+Qj1u)mr>RGeVS{Oyz*=W5Q%*VpBX{jS%5u+mK`HW+;@i&#JJ=AQ*0exC$&s{5R z9hRJp#g2nb^ugJ*l;qw}C*$lpTd1Q-Zm*4QPqLJt@*j8Si?*`W+w zJQxL8)Kx~#3!vmLBmYG(Vi>dMZI-j$u*05fS2c&R`UqIbT4j#yTjwx4_mbX-Kg^+} z4#Swx{^9|ioPxWMY8a%(xp@0gFoZA7#fEwkX4IXF4EWWYoQuWwgH6aV7h9<=tuyE1)ykut@?0#YlC@Kw%jkUu z-iFQs<{^pFdDJxz8H6$V<~-+h>@$zjdf;_v-TNr|D&0aKd=wq`!DdM1-Ew;LSuhZ-u2_k#=2r~EDI}cW4llji`^o#kl;BK%LJN!K@*vATNB37!ToH$S;b|vNf z35*zOB&noDI>92|t)%xT=N!tcq~tT;^H{!;l2uNVrCaRNR%Y|3Y?OG)Z2J`D|C}ee z_{LMzvIUGVuRTS(>q(5&%Tu&_Klm(>$|`*61Q?{2D%$Hb7^37VE3=9+FOm*pw<^k1 zPDx&6l2=jYVbU??)+)->TZMRR6k;?)bW=XtQ%p0v^j7b4FoP-hSek!KIsN#9wBpYH{`dA`W(vk3c~BONA2 zu?YM0fqBgAi>Ozqk$DmIHh{AEBJ8sbEW(D17*)=ITJ0>tKJSB#XtW4D&5ZNtD1WEgPllQP3=l|^VVW?_dxaK#pY>?sp~9h?aCL^cM{=U z72?BB({qK27(Y$F3xL{Lt)Uh@U&LEA)FP~9)~=xz;mekD z1tUofwdk#NhK+_zX zBImV8cmdR2vK9%Cfpzx$B}>0-s578iWK*6-L#^R!*=4A-R&=j553j}3B!lM4T72w; z^E|%#DX0^Z=kd~A;6`k?)Oy@f>v2nw|3^Ggk6UUzZmIRSrPkw?qQzRCtH&)hU6!KD zC!`gjT8dOXpk}wFSnLd_zP1!ePJP(@I5$PnT^>!V-^&qJAb{&%IiN=aLBtHe_vC^)iWTDpEb(H@asFRC2B;N@Z z;RAKp{5+@;qs~^^b+!(vLzi7VX=IG5LlV`cHFh2SS|zAo*P+)@P;2Zu`m(Ugup0~1 z;~R%T&2ja}_BN=!TRpOU3~KJEw^eJs>0WR0)T8@Ro0^;Zmas`tO^38b>6X@Re>-{Ut7+qKv+ik%jqM> zLB+Xvxe+}VVgxe z5>+KCyAlf=2J`Tul~_O+YR$jOM%Puy^K;Ug%~v7M7Emp+ z3UAR9&E~7j&sQ;$#FKuOy~irX2c^YmSp`El0K+yF-)O)md%$!&xdETllPqd)psqt; z7)=|fOHVY5HBgr@inlaS*IQt|eOkag*nlg z+7q3$HsGInSN_?6l~mVelcXL0Z@^aDK+XOQSWG#)d3QCV**3J&-fFGkI<$C=aap_X zb!gEKDtf#Qsonw0+2gN6Dm~Y%v<^QR0@g8$tz#Wn2{vQxbx2aL7!CcX(aPl9l3BHp zGW)=6;_!`>+zZZN6l$dWHc;g^TKSEPgrAaDEsfNY2ujmNYWaJxnO1J3mKWi4>$JCt zT9$($PDq=mr3cLReg%p@&}0$OCTej>m$T++vRazh2lbM!WIx_Sjpsqt*km;}u`@bG zx(-V=QSV}~nNhlldjAR3&Zr4LKM8|7o)%ee^TK*0d7ZS*>DD7dH>f$Ca|vWyj}P>L z5u{p=59|TOQ(BJ?>;-jhwH|4EL3zS@q*VzESdFYFl6D-dW=*>usgz$Qbo4D|C|Klp z?|Ni=k7!FONTv5*`Lu(l=We2~UD8j8rY?yBX%bc7Gcv^AxDv z-v;y&YWKH+JW6jw$2M!DHmq@mbeNrf8`d}t>b$#+xAuWCY|_SX(8`-><%^)sq3GF`ZZwqq+(JcxCN5XdVu6A0sfpmy* zubnpC0fsp{=4a57*RWdtB9jK{W9<9<-RzTMVr?f7{gY1z3QJ0Anf@#=Ogybr8K zuXZea6nq)qXt!8FJ3jDx(mID~r)A$KekZ9qOsWo~dV_Qbc{s?3$lO&v(6 zw_1thbRx+qP$$=&$gl>~nzj>3PJr6^b|S+zP~%mn)!u0}c2eU3p2+t)sdpDxjm)H(pyEW0JqZ14ufj1t@O2%pyHWZkydx099B5@V%b2#Rd}BM z4v(LXV+VBIKsuhC+l>S11a8;7IFL?szRBF==jR*90;2}f*E!jNNyLv!xk+=s^L_sP zJMP##o)uCG4M-#{@Gfyu8>WZsX*f} z_muvEI9QqK`6$o6N2!wLVg7xDrw{V^-=IBz=hNEHVZVR7pZXkbgQOfsu6TBJ|H@6N zkFjkn>%=I2RpxBxR@D~nNR7vGJBZ~>MDIFn?4HvH-0+%2y=`WP zFJOV&+1q}|{j3KWo1TM>yNXqKHahB_m{=&f;YHjMPDU8Jqh@bwEds>fTf$tG5O)S5JiXt zh6Sz;TtnpkURJx`bUtNOvyAxo$b`Qx`r6kLrak`HBk>P>`+-D$zWtEl!~FgbKM!B? zz$1@8_Pxg+z5lU?9(gS3@$Wu#+iiKb4g4F^zqjB1Mg3iM`gDMiXgL4EQb(ptC-87- z#dpymK_By(J_&s1{>SvpSnWJXFyG=2wvq0(oO1(j1P;W_h;!q|$5+J9PsmL8R>IQ> zI}-LJ&QCl)Wb}}alfIEuk#uqBqeE9*^@Xcyhs_!G(bbvP#9g!V+9$62=5?!wUqAf5 z;f=$)uAh1RitC&0cKc%^o*a`fqGm+nh>u2WOa5x|+~oNq=OphL`K^(2`0sB={&eJv zBX^D(HmY(|?Wmn8x2HUt@@h(R%GuHUAxSAJ+#A;2n0ez9H&))b>!yh} zMQ*CR>Ef6K{u?&tt})ePc5*ZRh16fA9vC}h>^H|&kNw5iU1@)rwl3}bxCh4l0?p>q zGY0QGj>Xr;;ZNzD+l;r~0He};`tr?3`Eee5%P5}A$thk`h`(^AMSI^vE6z3#E~RhH zp@+=15v&|8q>o z#MSt^{7Wl--Jz5}Z=f%3wElYeHsw~lQg;w^13~u>bo)Se4|MZDaU|V35VJ-%4s_o@ zw+$4Z6i0jvZ^G1MmJnNBF&#y8qRbRpwJSbXhOa1sBMz+g4!Thwu9l)V;%Vt7f$kBA zp)0<*I9j?tppzdlKok=Zw~=q#B&Ge4qMtg)(0u{j7SOI#j6TJ=F4uOE+7x3O`kC5v zE5O!nl&E#5R&6RhjrsR1x^zN{=r&DqR$CxIzfq?Pch?)FDxd%c>G#H`#L01GLaZQ z(>g}Xeew3i+81YEjD595!0eaFD(5hoJb@teC=#nG3Iw5k+asEoCenEB%6 zi$FG=GcoSPw^w{YTzkJ& z4-sS7gS@O=DMS2vvFo+d7PB7i8Z{33jyUyV)cZbj78}Yp&hh3+-aN@$C#hd8P=+4j z&uhOeuhN-|_IQfx4_a8aJKz>0T{b&GtsTqw5l>zmufcXxOh;#};>P>Fc?M0?cBj$e zh}Ez56NgJIL7mOUF$anXpU!V$!HYj52E5{J;;_lmV!qGfN38c!e#Ce$!xCDtiYFtc zyI7WDxr^iO_mAtaY$Dq1F=o4Bnqsw!(=JB4`0TQ(xa{Ieh{vw8WSt?4Bf*VyY%Kn| z*z0~@sbLlQ2Q2(Np8OnMyqJB>KVs$AkZ3;=aW-ducN%FnBgtB7-^UrsbHx6BNX$>( z{2XJzbF{{fkzzmXd&+iHVv>l7E*`pA=;ELc!E+8_%Pn}tA##3#Uv9?(POu74EJD0< zvChRg7YjCr_r*3B*IZ0<@yx|CSD%m8`b6mV}vBt$27h_z^DzSIP6&DXuJaMta#Szz8z4+n2b&oOk zUmhp+;ZrbGsY#4*?T^I<_s0qC5#W&EW8#2oU*L}wrw4rQ+`w4Ti=Q1r8lpbr6WiM# zFW8Mzu0LL|ThUsd-(lckGqJnH?H04!_p&(K<=l*~ufo?iU|sm!u(@@PrpTt^nqqN_ z!z~84_}gM{i@UA3x_H}SZHu!l#gYPGdfD;#Svti`VuyIS08&0rU(&G#r-M@%j8wER=e1oHqfsl}rfi&`zL zQDPh|>hb0otfsf)ko6e8h~==N_I_eaEAFHnm-e`J{wrC@D}NJ1TKs6Sqs5IDGg^B+ zofwG|tub3?*op^>3*A9lJm@jh+DmPxsp&X19mg^-&8R`+hd=(Ex?+sd=@I7}e5Nr< zOlN=oq$g6E7|#COd59Vg(k5r9<&ce6e8UX=O`K*in#E@pn^|0DF`30<*7=n<%wjN$ zzby8$xXWTL&qFt{mc>~XV_AGOVWpIB^Safx+8uTvVai2aq$W^CF)t>>xrEVZ6x zB`)T$c*E-Tiu#H%EWWU25^*NP6c$g|_uE8TijyFI7du$oU`1ra3)XBVPOv|loYnXL z&}TF%iVG|zuz0{?0p}o_IIQCTijgSpuUM<%{c0rCEbfnlZ_`p+XsKgJ^gASiBY-aA z_==Y*R;t*&;`WM7??r+O=MxouaK8E4HKE zTUThe3+>vk(C+%rY1jHW?dY5IPhY$D2ef z?W2{}4m8ks3tI$l5Ia`fSe<5y7wfO8v|1gMT3)l=n6To(iqq*!+k=D}y8_t$Ft#T) z$B$UAinHe+l_E)6$^H^g(isJ}b2wQL&s8i}-{$)Uyy;!zw))cgqop{lVzi3SDmJUQ ztYWhI{eK5`Z^!OykY3}o`um4y(1Zr^`=kL4wC4UDUiAmGc+Hrq;;Bj#aa4V6;<5d9 z`owG4em9=A49$A*tgU#KR?DquN6ZoV#Y7bkRV-9-P*c$AQ?xmUq`gRb1WDl@F@B17 zD%Pn#d&r*hZ%!l0Bc`e5R{5{LZaP5e2Pyd=rS`GE5T`@&H=XN6th#jPO&<* z`r!sE^@-7`xT3sXr{X#>5hqfo$~sdPgH!xXu{Xut)GFg8WDsl9A94G!*>P;vLg{Z) zx@)bY6FRNmb$YC`W1Sp}k0WL#8l$1kjJ2x~CsQZK;$vQ_na{+x5erisOhqhpBCB&? zosIgdx$S7GxnJw$i|8!IrTCWG0f=iUcD~r<0j#J`{9U9@0b9v&6%y!XgKVu_Vq0IC zE6H+=#ZvuPNGsiQ16FzgS-G__;7vMF5_?kINiiS9n-ptOoJoHL#F;t2iz_LnqOrTy=(Hc54x^8DwA$lwI)I*HFZ%1rGv<+sE@;2c{R@6{X7xJS zi>;V|teo_d5>rt;MgFuQd41{jn~y5;Eq0=~iDD*-m*}q!;P2y`;v^x(K~Sr#V{1VQ0zi+3$>dOuTZQ) zaSFvK)XBb9lj0JJN$B^`bb9D@v^~-=ZfI>XIR1+_s5Q2HHOVlJ62%u(uMk&I=OsEV z5u--yRWSs`4-`AFl{SR)N4eMYP7m*>2dSt3iFb4#1dnHZA~v8_&0+%TOj9ht*U2vi zp!k0}Z5uY=*V_C19IKwC6z<3{X8F;W-(l5$JaPhi0df7r^wVjCSblzw;I18-iQRXp zeq`1;pSW^j^oh?WHlM}~G5N&fQ=9lZq*JuZ;5c!VcF{PiaiY)qfPaRlR@TYJC}hx> z#ob|AOiVqU?TV!*j-Eyg)hTwKxOrmciI*oOBk-&4bHDEa(=SNSmwtuJ*JE&1N0G@ZXmzTK48 zL}{Ac`f0r*c>6x&>!U4pSRe3LWFIkaa$3k7B>tS(bK=g4IX47Zx%bGA+DS3F!4+yE z9w}zK_KyjdR(!+FPsNfGM@|em@#Dmf6E{xGIPv1diqj59j5zV(#D)_WZUk>%OPRxr z2PYPsIB;UXiT@_{o49XczKQoH)|)tQV!Vm(CbpZnZW_%L30HhfF#_@2a?wB>H!<84 zm-Kto;7UtzfjD~90eaMKY~|6bKEZ$CG4V`1Ht9IH1N8g2{OLm*QTg63-qP$Z)|y`{ z_c|Ge#8$f;n>tLJYOFrV+Cve$!F}2VYSUT{#ud-RNfRSYu^X|`#6{Dp;7#6XMK{0g zIsK$n#RbqP_9^YEXvr={F?|F2W&hIb`g#9aJK$fEq!HrUU^CevGDl8Hwq7MaF{(-s9CoZk=Pi-YsKJY4fTx704p@2??&tg(}_wqft{ z=H;5({m~s}3nQY~VSazrye|K|a$Y}zfA(?;BsQ2of@wb2ii`Vs8cS$VU)pU*d(@a; zvawiS;(UqmB_4nujT(X$g;@V4)(N`fpMVW}{B;7KT#kbzGA1X|c1Q6P^(sX)75}@M zaaSt<#oh+j4N0sOwQE;fvB$x`6@L_WYXqeq!mjI)m|KuKEWQWQRt|rDgcbiv>??7v#Jm#kD#&Pe z5MS601s_Dlw|WrxKe= zQ9&`O{8bv92+9_NO8hB*1lH*IDKdyTr9M1_u|S+Df1S!rDq2fiDKVM+HK|Sn6yw>? zOjk+iin!Ke-FUpyfAdY`?_+-bXWs5*53EyfF;4sv#Df|f&m^DtPtDj;E8EeO@(HED z`yG^E+elm^F^zn?{GKxR8N*2YBA;EPDB9*rt20S;d37c}k=R5jW+8Ej z#3b^2wxXo_@VbwXSH7Uw-wBgjydlMI>v(oKBC2@o;2PCGuNg*Z?^2&)Ji1e=HNQA0 zdl(}$dk>BW`s<$J1c?#k*SUpU2N{9+%kfxua8>*hB-6UpU%!a`<6D$_Tl5RDe#H5? zEQP;Pz6lT5V{Ig!k61q9kBH%OIhv={M<=Bze%Q;r=%2m#dMi@17cYPtk4$3mh{L1R zvG_ZFtmu8#+Lvp2gIadr#U3?n8}K#N=CAd|(-BMOKi1~&k=3sk@FPx+_QQT{a8MbE z#KaK~M`PNlff(o-tfKjLa6P%r`i*q(W1u?0&>X9{%b%=7F>SOv8H3Dwv5fWz=kYRG zXS-R)kI${3R6nvRPL0?s;?u}N)9E*2(kNao7L8_dU*-eUKtz@2SIT=Gwe%18nEJ=B z2U_wl?X9(>xKoPR>ZI=IfUQ5Fq!Yxx{MG0&FsfH8Pwgjt z{)EvLS^%k(6; N7*;_XPXhc`@$Yk|8lV6G literal 0 HcmV?d00001 diff --git a/web/app/assets/fonts/Raleway/Raleway-Light.woff b/web/app/assets/fonts/Raleway/Raleway-Light.woff new file mode 100644 index 0000000000000000000000000000000000000000..85f92d954d3934333e0aec42d5de67d1db301da6 GIT binary patch literal 31592 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

nclP+UiD} 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 literal 0 HcmV?d00001 diff --git a/web/app/assets/fonts/Raleway/Raleway-Light.woff2 b/web/app/assets/fonts/Raleway/Raleway-Light.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..8e8ac1f40f9638fae522548eabf5d956343ade53 GIT binary patch literal 22628 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 literal 0 HcmV?d00001 diff --git a/web/app/assets/fonts/Raleway/Raleway.eot b/web/app/assets/fonts/Raleway/Raleway.eot new file mode 100644 index 0000000000000000000000000000000000000000..fc7ce0746b0385fea594471b97e0d407e7f3ee6f GIT binary patch literal 30373 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 literal 0 HcmV?d00001 diff --git a/web/app/assets/fonts/Raleway/Raleway.svg b/web/app/assets/fonts/Raleway/Raleway.svg new file mode 100644 index 000000000..92afeb5d6 --- /dev/null +++ b/web/app/assets/fonts/Raleway/Raleway.svg @@ -0,0 +1,2168 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/web/app/assets/fonts/Raleway/Raleway.ttf b/web/app/assets/fonts/Raleway/Raleway.ttf new file mode 100644 index 0000000000000000000000000000000000000000..3b354c87e94c41924cb93bb1888fa5e9f4add14d GIT binary patch literal 63796 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 literal 0 HcmV?d00001 diff --git a/web/app/assets/fonts/Raleway/Raleway.woff b/web/app/assets/fonts/Raleway/Raleway.woff new file mode 100644 index 0000000000000000000000000000000000000000..02b0dd8f5a252e6bf06b5775d0b24cd1e6300e42 GIT binary patch literal 31836 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 z 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

s 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 literal 0 HcmV?d00001 diff --git a/web/app/assets/stylesheets/client/client.css b/web/app/assets/stylesheets/client/client.css index 48b6cbfc7..1b1c05606 100644 --- a/web/app/assets/stylesheets/client/client.css +++ b/web/app/assets/stylesheets/client/client.css @@ -9,6 +9,7 @@ * compiled file, but it's generally better to create a new file per style scope. * *= require_self + *= require web/Raleway *= require jquery.ui.datepicker *= require ./ie *= require jquery.bt diff --git a/web/app/assets/stylesheets/client/jamkazam.css.scss b/web/app/assets/stylesheets/client/jamkazam.css.scss index 105946377..af98aad9a 100644 --- a/web/app/assets/stylesheets/client/jamkazam.css.scss +++ b/web/app/assets/stylesheets/client/jamkazam.css.scss @@ -24,11 +24,11 @@ body { height: 100%; overflow: hidden; font-size: 14px; - font-family: Raleway, Arial, Helvetica, sans-serif; + font-family: 'Raleway', Arial, Helvetica, sans-serif; font-weight: 300; input,textarea { - font-family: Raleway, Arial, Helvetica, sans-serif; + font-family: 'Raleway', Arial, Helvetica, sans-serif; font-weight: 300; } } @@ -556,22 +556,22 @@ hr { } ::-webkit-input-placeholder { - font-family: Raleway, Arial, Helvetica, sans-serif; + font-family: 'Raleway', Arial, Helvetica, sans-serif; font-size:14px; } :-moz-placeholder { /* Firefox 18- */ - font-family: Raleway, Arial, Helvetica, sans-serif; + font-family: 'Raleway', Arial, Helvetica, sans-serif; font-size:14px; } ::-moz-placeholder { /* Firefox 19+ */ - font-family: Raleway, Arial, Helvetica, sans-serif; + font-family: 'Raleway', Arial, Helvetica, sans-serif; font-size:14px; } :-ms-input-placeholder { - font-family: Raleway, Arial, Helvetica, sans-serif; + font-family: 'Raleway', Arial, Helvetica, sans-serif; font-size:14px; } diff --git a/web/app/assets/stylesheets/client/metronomePlaybackModeSelect.css.scss b/web/app/assets/stylesheets/client/metronomePlaybackModeSelect.css.scss index 7700a57be..79d52c274 100644 --- a/web/app/assets/stylesheets/client/metronomePlaybackModeSelect.css.scss +++ b/web/app/assets/stylesheets/client/metronomePlaybackModeSelect.css.scss @@ -7,7 +7,7 @@ overflow:auto; border:1px solid #ED3618; text-align:left; - font-family: Raleway, Arial, Helvetica, sans-serif; + font-family: 'Raleway', Arial, Helvetica, sans-serif; ul { height:100%; margin-left:20px; diff --git a/web/app/assets/stylesheets/client/muteSelect.css.scss b/web/app/assets/stylesheets/client/muteSelect.css.scss index bd73ce571..c155de69d 100644 --- a/web/app/assets/stylesheets/client/muteSelect.css.scss +++ b/web/app/assets/stylesheets/client/muteSelect.css.scss @@ -8,7 +8,7 @@ overflow:auto; border:1px solid #ED3618; text-align:center; - font-family: Raleway, Arial, Helvetica, sans-serif; + font-family: 'Raleway', Arial, Helvetica, sans-serif; ul { @include vertical-align-column; height:100%; diff --git a/web/app/assets/stylesheets/corp/corporate.css.scss.erb b/web/app/assets/stylesheets/corp/corporate.css.scss.erb index 640360bd1..f7e8907f2 100644 --- a/web/app/assets/stylesheets/corp/corporate.css.scss.erb +++ b/web/app/assets/stylesheets/corp/corporate.css.scss.erb @@ -1,4 +1,5 @@ /** +*= require web/Raleway *= require client/ie *= require client/jamkazam *= require client/header diff --git a/web/app/assets/stylesheets/landing/landing.css b/web/app/assets/stylesheets/landing/landing.css index c3ce73d41..a37a24675 100644 --- a/web/app/assets/stylesheets/landing/landing.css +++ b/web/app/assets/stylesheets/landing/landing.css @@ -1,4 +1,5 @@ /** +*= require web/Raleway *= require client/ie *= require client/jamkazam *= require client/screen_common diff --git a/web/app/assets/stylesheets/landings/partner_agreement_v1.css.scss b/web/app/assets/stylesheets/landings/partner_agreement_v1.css.scss index 4adb0e548..647f77f9a 100644 --- a/web/app/assets/stylesheets/landings/partner_agreement_v1.css.scss +++ b/web/app/assets/stylesheets/landings/partner_agreement_v1.css.scss @@ -4,7 +4,7 @@ * { color:black! important; background-color:#eee; - font-family: Raleway, Arial, Helvetica, sans-serif ! important; + font-family: 'Raleway', Arial, Helvetica, sans-serif ! important; font-weight: 300 ! important; } diff --git a/web/app/assets/stylesheets/minimal/minimal.css.scss b/web/app/assets/stylesheets/minimal/minimal.css.scss index 9ec8c234a..f97d05c7f 100644 --- a/web/app/assets/stylesheets/minimal/minimal.css.scss +++ b/web/app/assets/stylesheets/minimal/minimal.css.scss @@ -1,4 +1,5 @@ /** +*= require web/Raleway *= require client/ie *= require client/jamkazam *= require client/screen_common diff --git a/web/app/assets/stylesheets/web/Raleway.css b/web/app/assets/stylesheets/web/Raleway.css new file mode 100644 index 000000000..e7c9f1caf --- /dev/null +++ b/web/app/assets/stylesheets/web/Raleway.css @@ -0,0 +1,36 @@ +@font-face { + font-family: 'Raleway'; + font-style: normal; + font-weight: 100; + src: local('Raleway Thin'), local('Raleway-Thin'), url(/assets/raleway/Raleway-Thin.ttf) format('truetype'), url(/assets/raleway/Raleway-Thin.woff2) format('woff2'), url(/assets/raleway/Raleway-Thin.woff) format('woff'); +} + +@font-face { + font-family: 'Raleway'; + font-style: normal; + font-weight: 300; + src: local('Raleway Light'), local('Raleway-Light'), url(/assets/raleway/Raleway-Light.ttf) format('truetype'), url(/assets/raleway/Raleway-Light.woff2) format('woff2'), url(/assets/raleway/Raleway-Light.woff) format('woff'); +} + +@font-face { + font-family: 'Raleway'; + font-style: normal; + font-weight: 400; + src: url(/assets/raleway/Raleway.eot); + src: local('Raleway'), url(/assets/raleway/Raleway.eot?#iefix) format('embedded-opentype'), url(/assets/raleway/Raleway.svg#Raleway) format('svg'), url(/assets/raleway/Raleway.ttf) format('truetype'), url(/assets/raleway/Raleway.woff2) format('woff2'), url(/assets/raleway/Raleway.woff) format('woff'); +} + +@font-face { + font-family: 'Raleway'; + font-style: normal; + font-weight: 700; + src: local('Raleway Bold'), local('Raleway-Bold'), url(/assets/raleway/Raleway-Bold.ttf) format('truetype'), url(/assets/raleway/Raleway-Bold.woff2) format('woff2'), url(/assets/raleway/Raleway-Bold.woff) format('woff'); +} + +@font-face { + font-family: 'Raleway'; + font-style: normal; + font-weight: 900; + src: local('Raleway Heavy'), local('Raleway-Heavy'), url(/assets/raleway/Raleway-Heavy.ttf) format('truetype'), url(/assets/raleway/Raleway-Heavy.woff2) format('woff2'), url(/assets/raleway/Raleway-Heavy.woff) format('woff'); +} + diff --git a/web/app/assets/stylesheets/web/web.css b/web/app/assets/stylesheets/web/web.css index 4a5ad0b12..12c614f5c 100644 --- a/web/app/assets/stylesheets/web/web.css +++ b/web/app/assets/stylesheets/web/web.css @@ -1,4 +1,6 @@ /** + +*= require ./Raleway *= require client/jamServer *= require client/ie *= require client/jamkazam diff --git a/web/app/views/layouts/application.html.erb b/web/app/views/layouts/application.html.erb index 26046c3f6..f97aca179 100644 --- a/web/app/views/layouts/application.html.erb +++ b/web/app/views/layouts/application.html.erb @@ -6,15 +6,6 @@ - - <%= stylesheet_link_tag "client/ie", media: "all" %> <%= stylesheet_link_tag "client/jamkazam", media: "all" %> diff --git a/web/app/views/layouts/client.html.erb b/web/app/views/layouts/client.html.erb index dd7d51a9b..033716248 100644 --- a/web/app/views/layouts/client.html.erb +++ b/web/app/views/layouts/client.html.erb @@ -6,17 +6,6 @@ - - <%= stylesheet_link_tag "client/client", media: "all" %> <% if bugsnag? %> diff --git a/web/app/views/layouts/corporate.html.erb b/web/app/views/layouts/corporate.html.erb index 763a78c93..5269a3781 100644 --- a/web/app/views/layouts/corporate.html.erb +++ b/web/app/views/layouts/corporate.html.erb @@ -2,17 +2,6 @@ <%= full_title(yield(:title)) %> - - <%= stylesheet_link_tag "corp/corporate", :media => "all" %> diff --git a/web/app/views/layouts/landing.html.erb b/web/app/views/layouts/landing.html.erb index e3c655fb0..51f1deab4 100644 --- a/web/app/views/layouts/landing.html.erb +++ b/web/app/views/layouts/landing.html.erb @@ -6,17 +6,6 @@ - - <%= stylesheet_link_tag "landing/landing", media: "all" %> <% if bugsnag? %> diff --git a/web/app/views/layouts/minimal.html.erb b/web/app/views/layouts/minimal.html.erb index 37bf88c9e..a4ab7f0d4 100644 --- a/web/app/views/layouts/minimal.html.erb +++ b/web/app/views/layouts/minimal.html.erb @@ -6,17 +6,6 @@ - - <%= stylesheet_link_tag "minimal/minimal", media: "all" %> <% if bugsnag? %> diff --git a/web/app/views/layouts/web.html.erb b/web/app/views/layouts/web.html.erb index 929e8d7ed..dfc3916de 100644 --- a/web/app/views/layouts/web.html.erb +++ b/web/app/views/layouts/web.html.erb @@ -6,17 +6,6 @@ - - <%= stylesheet_link_tag "web/web", media: "all" %> <% if bugsnag? %> diff --git a/web/public/maintenance.html b/web/public/maintenance.html index d0641191d..2edb104cc 100644 --- a/web/public/maintenance.html +++ b/web/public/maintenance.html @@ -82,7 +82,7 @@ table { border-collapse: collapse; border-spacing: 0px; } caption, th, td { text-align: left; font-weight: normal; vertical-align: middle; } a img { border: medium none; } - body { color: white; background-color: rgb(38, 38, 38); width: 100%; height: 100%; overflow: hidden; font-size: 14px; font-family: Raleway,Arial,Helvetica,sans-serif; font-weight: 300; } + body { color: white; background-color: rgb(38, 38, 38); width: 100%; height: 100%; overflow: hidden; font-size: 14px; font-family: 'Raleway',Arial,Helvetica,sans-serif; font-weight: 300; } a { cursor: pointer; color: rgb(255, 204, 0); text-decoration: none; display: inline-block; } a:hover { text-decoration: underline; color: rgb(130, 174, 175); } select { padding: 3px; font-size: 15px; border-radius: 6px; } From 2cb01d8492748c93d666e44059157adfdb38640e Mon Sep 17 00:00:00 2001 From: Seth Call Date: Fri, 29 May 2015 21:33:45 -0500 Subject: [PATCH 16/45] * VRFS-3268 - make bugsnag and recurly async --- web/app/assets/javascripts/application.js | 1 + web/app/assets/javascripts/checkout_order.js | 2 +- web/app/assets/javascripts/checkout_utils.js.coffee | 6 ++++++ web/app/assets/javascripts/corp/corporate.js | 1 + web/app/assets/javascripts/landing/landing.js | 1 + web/app/assets/javascripts/web/web.js | 1 + web/app/views/layouts/application.html.erb | 4 ---- web/app/views/layouts/client.html.erb | 4 ---- web/app/views/layouts/corporate.html.erb | 4 ---- web/app/views/layouts/landing.html.erb | 4 ---- web/app/views/layouts/minimal.html.erb | 4 ---- web/app/views/layouts/web.html.erb | 4 ---- web/app/views/shared/_facebook_sdk.html.slim | 2 +- web/app/views/shared/_google_nocaptcha.html.slim | 2 +- web/app/views/shared/_recurly.html.slim | 5 +---- web/config/initializers/gon.rb | 1 + web/vendor/assets/javascripts/bugsnag.js | 10 ++++++++++ 17 files changed, 25 insertions(+), 31 deletions(-) create mode 100644 web/vendor/assets/javascripts/bugsnag.js diff --git a/web/app/assets/javascripts/application.js b/web/app/assets/javascripts/application.js index 03ccbd2a7..d9ca26642 100644 --- a/web/app/assets/javascripts/application.js +++ b/web/app/assets/javascripts/application.js @@ -10,6 +10,7 @@ // WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD // GO AFTER THE REQUIRES BELOW. // +//= require bugsnag //= require bind-polyfill //= require jquery //= require jquery.monkeypatch diff --git a/web/app/assets/javascripts/checkout_order.js b/web/app/assets/javascripts/checkout_order.js index 70f5171a0..168b965d6 100644 --- a/web/app/assets/javascripts/checkout_order.js +++ b/web/app/assets/javascripts/checkout_order.js @@ -185,7 +185,7 @@ displayTax(effectiveQuantity, unitTax, 1.99 + unitTax) } else { - + checkoutUtils.configureRecurly() var pricing = context.recurly.Pricing(); pricing.plan_code = gon.recurly_tax_estimate_jam_track_plan; pricing.resolved = false; diff --git a/web/app/assets/javascripts/checkout_utils.js.coffee b/web/app/assets/javascripts/checkout_utils.js.coffee index 7f61f0fb8..4570bd052 100644 --- a/web/app/assets/javascripts/checkout_utils.js.coffee +++ b/web/app/assets/javascripts/checkout_utils.js.coffee @@ -8,6 +8,7 @@ class CheckoutUtils @rest = new context.JK.Rest(); @cookie_name = "preserve_billing" @lastPurchaseResponse = null + @configuredRecurly = false init: () => @@ -54,5 +55,10 @@ class CheckoutUtils return carts[0].product_info.free + configureRecurly: () => + unless @configuredRecurly + context.recurly.configure(gon.global.recurly_public_api_key) + @configuredRecurly = true + # global instance context.JK.CheckoutUtilsInstance = new CheckoutUtils() \ No newline at end of file diff --git a/web/app/assets/javascripts/corp/corporate.js b/web/app/assets/javascripts/corp/corporate.js index 989e7bb85..5d6e33bfa 100644 --- a/web/app/assets/javascripts/corp/corporate.js +++ b/web/app/assets/javascripts/corp/corporate.js @@ -1,3 +1,4 @@ +//= require bugsnag //= require jquery //= require jquery.queryparams //= require AAA_Log diff --git a/web/app/assets/javascripts/landing/landing.js b/web/app/assets/javascripts/landing/landing.js index 19034e53c..de23401db 100644 --- a/web/app/assets/javascripts/landing/landing.js +++ b/web/app/assets/javascripts/landing/landing.js @@ -1,3 +1,4 @@ +//= require bugsnag //= require bind-polyfill //= require jquery //= require jquery.monkeypatch diff --git a/web/app/assets/javascripts/web/web.js b/web/app/assets/javascripts/web/web.js index a2a2c58d2..89f49d6fe 100644 --- a/web/app/assets/javascripts/web/web.js +++ b/web/app/assets/javascripts/web/web.js @@ -1,3 +1,4 @@ +//= require bugsnag //= require bind-polyfill //= require jquery //= require jquery.monkeypatch diff --git a/web/app/views/layouts/application.html.erb b/web/app/views/layouts/application.html.erb index f97aca179..8c5742678 100644 --- a/web/app/views/layouts/application.html.erb +++ b/web/app/views/layouts/application.html.erb @@ -23,10 +23,6 @@ <%= stylesheet_link_tag "client/search", media: "all" %> <%= stylesheet_link_tag "client/ftue", media: "all" %> <%= stylesheet_link_tag "client/createSession", media: "all" %> - <% if bugsnag? %> - - - <% end %> <%= include_gon %> <%= csrf_meta_tags %> diff --git a/web/app/views/layouts/client.html.erb b/web/app/views/layouts/client.html.erb index 033716248..6c234aba7 100644 --- a/web/app/views/layouts/client.html.erb +++ b/web/app/views/layouts/client.html.erb @@ -8,10 +8,6 @@ <%= stylesheet_link_tag "client/client", media: "all" %> - <% if bugsnag? %> - - - <% end %> <%= include_gon %> <%= javascript_include_tag "application" %> <%= csrf_meta_tags %> diff --git a/web/app/views/layouts/corporate.html.erb b/web/app/views/layouts/corporate.html.erb index 5269a3781..1d1f31f41 100644 --- a/web/app/views/layouts/corporate.html.erb +++ b/web/app/views/layouts/corporate.html.erb @@ -5,10 +5,6 @@ <%= stylesheet_link_tag "corp/corporate", :media => "all" %> - <% if bugsnag? %> - - - <% end %> <%= include_gon(:init => true) %> <%= javascript_include_tag "corp/corporate" %> <%= csrf_meta_tags %> diff --git a/web/app/views/layouts/landing.html.erb b/web/app/views/layouts/landing.html.erb index 51f1deab4..54a316d1d 100644 --- a/web/app/views/layouts/landing.html.erb +++ b/web/app/views/layouts/landing.html.erb @@ -8,10 +8,6 @@ <%= stylesheet_link_tag "landing/landing", media: "all" %> - <% if bugsnag? %> - - - <% end %> <%= include_gon(:init => true) %> <%= csrf_meta_tags %> diff --git a/web/app/views/layouts/minimal.html.erb b/web/app/views/layouts/minimal.html.erb index a4ab7f0d4..411b792c5 100644 --- a/web/app/views/layouts/minimal.html.erb +++ b/web/app/views/layouts/minimal.html.erb @@ -8,10 +8,6 @@ <%= stylesheet_link_tag "minimal/minimal", media: "all" %> - <% if bugsnag? %> - - - <% end %> <%= include_gon(:init => true) %> <%= csrf_meta_tags %> diff --git a/web/app/views/layouts/web.html.erb b/web/app/views/layouts/web.html.erb index dfc3916de..9a8965853 100644 --- a/web/app/views/layouts/web.html.erb +++ b/web/app/views/layouts/web.html.erb @@ -8,10 +8,6 @@ <%= stylesheet_link_tag "web/web", media: "all" %> - <% if bugsnag? %> - - - <% end %> <%= include_gon(:init => true) %> <%= csrf_meta_tags %> diff --git a/web/app/views/shared/_facebook_sdk.html.slim b/web/app/views/shared/_facebook_sdk.html.slim index f1ba82ae2..ff6de72df 100644 --- a/web/app/views/shared/_facebook_sdk.html.slim +++ b/web/app/views/shared/_facebook_sdk.html.slim @@ -1 +1 @@ -script src="https://apis.google.com/js/platform.js" async defer \ No newline at end of file +script src="https://apis.google.com/js/platform.js" async="async" defer="defer" \ No newline at end of file diff --git a/web/app/views/shared/_google_nocaptcha.html.slim b/web/app/views/shared/_google_nocaptcha.html.slim index c0df3c331..c804c37b7 100644 --- a/web/app/views/shared/_google_nocaptcha.html.slim +++ b/web/app/views/shared/_google_nocaptcha.html.slim @@ -1 +1 @@ -script src="https://www.google.com/recaptcha/api.js" async defer \ No newline at end of file +script src="https://www.google.com/recaptcha/api.js" async="async" defer="defer" \ No newline at end of file diff --git a/web/app/views/shared/_recurly.html.slim b/web/app/views/shared/_recurly.html.slim index d22bdabbd..7f566e136 100644 --- a/web/app/views/shared/_recurly.html.slim +++ b/web/app/views/shared/_recurly.html.slim @@ -1,4 +1 @@ -script src="https://js.recurly.com/v3/recurly.js" - -javascript: - recurly.configure(gon.global.recurly_public_api_key) \ No newline at end of file +script src="https://js.recurly.com/v3/recurly.js" async="async" defer="defer" \ No newline at end of file diff --git a/web/config/initializers/gon.rb b/web/config/initializers/gon.rb index f82a4a1d7..587a89626 100644 --- a/web/config/initializers/gon.rb +++ b/web/config/initializers/gon.rb @@ -19,4 +19,5 @@ Gon.global.estimate_taxes = Rails.application.config.estimate_taxes Gon.global.web_performance_timing_enabled = Rails.application.config.web_performance_timing_enabled Gon.global.jamtrack_landing_bubbles_enabled = Rails.application.config.jamtrack_landing_bubbles_enabled Gon.global.jamtrack_browser_bubbles_enabled = Rails.application.config.jamtrack_browser_bubbles_enabled +Gon.global.bugsnag_key = Rails.application.config.bugsnag_key Gon.global.env = Rails.env diff --git a/web/vendor/assets/javascripts/bugsnag.js b/web/vendor/assets/javascripts/bugsnag.js new file mode 100644 index 000000000..0bdefaadb --- /dev/null +++ b/web/vendor/assets/javascripts/bugsnag.js @@ -0,0 +1,10 @@ +// 2.4.8 http://d2wy8f7a9ursnm.cloudfront.net/bugsnag-2.4.8.min.js + + +// START COPY/PASTE FROM BUGSNAG CDN +!function(a,b){function c(a,b){try{if("function"!=typeof a)return a;if(!a.bugsnag){var c=e();a.bugsnag=function(d){if(b&&b.eventHandler&&(u=d),v=c,!y){var e=a.apply(this,arguments);return v=null,e}try{return a.apply(this,arguments)}catch(f){throw l("autoNotify",!0)&&(x.notifyException(f,null,null,"error"),s()),f}finally{v=null}},a.bugsnag.bugsnag=a.bugsnag}return a.bugsnag}catch(d){return a}}function d(){B=!1}function e(){var a=document.currentScript||v;if(!a&&B){var b=document.scripts||document.getElementsByTagName("script");a=b[b.length-1]}return a}function f(a){var b=e();b&&(a.script={src:b.src,content:l("inlineScript",!0)?b.innerHTML:""})}function g(b){var c=l("disableLog"),d=a.console;void 0===d||void 0===d.log||c||d.log("[Bugsnag] "+b)}function h(b,c,d){if(d>=5)return encodeURIComponent(c)+"=[RECURSIVE]";d=d+1||1;try{if(a.Node&&b instanceof a.Node)return encodeURIComponent(c)+"="+encodeURIComponent(r(b));var e=[];for(var f in b)if(b.hasOwnProperty(f)&&null!=f&&null!=b[f]){var g=c?c+"["+f+"]":f,i=b[f];e.push("object"==typeof i?h(i,g,d):encodeURIComponent(g)+"="+encodeURIComponent(i))}return e.join("&")}catch(j){return encodeURIComponent(c)+"="+encodeURIComponent(""+j)}}function i(a,b){if(null==b)return a;a=a||{};for(var c in b)if(b.hasOwnProperty(c))try{a[c]=b[c].constructor===Object?i(a[c],b[c]):b[c]}catch(d){a[c]=b[c]}return a}function j(a,b){a+="?"+h(b)+"&ct=img&cb="+(new Date).getTime();var c=new Image;c.src=a}function k(a){var b={},c=/^data\-([\w\-]+)$/;if(a)for(var d=a.attributes,e=0;e\n";var f=[];try{for(var h=arguments.callee.caller.caller;h&&f.length"}return a.nodeName}}function s(){z+=1,a.setTimeout(function(){z-=1})}function t(a,b,c){var d=a[b],e=c(d);a[b]=e}var u,v,w,x={},y=!0,z=0,A=10;x.noConflict=function(){return a.Bugsnag=b,x},x.refresh=function(){A=10},x.notifyException=function(a,b,c,d){b&&"string"!=typeof b&&(c=b,b=void 0),c||(c={}),f(c),n({name:b||a.name,message:a.message||a.description,stacktrace:p(a)||o(),file:a.fileName||a.sourceURL,lineNumber:a.lineNumber||a.line,columnNumber:a.columnNumber?a.columnNumber+1:void 0,severity:d||"warning"},c)},x.notify=function(b,c,d,e){n({name:b,message:c,stacktrace:o(),file:a.location.toString(),lineNumber:1,severity:e||"warning"},d)};var B="complete"!==document.readyState;document.addEventListener?(document.addEventListener("DOMContentLoaded",d,!0),a.addEventListener("load",d,!0)):a.attachEvent("onload",d);var C,D=/^[0-9a-f]{32}$/i,E=/function\s*([\w\-$]+)?\s*\(/i,F="https://notify.bugsnag.com/",G=F+"js",H="2.4.8",I=document.getElementsByTagName("script"),J=I[I.length-1];if(a.atob){if(a.ErrorEvent)try{0===new a.ErrorEvent("test").colno&&(y=!1)}catch(K){}}else y=!1;if(l("autoNotify",!0)){t(a,"onerror",function(b){return function(c,d,e,g,h){var i=l("autoNotify",!0),j={};!g&&a.event&&(g=a.event.errorCharacter),f(j),v=null,i&&!z&&n({name:h&&h.name||"window.onerror",message:c,file:d,lineNumber:e,columnNumber:g,stacktrace:h&&p(h)||o(),severity:"error"},j),b&&b(c,d,e,g,h)}});var L=function(a){return function(b,d){if("function"==typeof b){b=c(b);var e=Array.prototype.slice.call(arguments,2);return a(function(){b.apply(this,e)},d)}return a(b,d)}};t(a,"setTimeout",L),t(a,"setInterval",L),a.requestAnimationFrame&&t(a,"requestAnimationFrame",function(a){return function(b){return a(c(b))}}),a.setImmediate&&t(a,"setImmediate",function(a){return function(){var b=Array.prototype.slice.call(arguments);return b[0]=c(b[0]),a.apply(this,b)}}),"EventTarget Window Node ApplicationCache AudioTrackList ChannelMergerNode CryptoOperation EventSource FileReader HTMLUnknownElement IDBDatabase IDBRequest IDBTransaction KeyOperation MediaController MessagePort ModalWindow Notification SVGElementInstance Screen TextTrack TextTrackCue TextTrackList WebSocket WebSocketWorker Worker XMLHttpRequest XMLHttpRequestEventTarget XMLHttpRequestUpload".replace(/\w+/g,function(b){var d=a[b]&&a[b].prototype;d&&d.hasOwnProperty&&d.hasOwnProperty("addEventListener")&&(t(d,"addEventListener",function(a){return function(b,d,e,f){try{d&&d.handleEvent&&(d.handleEvent=c(d.handleEvent,{eventHandler:!0}))}catch(h){g(h)}return a.call(this,b,c(d,{eventHandler:!0}),e,f)}}),t(d,"removeEventListener",function(a){return function(b,d,e,f){return a.call(this,b,d,e,f),a.call(this,b,c(d),e,f)}}))})}a.Bugsnag=x,"function"==typeof define&&define.amd?define([],function(){return x}):"object"==typeof module&&"object"==typeof module.exports&&(module.exports=x)}(window,window.Bugsnag); +// END COPY/PASTE FROM BUGSNAG CDN + + +// manual code: make sure Bugsnag has it's API KEY +window.Bugsnag.apiKey = gon.global.bugsnag_key \ No newline at end of file From 7199a76e3de1da976e2ef449433a54dbc1a75a58 Mon Sep 17 00:00:00 2001 From: Seth Call Date: Fri, 29 May 2015 22:41:01 -0500 Subject: [PATCH 17/45] * cors gem added to gemfile for cloudfront and https --- web/Gemfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/web/Gemfile b/web/Gemfile index 3092b19d7..0d4a0f4af 100644 --- a/web/Gemfile +++ b/web/Gemfile @@ -18,6 +18,7 @@ else gem 'jam_websockets', "0.1.#{ENV["BUILD_NUMBER"]}" ENV['NOKOGIRI_USE_SYSTEM_LIBRARIES'] ||= "true" end + gem 'oj', '2.10.2' gem 'builder' gem 'rails', '~>3.2.11' @@ -142,6 +143,7 @@ group :production do gem 'unicorn' gem 'newrelic_rpm' gem 'god' + gem 'rack-cors', :require => 'rack/cors' end group :package do From ecd8b75f91e0c53aa9557d2ad82025858c0a94c9 Mon Sep 17 00:00:00 2001 From: Seth Call Date: Fri, 29 May 2015 23:21:29 -0500 Subject: [PATCH 18/45] * fix case in raleway assets path --- web/Gemfile | 1 - web/app/assets/stylesheets/web/Raleway.css | 12 ++++++------ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/web/Gemfile b/web/Gemfile index 0d4a0f4af..0dc9d2806 100644 --- a/web/Gemfile +++ b/web/Gemfile @@ -143,7 +143,6 @@ group :production do gem 'unicorn' gem 'newrelic_rpm' gem 'god' - gem 'rack-cors', :require => 'rack/cors' end group :package do diff --git a/web/app/assets/stylesheets/web/Raleway.css b/web/app/assets/stylesheets/web/Raleway.css index e7c9f1caf..14c53019b 100644 --- a/web/app/assets/stylesheets/web/Raleway.css +++ b/web/app/assets/stylesheets/web/Raleway.css @@ -2,35 +2,35 @@ font-family: 'Raleway'; font-style: normal; font-weight: 100; - src: local('Raleway Thin'), local('Raleway-Thin'), url(/assets/raleway/Raleway-Thin.ttf) format('truetype'), url(/assets/raleway/Raleway-Thin.woff2) format('woff2'), url(/assets/raleway/Raleway-Thin.woff) format('woff'); + src: local('Raleway Thin'), local('Raleway-Thin'), url(/assets/Raleway/Raleway-Thin.ttf) format('truetype'), url(/assets/Raleway/Raleway-Thin.woff2) format('woff2'), url(/assets/Raleway/Raleway-Thin.woff) format('woff'); } @font-face { font-family: 'Raleway'; font-style: normal; font-weight: 300; - src: local('Raleway Light'), local('Raleway-Light'), url(/assets/raleway/Raleway-Light.ttf) format('truetype'), url(/assets/raleway/Raleway-Light.woff2) format('woff2'), url(/assets/raleway/Raleway-Light.woff) format('woff'); + src: local('Raleway Light'), local('Raleway-Light'), url(/assets/Raleway/Raleway-Light.ttf) format('truetype'), url(/assets/Raleway/Raleway-Light.woff2) format('woff2'), url(/assets/Raleway/Raleway-Light.woff) format('woff'); } @font-face { font-family: 'Raleway'; font-style: normal; font-weight: 400; - src: url(/assets/raleway/Raleway.eot); - src: local('Raleway'), url(/assets/raleway/Raleway.eot?#iefix) format('embedded-opentype'), url(/assets/raleway/Raleway.svg#Raleway) format('svg'), url(/assets/raleway/Raleway.ttf) format('truetype'), url(/assets/raleway/Raleway.woff2) format('woff2'), url(/assets/raleway/Raleway.woff) format('woff'); + src: url(/assets/Raleway/Raleway.eot); + src: local('Raleway'), url(/assets/Raleway/Raleway.eot?#iefix) format('embedded-opentype'), url(/assets/Raleway/Raleway.svg#Raleway) format('svg'), url(/assets/Raleway/Raleway.ttf) format('truetype'), url(/assets/Raleway/Raleway.woff2) format('woff2'), url(/assets/Raleway/Raleway.woff) format('woff'); } @font-face { font-family: 'Raleway'; font-style: normal; font-weight: 700; - src: local('Raleway Bold'), local('Raleway-Bold'), url(/assets/raleway/Raleway-Bold.ttf) format('truetype'), url(/assets/raleway/Raleway-Bold.woff2) format('woff2'), url(/assets/raleway/Raleway-Bold.woff) format('woff'); + src: local('Raleway Bold'), local('Raleway-Bold'), url(/assets/Raleway/Raleway-Bold.ttf) format('truetype'), url(/assets/Raleway/Raleway-Bold.woff2) format('woff2'), url(/assets/Raleway/Raleway-Bold.woff) format('woff'); } @font-face { font-family: 'Raleway'; font-style: normal; font-weight: 900; - src: local('Raleway Heavy'), local('Raleway-Heavy'), url(/assets/raleway/Raleway-Heavy.ttf) format('truetype'), url(/assets/raleway/Raleway-Heavy.woff2) format('woff2'), url(/assets/raleway/Raleway-Heavy.woff) format('woff'); + src: local('Raleway Heavy'), local('Raleway-Heavy'), url(/assets/Raleway/Raleway-Heavy.ttf) format('truetype'), url(/assets/Raleway/Raleway-Heavy.woff2) format('woff2'), url(/assets/Raleway/Raleway-Heavy.woff) format('woff'); } From b436ed7da3697402df0a8660223ce65d4b373e0f Mon Sep 17 00:00:00 2001 From: Seth Call Date: Sat, 30 May 2015 08:01:17 -0500 Subject: [PATCH 19/45] build bump --- web/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/web/README.md b/web/README.md index 975118c93..393628cf1 100644 --- a/web/README.md +++ b/web/README.md @@ -3,3 +3,4 @@ Jasmine Javascript Unit Tests Open browser to localhost:3000/teaspoon + From cdaac868de12c5517dec252d333147719b6990e6 Mon Sep 17 00:00:00 2001 From: Seth Call Date: Sat, 30 May 2015 13:30:32 -0500 Subject: [PATCH 20/45] * JamPermissionError instead of PermissionError --- web/app/controllers/api_music_sessions_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/app/controllers/api_music_sessions_controller.rb b/web/app/controllers/api_music_sessions_controller.rb index 9f43e909e..32b7726fc 100644 --- a/web/app/controllers/api_music_sessions_controller.rb +++ b/web/app/controllers/api_music_sessions_controller.rb @@ -166,7 +166,7 @@ class ApiMusicSessionsController < ApiController def show unless @music_session.can_see? current_user # render :json => { :message => ValidationMessages::PERMISSION_VALIDATION_ERROR }, :status => 403 - raise JamRuby::PermissionError + raise JamRuby::JamPermissionError end end From 972b65c4efbb6eebecfc0d5a94c7cc6ba0be0375 Mon Sep 17 00:00:00 2001 From: Steven Miers Date: Thu, 4 Jun 2015 14:05:20 -0500 Subject: [PATCH 21/45] VRFS-3190 : Fix a few functional and style problems. Cleanup as necessary. --- .../javascripts/accounts_profile_samples.js | 50 +++++++++++-------- .../client/accountProfileSamples.css.scss | 10 ++++ .../_profile_online_sample_controls.html.slim | 16 ++++-- web/app/views/clients/index.html.erb | 2 +- 4 files changed, 50 insertions(+), 28 deletions(-) diff --git a/web/app/assets/javascripts/accounts_profile_samples.js b/web/app/assets/javascripts/accounts_profile_samples.js index 30cd85c20..4ba0afd28 100644 --- a/web/app/assets/javascripts/accounts_profile_samples.js +++ b/web/app/assets/javascripts/accounts_profile_samples.js @@ -32,9 +32,9 @@ var $twitterUsername = $screen.find('.twitter-username'); // performance samples - var $jamkazamSampleList = $screen.find('.samples.jamkazam').find('.sample-list'); - var $soundCloudSampleList = $screen.find('.samples.soundcloud').find('.sample-list'); - var $youTubeSampleList = $screen.find('.samples.youtube').find('.sample-list'); + var $jamkazamSampleList = $screen.find(".sample-list[source-type='jamkazam']") + var $soundCloudSampleList = $screen.find(".sample-list[source-type='soundcloud']") + var $youTubeSampleList = $screen.find(".sample-list[source-type='youtube']") // buttons var $btnAddJkRecording = $screen.find('.btn-add-jk-recording'); @@ -51,7 +51,7 @@ if (targetPlayer && targetPlayer.keys && targetPlayer.keys.length > 0) { renderPlayer(targetPlayer) } - }); + }) } function renderPlayer(targetPlayer) { @@ -120,7 +120,7 @@ } function loadSamples(samples, type, $sampleList, recordingSources) { - $sampleList.empty(); + $sampleList.empty(); if (type === 'jamkazam') { $.each(samples, function(index, val) { @@ -131,8 +131,7 @@ buildJamkazamEntry(val.claimed_recording.id, val.claimed_recording.name); }); - } - else { + } else { if (samples && samples.length > 0) { $.each(samples, function(index, val) { @@ -208,6 +207,9 @@ }); enableSubmits(); + + $(".sample-list .close-button", $screen).on("click", function(e) { + } } function enableSubmits() { @@ -257,9 +259,7 @@ 'service_type': type, 'claimed_recording_id': id, }); - } - - else { + } else { var url = $(this).attr('data-recording-url'); var title = $(this).attr('data-recording-title'); @@ -325,14 +325,19 @@ if(xhr.status == 422) { - } - else { + } else { app.ajaxError(xhr, textStatus, errorMessage) } } function removeRow(recordingId, type) { $('div[data-recording-id=' + recordingId + ']').remove(); + var sampleList = $('.sample-list[source-type="' + type + '"]') + var rowCnt = sampleList.find('.recording-row').length + + if (rowCnt==0) { + sampleList.find(".empty").removeClass("hidden") + } if (type === 'soundcloud') { window.soundCloudRecordingValidator.removeRecordingId(recordingId); @@ -361,10 +366,11 @@ //var $screen = $('#account-profile-samples'); var $btnAddSoundCloudRecording = $screen.find('.btn-add-soundcloud-recording'); var $btnAddYouTubeVideo = $screen.find('.btn-add-youtube-video'); - var $soundCloudSampleList = $screen.find('.samples.soundcloud'); - var $youTubeSampleList = $screen.find('.samples.youtube'); + // var $soundCloudSampleList = $screen.find('.samples.soundcloud'); + // var $youTubeSampleList = $screen.find('.samples.youtube'); + - setTimeout(function() { + setTimeout(function() { window.urlValidator = new JK.SiteValidator('url', userNameSuccessCallback, userNameFailCallback, parent); window.urlValidator.init(); @@ -390,7 +396,7 @@ window.twitterValidator.init(); window.soundCloudRecordingValidator = new JK.RecordingSourceValidator('rec_soundcloud', soundCloudSuccessCallback, siteFailCallback, parent); - logger.debug("window.soundCloudRecordingValidator", window.soundCloudRecordingValidator) + logger.debug("window.soundCloudRecordingValidator", window.soundCloudRecordingValidator, parent) window.youTubeRecordingValidator = new JK.RecordingSourceValidator('rec_youtube', youTubeSuccessCallback, siteFailCallback, parent); $document.triggerHandler('INIT_SITE_VALIDATORS'); @@ -408,7 +414,7 @@ $inputDiv.append("Invalid username").show(); } - function soundCloudSuccessCallback($inputDiv) { + function soundCloudSuccessCallback($inputDiv) { siteSuccessCallback($inputDiv, window.soundCloudRecordingValidator, $soundCloudSampleList, 'soundcloud'); } @@ -416,24 +422,24 @@ siteSuccessCallback($inputDiv, window.youTubeRecordingValidator, $youTubeSampleList, 'youtube'); } - function siteSuccessCallback($inputDiv, recordingSiteValidator, $sampleList, type) { + function siteSuccessCallback($inputDiv, recordingSiteValidator, sampleList, type) { + sampleList.find(".empty").addClass("hidden") $inputDiv.removeClass('error'); $inputDiv.find('.error-text').remove(); var recordingSources = recordingSiteValidator.recordingSources(); if (recordingSources && recordingSources.length > 0) { - var $sampleList = $sampleList.find('.sample-list'); var addedRecording = recordingSources[recordingSources.length-1]; - // TODO: this code is repeated in JS file + // TODO: this code is repeated in elsewhere in this JS file: var recordingIdAttr = ' data-recording-id="' + addedRecording.recording_id + '" '; var recordingUrlAttr = ' data-recording-url="' + addedRecording.url + '" '; var recordingTitleAttr = ' data-recording-title="' + addedRecording.recording_title + '"'; var title = formatTitle(addedRecording.recording_title); - $sampleList.append('

' + title + '
'); + sampleList.append('
' + title + '
'); var onclick = "onclick=removeRow(\'" + addedRecording.recording_id + "\',\'" + type + "\');"; - $sampleList.append('
X
'); + sampleList.append('
X
'); } $inputDiv.find('input').val(''); diff --git a/web/app/assets/stylesheets/client/accountProfileSamples.css.scss b/web/app/assets/stylesheets/client/accountProfileSamples.css.scss index a6f641d57..629ebc3f1 100644 --- a/web/app/assets/stylesheets/client/accountProfileSamples.css.scss +++ b/web/app/assets/stylesheets/client/accountProfileSamples.css.scss @@ -14,6 +14,16 @@ } } + .sample-list { + border: 1px inset #cfcfcf; + padding: 0.5em; + .empty { + font-style: italic; + } + min-height: 150px; + overflow: scroll; + } + table.control-table { width: 100%; } diff --git a/web/app/views/clients/_profile_online_sample_controls.html.slim b/web/app/views/clients/_profile_online_sample_controls.html.slim index 55f59fb39..67e57337d 100644 --- a/web/app/views/clients/_profile_online_sample_controls.html.slim +++ b/web/app/views/clients/_profile_online_sample_controls.html.slim @@ -65,7 +65,7 @@ td colspan="33.33%": label JamKazam Recordings: td colspan="33.33%": label SoundCloud Recordings (URL): td colspan="33.33%": label YouTube Videos (URL): - tr + tr.add-samples-controls-row td colspan="33.33%" a.btn-add-jk-recording.button-grey BROWSE td colspan="33.33%" @@ -82,7 +82,13 @@ td a.btn-add-youtube-video.button-grey.add-recording-source ADD span.spinner-small - tr - td colspan="33.33%": .sample-list - td colspan="33.33%": .sample-list - td colspan="33.33%": .sample-list \ No newline at end of file + tr.add-samples-list-row + td colspan="33.33%" + .sample-list source-type='jamkazam' + .empty No recordings + td colspan="33.33%" + .sample-list source-type='soundcloud' + .empty No recordings + td colspan="33.33%" + .sample-list source-type='youtube' + .empty No recordings \ No newline at end of file diff --git a/web/app/views/clients/index.html.erb b/web/app/views/clients/index.html.erb index c41ae70bc..09aab62fa 100644 --- a/web/app/views/clients/index.html.erb +++ b/web/app/views/clients/index.html.erb @@ -236,7 +236,7 @@ var accountProfileInterests = new JK.AccountProfileInterests(JK.app); accountProfileInterests.initialize(); - var accountProfileSamples = new JK.AccountProfileSamples(JK.app, null) + var accountProfileSamples = new JK.AccountProfileSamples(JK.app, $(".account-profile-samples")) accountProfileSamples.initialize(); var accountAudioProfile = new JK.AccountAudioProfile(JK.app); From cb058e851b1a1f9900c12a0428e9ada143b066f3 Mon Sep 17 00:00:00 2001 From: Steven Miers Date: Thu, 4 Jun 2015 18:55:15 -0500 Subject: [PATCH 22/45] VRFS-3190 : Several bug fixes for band profile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Storing validator in window was screwing things up now that we have multiple of these. This is now stored at the class instance level. * Deleting a performance sample didn’t delete it from the validator, as the comparison was flaky. * Styling fixes --- .../javascripts/accounts_profile_samples.js | 151 +++++++++--------- .../javascripts/site_validator.js.coffee | 39 ++--- .../client/accountProfileSamples.css.scss | 13 +- 3 files changed, 105 insertions(+), 98 deletions(-) diff --git a/web/app/assets/javascripts/accounts_profile_samples.js b/web/app/assets/javascripts/accounts_profile_samples.js index 4ba0afd28..b2b34132a 100644 --- a/web/app/assets/javascripts/accounts_profile_samples.js +++ b/web/app/assets/javascripts/accounts_profile_samples.js @@ -5,14 +5,14 @@ context.JK = context.JK || {}; // TODO: Add a target type, which can be band or user -- call the - // appropriate API methods. + // appropriate API methods. context.JK.AccountProfileSamples = function(app, parent, loadFn, updateFn) { var $document = $(document) // used to initialize RecordingSourceValidator in site_validator.js.coffee - window.jamkazamRecordingSources = []; - window.soundCloudRecordingSources = []; - window.youTubeRecordingSources = []; + var jamkazamRecordingSources = []; + var soundCloudRecordingSources = []; + var youTubeRecordingSources = []; var logger = context.JK.logger; var EVENTS = context.JK.EVENTS; @@ -20,9 +20,9 @@ var ui = new context.JK.UIHelper(JK.app); var target = {}; var profileUtils = context.JK.ProfileUtils; - var $screen = $('.profile-online-sample-controls', parent); + var $screen = $('.profile-online-sample-controls', parent); // online presences - var $website = $screen.find('.website'); + var $website = $screen.find('.website'); var $soundCloudUsername = $screen.find('.soundcloud-username'); var $reverbNationUsername = $screen.find('.reverbnation-username'); var $bandCampUsername = $screen.find('.bandcamp-username'); @@ -42,10 +42,22 @@ var $btnBack = $screen.find('.account-edit-profile-back'); var $btnSubmit = $screen.find('.account-edit-profile-submit'); + + var urlValidator=null; + var soundCloudValidator=null; + var reverbNationValidator=null; + var bandCampValidator=null; + var fandalismValidator=null; + var youTubeValidator=null; + var facebookValidator=null; + var twitterValidator=null; + var soundCloudRecordingValidator=null; + var youTubeRecordingValidator=null; + function beforeShow(data) { } - function afterShow(data) { + function afterShow(data) { $.when(loadFn()) .done(function(targetPlayer) { if (targetPlayer && targetPlayer.keys && targetPlayer.keys.length > 0) { @@ -56,7 +68,7 @@ function renderPlayer(targetPlayer) { renderPresence(targetPlayer); - renderSamples(targetPlayer); + renderSamples(targetPlayer); } function renderPresence(targetPlayer) { @@ -108,20 +120,20 @@ function renderSamples(targetPlayer) { // JamKazam recordings var samples = profileUtils.jamkazamSamples(targetPlayer.performance_samples); - loadSamples(samples, 'jamkazam', $jamkazamSampleList, window.jamkazamRecordingSources); + loadSamples(samples, 'jamkazam', $jamkazamSampleList, jamkazamRecordingSources); // SoundCloud recordings samples = profileUtils.soundCloudSamples(targetPlayer.performance_samples); - loadSamples(samples, 'soundcloud', $soundCloudSampleList, window.soundCloudRecordingSources); + loadSamples(samples, 'soundcloud', $soundCloudSampleList, soundCloudRecordingSources); // YouTube videos samples = profileUtils.youTubeSamples(targetPlayer.performance_samples); - loadSamples(samples, 'youtube', $youTubeSampleList, window.youTubeRecordingSources); + loadSamples(samples, 'youtube', $youTubeSampleList, youTubeRecordingSources); } function loadSamples(samples, type, $sampleList, recordingSources) { - $sampleList.empty(); - + $sampleList.find(":not(.empty)").remove(); + if (type === 'jamkazam') { $.each(samples, function(index, val) { recordingSources.push({ @@ -147,9 +159,7 @@ var recordingTitleAttr = ' data-recording-title="' + val.description + '"'; var title = formatTitle(val.description); $sampleList.append('
' + title + '
'); - - var onclick = "onclick=removeRow(\'" + val.service_id + "\',\'" + type + "\');"; - $sampleList.append('
X
'); + $sampleList.append('
X
'); }); } } @@ -160,9 +170,7 @@ var recordingIdAttr = ' data-recording-id="' + recordingId + '" '; $jamkazamSampleList.append('
' + title + '
'); - - var onclick = "onclick=removeRow(\'" + recordingId + "\',\'jamkazam\');"; - $jamkazamSampleList.append('
X
'); + $jamkazamSampleList.append('
X
'); } function events() { @@ -174,14 +182,14 @@ // retrieve recordings and pass to modal dialog api.getClaimedRecordings() .done(function(response) { - ui.launchRecordingSelectorDialog(response, window.jamkazamRecordingSources, function(selectedRecordings) { + ui.launchRecordingSelectorDialog(response, jamkazamRecordingSources, function(selectedRecordings) { $jamkazamSampleList.empty(); - window.jamkazamRecordingSources = []; + jamkazamRecordingSources = []; // update the list with the selected recordings $.each(selectedRecordings, function(index, val) { - window.jamkazamRecordingSources.push({ + jamkazamRecordingSources.push({ 'claimed_recording_id': val.id, 'description': val.name }); @@ -190,7 +198,7 @@ }); }); }); - + return false; }); @@ -208,8 +216,9 @@ enableSubmits(); - $(".sample-list .close-button", $screen).on("click", function(e) { - } + $screen.find(".sample-list").off("click").on("click", ".close-button", function(e) { + removeRow($(this).data("recording-id"), $(this).data("recording-type")) + }) } function enableSubmits() { @@ -291,7 +300,7 @@ function buildPlayer() { // extract online presences var op = []; - var presenceTypes = profileUtils.ONLINE_PRESENCE_TYPES; + var presenceTypes = profileUtils.ONLINE_PRESENCE_TYPES; addOnlinePresence(op, $soundCloudUsername.val(), presenceTypes.SOUNDCLOUD.description); addOnlinePresence(op, $reverbNationUsername.val(), presenceTypes.REVERBNATION.description); addOnlinePresence(op, $bandCampUsername.val(), presenceTypes.BANDCAMP.description); @@ -306,12 +315,12 @@ addPerformanceSamples(ps, $jamkazamSampleList, performanceSampleTypes.JAMKAZAM.description); addPerformanceSamples(ps, $soundCloudSampleList, performanceSampleTypes.SOUNDCLOUD.description); addPerformanceSamples(ps, $youTubeSampleList, performanceSampleTypes.YOUTUBE.description); - + return { website: $website.val(), online_presences: op, performance_samples: ps - } + } } function postUpdateProfileSuccess(response) { @@ -334,16 +343,14 @@ $('div[data-recording-id=' + recordingId + ']').remove(); var sampleList = $('.sample-list[source-type="' + type + '"]') var rowCnt = sampleList.find('.recording-row').length - - if (rowCnt==0) { + if (0==parseInt(rowCnt)) { sampleList.find(".empty").removeClass("hidden") } if (type === 'soundcloud') { - window.soundCloudRecordingValidator.removeRecordingId(recordingId); - } - else if (type === 'youtube') { - window.youTubeRecordingValidator.removeRecordingId(recordingId); + soundCloudRecordingValidator.removeRecordingId(recordingId); + } else if (type === 'youtube') { + youTubeRecordingValidator.removeRecordingId(recordingId); } } @@ -352,13 +359,13 @@ } // This function is a bit of a mess. It was pulled - // from the html.erb file verbatim, and could use a + // from the html.erb file verbatim, and could use a // refactor: - function initializeValidators() { + function initializeValidators() { var initialized = false; - //$document.on('JAMKAZAM_READY', function(e, data) { - window.JK.JamServer.get$Server().on(window.JK.EVENTS.CONNECTION_UP, function() { - if(initialized) { + //$document.on('JAMKAZAM_READY', function(e, data) { + JK.JamServer.get$Server().on(JK.EVENTS.CONNECTION_UP, function() { + if(initialized) { return; } initialized = true; @@ -368,36 +375,35 @@ var $btnAddYouTubeVideo = $screen.find('.btn-add-youtube-video'); // var $soundCloudSampleList = $screen.find('.samples.soundcloud'); // var $youTubeSampleList = $screen.find('.samples.youtube'); - - setTimeout(function() { - window.urlValidator = new JK.SiteValidator('url', userNameSuccessCallback, userNameFailCallback, parent); - window.urlValidator.init(); - window.soundCloudValidator = new JK.SiteValidator('soundcloud', userNameSuccessCallback, userNameFailCallback, parent); - window.soundCloudValidator.init(); + setTimeout(function() { + urlValidator = new JK.SiteValidator('url', userNameSuccessCallback, userNameFailCallback, parent); + urlValidator.init(); - window.reverbNationValidator = new JK.SiteValidator('reverbnation', userNameSuccessCallback, userNameFailCallback, parent); - window.reverbNationValidator.init(); + soundCloudValidator = new JK.SiteValidator('soundcloud', userNameSuccessCallback, userNameFailCallback, parent); + soundCloudValidator.init(); - window.bandCampValidator = new JK.SiteValidator('bandcamp', userNameSuccessCallback, userNameFailCallback, parent); - window.bandCampValidator.init(); + reverbNationValidator = new JK.SiteValidator('reverbnation', userNameSuccessCallback, userNameFailCallback, parent); + reverbNationValidator.init(); - window.fandalismValidator = new JK.SiteValidator('fandalism', userNameSuccessCallback, userNameFailCallback, parent); - window.fandalismValidator.init(); + bandCampValidator = new JK.SiteValidator('bandcamp', userNameSuccessCallback, userNameFailCallback, parent); + bandCampValidator.init(); - window.youTubeValidator = new JK.SiteValidator('youtube', userNameSuccessCallback, userNameFailCallback, parent); - window.youTubeValidator.init(); + fandalismValidator = new JK.SiteValidator('fandalism', userNameSuccessCallback, userNameFailCallback, parent); + fandalismValidator.init(); - window.facebookValidator = new JK.SiteValidator('facebook', userNameSuccessCallback, userNameFailCallback, parent); - window.facebookValidator.init(); + youTubeValidator = new JK.SiteValidator('youtube', userNameSuccessCallback, userNameFailCallback, parent); + youTubeValidator.init(); - window.twitterValidator = new JK.SiteValidator('twitter', userNameSuccessCallback, userNameFailCallback, parent); - window.twitterValidator.init(); + facebookValidator = new JK.SiteValidator('facebook', userNameSuccessCallback, userNameFailCallback, parent); + facebookValidator.init(); - window.soundCloudRecordingValidator = new JK.RecordingSourceValidator('rec_soundcloud', soundCloudSuccessCallback, siteFailCallback, parent); - logger.debug("window.soundCloudRecordingValidator", window.soundCloudRecordingValidator, parent) - window.youTubeRecordingValidator = new JK.RecordingSourceValidator('rec_youtube', youTubeSuccessCallback, siteFailCallback, parent); + twitterValidator = new JK.SiteValidator('twitter', userNameSuccessCallback, userNameFailCallback, parent); + twitterValidator.init(); + + soundCloudRecordingValidator = new JK.RecordingSourceValidator('rec_soundcloud', soundCloudSuccessCallback, siteFailCallback, parent); + youTubeRecordingValidator = new JK.RecordingSourceValidator('rec_youtube', youTubeSuccessCallback, siteFailCallback, parent); $document.triggerHandler('INIT_SITE_VALIDATORS'); }, 1); @@ -408,21 +414,21 @@ $inputDiv.find('.error-text').remove(); } - function userNameFailCallback($inputDiv) { + function userNameFailCallback($inputDiv) { $inputDiv.addClass('error'); $inputDiv.find('.error-text').remove(); $inputDiv.append("Invalid username").show(); } - function soundCloudSuccessCallback($inputDiv) { - siteSuccessCallback($inputDiv, window.soundCloudRecordingValidator, $soundCloudSampleList, 'soundcloud'); + function soundCloudSuccessCallback($inputDiv) { + siteSuccessCallback($inputDiv, soundCloudRecordingValidator, $soundCloudSampleList, 'soundcloud'); } function youTubeSuccessCallback($inputDiv) { - siteSuccessCallback($inputDiv, window.youTubeRecordingValidator, $youTubeSampleList, 'youtube'); + siteSuccessCallback($inputDiv, youTubeRecordingValidator, $youTubeSampleList, 'youtube'); } - function siteSuccessCallback($inputDiv, recordingSiteValidator, sampleList, type) { + function siteSuccessCallback($inputDiv, recordingSiteValidator, sampleList, type) { sampleList.find(".empty").addClass("hidden") $inputDiv.removeClass('error'); $inputDiv.find('.error-text').remove(); @@ -437,9 +443,7 @@ var recordingTitleAttr = ' data-recording-title="' + addedRecording.recording_title + '"'; var title = formatTitle(addedRecording.recording_title); sampleList.append('
' + title + '
'); - - var onclick = "onclick=removeRow(\'" + addedRecording.recording_id + "\',\'" + type + "\');"; - sampleList.append('
X
'); + sampleList.append('
X
'); } $inputDiv.find('input').val(''); @@ -454,16 +458,15 @@ //}); $document.on('INIT_SITE_VALIDATORS', function(e, data) { - logger.debug("ZZZwindow.soundCloudRecordingValidator", window.soundCloudRecordingValidator) - window.soundCloudRecordingValidator.init(window.soundCloudRecordingSources); - window.youTubeRecordingValidator.init(window.youTubeRecordingSources); + soundCloudRecordingValidator.init(soundCloudRecordingSources); + youTubeRecordingValidator.init(youTubeRecordingSources); }); - - } // end initializeValidators. + + } // end initializeValidators. function resetForm() { - $("input", $screen).val("") + $("input", $screen).val("") } function initialize() { diff --git a/web/app/assets/javascripts/site_validator.js.coffee b/web/app/assets/javascripts/site_validator.js.coffee index 41636af26..111457aff 100644 --- a/web/app/assets/javascripts/site_validator.js.coffee +++ b/web/app/assets/javascripts/site_validator.js.coffee @@ -9,8 +9,8 @@ context.JK.SiteValidator = class SiteValidator @rest = context.JK.Rest() @site_type = site_type @input_div = $(".site_validator."+site_type+"_validator", parent) - @data_input = @input_div.find('input') - + @data_input = @input_div.find('input') + @logger = context.JK.logger @spinner = @input_div.find('span.spinner-small') @checkmark = @input_div.find('.validate-checkmark') @@ -34,7 +34,7 @@ context.JK.SiteValidator = class SiteValidator @site_status = null dataToValidate: () => - url = @data_input.val() + url = @data_input.val() if url && 0 < url.length url.substring(0,2000) else @@ -50,7 +50,7 @@ context.JK.SiteValidator = class SiteValidator @checkmark.hide() yn - didBlur: () => + didBlur: () => if this.showFormatStatus() this.validateSite() @@ -100,14 +100,14 @@ context.JK.SiteValidator = class SiteValidator @checkmark.show() else @checkmark.hide() - - siteIsValid: () => + + siteIsValid: () => this.setSiteStatus(true) - - siteIsInvalid: () => + + siteIsInvalid: () => this.setSiteStatus(false) - - renderErrors: (errors) => + + renderErrors: (errors) => errdiv = @input_div.find('.error') if errmsg = context.JK.format_errors("site", errors) errdiv.show() @@ -120,7 +120,7 @@ context.JK.SiteValidator = class SiteValidator dfr = $.Deferred() if null == @site_status @deferred_status_check = dfr - this.validateSite() + this.validateSite() else if true == @site_status dfr.resolve() @@ -128,9 +128,9 @@ context.JK.SiteValidator = class SiteValidator dfr.reject() return dfr.promise() - -context.JK.RecordingSourceValidator = class RecordingSourceValidator extends SiteValidator - constructor: (site_type, success_callback, fail_callback, parent) -> + +context.JK.RecordingSourceValidator = class RecordingSourceValidator extends SiteValidator + constructor: (site_type, success_callback, fail_callback, parent) -> super(site_type, success_callback, fail_callback, parent) @recording_sources = [] @is_rec_src = true @@ -142,7 +142,7 @@ context.JK.RecordingSourceValidator = class RecordingSourceValidator extends Sit super() if sources @recording_sources = sources - @add_btn.on 'click', => + @add_btn.off('click').on 'click', => this.attemptAdd() processSiteCheckSucceed: (response) => @@ -163,7 +163,7 @@ context.JK.RecordingSourceValidator = class RecordingSourceValidator extends Sit if @site_fail_callback @site_fail_callback(@input_div) - didBlur: () => + didBlur: () => # do nothing, validate on add only validateSite: () => @@ -177,13 +177,14 @@ context.JK.RecordingSourceValidator = class RecordingSourceValidator extends Sit removeRecordingId: (recording_id) => start_len = @recording_sources.length - @recording_sources = $.grep @recording_sources, (src_data) -> - src_data['recording_id'] != recording_id + @recording_sources = @recording_sources.filter (src) -> + src["recording_id"] isnt recording_id.toString() start_len != @recording_sources.length containsRecordingUrl: (url) => vals = $.grep @recording_sources, (src_data) -> - src_data['url'] == url + src_data['url'] is url + 0 < vals.length recordingSources: () => diff --git a/web/app/assets/stylesheets/client/accountProfileSamples.css.scss b/web/app/assets/stylesheets/client/accountProfileSamples.css.scss index 629ebc3f1..76c76ebc8 100644 --- a/web/app/assets/stylesheets/client/accountProfileSamples.css.scss +++ b/web/app/assets/stylesheets/client/accountProfileSamples.css.scss @@ -1,11 +1,11 @@ @import "common.css.scss"; @import "site_validator.css.scss"; -.profile-online-sample-controls { +.profile-online-sample-controls { table.profile-table { width: 100%; tr:nth-child(even) td { - padding: 0.25em 0.25em 1em 0.25em; + padding: 0.25em 0.25em 1em 0.25em; vertical-align: top; } tr:nth-child(odd) td { @@ -22,12 +22,15 @@ } min-height: 150px; overflow: scroll; + .close-button { + cursor:pointer; + } } table.control-table { width: 100%; } - + .sample-row { position: relative; clear: both; @@ -39,12 +42,12 @@ } .presence { - margin: 3px 30px 15px 0px; + margin: 3px 30px 15px 0px; } .site_validator { a, .spinner-small { - margin: 1px 1px 2px 2px; + margin: 1px 1px 2px 2px; vertical-align: top; } } From 61268bdc309328e7d959042133e6c31ba41c3bd6 Mon Sep 17 00:00:00 2001 From: Steven Miers Date: Fri, 5 Jun 2015 09:24:49 -0500 Subject: [PATCH 23/45] VRFS-3190 : Fix race condition. Init should be called in the same asynchronous block as construction. --- .../javascripts/accounts_profile_samples.js | 48 +++++++++---------- 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/web/app/assets/javascripts/accounts_profile_samples.js b/web/app/assets/javascripts/accounts_profile_samples.js index b2b34132a..67fc330be 100644 --- a/web/app/assets/javascripts/accounts_profile_samples.js +++ b/web/app/assets/javascripts/accounts_profile_samples.js @@ -378,36 +378,36 @@ setTimeout(function() { - urlValidator = new JK.SiteValidator('url', userNameSuccessCallback, userNameFailCallback, parent); - urlValidator.init(); + urlValidator = new JK.SiteValidator('url', userNameSuccessCallback, userNameFailCallback, parent) + urlValidator.init() - soundCloudValidator = new JK.SiteValidator('soundcloud', userNameSuccessCallback, userNameFailCallback, parent); - soundCloudValidator.init(); + soundCloudValidator = new JK.SiteValidator('soundcloud', userNameSuccessCallback, userNameFailCallback, parent) + soundCloudValidator.init() - reverbNationValidator = new JK.SiteValidator('reverbnation', userNameSuccessCallback, userNameFailCallback, parent); - reverbNationValidator.init(); + reverbNationValidator = new JK.SiteValidator('reverbnation', userNameSuccessCallback, userNameFailCallback, parent) + reverbNationValidator.init() - bandCampValidator = new JK.SiteValidator('bandcamp', userNameSuccessCallback, userNameFailCallback, parent); - bandCampValidator.init(); + bandCampValidator = new JK.SiteValidator('bandcamp', userNameSuccessCallback, userNameFailCallback, parent) + bandCampValidator.init() - fandalismValidator = new JK.SiteValidator('fandalism', userNameSuccessCallback, userNameFailCallback, parent); - fandalismValidator.init(); + fandalismValidator = new JK.SiteValidator('fandalism', userNameSuccessCallback, userNameFailCallback, parent) + fandalismValidator.init() - youTubeValidator = new JK.SiteValidator('youtube', userNameSuccessCallback, userNameFailCallback, parent); - youTubeValidator.init(); + youTubeValidator = new JK.SiteValidator('youtube', userNameSuccessCallback, userNameFailCallback, parent) + youTubeValidator.init() - facebookValidator = new JK.SiteValidator('facebook', userNameSuccessCallback, userNameFailCallback, parent); - facebookValidator.init(); + facebookValidator = new JK.SiteValidator('facebook', userNameSuccessCallback, userNameFailCallback, parent) + facebookValidator.init() - twitterValidator = new JK.SiteValidator('twitter', userNameSuccessCallback, userNameFailCallback, parent); - twitterValidator.init(); + twitterValidator = new JK.SiteValidator('twitter', userNameSuccessCallback, userNameFailCallback, parent) + twitterValidator.init() - soundCloudRecordingValidator = new JK.RecordingSourceValidator('rec_soundcloud', soundCloudSuccessCallback, siteFailCallback, parent); - youTubeRecordingValidator = new JK.RecordingSourceValidator('rec_youtube', youTubeSuccessCallback, siteFailCallback, parent); - - $document.triggerHandler('INIT_SITE_VALIDATORS'); - }, 1); + soundCloudRecordingValidator = new JK.RecordingSourceValidator('rec_soundcloud', soundCloudSuccessCallback, siteFailCallback, parent) + youTubeRecordingValidator = new JK.RecordingSourceValidator('rec_youtube', youTubeSuccessCallback, siteFailCallback, parent) + soundCloudRecordingValidator.init(soundCloudRecordingSources) + youTubeRecordingValidator.init(youTubeRecordingSources) + }, 1) function userNameSuccessCallback($inputDiv) { $inputDiv.removeClass('error'); @@ -457,11 +457,7 @@ }); //}); - $document.on('INIT_SITE_VALIDATORS', function(e, data) { - soundCloudRecordingValidator.init(soundCloudRecordingSources); - youTubeRecordingValidator.init(youTubeRecordingSources); - }); - + } // end initializeValidators. From 01c3b8af5fa76237746f095098007feb755dcd53 Mon Sep 17 00:00:00 2001 From: Steven Miers Date: Fri, 5 Jun 2015 12:55:55 -0500 Subject: [PATCH 24/45] VRFS-3190 : Use scoped classes instead of ids for navigation buttons. Initialize musician profile samples properly. --- .../assets/javascripts/accounts_profile.js | 4 +-- .../accounts_profile_experience.js | 6 ++-- .../javascripts/accounts_profile_interests.js | 6 ++-- .../javascripts/accounts_profile_samples.js | 36 +++++++++---------- web/app/views/clients/_account.html.erb | 4 +-- .../clients/_account_profile_samples.html.erb | 6 ++-- web/app/views/clients/index.html.erb | 4 +-- web/spec/features/account_spec.rb | 6 ++-- 8 files changed, 36 insertions(+), 36 deletions(-) diff --git a/web/app/assets/javascripts/accounts_profile.js b/web/app/assets/javascripts/accounts_profile.js index 584fb6ff8..9938d4cf0 100644 --- a/web/app/assets/javascripts/accounts_profile.js +++ b/web/app/assets/javascripts/accounts_profile.js @@ -28,8 +28,8 @@ var $biography = $screen.find('#biography'); var $subscribe = $screen.find('#subscribe'); - var $btnCancel = $screen.find('#account-edit-profile-cancel'); - var $btnSubmit = $screen.find('#account-edit-profile-submit'); + var $btnCancel = $screen.find('.account-edit-profile-cancel'); + var $btnSubmit = $screen.find('.account-edit-profile-submit'); function beforeShow(data) { userId = data.id; diff --git a/web/app/assets/javascripts/accounts_profile_experience.js b/web/app/assets/javascripts/accounts_profile_experience.js index 6bb22fbab..de57e8695 100644 --- a/web/app/assets/javascripts/accounts_profile_experience.js +++ b/web/app/assets/javascripts/accounts_profile_experience.js @@ -10,9 +10,9 @@ var api = context.JK.Rest(); var $screen = $('#account-profile-experience'); var profileUtils = context.JK.ProfileUtils; - var $btnCancel = $screen.find('#account-edit-profile-cancel'); - var $btnBack = $screen.find('#account-edit-profile-back'); - var $btnSubmit = $screen.find('#account-edit-profile-submit'); + var $btnCancel = $screen.find('.account-edit-profile-cancel'); + var $btnBack = $screen.find('.account-edit-profile-back'); + var $btnSubmit = $screen.find('.account-edit-profile-submit'); var $instrumentSelector = $screen.find('.instrument_selector'); var $userGenres = $screen.find('#user-genres'); diff --git a/web/app/assets/javascripts/accounts_profile_interests.js b/web/app/assets/javascripts/accounts_profile_interests.js index 6257e69ed..6a4a65e2c 100644 --- a/web/app/assets/javascripts/accounts_profile_interests.js +++ b/web/app/assets/javascripts/accounts_profile_interests.js @@ -62,9 +62,9 @@ var $cowritingGenreList = $cowritingGenres.find(GENRE_LIST_SELECTOR) var $cowritingPurpose = $screen.find('#cowriting-purpose') - var $btnCancel = $screen.find('#account-edit-profile-cancel') - var $btnBack = $screen.find('#account-edit-profile-back') - var $btnSubmit = $screen.find('#account-edit-profile-submit') + var $btnCancel = $screen.find('.account-edit-profile-cancel') + var $btnBack = $screen.find('.account-edit-profile-back') + var $btnSubmit = $screen.find('.account-edit-profile-submit') function beforeShow(data) { } diff --git a/web/app/assets/javascripts/accounts_profile_samples.js b/web/app/assets/javascripts/accounts_profile_samples.js index 67fc330be..6cce9de0e 100644 --- a/web/app/assets/javascripts/accounts_profile_samples.js +++ b/web/app/assets/javascripts/accounts_profile_samples.js @@ -37,22 +37,22 @@ var $youTubeSampleList = $screen.find(".sample-list[source-type='youtube']") // buttons - var $btnAddJkRecording = $screen.find('.btn-add-jk-recording'); - var $btnCancel = $screen.find('.account-edit-profile-cancel'); - var $btnBack = $screen.find('.account-edit-profile-back'); - var $btnSubmit = $screen.find('.account-edit-profile-submit'); + var $btnAddJkRecording = $screen.find('.btn-add-jk-recording') + var $btnCancel = parent.find('.account-edit-profile-cancel') + var $btnBack = parent.find('.account-edit-profile-back') + var $btnSubmit = parent.find('.account-edit-profile-submit') - var urlValidator=null; - var soundCloudValidator=null; - var reverbNationValidator=null; - var bandCampValidator=null; - var fandalismValidator=null; - var youTubeValidator=null; - var facebookValidator=null; - var twitterValidator=null; - var soundCloudRecordingValidator=null; - var youTubeRecordingValidator=null; + var urlValidator=null + var soundCloudValidator=null + var reverbNationValidator=null + var bandCampValidator=null + var fandalismValidator=null + var youTubeValidator=null + var facebookValidator=null + var twitterValidator=null + var soundCloudRecordingValidator=null + var youTubeRecordingValidator=null function beforeShow(data) { } @@ -221,12 +221,12 @@ }) } - function enableSubmits() { - $btnSubmit.on("click", function(evt) { - evt.stopPropagation(); + function enableSubmits() { + $btnSubmit.off("click").on("click", function(e) { + e.stopPropagation(); handleUpdateProfile(); return false; - }); + }) $btnSubmit.removeClass("disabled") } diff --git a/web/app/views/clients/_account.html.erb b/web/app/views/clients/_account.html.erb index 29d806a94..02afa69d4 100644 --- a/web/app/views/clients/_account.html.erb +++ b/web/app/views/clients/_account.html.erb @@ -112,12 +112,12 @@