From d4aa3bef2b3bfcb4f38b335e5b58f59255a6f43e Mon Sep 17 00:00:00 2001
From: Seth Call We’re delighted you have joined our community of 30,000+ musicians. We’d like to send you an orientation email with information and resource links that will help you get the most out of JamKazam. Please click here to confirm this email has reached you successfully and we will then send the orientation email. We’re delighted you have joined our community of <%= APP_CONFIG.musician_count %> musicians. We’d like to send you an orientation email with information and resource links that will help you get the most out of JamKazam. Please click here to confirm this email has reached you successfully and we will then send the orientation email. If you have received this email but aren’t familiar with JamKazam or JamTracks, then someone has registered at our website using your email address, and you can just ignore and delete this email.
@@ -20,58 +20,31 @@
1. Find a Teacher & Book Lessons
- If you already know the teacher from whom you want to learn, then you can simply
- use this link to search for
- them, and
- click the Book Lesson button to get started. But if you're like most of us, you don't know. In this case, we strongly
- advise signing up for our unique TestDrive service.
-
-
+ If you haven't done so already, use this link to search our teachers, and click to book a TestDrive with a teacher who looks good for you. When you do this, you'll be given the option to take full 30-minute TestDrive lessons:
- TestDrive lets you take 4 full lessons (30 minutes each) from 4 different teachers for just $49.99 to find the best
- teacher for you. Finding the right teacher is the single most important determinant of success in your lessons. Would
- you marry the first person you ever dated? No? Same here. Pick 4 teachers who look great, and then see who you click
- with. It's a phenomenal value, and then you can stick with the best teacher for you.
- Click this link
- to sign up now
- for TestDrive. Then you can book 4 TestDrive lessons to get rolling.
+
+ Pick whichever option you prefer. TestDrive lets you safely and easily try multiple teachers to find the one who is best specifically for you, which is a great way to maximize the benefit from your lessons. And TestDrive lessons are heavily discounted to give you a risk-free way to get started. We'd suggest scheduling your first lesson for about a week in the future to give you plenty of time to get up and running with our free app. +
2. Set Up Your Gear
- Use this link to a set of
- help
- articles on how to set up your gear to be ready to teach online. After you have signed
- up, someone from JamKazam will contact you to schedule a test online session, in which we will make sure your audio
- and video gear are working properly in an online session, and to make sure you feel comfortable with the key features
- you will be using in sessions with teachers.
+ Please review our help articles on gear recommendations
+ to make sure you have everything you need to get set up properly for best results in your online lessons.
+ If you have everything you need, then you can follow the instructions on our setup help articles to download and install our free app and set it up with your audio gear and webcam. Please email us at support@jamkazam.com or call us at 1-877-376-8742 any time so that we can help you with these steps. We are very happy to help, and we also strongly suggest that you let one of our staff get into an online session with you to make sure everything is working properly and to make sure you're comfortable with the app and ready for your first lesson.
3. Learn About JamClass Features
- Use this link to a set of
- help
- articles for students on JamClass to familiarize yourself with the most useful features
- for online lessons. This includes how to search for the best teacher for you, how to request/book lessons, how to join
- your teacher in online lessons, features you can use while in lessons, and much more. There is very important basic
- information, plus some really nifty stuff here, so be sure to look through it at least briefly to see how we can
- turbocharge your online lessons!
-
4. Play With Other Musicians Online - It's Free!
- With JamKazam, you can use the things you're learning in lessons to play with other amateur musicians in online
- sessions, free! Or just play for fun. Once you've set up your gear for lessons, you can
- create
- online music sessions
- that others can join, or find other musicians' online music sessions and hop into those to play with others. If you
- want to take advantage of this part of the JamKazam platform, we'd advise that you edit your musician profile to make
- it easier to connect with other musicians in our community to expand your set of musician friends. It's a ton of fun,
- so give it a try!
+ Please review our JamClass user guide for students to familiarize yourself with the features and resources available to you through our JamClass lesson service. This includes how to search for the best teacher for you, how to request/book lessons, how to join your teacher in online lessons, features you can use while in lessons, and much more.
- As you work through these things, if you ever get stuck or have questions, please don't hesitate to reach out for - help. You can email us any time at support@jamkazam.com. We are happy to - help you, and we look forward to helping you - learn and grow as a musician, and expand your musical universe! + + Again, welcome to JamKazam and our JamClass online music lesson service, and we look forward to helping you learn and grow as a musician!
diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/student_welcome_message.text.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/student_welcome_message.text.erb index 0cff2ed3e..b16eef375 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/student_welcome_message.text.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/student_welcome_message.text.erb @@ -3,7 +3,7 @@ Thank you for signing up to take online music lessons using the JamClass service by JamKazam. JamKazam technology was built from the ground up for playing music live in sync with high quality audio from different locations over the Internet. Unlike other lesson services, this means we can deliver a massively better online music lesson experience -than voice/chat apps like Skype, etc. Our rapidly growing community of 35,000+ musicians will attest to this. +than voice/chat apps like Skype, etc. Our rapidly growing community of <%= APP_CONFIG.musician_count %> musicians will attest to this. To get ready to take JamClass lessons online, here are the things you'll want to do: diff --git a/ruby/lib/jam_ruby/models/lesson_package_purchase.rb b/ruby/lib/jam_ruby/models/lesson_package_purchase.rb index f036572f1..d0e592358 100644 --- a/ruby/lib/jam_ruby/models/lesson_package_purchase.rb +++ b/ruby/lib/jam_ruby/models/lesson_package_purchase.rb @@ -54,6 +54,9 @@ module JamRuby end + def to_s + "#{name} (#{amount_charged})" + end def name lesson_package_type.sale_display diff --git a/ruby/lib/jam_ruby/models/test_drive_package.rb b/ruby/lib/jam_ruby/models/test_drive_package.rb index 98c3c3964..d85f1b086 100644 --- a/ruby/lib/jam_ruby/models/test_drive_package.rb +++ b/ruby/lib/jam_ruby/models/test_drive_package.rb @@ -10,6 +10,16 @@ module JamRuby validates :name, presence: true, uniqueness: true validates :package_type, presence: true + + #validate :teacher_count + + def teacher_count + if package_type != test_drive_package_teachers.length + self.errors.add(:test_drive_package_teachers, "wrong number of teachers specified for the given package type #{package_type}") + end + end + + accepts_nested_attributes_for :test_drive_package_teachers, allow_destroy: true end end diff --git a/ruby/lib/jam_ruby/models/test_drive_package_choice.rb b/ruby/lib/jam_ruby/models/test_drive_package_choice.rb new file mode 100644 index 000000000..569e1e352 --- /dev/null +++ b/ruby/lib/jam_ruby/models/test_drive_package_choice.rb @@ -0,0 +1,13 @@ +# when a user picks a package, we mark which teachers they actually went with from the package +module JamRuby + class TestDrivePackageChoice < ActiveRecord::Base + + @@log = Logging.logger[TestDrivePackageChoice] + + belongs_to :test_drive_package, class_name: "JamRuby::TestDrivePackage" + belongs_to :user, class_name: "JamRuby::User" + has_many :test_drive_package_choice_teachers, class_name: "JamRuby::TestDrivePackageChoiceTeacher", foreign_key: :teacher_id + + end +end + diff --git a/ruby/lib/jam_ruby/models/test_drive_package_choice_teacher.rb b/ruby/lib/jam_ruby/models/test_drive_package_choice_teacher.rb new file mode 100644 index 000000000..02397f886 --- /dev/null +++ b/ruby/lib/jam_ruby/models/test_drive_package_choice_teacher.rb @@ -0,0 +1,12 @@ +# when a user picks a package, we mark which teachers they actually went with from the package +module JamRuby + class TestDrivePackageChoiceTeacher < ActiveRecord::Base + + @@log = Logging.logger[TestDrivePackageChoiceTeacher] + + belongs_to :test_drive_package_choice, class_name: "JamRuby::TestDrivePackageChoice" + belongs_to :teacher, class_name: "JamRuby::User", foreign_key: :teacher_id + + end +end + diff --git a/ruby/lib/jam_ruby/models/test_drive_package_teacher.rb b/ruby/lib/jam_ruby/models/test_drive_package_teacher.rb index eb232d194..ab5d29fcf 100644 --- a/ruby/lib/jam_ruby/models/test_drive_package_teacher.rb +++ b/ruby/lib/jam_ruby/models/test_drive_package_teacher.rb @@ -4,13 +4,30 @@ module JamRuby @@log = Logging.logger[TestDrivePackageTeacher] - attr_accessible :user_id, :test_drive_package_id, as: :admin + attr_accessor :short_bio_temp + attr_accessible :user_id, :test_drive_package_id, :short_bio, as: :admin belongs_to :test_drive_package, class_name: "JamRuby::TestDrivePackage" belongs_to :user, class_name: "JamRuby::User" validates :user, presence: true validates :test_drive_package, presence: true + + after_save :after_save + + # silly pass through for activeadmin. We pass short_bio set here on to teacher + def after_save + if user && user.teacher + user.teacher.short_bio = short_bio + user.teacher.save! + end + end + + def short_bio + if user && user.teacher + user.teacher.short_bio + end + end end end diff --git a/ruby/lib/jam_ruby/models/user.rb b/ruby/lib/jam_ruby/models/user.rb index 93b19b48f..ad92ac057 100644 --- a/ruby/lib/jam_ruby/models/user.rb +++ b/ruby/lib/jam_ruby/models/user.rb @@ -1159,7 +1159,7 @@ module JamRuby elsif user.is_a_teacher school = School.find_by_id(school_id) school_name = school ? school.name : 'a music school' - user.teacher = Teacher.build_teacher(user, validate_introduction: true, biography: "Teaches for #{school_name}", school_id: school_id) + user.teacher = Teacher.build_teacher(user, validate_introduction: true, biography: "Empty biography", school_id: school_id) user.affiliate_referral = school.affiliate_partner end else diff --git a/ruby/spec/factories.rb b/ruby/spec/factories.rb index 8cde0eff7..893a4a2b5 100644 --- a/ruby/spec/factories.rb +++ b/ruby/spec/factories.rb @@ -6,9 +6,9 @@ FactoryGirl.define do specific_instruments nil end - sequence(:email) { |n| "person_#{n}@example.com"} - sequence(:first_name) { |n| "Person" } - sequence(:last_name) { |n| "#{n}" } + sequence(:email) { |n| "person_#{n}@example.com" } + sequence(:first_name) { |n| "Person" } + sequence(:last_name) { |n| "#{n}" } password "foobar" password_confirmation "foobar" email_confirmed true @@ -47,7 +47,7 @@ FactoryGirl.define do factory :austin_user do first_name 'Austin' - sequence(:last_name) { |n| "#{n}" } + sequence(:last_name) { |n| "#{n}" } state 'TX' city 'Austin' last_jam_locidispid { austin_geoip[:locidispid] } @@ -56,7 +56,7 @@ FactoryGirl.define do factory :dallas_user do first_name 'Dallas' - sequence(:last_name) { |n| "#{n}" } + sequence(:last_name) { |n| "#{n}" } state 'TX' city 'Dallas' last_jam_locidispid { dallas_geoip[:locidispid] } @@ -65,7 +65,7 @@ FactoryGirl.define do factory :houston_user do first_name 'Houston' - sequence(:last_name) { |n| "#{n}" } + sequence(:last_name) { |n| "#{n}" } state 'TX' city 'Houston' last_jam_locidispid { houston_geoip[:locidispid] } @@ -74,7 +74,7 @@ FactoryGirl.define do factory :miami_user do first_name 'Miami' - sequence(:last_name) { |n| "#{n}" } + sequence(:last_name) { |n| "#{n}" } state 'FL' city 'Miami' last_jam_locidispid { miami_geoip[:locidispid] } @@ -83,7 +83,7 @@ FactoryGirl.define do factory :seattle_user do first_name 'Seattle' - sequence(:last_name) { |n| "#{n}" } + sequence(:last_name) { |n| "#{n}" } state 'WA' city 'Seattle' last_jam_locidispid { seattle_geoip[:locidispid] } @@ -106,7 +106,7 @@ FactoryGirl.define do factory :teacher, :class => JamRuby::Teacher do association :user, factory: :user - price_per_lesson_60_cents 3000 + price_per_lesson_60_cents 3000 price_per_month_60_cents 3000 end @@ -156,7 +156,7 @@ FactoryGirl.define do end end end - + factory :music_session, :class => JamRuby::MusicSession do ignore do student nil @@ -208,7 +208,7 @@ FactoryGirl.define do client_type 'client' gateway 'gateway1' last_jam_audio_latency { user.last_jam_audio_latency if user } - sequence(:channel_id) { |n| "Channel#{n}"} + sequence(:channel_id) { |n| "Channel#{n}" } association :user, factory: :user scoring_timeout Time.now end @@ -230,7 +230,7 @@ FactoryGirl.define do end factory :band, :class => JamRuby::Band do - sequence(:name) { |n| "Band" } + sequence(:name) { |n| "Band" } biography "My Biography" city "Apex" state "NC" @@ -260,57 +260,57 @@ FactoryGirl.define do factory :track, :class => JamRuby::Track do sound "mono" - sequence(:client_track_id) { |n| "client_track_id#{n}"} - sequence(:client_resource_id) { |n| "resource_id#{n}"} + sequence(:client_track_id) { |n| "client_track_id#{n}" } + sequence(:client_resource_id) { |n| "resource_id#{n}" } end factory :backing_track, :class => JamRuby::BackingTrack do - sequence(:client_track_id) { |n| "client_track_id#{n}"} + sequence(:client_track_id) { |n| "client_track_id#{n}" } filename 'foo.mp3' end factory :video_source, :class => JamRuby::VideoSource do #client_video_source_id "test_source_id" - sequence(:client_video_source_id) { |n| "client_video_source_id#{n}"} + sequence(:client_video_source_id) { |n| "client_video_source_id#{n}" } end factory :recorded_track, :class => JamRuby::RecordedTrack do instrument JamRuby::Instrument.first sound 'stereo' - sequence(:client_id) { |n| "client_id-#{n}"} - sequence(:track_id) { |n| "track_id-#{n}"} - sequence(:client_track_id) { |n| "client_track_id-#{n}"} + sequence(:client_id) { |n| "client_id-#{n}" } + sequence(:track_id) { |n| "track_id-#{n}" } + sequence(:client_track_id) { |n| "client_track_id-#{n}" } md5 'abc' length 1 fully_uploaded true - association :user, factory: :user - association :recording, factory: :recording + association :user, factory: :user + association :recording, factory: :recording end factory :recorded_backing_track, :class => JamRuby::RecordedBackingTrack do - sequence(:client_id) { |n| "client_id-#{n}"} - sequence(:backing_track_id) { |n| "track_id-#{n}"} - sequence(:client_track_id) { |n| "client_track_id-#{n}"} - sequence(:filename) { |n| "filename-{#n}"} - sequence(:url) { |n| "/recordings/blah/#{n}"} + sequence(:client_id) { |n| "client_id-#{n}" } + sequence(:backing_track_id) { |n| "track_id-#{n}" } + sequence(:client_track_id) { |n| "client_track_id-#{n}" } + sequence(:filename) { |n| "filename-{#n}" } + sequence(:url) { |n| "/recordings/blah/#{n}" } md5 'abc' length 1 fully_uploaded true - association :user, factory: :user - association :recording, factory: :recording + association :user, factory: :user + association :recording, factory: :recording end factory :recorded_video, :class => JamRuby::RecordedVideo do - sequence(:client_video_source_id) { |n| "client_video_source_id-#{n}"} + sequence(:client_video_source_id) { |n| "client_video_source_id-#{n}" } fully_uploaded true length 1 - association :user, factory: :user - association :recording, factory: :recording + association :user, factory: :user + association :recording, factory: :recording end factory :recorded_jam_track_track, :class => JamRuby::RecordedJamTrackTrack do - association :user, factory: :user - association :recording, factory: :recording + association :user, factory: :user + association :recording, factory: :recording association :jam_track_track, factory: :jam_track_track end @@ -320,9 +320,9 @@ FactoryGirl.define do factory :recording, :class => JamRuby::Recording do - association :owner, factory: :user - association :music_session, factory: :active_music_session - association :band, factory: :band + association :owner, factory: :user + association :music_session, factory: :active_music_session + association :band, factory: :band factory :recording_with_track do before(:create) { |recording| @@ -335,8 +335,8 @@ FactoryGirl.define do sequence(:name) { |n| "name-#{n}" } sequence(:description) { |n| "description-#{n}" } is_public true - association :genre, factory: :genre - association :user, factory: :user + association :genre, factory: :genre + association :user, factory: :user before(:create) { |claimed_recording, evaluator| claimed_recording.recording = FactoryGirl.create(:recording_with_track, owner: claimed_recording.user) unless evaluator.recording @@ -359,7 +359,7 @@ FactoryGirl.define do sequence(:mp3_url) { |n| "recordings/mp3/#{n}" } completed true - before(:create) {|mix, evaluator| + before(:create) { |mix, evaluator| if evaluator.autowire user = FactoryGirl.create(:user) mix.recording = FactoryGirl.create(:recording_with_track, owner: user) @@ -382,7 +382,7 @@ FactoryGirl.define do mp3_url nil completed false - before(:create) {|mix, evaluator| + before(:create) { |mix, evaluator| if evaluator.autowire user = FactoryGirl.create(:user) mix.user = user @@ -434,63 +434,63 @@ FactoryGirl.define do end factory :icecast_admin_authentication, :class => JamRuby::IcecastAdminAuthentication do - source_pass Faker::Lorem.characters(10) - admin_user Faker::Lorem.characters(10) - admin_pass Faker::Lorem.characters(10) - relay_user Faker::Lorem.characters(10) - relay_pass Faker::Lorem.characters(10) + source_pass Faker::Lorem.characters(10) + admin_user Faker::Lorem.characters(10) + admin_pass Faker::Lorem.characters(10) + relay_user Faker::Lorem.characters(10) + relay_pass Faker::Lorem.characters(10) end factory :icecast_directory, :class => JamRuby::IcecastDirectory do - yp_url_timeout 15 - yp_url Faker::Lorem.characters(10) + yp_url_timeout 15 + yp_url Faker::Lorem.characters(10) end factory :icecast_master_server_relay, :class => JamRuby::IcecastMasterServerRelay do - master_server Faker::Lorem.characters(10) - master_server_port 8000 + master_server Faker::Lorem.characters(10) + master_server_port 8000 master_update_interval 120 - master_username Faker::Lorem.characters(10) - master_pass Faker::Lorem.characters(10) - relays_on_demand 1 + master_username Faker::Lorem.characters(10) + master_pass Faker::Lorem.characters(10) + relays_on_demand 1 end factory :icecast_path, :class => JamRuby::IcecastPath do - base_dir Faker::Lorem.characters(10) - log_dir Faker::Lorem.characters(10) - pid_file Faker::Lorem.characters(10) - web_root Faker::Lorem.characters(10) - admin_root Faker::Lorem.characters(10) + base_dir Faker::Lorem.characters(10) + log_dir Faker::Lorem.characters(10) + pid_file Faker::Lorem.characters(10) + web_root Faker::Lorem.characters(10) + admin_root Faker::Lorem.characters(10) end factory :icecast_logging, :class => JamRuby::IcecastLogging do - access_log Faker::Lorem.characters(10) - error_log Faker::Lorem.characters(10) - log_level 3 - log_archive nil - log_size 10000 + access_log Faker::Lorem.characters(10) + error_log Faker::Lorem.characters(10) + log_level 3 + log_archive nil + log_size 10000 end factory :icecast_security, :class => JamRuby::IcecastSecurity do - chroot 0 + chroot 0 end factory :icecast_mount, :class => JamRuby::IcecastMount do - sequence(:name) { |n| "/mount_#{n}" } - source_username Faker::Lorem.characters(10) - source_pass Faker::Lorem.characters(10) - max_listeners 100 + sequence(:name) { |n| "/mount_#{n}" } + source_username Faker::Lorem.characters(10) + source_pass Faker::Lorem.characters(10) + max_listeners 100 max_listener_duration 3600 - fallback_mount Faker::Lorem.characters(10) - fallback_override 1 - fallback_when_full 1 - is_public -1 - stream_name Faker::Lorem.characters(10) - stream_description Faker::Lorem.characters(10) - stream_url Faker::Lorem.characters(10) - genre Faker::Lorem.characters(10) - hidden 0 - association :server, factory: :icecast_server_with_overrides + fallback_mount Faker::Lorem.characters(10) + fallback_override 1 + fallback_when_full 1 + is_public -1 + stream_name Faker::Lorem.characters(10) + stream_description Faker::Lorem.characters(10) + stream_url Faker::Lorem.characters(10) + genre Faker::Lorem.characters(10) + hidden 0 + association :server, factory: :icecast_server_with_overrides factory :icecast_mount_with_auth do association :authentication, :factory => :icecast_user_authentication @@ -508,39 +508,39 @@ FactoryGirl.define do factory :icecast_source_change, :class => JamRuby::IcecastSourceChange do source_direction true success true - sequence(:client_id) { |n| "client_id#{n}" } + sequence(:client_id) { |n| "client_id#{n}" } change_type JamRuby::IcecastSourceChange::CHANGE_TYPE_CLIENT - association :user, :factory => :user - association :mount, :factory => :iceast_mount_with_music_session + association :user, :factory => :user + association :mount, :factory => :iceast_mount_with_music_session end factory :icecast_listen_socket, :class => JamRuby::IcecastListenSocket do - port 8000 + port 8000 end factory :icecast_relay, :class => JamRuby::IcecastRelay do - port 8000 - mount Faker::Lorem.characters(10) - server Faker::Lorem.characters(10) - on_demand 1 + port 8000 + mount Faker::Lorem.characters(10) + server Faker::Lorem.characters(10) + on_demand 1 end factory :icecast_user_authentication, :class => JamRuby::IcecastUserAuthentication do authentication_type 'url' - unused_username Faker::Lorem.characters(10) - unused_pass Faker::Lorem.characters(10) - mount_add Faker::Lorem.characters(10) - mount_remove Faker::Lorem.characters(10) - listener_add Faker::Lorem.characters(10) - listener_remove Faker::Lorem.characters(10) - auth_header 'icecast-auth-user: 1' - timelimit_header 'icecast-auth-timelimit:' + unused_username Faker::Lorem.characters(10) + unused_pass Faker::Lorem.characters(10) + mount_add Faker::Lorem.characters(10) + mount_remove Faker::Lorem.characters(10) + listener_add Faker::Lorem.characters(10) + listener_remove Faker::Lorem.characters(10) + auth_header 'icecast-auth-user: 1' + timelimit_header 'icecast-auth-timelimit:' end factory :icecast_server, :class => JamRuby::IcecastServer do - sequence(:hostname) { |n| "hostname-#{n}"} - sequence(:server_id) { |n| "test-server-#{n}"} + sequence(:hostname) { |n| "hostname-#{n}" } + sequence(:server_id) { |n| "test-server-#{n}" } factory :icecast_server_minimal do association :template, :factory => :icecast_template_minimal @@ -561,27 +561,27 @@ FactoryGirl.define do end factory :icecast_mount_template, :class => JamRuby::IcecastMountTemplate do - sequence(:name) { |n| "name-#{n}"} - source_username Faker::Lorem.characters(10) - source_pass Faker::Lorem.characters(10) - max_listeners 100 + sequence(:name) { |n| "name-#{n}" } + source_username Faker::Lorem.characters(10) + source_pass Faker::Lorem.characters(10) + max_listeners 100 max_listener_duration 3600 - fallback_mount Faker::Lorem.characters(10) - fallback_override 1 - fallback_when_full 1 - is_public -1 - stream_name Faker::Lorem.characters(10) - stream_description Faker::Lorem.characters(10) - stream_url Faker::Lorem.characters(10) - genre Faker::Lorem.characters(10) - hidden 0 - association :authentication, :factory => :icecast_user_authentication + fallback_mount Faker::Lorem.characters(10) + fallback_override 1 + fallback_when_full 1 + is_public -1 + stream_name Faker::Lorem.characters(10) + stream_description Faker::Lorem.characters(10) + stream_url Faker::Lorem.characters(10) + genre Faker::Lorem.characters(10) + hidden 0 + association :authentication, :factory => :icecast_user_authentication end factory :icecast_template, :class => JamRuby::IcecastTemplate do - sequence(:name) { |n| "name-#{n}"} - sequence(:location) { |n| "location-#{n}"} + sequence(:name) { |n| "name-#{n}" } + sequence(:location) { |n| "location-#{n}" } factory :icecast_template_minimal do association :limit, :factory => :icecast_limit @@ -597,25 +597,25 @@ FactoryGirl.define do end factory :facebook_signup, :class => JamRuby::FacebookSignup do - sequence(:lookup_id) { |n| "lookup-#{n}"} - sequence(:first_name) { |n| "first-#{n}"} - sequence(:last_name) { |n| "last-#{n}"} - gender 'M' - sequence(:email) { |n| "jammin-#{n}@jamkazam.com"} - sequence(:uid) { |n| "uid-#{n}"} - sequence(:token) { |n| "token-#{n}"} - token_expires_at Time.now + sequence(:lookup_id) { |n| "lookup-#{n}" } + sequence(:first_name) { |n| "first-#{n}" } + sequence(:last_name) { |n| "last-#{n}" } + gender 'M' + sequence(:email) { |n| "jammin-#{n}@jamkazam.com" } + sequence(:uid) { |n| "uid-#{n}" } + sequence(:token) { |n| "token-#{n}" } + token_expires_at Time.now end factory :recording_comment, :class => JamRuby::RecordingComment do sequence(:comment) { |n| "comment-#{n}" } - association :recording, factory: :recording - association :user, factory: :recording + association :recording, factory: :recording + association :user, factory: :recording end factory :playable_play, :class => JamRuby::PlayablePlay do - association :user, factory: :user + association :user, factory: :user end factory :recording_like, :class => JamRuby::RecordingLiker do @@ -627,9 +627,9 @@ FactoryGirl.define do end factory :event, :class => JamRuby::Event do - sequence(:slug) { |n| "slug-#{n}" } - title 'event title' - description 'event description' + sequence(:slug) { |n| "slug-#{n}" } + title 'event title' + description 'event description' end factory :event_session, :class => JamRuby::EventSession do @@ -676,7 +676,7 @@ FactoryGirl.define do after(:create) do |rsvp_slot, evaluator| rsvp_request = FactoryGirl.create(:rsvp_request, user: evaluator.user) - rsvp_request_rsvp_slot = FactoryGirl.create(:rsvp_request_rsvp_slot, chosen:true, rsvp_request: rsvp_request, rsvp_slot:rsvp_slot) + rsvp_request_rsvp_slot = FactoryGirl.create(:rsvp_request_rsvp_slot, chosen: true, rsvp_request: rsvp_request, rsvp_slot: rsvp_slot) end end end @@ -694,10 +694,10 @@ FactoryGirl.define do chosen nil end - after(:create) { |rsvp_request, evaluator | + after(:create) { |rsvp_request, evaluator| evaluator.number.times do |i| slot = FactoryGirl.create(:rsvp_slot, music_session: evaluator.music_session, instrument: Instrument.order(:id).limit(1).offset(i).first, proficiency_level: 1) - FactoryGirl.create(:rsvp_request_rsvp_slot, chosen: evaluator.chosen, rsvp_request: rsvp_request, rsvp_slot:slot) + FactoryGirl.create(:rsvp_request_rsvp_slot, chosen: evaluator.chosen, rsvp_request: rsvp_request, rsvp_slot: slot) end } end @@ -709,9 +709,9 @@ FactoryGirl.define do chosen nil end - after(:create) { |rsvp_request, evaluator | + after(:create) { |rsvp_request, evaluator| evaluator.slots.each do |slot| - FactoryGirl.create(:rsvp_request_rsvp_slot, chosen:evaluator.chosen, rsvp_request: rsvp_request, rsvp_slot:slot) + FactoryGirl.create(:rsvp_request_rsvp_slot, chosen: evaluator.chosen, rsvp_request: rsvp_request, rsvp_slot: slot) end } end @@ -724,7 +724,7 @@ FactoryGirl.define do factory :latency_tester, :class => JamRuby::LatencyTester do ignore do connection nil - make_connection true + make_connection true end sequence(:client_id) { |n| "LatencyTesterClientId-#{n}" } @@ -755,19 +755,19 @@ FactoryGirl.define do end factory :jam_track_mixdown, :class => JamRuby::JamTrackMixdown do - association :user, factory: :user - association :jam_track, factory: :jam_track - sequence(:name) { |n| "mixdown-#{n}"} - settings '{"speed":5}' + association :user, factory: :user + association :jam_track, factory: :jam_track + sequence(:name) { |n| "mixdown-#{n}" } + settings '{"speed":5}' end factory :jam_track_mixdown_package, :class => JamRuby::JamTrackMixdownPackage do - file_type JamRuby::JamTrackMixdownPackage::FILE_TYPE_OGG - sample_rate 48 - signing false - signed false + file_type JamRuby::JamTrackMixdownPackage::FILE_TYPE_OGG + sample_rate 48 + signing false + signed false - association :jam_track_mixdown, factory: :jam_track_mixdown + association :jam_track_mixdown, factory: :jam_track_mixdown end @@ -775,22 +775,22 @@ FactoryGirl.define do sequence(:name) { |n| "jam-track-#{n}" } sequence(:description) { |n| "description-#{n}" } sequence(:slug) { |n| "slug-#{n}" } - time_signature '4/4' - status 'Production' - recording_type 'Cover' + time_signature '4/4' + status 'Production' + recording_type 'Cover' sequence(:original_artist) { |n| "original-artist-#{n}" } sequence(:songwriter) { |n| "songwriter-#{n}" } sequence(:publisher) { |n| "publisher-#{n}" } - sales_region 'United States' - price 1.99 - reproduction_royalty true + sales_region 'United States' + price 1.99 + reproduction_royalty true public_performance_royalty true reproduction_royalty_amount 0.999 licensor_royalty_amount 0.999 - sequence(:plan_code) { |n| "jamtrack-#{n}" } + sequence(:plan_code) { |n| "jamtrack-#{n}" } - genres [JamRuby::Genre.first] - association :licensor, factory: :jam_track_licensor + genres [JamRuby::Genre.first] + association :licensor, factory: :jam_track_licensor factory :jam_track_with_tracks do after(:create) do |jam_track, evaluator| @@ -800,46 +800,46 @@ FactoryGirl.define do end factory :jam_track_track, :class => JamRuby::JamTrackTrack do - position 1 - part 'lead guitar' - track_type 'Track' - instrument JamRuby::Instrument.find('electric guitar') - association :jam_track, factory: :jam_track + position 1 + part 'lead guitar' + track_type 'Track' + instrument JamRuby::Instrument.find('electric guitar') + association :jam_track, factory: :jam_track end factory :jam_track_right, :class => JamRuby::JamTrackRight do - association :jam_track, factory: :jam_track - association :user, factory: :user + association :jam_track, factory: :jam_track + association :user, factory: :user signing_44 false signing_48 false end factory :jam_track_tap_in, :class => JamRuby::JamTrackTapIn do - association :jam_track, factory: :jam_track - offset_time 0 - bpm 120 - tap_in_count 3 + association :jam_track, factory: :jam_track + offset_time 0 + bpm 120 + tap_in_count 3 end factory :download_tracker, :class => JamRuby::DownloadTracker do - remote_ip '1.1.1.1' - paid false + remote_ip '1.1.1.1' + paid false association :user, factory: :user association :jam_track, factory: :jam_track end factory :sale, :class => JamRuby::Sale do order_total 0 - association :user, factory:user + association :user, factory: user end factory :recurly_transaction_web_hook, :class => JamRuby::RecurlyTransactionWebHook do transaction_type JamRuby::RecurlyTransactionWebHook::SUCCESSFUL_PAYMENT - sequence(:recurly_transaction_id ) { |n| "recurly-transaction-id-#{n}" } - sequence(:subscription_id ) { |n| "subscription-id-#{n}" } - sequence(:invoice_id ) { |n| "invoice-id-#{n}" } - sequence(:invoice_number ) { |n| 1000 + n } + sequence(:recurly_transaction_id) { |n| "recurly-transaction-id-#{n}" } + sequence(:subscription_id) { |n| "subscription-id-#{n}" } + sequence(:invoice_id) { |n| "invoice-id-#{n}" } + sequence(:invoice_number) { |n| 1000 + n } invoice_number_prefix nil action 'purchase' status 'success' @@ -890,12 +890,12 @@ FactoryGirl.define do end factory :gift_card, class: 'JamRuby::GiftCard' do - sequence(:code) {n.to_s} - card_type JamRuby::GiftCardType::JAM_TRACKS_5 + sequence(:code) { n.to_s } + card_type JamRuby::GiftCardType::JAM_TRACKS_5 end factory :gift_card_type, class: 'JamRuby::GiftCardType' do - card_type JamRuby::GiftCardType::JAM_TRACKS_5 + card_type JamRuby::GiftCardType::JAM_TRACKS_5 end factory :gift_card_purchase, class: 'JamRuby::GiftCardPurchase' do @@ -907,8 +907,8 @@ FactoryGirl.define do association :user, factory: :user - sequence(:serial_no ) { |n| "serial_no#{n}" } - sequence(:client_id ) { |n| "client_id#{n}" } + sequence(:serial_no) { |n| "serial_no#{n}" } + sequence(:client_id) { |n| "client_id#{n}" } end factory :jamblaster_pairing_request, class: 'JamRuby::JamblasterPairingRequest' do @@ -916,13 +916,13 @@ FactoryGirl.define do association :user, factory: :user association :jamblaster, factory: :jamblaster - sequence(:jamblaster_client_id ) { |n| "jamblaster_client_id#{n}" } - sequence(:sibling_key ) { |n| "sibling_key#{n}" } + sequence(:jamblaster_client_id) { |n| "jamblaster_client_id#{n}" } + sequence(:sibling_key) { |n| "sibling_key#{n}" } end factory :school, class: 'JamRuby::School' do association :user, factory: :user - sequence(:name) {|n| "Dat Music School"} + sequence(:name) { |n| "Dat Music School" } enabled true scheduling_communication 'teacher' end @@ -931,16 +931,16 @@ FactoryGirl.define do association :school, factory: :school note "hey come in in" as_teacher true - sequence(:email) {|n| "school_person#{n}@example.com"} - sequence(:first_name) {|n| "FirstName"} - sequence(:last_name) {|n| "LastName"} + sequence(:email) { |n| "school_person#{n}@example.com" } + sequence(:first_name) { |n| "FirstName" } + sequence(:last_name) { |n| "LastName" } accepted false end factory :lesson_booking_slot, class: 'JamRuby::LessonBookingSlot' do factory :lesson_booking_slot_single do slot_type 'single' - preferred_day {Date.today + 3} + preferred_day { Date.today + 3 } day_of_week nil hour 12 minute 30 @@ -960,14 +960,14 @@ FactoryGirl.define do factory :lesson_booking, class: 'JamRuby::LessonBooking' do association :user, factory: :user association :teacher, factory: :teacher_user - card_presumed_ok false - sent_notices false - recurring false - lesson_length 30 - lesson_type JamRuby::LessonBooking::LESSON_TYPE_FREE - payment_style JamRuby::LessonBooking::PAYMENT_STYLE_ELSEWHERE - description "Oh my goodness!" - status JamRuby::LessonBooking::STATUS_REQUESTED + card_presumed_ok false + sent_notices false + recurring false + lesson_length 30 + lesson_type JamRuby::LessonBooking::LESSON_TYPE_FREE + payment_style JamRuby::LessonBooking::PAYMENT_STYLE_ELSEWHERE + description "Oh my goodness!" + status JamRuby::LessonBooking::STATUS_REQUESTED before(:create) do |lesson_booking, evaluator| lesson_booking.lesson_booking_slots = [FactoryGirl.build(:lesson_booking_slot_single, lesson_booking: lesson_booking), FactoryGirl.build(:lesson_booking_slot_single, lesson_booking: lesson_booking)] @@ -994,8 +994,8 @@ FactoryGirl.define do student nil end - music_session {FactoryGirl.create(:music_session, creator: student)} - lesson_booking {FactoryGirl.create(:lesson_booking, user: student, teacher: teacher)} + music_session { FactoryGirl.create(:music_session, creator: student) } + lesson_booking { FactoryGirl.create(:lesson_booking, user: student, teacher: teacher) } association :teacher, factory: :teacher_user lesson_type JamRuby::LessonSession::LESSON_TYPE_SINGLE duration 30 @@ -1006,18 +1006,18 @@ FactoryGirl.define do end factory :charge, class: 'JamRuby::Charge' do - type 'JamRuby::Charge' + type 'JamRuby::Charge' amount_in_cents 1000 end factory :teacher_payment_charge, parent: :charge, class: 'JamRuby::TeacherPaymentCharge' do - type 'JamRuby::TeacherPaymentCharge' + type 'JamRuby::TeacherPaymentCharge' association :user, factory: :user end factory :lesson_payment_charge, parent: :charge, class: 'JamRuby::LessonPaymentCharge' do - type 'JamRuby::LessonPaymentCharge' + type 'JamRuby::LessonPaymentCharge' association :user, factory: :user end @@ -1037,7 +1037,7 @@ FactoryGirl.define do amount_in_cents 1000 end - + factory :ip_blacklist, class: "JamRuby::IpBlacklist" do remote_ip '1.1.1.1' end @@ -1055,15 +1055,63 @@ FactoryGirl.define do end factory :email_blacklist, class: "JamRuby::EmailBlacklist" do - sequence(:email) { |n| "person_#{n}@example.com"} + sequence(:email) { |n| "person_#{n}@example.com" } end factory :music_notation, class: "JamRuby::MusicNotation" do - attachment_type {JamRuby::MusicNotation::TYPE_NOTATION} + attachment_type { JamRuby::MusicNotation::TYPE_NOTATION } association :user, factory: :user file_url 'abc' size 100 file_name 'some_file.jpg' end + + factory :test_drive_package, class: "JamRuby::TestDrivePackage" do + + sequence(:name) { |n| "package-#{n}" } + + trait :one_pack do + package_type 1 + after(:create) do |package, evaluator| + 1.times.each do + FactoryGirl.create(:test_drive_package_teachers, test_drive_package: package) + end + end + end + + trait :two_pack do + package_type 2 + after(:create) do |package, evaluator| + 2.times.each do + FactoryGirl.create(:test_drive_package_teachers, test_drive_package: package) + end + end + end + + trait :four_pack do + package_type 4 + after(:create) do |package, evaluator| + 4.times.each do + FactoryGirl.create(:test_drive_package_teachers, test_drive_package: package) + end + end + end + + end + + factory :test_drive_package_teachers, class: "JamRuby::TestDrivePackageTeacher" do + association :user, factory: :teacher_user + association :test_drive_package, factory: [:test_drive_package, :four_pack] + end + + factory :test_drive_package_choice, class: "JamRuby::TestDrivePackageChoice" do + association :user, factory: :user + association :test_drive_package, factory: [:test_drive_package, :four_pack] + end + + factory :test_drive_package_choice_teacher, class: "JamRuby::TestDrivePackageChoiceTeacher" do + association :teacher, factory: :teacher_user + association :test_drive_package_choice, factory: :test_drive_package_choice + end end diff --git a/ruby/spec/jam_ruby/models/test_drive_package_choice_spec.rb b/ruby/spec/jam_ruby/models/test_drive_package_choice_spec.rb new file mode 100644 index 000000000..564ffd1d3 --- /dev/null +++ b/ruby/spec/jam_ruby/models/test_drive_package_choice_spec.rb @@ -0,0 +1,14 @@ +require 'spec_helper' + +describe TestDrivePackageChoice do + + it "works" do + + choice = FactoryGirl.create(:test_drive_package_choice) + choice.test_drive_package.package_type.should eql 4 + choice.test_drive_package.test_drive_package_teachers.count.should eql 4 + + teacher_choice = FactoryGirl.create(:test_drive_package_choice_teacher, test_drive_package_choice: choice) + teacher_choice.test_drive_package_choice.should eql choice + end +end \ No newline at end of file diff --git a/ruby/spec/spec_helper.rb b/ruby/spec/spec_helper.rb index bc1163e38..911452807 100644 --- a/ruby/spec/spec_helper.rb +++ b/ruby/spec/spec_helper.rb @@ -38,7 +38,7 @@ require 'timecop' require 'resque_spec/scheduler' # uncomment this to see active record logs -ActiveRecord::Base.logger = Logger.new(STDOUT) if defined?(ActiveRecord::Base) +# ActiveRecord::Base.logger = Logger.new(STDOUT) if defined?(ActiveRecord::Base) include JamRuby diff --git a/ruby/spec/support/utilities.rb b/ruby/spec/support/utilities.rb index b058ea23e..ca203612f 100644 --- a/ruby/spec/support/utilities.rb +++ b/ruby/spec/support/utilities.rb @@ -305,6 +305,9 @@ def app_config :ach_pct => 0.008 } end + def musician_count + '40,000+' + end private def audiomixer_workspace_path diff --git a/web/app/assets/javascripts/everywhere/everywhere.js b/web/app/assets/javascripts/everywhere/everywhere.js index 234b7d105..a6e5a721d 100644 --- a/web/app/assets/javascripts/everywhere/everywhere.js +++ b/web/app/assets/javascripts/everywhere/everywhere.js @@ -213,6 +213,7 @@ } function handleGettingStarted(app) { + /** var user = app.user() if(user) { user.done(function(userProfile) { @@ -226,7 +227,7 @@ app.layout.showDialog('getting-started'); } }) - } + }*/ } function initShoppingCart(app) { diff --git a/web/app/assets/javascripts/helpBubbleHelper.js b/web/app/assets/javascripts/helpBubbleHelper.js index 0c7c05f65..df99b0bac 100644 --- a/web/app/assets/javascripts/helpBubbleHelper.js +++ b/web/app/assets/javascripts/helpBubbleHelper.js @@ -233,7 +233,10 @@ callback(container.find('.note').val(), container.find('.email').val(), container.find('.phonenumber').val()) return false; }) - console.log("hehelllo!") }}) } + + helpBubble.testDrivePackageGo = function($element, $offsetParent, package_type) { + return context.JK.prodBubble($element, 'test-drive-package-go', {plural: package_type != '1'}, bigHelpDarkOptions({offsetParent:$offsetParent, width:260, positions:['bottom']})) + } })(window, jQuery); \ No newline at end of file diff --git a/web/app/assets/javascripts/react-components/TestDrivePackageDialog.js.jsx.coffee b/web/app/assets/javascripts/react-components/TestDrivePackageDialog.js.jsx.coffee new file mode 100644 index 000000000..cc40d30fb --- /dev/null +++ b/web/app/assets/javascripts/react-components/TestDrivePackageDialog.js.jsx.coffee @@ -0,0 +1,97 @@ +context = window +@TestDrivePackageDialog = React.createClass({ + + mixins: [Reflux.listenTo(@AppStore, "onAppInit")] + teacher: null + + beforeShow: (args) -> + # d1 should be a teacher ID (vs a user ID that happens to be a teacher) + logger.debug("TestDrivePackageDialog.beforeShow", args.d1) + @setState({target: args.d1, page_data: window.page_data}) + + + afterHide: () -> + + onAppInit: (@app) -> + dialogBindings = { + 'beforeShow': @beforeShow, + 'afterHide': @afterHide + }; + + @app.bindDialog('test-drive-package-dialog', dialogBindings); + + getInitialState: () -> + { + target: null, + page_data: null + } + + + componentDidMount: () -> + @root = $(@getDOMNode()) + + doCancel: (e) -> + e.preventDefault() + @app.layout.closeDialog('test-drive-package-dialog', true); + + selectTeachers: (e) -> + e.preventDefault() + + # validate + + if @state.target == '2' + checked = @root.find('input[type="checkbox"]:checked') + + if checked.length != 2 + context.JK.Banner.showNotice('hold on there', 'Please select 2 teachers.') + return + + if @state.target == '1' + checked = @root.find('input[type="checkbox"]:checked') + + if checked.length != 1 + context.JK.Banner.showNotice('hold on there', 'Please select a teacher.') + return + + teachers = [] + $.each(checked, (i, node) => ( + $node = $(node) + teachers.push($node.data('teacher')) + )) + @root.data('result', { package_type: @state.target, teachers: teachers }) + render: () -> + + if @state.target == '2' + help = + `+ Check the boxes under the 2 instructors you want to select for your TestDrive package. Then click the Select button below. +
` + else + help = + `+ Check the box under the instructor you want to select for your TestDrive package. Then click the Select button below. +
` + + teachers = [] + + + `` + +}) \ No newline at end of file diff --git a/web/app/assets/javascripts/react-components/landing/JamClassAffiliateLandingPage.js.jsx.coffee b/web/app/assets/javascripts/react-components/landing/JamClassAffiliateLandingPage.js.jsx.coffee index 379a8d79f..3bd61abf5 100644 --- a/web/app/assets/javascripts/react-components/landing/JamClassAffiliateLandingPage.js.jsx.coffee +++ b/web/app/assets/javascripts/react-components/landing/JamClassAffiliateLandingPage.js.jsx.coffee @@ -72,7 +72,7 @@ rest = context.JK.Rest() JamKazam has developed incredibly unique and engaging digital music technologies, content, - and marketplaces used by our rapidly growing community of 30,000+ musicians. Now we’ve + and marketplaces used by our rapidly growing community of {gon.global.musician_count} musicians. Now we’ve crafted an affiliate program specifically for music stores and music schools to increase your diff --git a/web/app/assets/javascripts/react-components/landing/JamClassStudentLandingMiddlePage.js.jsx.coffee b/web/app/assets/javascripts/react-components/landing/JamClassStudentLandingMiddlePage.js.jsx.coffee new file mode 100644 index 000000000..bb1d8366a --- /dev/null +++ b/web/app/assets/javascripts/react-components/landing/JamClassStudentLandingMiddlePage.js.jsx.coffee @@ -0,0 +1,143 @@ +@JamClassStudentLandingMiddlePage = React.createClass({ + + avatar: (name = 'your choice', photo_url = '/assets/shared/avatar_generic.png') -> + `The single most important factor in the success of your music lessons is your teacher. You wouldn't marry + the first person you date, right?
+ +Take full 30-minute lessons from each of these 4 amazing teachers for just $12.50 each - a total of + $49.99. Then you can pick the one who is best for you to continue your musical journey, with the + confidence that your investment in lessons will deliver maximum growth!
+Like the TestDrive concept, but 4 teachers is too many for you?
+The single most important factor in the success of your music lessons is your teacher. You wouldn't marry + the first person you date, right?
+ +Take full 30-minute lessons from each of these 2 amazing teachers for just $14.99 each - a total of + $29.99. Then you can pick the one who is best for you to continue your musical journey, with the + confidence that your investment in lessons will deliver maximum growth!
+Like the TestDrive concept, but prefer not to try 2 different teachers?
+Take a full 30-minute lesson from this great teacher for just $14.99 - half the cost of a typical music + lesson. You can make sure everything is working great, and then continue your musical journey with the + confidence that your investment in lessons will deliver maximum growth!
+You can book a TestDrive lesson with this awesome teacher now!
+Or you can search all of our teachers and then book a TestDrive package.
+The single most important factor in the success of your music lessons is your teacher. You wouldn't marry the + first person you date, right? Our TestDrive program lets you:
+Then continue your lessons with the best teacher for you!
+ +Join 40,000+ other musicians in the JamKazam community. Sign up for TestDrive today, and + you'll be eligible for any of the three special offers above!
+ +Not sure if this is for you? Scroll down to learn more...
+When we initially built the free JamKazam service to let musicians play together live over the Internet, we started by having musicians use the Mac and Windows computers and audio interfaces they already own. We've signed up 30,000+ musicians along the way. We've analyzed data from more than 100,000 online sessions. And we've collected audio processing latency data on thousands of combinations of computers and interfaces, as well as 10 million Internet latency measurements between unique pairs of locations and ISPs. We've learned a lot from all this data.
+When we initially built the free JamKazam service to let musicians play together live over the Internet, we started by having musicians use the Mac and Windows computers and audio interfaces they already own. We've signed up {gon.global.musician_count} musicians along the way. We've analyzed data from more than 100,000 online sessions. And we've collected audio processing latency data on thousands of combinations of computers and interfaces, as well as 10 million Internet latency measurements between unique pairs of locations and ISPs. We've learned a lot from all this data.
Typically you need to keep total one way latency down to 30 to 35 milliseconds or less in an online session, or the session will get too sloppy and fall apart. We found that the average audio processing latency of industry standard gear is 14 milliseconds (full round trip including analog-to-digital and digital-to-analog conversions). So just processing the audio eats up half of your total latency budget!
We designed the JamBlaster from the ground up to be the fastest audio processing device possible, and we have the JamBlaster running at 2.8 milliseconds of latency full round trip - a massive latency savings. Every one millisecond saved on audio processing is worth about 100 miles of range on the Internet backbone. The JamBlaster also reduces something called audio processing jitter, which delivers additional latency savings. The result is that the JamBlaster saves audio latency equivalent to about 1,500 miles of distance compared to today's standard computers and interfaces.
Looking at it another way, using JamKazam with standard computers and interfaces, a musician in the U.S. can play effectively with about 10% of the other musicians in the U.S. With the JamBlaster, that same musician can now play with about 35% of the other musicians in the U.S.
@@ -206,7 +206,7 @@ context = windowJamKazam has already signed up 30,000+ musicians who play in thousands of online sessions per month using their computers and audio interfaces. The JamBlaster interoperates seamlessly with other musicians who are running Mac and Windows PC setups, so you can jump right in and start playing with other musicians in the community using your JamBlaster from day one.
+JamKazam has already signed up {gon.global.musician_count} musicians who play in thousands of online sessions per month using their computers and audio interfaces. The JamBlaster interoperates seamlessly with other musicians who are running Mac and Windows PC setups, so you can jump right in and start playing with other musicians in the community using your JamBlaster from day one.