diff --git a/Gemfile b/Gemfile index ee01535..16ef52b 100644 --- a/Gemfile +++ b/Gemfile @@ -75,7 +75,7 @@ gem 'compass-rails', :git => 'git://github.com/Compass/compass-rails.git' # GG! # Don't commit the :path! -gem 'gg', :git => 'git@github.com:dsjoerg/gg.git', :ref => 'b58ed5e12c2d201b368980e74090987d2050f321' +gem 'gg', :git => 'git://github.com/dsjoerg/gg.git', :ref => 'b58ed5e12c2d201b368980e74090987d2050f321' # gem 'gg', :path => '/Users/mr/dev/ruby/gems/gg' #gem 'gg', :path => '/Users/david/Dropbox/Programming/gg' @@ -107,7 +107,7 @@ gem 'gon' # create our own (it's a simple Nokogiri based scraper..) # Forked it and added portraits to profile scraping -gem 'bnet_scraper', :git => 'git@github.com:ggtracker/bnet_scraper.git', :ref => 'battlenetify' +gem 'bnet_scraper', :git => 'git://github.com/ggtracker/bnet_scraper.git', :ref => 'battlenetify' #gem 'bnet_scraper', :path => '/Users/david/Dropbox/Programming/bnet_scraper/' @@ -147,3 +147,4 @@ gem 'rack-attack' gem 'unf_ext', '0.0.6' gem 'foreman' +gem "recaptcha", :git => 'git://github.com/brendon/recaptcha.git', :ref => 'remove-ruby-restriction', require: "recaptcha/rails" diff --git a/Gemfile.lock b/Gemfile.lock index 31759a0..cfd390e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -5,6 +5,14 @@ GIT compass-rails (2.0.alpha.0) compass (>= 0.12.2, < 0.14) +GIT + remote: git://github.com/brendon/recaptcha.git + revision: 21473e536b93c0237ec02edcc78cf4f7a547a221 + ref: remove-ruby-restriction + specs: + recaptcha (1.3.0) + json + GIT remote: git://github.com/chriseppstein/compass.git revision: 0a74e91931e53fb798323cd8684198c38a2b76b8 @@ -16,15 +24,7 @@ GIT sass (~> 3.3.0.rc.1) GIT - remote: git://github.com/thedarkone/rails-dev-boost.git - revision: 1e0cc0e1a3f6e51820b908d7de1f3e160ec2af0d - specs: - rails-dev-boost (0.2.1) - listen (>= 0.5) - railties (>= 3.0) - -GIT - remote: git@github.com:dsjoerg/gg.git + remote: git://github.com/dsjoerg/gg.git revision: b58ed5e12c2d201b368980e74090987d2050f321 ref: b58ed5e12c2d201b368980e74090987d2050f321 specs: @@ -35,7 +35,7 @@ GIT yajl-ruby GIT - remote: git@github.com:ggtracker/bnet_scraper.git + remote: git://github.com/ggtracker/bnet_scraper.git revision: 624e28dddbdbafba9fc5a48693ef1aa86ae8ca9f ref: battlenetify specs: @@ -43,6 +43,14 @@ GIT faraday nokogiri +GIT + remote: git://github.com/thedarkone/rails-dev-boost.git + revision: 1e0cc0e1a3f6e51820b908d7de1f3e160ec2af0d + specs: + rails-dev-boost (0.2.1) + listen (>= 0.5) + railties (>= 3.0) + GEM remote: https://rubygems.org/ specs: @@ -331,6 +339,7 @@ DEPENDENCIES rack-attack rails (= 3.2.22) rails-dev-boost! + recaptcha! resque rspec rspec-rails @@ -340,5 +349,8 @@ DEPENDENCIES unf_ext (= 0.0.6) unicorn +RUBY VERSION + ruby 1.9.3p484 + BUNDLED WITH - 1.11.2 + 1.15.3 diff --git a/app/assets/javascripts/angular/controllers/match.js b/app/assets/javascripts/angular/controllers/match.js index fbc359a..e3737d2 100644 --- a/app/assets/javascripts/angular/controllers/match.js +++ b/app/assets/javascripts/angular/controllers/match.js @@ -44,7 +44,7 @@ function($scope, $window, $route, $location, $element, Match) { // console.log("matchscope", $scope); $scope.$watch('current_frame', function(v) { if(v) { - $scope.current_time = Sc2.frameToTime(v); + $scope.current_time = Sc2.frameToTime(v, $scope.match.expansion); $scope.time_has_been_set = true } }); diff --git a/app/assets/javascripts/angular/directives/armychart.js b/app/assets/javascripts/angular/directives/armychart.js index ea790bd..fc01823 100644 --- a/app/assets/javascripts/angular/directives/armychart.js +++ b/app/assets/javascripts/angular/directives/armychart.js @@ -115,7 +115,7 @@ gg.directive('armychart', ['$location', '$timeout', function($location, $timeout scope.freeze = function(frame, updateURL) { switch(typeof frame) { case "number": frame = frame; break; - case "string": frame = Sc2.timeToFrame(frame); break; + case "string": frame = Sc2.timeToFrame(frame, scope.match.expansion); break; default: return false; } @@ -162,7 +162,7 @@ gg.directive('armychart', ['$location', '$timeout', function($location, $timeout if(typeof e == "number") { frame = e; } else if(typeof e == "string") { - frame = Sc2.timeToFrame(e); + frame = Sc2.timeToFrame(e, scope.match.expansion); } else { // If clicked on the background, we have xAxis on the event, if clicked // on a series, we'll have the point. diff --git a/app/assets/javascripts/angular/directives/chart.js b/app/assets/javascripts/angular/directives/chart.js index 2fdcec4..20b1f16 100644 --- a/app/assets/javascripts/angular/directives/chart.js +++ b/app/assets/javascripts/angular/directives/chart.js @@ -125,11 +125,15 @@ gg.directive('chart', ['$compile', function($compile) { if (scope.$parent.match.engagements) { options.xAxis.plotBands = []; + speed_multiplier = 1; + if (scope.$parent.match.expansion_tag == 'LotV') { + speed_multiplier = Sc2.LOTV_SPEEDUP; + } _.each(scope.$parent.match.engagements, function(engagement) { options.xAxis.plotBands.push({ color: 'rgba(150, 50, 50, 0.10)', - from: engagement[0] / 960.0, - to: engagement[1] / 960.0, + from: engagement[0] / 960.0 / speed_multiplier, + to: engagement[1] / 960.0 / speed_multiplier, zIndex: 10 }); }); diff --git a/app/assets/javascripts/angular/directives/macrochart.js b/app/assets/javascripts/angular/directives/macrochart.js index a4168f8..3e4397c 100644 --- a/app/assets/javascripts/angular/directives/macrochart.js +++ b/app/assets/javascripts/angular/directives/macrochart.js @@ -73,13 +73,18 @@ gg.directive('macrochart', [function() { }; + speed_multiplier = 1; + if (scope.$parent.match.expansion_tag == 'LotV') { + speed_multiplier = Sc2.LOTV_SPEEDUP; + } + if (scope.$parent.match.engagements) { options.yAxis.plotBands = []; _.each(scope.$parent.match.engagements, function(engagement) { options.yAxis.plotBands.push({ color: 'rgba(150, 50, 50, 0.1)', - from: engagement[0] / 960.0, - to: engagement[1] / 960.0, + from: engagement[0] / 960.0 / speed_multiplier, + to: engagement[1] / 960.0 / speed_multiplier, zIndex: 10 }); }); @@ -105,7 +110,7 @@ gg.directive('macrochart', [function() { for (i=0; i= 2) { + fps *= Sc2.LOTV_SPEEDUP; + } + minute = Math.floor(frame / (60 * fps)); + second = Math.floor((frame / fps) % 60).toString(); if (second.length < 2) { second = "0" + second; } @@ -271,7 +275,11 @@ Sc2.timeToFrame = function(time) { parts = time.split(':'); seconds = parseInt(parts[parts.length-1]); minutes = parseInt(parts[parts.length-2]); - frame = ((minutes*60) + seconds) * 16; + fps = 16; + if (expansion >= 2) { + fps *= Sc2.LOTV_SPEEDUP; + } + frame = ((minutes*60) + seconds) * fps; return frame; } @@ -282,3 +290,4 @@ Sc2.armyInfo = function(expansion_tag, unitname, infonum) { Sc2.isArmyUnit = function(unitname) { return (unitname in Sc2.armyUnits['LotV']); } + diff --git a/app/assets/javascripts/angular/resources/match.js b/app/assets/javascripts/angular/resources/match.js index 7a795d1..bfa5047 100644 --- a/app/assets/javascripts/angular/resources/match.js +++ b/app/assets/javascripts/angular/resources/match.js @@ -103,20 +103,20 @@ Entity.prototype.race_macro_pretty = function() { Entity.prototype.mdelta2 = function() { if (this.stats == null || - this.stats.mineral_saturation_2 == null || - this.stats.miningbase_2 == null) { + this.stats.mineral_saturation_2_adjusted == null || + this.stats.miningbase_2_adjusted == null) { return null; } - return Math.max(0, this.stats.mineral_saturation_2 - this.stats.miningbase_2); + return Math.max(0, this.stats.mineral_saturation_2_adjusted - this.stats.miningbase_2_adjusted); } Entity.prototype.mdelta3 = function() { if (this.stats == null || - this.stats.mineral_saturation_3 == null || - this.stats.miningbase_3 == null) { + this.stats.mineral_saturation_3_adjusted == null || + this.stats.miningbase_3_adjusted == null) { return null; } - return Math.max(0, this.stats.mineral_saturation_3 - this.stats.miningbase_3); + return Math.max(0, this.stats.mineral_saturation_3_adjusted - this.stats.miningbase_3_adjusted); } Entity.prototype.color_style = function() { @@ -554,7 +554,11 @@ gg.factory('Match', ['$ggResource', '$compile', 'Matchnote', function($ggResourc // don't graph the last base-time; its y-value is zero by definition _bases_x.pop(); - _bases_x_minutes = _.map(_bases_x, function(_frame_x) { return _frame_x / 960.0 }); + speed_multiplier = 1.0; + if (this.expansion_tag == 'LotV') { + speed_multiplier = Sc2.LOTV_SPEEDUP; + } + _bases_x_minutes = _.map(_bases_x, function(_frame_x) { return _frame_x / 960.0 / speed_multiplier }); _series_y = []; _.each(_bases_x, function(_x) { @@ -566,12 +570,40 @@ gg.factory('Match', ['$ggResource', '$compile', 'Matchnote', function($ggResourc return _.zip(_bases_x_minutes, _series_y); }; + // Rescale series to a point per game minute + statxminutes = function(statarray) { + // Don't rescale the series if it is all zeros, since it will show up even as zero when rescaled + var sum = 0; + $.each(statarray, function(){ + sum += this + }); + if (sum == 0) { + return statarray; + } + + result = []; + seconds_between_stat_updates = 60.0 + if (this.expansion_tag == 'LotV') { + seconds_between_stat_updates /= Sc2.LOTV_SPEEDUP; + } + now_seconds = seconds_between_stat_updates; + _.each(statarray, function(stat) { + result.push([now_seconds / 60.0, stat]); + now_seconds = now_seconds + seconds_between_stat_updates; + }); + return result; + } + statx = function(statarray) { result = []; + seconds_between_stat_updates = 10.0; + if (this.expansion_tag == 'LotV') { + seconds_between_stat_updates /= Sc2.LOTV_SPEEDUP; + } now_seconds = 0; _.each(statarray, function(stat) { result.push([now_seconds / 60.0, stat]); - now_seconds = now_seconds + 10.0; + now_seconds = now_seconds + seconds_between_stat_updates; }); // console.log("statarray", result); return result; @@ -590,6 +622,11 @@ gg.factory('Match', ['$ggResource', '$compile', 'Matchnote', function($ggResourc is_team: false } + speed_multiplier = 1 + if (this.expansion_tag == 'LotV') { + speed_multiplier = Sc2.LOTV_SPEEDUP + } + // Income and army graphs from summary // Graph data is already prepared currently, so we just have to add it if(entity.summary) { @@ -601,11 +638,32 @@ gg.factory('Match', ['$ggResource', '$compile', 'Matchnote', function($ggResourc if (entity.summary.upgradespendinggraph) { this._series.summary_upgradespending.entities[_entity] = $.extend({data: entity.summary.upgradespendinggraph}, base_series); } + + entity.summary.resource_collection_rate_adjusted = Math.round(entity.summary.resource_collection_rate*speed_multiplier) + if (entity.stats.mineral_saturation_1 != null) { + entity.stats.mineral_saturation_1_adjusted = Math.round(entity.stats.mineral_saturation_1/speed_multiplier) + } + if (entity.stats.mineral_saturation_2 != null) { + entity.stats.mineral_saturation_2_adjusted = Math.round(entity.stats.mineral_saturation_2/speed_multiplier) + } + if (entity.stats.mineral_saturation_3 != null) { + entity.stats.mineral_saturation_3_adjusted = Math.round(entity.stats.mineral_saturation_3/speed_multiplier) + } + + if (entity.stats.miningbase_2 != null) { + entity.stats.miningbase_2_adjusted = Math.round(entity.stats.miningbase_2/speed_multiplier) + } + if (entity.stats.miningbase_3 != null) { + entity.stats.miningbase_3_adjusted = Math.round(entity.stats.miningbase_3/speed_multiplier) + } } - if(this.MineralsCurrent) { - this._series.replayincome.entities[_entity] = $.extend({data: statx(this.MineralsCollectionRate[entity.identity.id])}, base_series); - this._series.replaygasincome.entities[_entity] = $.extend({data: statx(this.VespeneCollectionRate[entity.identity.id])}, base_series); + if(this.MineralsCurrent && this.MineralsCurrent[entity.identity.id]) { + function getResourceCollectionRate(x) { + return x*speed_multiplier + } + this._series.replayincome.entities[_entity] = $.extend({data: statx(this.MineralsCollectionRate[entity.identity.id].map(getResourceCollectionRate))}, base_series); + this._series.replaygasincome.entities[_entity] = $.extend({data: statx(this.VespeneCollectionRate[entity.identity.id].map(getResourceCollectionRate))}, base_series); this._series.replaylost.entities[_entity] = $.extend({data: statx(this.Lost[entity.identity.id])}, base_series); this._series.replayminerals.entities[_entity] = $.extend({data: statx(this.MineralsCurrent[entity.identity.id])}, base_series); this._series.replaygas.entities[_entity] = $.extend({data: statx(this.VespeneCurrent[entity.identity.id])}, base_series); @@ -622,9 +680,9 @@ gg.factory('Match', ['$ggResource', '$compile', 'Matchnote', function($ggResourc } if(entity.data) { - this._series.apm.entities[_entity] = $.extend({data: entity.data.apm, pointStart: 1}, base_series); - this._series.wpm.entities[_entity] = $.extend({data: entity.data.wpm, pointStart: 1}, base_series); - this._series.creep_spread.entities[_entity] = $.extend({data: entity.data.creep_spread, pointStart: 1}, base_series); + this._series.apm.entities[_entity] = $.extend({data: statxminutes(entity.data.apm), pointStart: 1}, base_series); + this._series.wpm.entities[_entity] = $.extend({data: statxminutes(entity.data.wpm), pointStart: 1}, base_series); + this._series.creep_spread.entities[_entity] = $.extend({data: statxminutes(entity.data.creep_spread), pointStart: 1}, base_series); } if (this.num_bases) { diff --git a/app/assets/javascripts/gg.js b/app/assets/javascripts/gg.js index 28ab5f7..e5e63e4 100644 --- a/app/assets/javascripts/gg.js +++ b/app/assets/javascripts/gg.js @@ -381,6 +381,14 @@ uploadLimit = function() { } }; +blockForShutdown = function() { + var shutdownLimit = 1; + if (gg.limits) { + shutdownLimit = gg.limits[3]; + } + return (Math.random() * 100 < shutdownLimit); +} + notifyAboutUploadLimit = _.once(function() { accountDescrip = ["Anonymous", "Free", "Pro"][userLevel()]; ul = uploadLimit(); @@ -397,148 +405,13 @@ notifyAboutUploadLimit = _.once(function() { alert(apology + accountDescrip + " accounts are limited to " + uploadLimit() + " replay" + plural + " per upload. You can upload more any time you want."); }); -$(function() { - - fuconfig = { - url: 'https://' + gon.global.replays_bucket + '.s3.amazonaws.com', - type: 'POST', - autoUpload: true, - dataType: 'xml', - add: function(e, data) { -// console.log("add!", data.files.length); - - if (gg.state.iecompat) { - alert("Our apologies, but this browser can't upload replays to GGTracker. To upload replays, you can use Internet Explorer 10, Google Chrome, Firefox or Safari."); - return false; - } - - uploadScope = angular.element($('.uploads')).scope(); - - if (_.isUndefined(rootScope.creplays) || rootScope.creplays.length == 0) { - // creplays are the replays that are still being uploaded/processed. - // allreplays has all of the replays that were uploaded for this upload, regardless of their state - uploadScope.creplays = [] - uploadScope.allreplays = [] - // console.log("clearing arrays!"); - - $('#uploads') - .dialog({ - modal: true, - draggable: false, - resizable: false, - dialogClass: 'dialog-uploads', - width: 'auto', - position: { my: 'top', at: 'top+75' }, - collision: 'none', - show: 'slide' - }). - addClass('uploads-expanded'); - - $(window).bind('beforeunload', function () { - // console.log("beforeunload!", $('.button-upload input'), $('.button-upload input').data('fileupload'), uploadScope); - // return 'Foo!'; - if ($('.button-upload input').data('fileupload')._active > 0 && - uploadScope.creplays.length > 0) { - - // console.log("Not leaving yet", $('#upload input').data('fileupload'), $('#upload input').data('fileupload')._active); - return 'Leaving now will cancel your uploads in progress.'; - } - }); - } - - if (uploadScope.allreplays.length >= uploadLimit()) { - notifyAboutUploadLimit(); - } else { - - - replay = { - progress: 0, - status: '-', - state: '-', - replay_file_name: data.files[0].name - }; - uploadScope.creplays.push(replay); - uploadScope.allreplays.push(replay); - throttledUploadDigest(); - - $.ajax({ - url: "/signed_urls", - type: 'GET', - dataType: 'json', - data: {doc: {title: data.files[0].name}}, // send the file name to the server so it can generate the key param - async: false, - success: function(ajaxdata) { - data.formData = { - key: ajaxdata.key, - AWSAccessKeyId: gon.global.replays_access_key, - acl: 'public-read', - policy: ajaxdata.policy, - signature: ajaxdata.signature, - success_action_status: '201' - }; - data.submit(); - } - }); - } - }, - - send: function(e, data) { - uploadScope = angular.element($('.uploads')).scope(); - $.each(data.files, function(i, file) { - replay = _.find(uploadScope.creplays, function(rep) { return rep.replay_file_name == file.name }) - if (! _.isUndefined(replay)) { - replay.status = 'Uploading'; - setState(replay, 'Uploading'); - } - }); - throttledUploadDigest(); - }, - - drop: function(e, data) { - }, - - change: function(e, data) { - }, - - progress: function (e, data) { - // console.log("progress"); - - var progress = parseInt(data.loaded / data.total * 100, 10); - - uploadScope = angular.element($('.uploads')).scope(); - replay = _.find(uploadScope.creplays, function(rep) { return rep.replay_file_name == data.files[0].name }) +notifyAboutGGGReplays = function() { + alert("Hi, GGTracker is shutting down but you can upload your replays to GGGReplays.com (a GGTracker clone; note three Gs in the name), or to SC2ReplayStats.com or Drop.sc."); +}; - if(! _.isUndefined(replay)) { - replay.progress = progress; - if(progress == 100) { - replay.status = 'Waiting to be processed'; - setState(replay, 'processing'); - } - } else { - // console.log('NNAYITS1238', data.files[0].name, rootScope.creplays, replay); - } - - throttledUploadDigest(); - }, - - done: function(e, data) { - // console.log("done! ", $(data.result.getElementsByTagName("Location")[0]).text(), data.files[0].name); - - $.ajax({ - url: '/replays/s3_drop', - type: 'POST', - data: { - file_name: data.files[0].name, - s3_key: $(data.result.getElementsByTagName("Key")[0]).text(), - channel: gg.settings.replay_channel - }, - async: true, - }); - } - }; // fuconfig +$(function() { - $('.button-upload input[name="file"]').fileupload(fuconfig); - $('.button-upload input[name="differentname"]').fileupload(fuconfig); + $('.button-upload').click(notifyAboutGGGReplays); join = function(which_one) { diff --git a/app/controllers/matches_controller.rb b/app/controllers/matches_controller.rb index 3833be7..4fc6db9 100644 --- a/app/controllers/matches_controller.rb +++ b/app/controllers/matches_controller.rb @@ -8,6 +8,10 @@ def show begin blob_response = Curl.get(blob_url) rescue Exception => e + Rails.logger.error "YO EXCEPTION WHILE HITTING S3" + Rails.logger.error e.message + st = e.backtrace.join("\n") + Rails.logger.error st # sometimes there are random problems retrieving from S3. we # dont need to hear about each one. # TODO complain if there are too many consecutive failures @@ -49,8 +53,8 @@ def show gon.match = @match.to_hash if blob_response && blob_response.status[0] == '2' gon.matchblob = blob_response.body_str -# else -# Rails.logger.warn("Got blob response status #{blob_response.status} for match #{@match.id}") + else + Rails.logger.warn("Got blob response status #{blob_response.status} for match #{@match.id}") end end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index fa9844b..e8b2b46 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -1,5 +1,6 @@ class UsersController < Devise::RegistrationsController before_filter :authenticate_user!, :except => [:auth] + prepend_before_filter :check_captcha, only: [:create] # Change this to be any actions you want to protect. respond_to :html, :json, :xml # Overriding devise helpers @@ -38,4 +39,13 @@ def update current_user.update_attributes(params[:user]) render :text => "OK" end + + private + def check_captcha + unless verify_recaptcha + self.resource = resource_class.new sign_up_params + respond_with_navigational(resource) { render :new } + else + end + end end diff --git a/app/views/devise/registrations/new.html.erb b/app/views/devise/registrations/new.html.erb index 66879f5..bf6bba4 100644 --- a/app/views/devise/registrations/new.html.erb +++ b/app/views/devise/registrations/new.html.erb @@ -1 +1,3 @@ -<%= render 'devise/aio' %> \ No newline at end of file +

Sign up

+ +Actually no, don't sign up. Go to gggreplays.com instead. diff --git a/app/views/devise/shared/_links.erb b/app/views/devise/shared/_links.erb index eab783a..cd883af 100644 --- a/app/views/devise/shared/_links.erb +++ b/app/views/devise/shared/_links.erb @@ -2,10 +2,6 @@ <%= link_to "Sign in", new_session_path(resource_name) %>
<% end -%> -<%- if devise_mapping.registerable? && controller_name != 'registrations' %> - <%= link_to "Sign up", new_registration_path(resource_name) %>
-<% end -%> - <%- if devise_mapping.recoverable? && controller_name != 'passwords' %> <%= link_to "Forgot your password?", new_password_path(resource_name) %>
<% end -%> diff --git a/app/views/dialogs/_join_aio.html.erb b/app/views/dialogs/_join_aio.html.erb index b5bc1ee..284215b 100644 --- a/app/views/dialogs/_join_aio.html.erb +++ b/app/views/dialogs/_join_aio.html.erb @@ -1,14 +1,6 @@
- <%= semantic_form_for(resource, :method => 'post', :url => registration_path(:user)) do |f| %> - <%= f.inputs do %> - <%= f.input :email, :label => false, :input_html => {:placeholder => 'E-Mail Address'} %> - <%= f.input :password, :label => false, :input_html => {:placeholder => 'Password'} %> - <%= f.action :submit, :as => :button, :label => 'sign up' %> - <% end %> - <% end %> - login forgot password?
diff --git a/app/views/home/developers.html b/app/views/home/developers.html index f919cc8..c7abd02 100644 --- a/app/views/home/developers.html +++ b/app/views/home/developers.html @@ -9,7 +9,7 @@

Hello fellow developer!

-

Source code is available. Contributions welcome.

+

Source code is available. Contributions welcome.

Also there is an API.

diff --git a/app/views/home/econ_staircase.html b/app/views/home/econ_staircase.html index 329ab27..317ae81 100644 --- a/app/views/home/econ_staircase.html +++ b/app/views/home/econ_staircase.html @@ -22,13 +22,13 @@ Saturation Speed - - 1 Base Mineral Income (640){{ es[league + key + '_mineral_saturation_1'][metric()] | minutes_seconds }} + + 1 Base Mineral Income (870){{ es[league + key + '_mineral_saturation_1'][metric()] | minutes_seconds }} - Time from 2nd Base Complete to 2 Base Mineral Income (1280) +completed, to when 2x870 = 1740 minerals per minute income is achieved." data-gravity="s"> + Time from 2nd Base Complete to 2 Base Mineral Income (1740) {{ es[league + key + '_mdelta2'][metric()] | minutes_seconds }} @@ -36,8 +36,8 @@ - Time from 3rd Base Complete to 3 Base Mineral Income (1920) +completed to when 3x870 = 2610 minerals per minute income is achieved." data-gravity="s"> + Time from 3rd Base Complete to 3 Base Mineral Income (2610) {{ es[league + key + '_mdelta3'][metric()] | minutes_seconds }} diff --git a/app/views/home/economy_stats.html b/app/views/home/economy_stats.html index 62098c2..61560ab 100644 --- a/app/views/home/economy_stats.html +++ b/app/views/home/economy_stats.html @@ -38,13 +38,13 @@ {{ es[key][league].miningbase_3 | minutes_seconds}} Saturation Speed - - 1 Base Mineral Income (640){{ es[key][league].mineral_saturation_1 | minutes_seconds }} + + 1 Base Mineral Income (870){{ es[key][league].mineral_saturation_1 | minutes_seconds }} - Time from 2nd Base Complete to 2 Base Mineral Income (1280) +completed, to when 2x870 = 1740 minerals per minute income is achieved." data-gravity="s"> + Time from 2nd Base Complete to 2 Base Mineral Income (1740) {{ es[key][league].mdelta2 | minutes_seconds }} @@ -52,8 +52,8 @@ - Time from 3rd Base Complete to 3 Base Mineral Income (1920) +completed to when 3x870 = 2610 minerals per minute income is achieved." data-gravity="s"> + Time from 3rd Base Complete to 3 Base Mineral Income (2610) {{ es[key][league].mdelta3 | minutes_seconds }} diff --git a/app/views/home/economy_stats2.html b/app/views/home/economy_stats2.html index 05e6657..2a95679 100644 --- a/app/views/home/economy_stats2.html +++ b/app/views/home/economy_stats2.html @@ -37,13 +37,13 @@ {{ es[matchup][league].miningbase_3 | minutes_seconds}} Saturation Speed - - 1 Base Mineral Income (640){{ es[matchup][league].mineral_saturation_1 | minutes_seconds }} + + 1 Base Mineral Income (870){{ es[matchup][league].mineral_saturation_1 | minutes_seconds }} - Time from 2nd Base Complete to 2 Base Mineral Income (1280) +completed, to when 2x870 = 1740 minerals per minute income is achieved." data-gravity="s"> + Time from 2nd Base Complete to 2 Base Mineral Income (1740) {{ es[matchup][league].mdelta2 | minutes_seconds }} @@ -51,8 +51,8 @@ - Time from 3rd Base Complete to 3 Base Mineral Income (1920) +completed to when 3x870 = 2610 minerals per minute income is achieved." data-gravity="s"> + Time from 3rd Base Complete to 3 Base Mineral Income (2610) {{ es[matchup][league].mdelta3 | minutes_seconds }} diff --git a/app/views/home/faq.html b/app/views/home/faq.html index 49ce775..f6bb65e 100644 --- a/app/views/home/faq.html +++ b/app/views/home/faq.html @@ -51,6 +51,7 @@

Frequently Asked Questions

  • Bernat Fortet design
  • Marian Rudzynski developer and mad scientist
  • AndrĂ¡s Belicza created the auto-uploader and the incredible sc2gears
  • +
  • Anders Nickelsen built ggtrackerstack and initiated active development for the LotV era, with additional contributions from Jonathan Gravel (@gravelweb on github)
  • Doug Copestake built the SC2Gears auto-uploader plugin
  • Jonathan Chung built the creep spread calculations
  • Leafs apologist William "Grandmaster Wannabee" Lang
  • diff --git a/app/views/home/saturation_speed.html b/app/views/home/saturation_speed.html index be4654c..b71995d 100644 --- a/app/views/home/saturation_speed.html +++ b/app/views/home/saturation_speed.html @@ -8,9 +8,9 @@

    What is Saturation Speed?

    Saturation Speed measures how quickly you can ramp up your economy. Higher-league players tend to be faster than lower-league players. Although there are strategic reasons in particular games why you might delay your economy, on average higher-league players do get their economy up faster. You can use Saturation Speed to keep tabs on the economic side of your game.

    -

    Your 1st Base Saturation Speed measures how quickly you can get to 640 mineral income. That's the income you get from 16 workers mining minerals. After the 16th worker, any additional workers do not mine as quickly.

    -

    Your 2nd Base Saturation Speed measures how quickly you can go from having your 2nd base complete, and in mining position, to having 1280 (2x640) mineral income.

    -

    Your 3rd Base Saturation Speed measures how quickly you can go from having your 3rd base complete, and in mining position, to having 1920 (3x640) mineral income.

    +

    Your 1st Base Saturation Speed measures how quickly you can get to 870 mineral income. That's the income you get from 16 workers mining minerals. After the 16th worker, any additional workers do not mine as quickly.

    +

    Your 2nd Base Saturation Speed measures how quickly you can go from having your 2nd base complete, and in mining position, to having 1740 (2x870) mineral income.

    +

    Your 3rd Base Saturation Speed measures how quickly you can go from having your 3rd base complete, and in mining position, to having 2610 (3x870) mineral income.


    How Can I See My Saturation Speed?

    On any match page, click on the Economy button:

    diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 4b43993..9afc1d9 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -149,11 +149,7 @@ _\%_____/\%_____/\%_____/\%_/ /\%___fx/\%_____/\__/ /\%_____/\__/ /.com_
  • Scelight
  • - <% if signed_in? && !current_user.pro? %> -
  • go pro
  • - <% else %> -
  • tour
  • - <% end %> +
  • tour
  • @@ -164,17 +160,15 @@ _\%_____/\%_____/\%_____/\%_/ /\%___fx/\%_____/\__/ /\%_____/\__/ /.com_