caddie 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/app/models/caddie/crest_data_retriever.rb +1 -1
  3. data/app/models/caddie/crest_price_history_update.rb +11 -3
  4. data/app/models/caddie/m_threaded_updater.rb +38 -1
  5. data/app/models/crest_price_history.rb +4 -0
  6. data/db/migrate/20160725091214_add_indexes_to_crest_price_history_update.rb +8 -0
  7. data/lib/caddie/version.rb +1 -1
  8. data/lib/tasks/caddie_tasks.rake +8 -3
  9. data/lib/tasks/m_threaded_updater_test.rake +53 -0
  10. data/test/dummy/app/models/eve_item.rb +53 -0
  11. data/test/dummy/app/models/region.rb +4 -0
  12. data/test/dummy/config/database.yml +3 -3
  13. data/test/dummy/db/migrate/20150410082132_create_eve_items.rb +11 -0
  14. data/test/dummy/db/migrate/20150414095303_add_name_lowcase_to_eve_item.rb +5 -0
  15. data/test/dummy/db/migrate/20150416154256_rename_eve_item_id.rb +5 -0
  16. data/test/dummy/db/migrate/20150417135716_add_cost_to_eve_item.rb +5 -0
  17. data/test/dummy/db/migrate/20150906171550_add_cpp_market_group_id_to_eve_item.rb +6 -0
  18. data/test/dummy/db/migrate/20150909162142_add_involved_in_blueprint_to_eve_item.rb +5 -0
  19. data/test/dummy/db/migrate/20150910074544_create_regions.rb +11 -0
  20. data/test/dummy/db/migrate/20150910080646_create_crest_price_histories.rb +18 -0
  21. data/test/dummy/db/schema.rb +19 -299
  22. data/test/dummy/log/development.log +446 -54107
  23. data/test/dummy/log/test.log +46048 -0
  24. data/test/factories/caddie/crest_price_history_updates.rb +4 -0
  25. data/test/factories/caddie/eve_items.rb +54 -0
  26. data/test/factories/caddie/regions.rb +33 -0
  27. data/test/models/caddie/crest_price_history_update_test.rb +19 -4
  28. data/test/models/caddie/m_threaded_updater_test.rb +26 -0
  29. data/test/test_helper.rb +10 -0
  30. metadata +72 -30
  31. data/app/models/crest_price_history.rb +0 -1
  32. data/app/models/eve_item.rb +0 -1
  33. data/app/models/region.rb +0 -1
  34. data/test/fixtures/caddie/crest_price_history_update_logs.yml +0 -11
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9ae68e873fe5e7e634110966042264a149da5f8b
4
- data.tar.gz: 18100d92938dc47517cbcb0b058c4b309e2cbe96
3
+ metadata.gz: dec5dc1e0bf8562abd8ce5afcbefcb44ef4d0f4c
4
+ data.tar.gz: b27051154d8eb7d652ad9dc79b0f91397ca6fc75
5
5
  SHA512:
6
- metadata.gz: f7a9babedd01608b5b19751525e57fe7127e056b7410df5c130d783c41cd3e6c9f1620e7b5c21e13c046f437b4730d0ca0779288b4d5c3186e55502c23f1ddf6
7
- data.tar.gz: f9ff63e670a1bd2bc334c405b4cb9ad47a944bd23ee7950a2fbfe3925bc637111eeec735400ef091743ab0c8a98d4c730b27f78e44557112f42f2aa4bd71cf31
6
+ metadata.gz: 0d0b8305fd526f1f677d77554b466b6264f95cb6fe1ad2b586a5cc4e82e8963cae7ce45dd2cd10b6d475ef4545175d3e2c5818a4985416a54158c69b0e8d6543
7
+ data.tar.gz: 29b46515c9bfd855198f712468ea687d7441dc90635c004e7d86c9313a51735a296e1cc84b94864f3d043e7e2b328dc7b9a386c352860852b77162e3d825c921
@@ -7,7 +7,7 @@ module Caddie
7
7
 
8
8
  def get_markets( region_id, type_id )
9
9
 
10
- debug = ENV[ 'CADDIE_DEBUG_MODE' ] && ENV[ 'CADDIE_DEBUG_MODE' ].downcase == 'true'
10
+ debug = ENV[ 'EBS_DEBUG_MODE' ] && ENV[ 'EBS_DEBUG_MODE' ].downcase == 'true'
11
11
 
12
12
  type_url = "https://crest-tq.eveonline.com/inventory/types/#{type_id}"
13
13
  items, connections_count = get_multipage_data( "market/#{region_id}/history/?type=#{type_url}", debug )
@@ -8,18 +8,26 @@ module Caddie
8
8
 
9
9
  extend Caddie::CrestDataRetriever
10
10
 
11
+ NB_THREADS=4
12
+
11
13
  def self.update
12
14
  current_path = File.dirname( __FILE__ )
13
15
  request = File.open( "#{current_path}/update_table.sql" ).read
14
16
  ActiveRecord::Base.connection.execute( request )
15
17
  end
16
18
 
17
- def self.feed_price_histories
19
+ def self.feed_price_histories( thread_id = nil )
18
20
  total_connections_counts = 0
19
21
  total_inserts = 0
20
22
  date_deb = Time.now
21
23
 
22
- daily_operations_list.joins( :eve_item, :region ).pluck( :eve_item_id, :region_id, :cpp_eve_item_id, :cpp_region_id ).each do |row|
24
+ dol = daily_operations_list
25
+
26
+ # pp dol.to_a
27
+ dol = dol.where( thread_slice_id: thread_id ) if thread_id
28
+
29
+ # puts dol.reload.count
30
+ dol.joins( :eve_item, :region ).pluck( :eve_item_id, :region_id, :cpp_eve_item_id, :cpp_region_id ).each do |row|
23
31
 
24
32
  # puts "Processing row = #{row}"
25
33
 
@@ -30,6 +38,7 @@ module Caddie
30
38
 
31
39
  ActiveRecord::Base.transaction do
32
40
 
41
+ # TODO : This operation is extremely costly. Keep the last updated timestamp and use it to shorten insert.
33
42
  # puts 'About to reject already used lines'
34
43
  timestamps = CrestPriceHistory.where( region_id: region_id, eve_item_id: eve_item_id ).pluck( :day_timestamp ).to_set
35
44
  items.reject! do |item|
@@ -39,7 +48,6 @@ module Caddie
39
48
  end
40
49
  # puts 'Lines rejected'
41
50
 
42
-
43
51
  items.each do |item_data|
44
52
 
45
53
  date_info = DateTime.parse( item_data['date'] )
@@ -1,6 +1,43 @@
1
- class MThreadedUpdater
1
+ require 'thwait'
2
+ require 'matrix'
3
+
4
+ class Caddie::MThreadedUpdater
2
5
 
3
6
  # TODO : - split the work in database using thread_slice_id (set numbers : 1 .. MAX_THREADS)
4
7
  # TODO : Then run N threads each threads get the records associated to it's number
5
8
 
9
+ def initialize( max_threads, daily_operations_list )
10
+ @max_threads = max_threads
11
+ @daily_operations_list = daily_operations_list
12
+ end
13
+
14
+ def feed_price_histories_threaded
15
+ Thread::abort_on_exception = true
16
+ threads = []
17
+ 0.upto( @max_threads-1 ).each do |thread_id|
18
+ threads << Thread.new {
19
+ puts Thread.inspect
20
+ Thread.current[:timings] = Caddie::CrestPriceHistoryUpdate.feed_price_histories( thread_id )
21
+ }
22
+ end
23
+ result = []
24
+ ThreadsWait.all_waits( *threads ) do |t|
25
+ thread_result = t[:timings]
26
+ result << thread_result
27
+ end
28
+ tmp = result.map { |a| Vector[*a] }.inject(:+)
29
+ tmp.to_a
30
+ end
31
+
32
+ def split_work_for_threads
33
+ ids = @daily_operations_list.pluck( :id )
34
+ ActiveRecord::Base.transaction do
35
+ slice_size = ids.count/@max_threads + 1
36
+ ( 0 ... @max_threads ).each do |thread_id|
37
+ ids_slice = ids.shift( slice_size )
38
+ @daily_operations_list.where( id: ids_slice ).update_all( thread_slice_id: thread_id )
39
+ end
40
+ end
41
+ end
42
+
6
43
  end
@@ -0,0 +1,4 @@
1
+ class CrestPriceHistory < ActiveRecord::Base
2
+ belongs_to :region
3
+ belongs_to :eve_item
4
+ end
@@ -0,0 +1,8 @@
1
+ class AddIndexesToCrestPriceHistoryUpdate < ActiveRecord::Migration
2
+ def change
3
+ add_index :caddie_crest_price_history_updates, :nb_days
4
+ add_index :caddie_crest_price_history_updates, :process_queue
5
+ add_index :caddie_crest_price_history_updates, :next_process_date
6
+ add_index :caddie_crest_price_history_updates, :thread_slice_id
7
+ end
8
+ end
@@ -1,3 +1,3 @@
1
1
  module Caddie
2
- VERSION = '0.1.2'
2
+ VERSION = '0.2.0'
3
3
  end
@@ -6,14 +6,19 @@ namespace :caddie do
6
6
  start_time = Time.now
7
7
  feed_date = start_time.to_date
8
8
 
9
- puts 'About to compute crest_price_history_updates'
10
- Caddie::CrestPriceHistoryUpdate.update
9
+ unless ENV[ 'EBS_NO_HIST_UPDATE' ] && ENV[ 'EBS_NO_HIST_UPDATE' ].downcase == 'true'
10
+ puts 'About to compute crest_price_history_updates'
11
+ Caddie::CrestPriceHistoryUpdate.update
12
+ end
11
13
 
12
14
  end_update_time = Time.now
13
15
  update_planning_time = end_update_time - start_time
14
16
 
15
17
  puts 'About to feed crest_price_histories'
16
- total_inserts, total_connections, total_time = Caddie::CrestPriceHistoryUpdate.feed_price_histories
18
+ total_inserts, total_connections, total_time = Caddie::CrestPriceHistoryUpdate.feed_price_histories
19
+ th = Caddie::MThreadedUpdater.new( Caddie::CrestPriceHistoryUpdate::NB_THREADS, Caddie::CrestPriceHistoryUpdate.daily_operations_list )
20
+ th.split_work_for_threads
21
+ total_inserts, total_connections, total_time = th.feed_price_histories_threaded
17
22
  puts "#{total_inserts} insertions, #{total_connections} connections in #{total_time.round( 2 )} seconds. #{(total_connections/total_time).round( 2 )} co/sec"
18
23
 
19
24
  end_feeding_time = Time.now
@@ -0,0 +1,53 @@
1
+ require 'mocha/api'
2
+ require 'minitest'
3
+
4
+ include Mocha::API
5
+ include FactoryGirl::Syntax::Methods
6
+
7
+ require_relative '../../test/dummy/app/models/eve_item'
8
+ require_relative '../../test/dummy/app/models/region'
9
+ require_relative '../../test/factories/caddie/eve_items'
10
+ require_relative '../../test/factories/caddie/regions'
11
+ require_relative '../../app/models/caddie/crest_data_retriever'
12
+ require_relative '../../app/models/caddie/crest_price_history_update'
13
+ require_relative '../../test/factories/caddie/crest_price_history_updates'
14
+
15
+ # Regular test unit does not commit between insertions, this algo rely on database to split work between threads
16
+ # So we have to fake a test outside the test unit
17
+ namespace :test do
18
+
19
+ desc "M threaded uptader test"
20
+ task :m_threaded_uptader_test=> :environment do
21
+ if (ENV['RAILS_ENV'] == "test") # protect against execution in dev mode
22
+
23
+ Caddie::CrestPriceHistoryUpdate.stubs( :get_multipage_data ).returns( [ [], 5 ] )
24
+
25
+ Region.delete_all
26
+ EveItem.delete_all
27
+ Caddie::CrestPriceHistoryUpdate.delete_all
28
+
29
+ next_process_date = Time.now.to_date
30
+ region = create( :caddie_heimatar )
31
+ 1.upto( 53 ).each do
32
+ item = create( :caddie_eve_item )
33
+ create( :crest_price_history_update, region: region, eve_item: item, next_process_date: next_process_date )
34
+ end
35
+
36
+ th = Caddie::MThreadedUpdater.new( 4, Caddie::CrestPriceHistoryUpdate.daily_operations_list )
37
+ th.split_work_for_threads
38
+ timings = th.feed_price_histories_threaded
39
+ # pp timings
40
+ unless 53 == timings[1]/5
41
+ "Test failed : #{timings[1]/5} != 53"
42
+ else
43
+ puts 'Test passed'
44
+ end
45
+ else
46
+ puts 'Can be only executed in test env'
47
+ end
48
+
49
+ Region.delete_all
50
+ EveItem.delete_all
51
+ Caddie::CrestPriceHistoryUpdate.delete_all
52
+ end
53
+ end
@@ -0,0 +1,53 @@
1
+ # require 'open-uri'
2
+ # # require 'open-uri/cached'
3
+ require 'pp'
4
+
5
+ class EveItem < ActiveRecord::Base
6
+
7
+ # include Assert
8
+ # include ItemsInit::ItemSetupAndComp
9
+ # extend ItemsInit::ItemSetupAndCompSelf
10
+ # extend MultiplePriceRetriever
11
+ # extend Setup::UpdateEveItems
12
+
13
+ has_and_belongs_to_many :users
14
+ has_one :blueprint, dependent: :destroy
15
+ has_many :materials, through: :blueprint
16
+ has_many :components, through: :materials
17
+ belongs_to :market_group
18
+ has_many :crest_price_histories, dependent: :destroy
19
+ has_many :crest_prices_last_month_averages, dependent: :destroy
20
+
21
+ # Itemps containing non ascii characters
22
+ UNPROCESSABLE_ITEMS=[34457,34458,34459,34460,34461,34462,34463,34464,34465,34466,34467,34468,34469,34470,34471,34472,
23
+ 34473,34474,34475,34476,34477,34478,34479,34480,30952,32371,32372]
24
+
25
+ AVG_INDUSTRY_TAX = 0.11 # 10 % base + 1 % system costs (assuming players are smart enough to go in low cost systems)
26
+
27
+ def self.to_eve_item_id(cpp_eve_item_id)
28
+ eve_item=EveItem.where( 'cpp_eve_item_id=?', cpp_eve_item_id).first
29
+ eve_item ? eve_item.id : nil
30
+ end
31
+
32
+ def self.used_items
33
+ used_items, _ = User.get_used_items_and_trade_hubs
34
+ used_items
35
+ end
36
+
37
+ def single_unit_cost
38
+ (cost*(1+AVG_INDUSTRY_TAX))/blueprint.prod_qtt if cost && blueprint
39
+ end
40
+
41
+ def pcent_margin( price )
42
+ (price / single_unit_cost)-1 if price && single_unit_cost
43
+ end
44
+
45
+ def margin( price )
46
+ price - single_unit_cost if price && single_unit_cost
47
+ end
48
+
49
+ def full_batch_size
50
+ blueprint.nb_runs*blueprint.prod_qtt if blueprint
51
+ end
52
+
53
+ end
@@ -0,0 +1,4 @@
1
+ class Region < ActiveRecord::Base
2
+ has_many :trade_hubs
3
+ has_many :crest_prices_last_month_averages
4
+ end
@@ -9,11 +9,11 @@ default: &default
9
9
  timeout: 5000
10
10
  adapter: postgresql
11
11
  encoding: unicode
12
- username: eve_business_server
12
+ username: caddie
13
13
 
14
14
  development:
15
15
  <<: *default
16
- database: eve_business_server_dev
16
+ database: caddie_dev
17
17
 
18
18
 
19
19
  # Warning: The database defined as "test" will be erased and
@@ -21,4 +21,4 @@ development:
21
21
  # Do not set this db to the same as development or production.
22
22
  test:
23
23
  <<: *default
24
- database: eve_business_server_test
24
+ database: caddie_test
@@ -0,0 +1,11 @@
1
+ class CreateEveItems < ActiveRecord::Migration
2
+ def change
3
+ create_table :eve_items do |t|
4
+ t.integer :eve_item_id
5
+ t.string :name
6
+
7
+ t.timestamps
8
+ end
9
+ add_index :eve_items, :eve_item_id
10
+ end
11
+ end
@@ -0,0 +1,5 @@
1
+ class AddNameLowcaseToEveItem < ActiveRecord::Migration
2
+ def change
3
+ add_column :eve_items, :name_lowcase, :string
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class RenameEveItemId < ActiveRecord::Migration
2
+ def change
3
+ rename_column :eve_items, :eve_item_id, :cpp_eve_item_id
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class AddCostToEveItem < ActiveRecord::Migration
2
+ def change
3
+ add_column :eve_items, :cost, :float
4
+ end
5
+ end
@@ -0,0 +1,6 @@
1
+ class AddCppMarketGroupIdToEveItem < ActiveRecord::Migration
2
+ def change
3
+ add_column :eve_items, :cpp_market_group_id, :integer
4
+ add_index :eve_items, :cpp_market_group_id
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ class AddInvolvedInBlueprintToEveItem < ActiveRecord::Migration
2
+ def change
3
+ add_column :eve_items, :involved_in_blueprint, :bool, default: false, index: true
4
+ end
5
+ end
@@ -0,0 +1,11 @@
1
+ class CreateRegions < ActiveRecord::Migration
2
+ def change
3
+ create_table :regions do |t|
4
+ t.string :cpp_region_id, null: false
5
+ t.string :name, null: false
6
+
7
+ t.timestamps null: false
8
+ end
9
+ add_index :regions, :cpp_region_id, unique: true
10
+ end
11
+ end
@@ -0,0 +1,18 @@
1
+ class CreateCrestPriceHistories < ActiveRecord::Migration
2
+ def change
3
+ create_table :crest_price_histories do |t|
4
+ t.references :region, index: true, foreign_key: true, null: false
5
+ t.references :eve_item, index: true, foreign_key: true, null: false
6
+ t.string :day_timestamp, index: true, null: false
7
+ t.timestamp :history_date, null: false
8
+ t.column :order_count, :bigint
9
+ t.column :volume, :bigint
10
+ t.float :low_price
11
+ t.float :avg_price
12
+ t.float :high_price
13
+
14
+ t.timestamps null: false
15
+ end
16
+ add_index :crest_price_histories, [:region_id, :eve_item_id, :day_timestamp], unique: true, name: 'price_histories_all_keys_index'
17
+ end
18
+ end