tac_scribe 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ddf21892437d67f745cc10328223aae85ade3459fb8dfdc5f758658cc5af4676
4
- data.tar.gz: d71160d27dbc0a52b1b606c5b52ede5714a7ef1a7897bb18a93a3933003b393c
3
+ metadata.gz: f6540479b0949db23d8dcbfc7965a716d4909b7e03b314f9b1687b7b7b044e1b
4
+ data.tar.gz: 9c6ee7a6e020b81eea6cd809c043eb31f2353256a41463da5349ee78699d3f1b
5
5
  SHA512:
6
- metadata.gz: bd25300946c4fb0d98749097c3e115af921b407802ad88fa8d6d3fea8d98eb3bf59874137d4ec560497cf9c477872a7af900e449ac568400109d65dd25c2c6e6
7
- data.tar.gz: 56e62c543996a89203d85633094e745cc43193f4232d46790f8253df1fb3c407209e2d3d736f063be50625c29af319c1ad64f849c7761b1a268895447444edec
6
+ metadata.gz: 5236421e641674570e47e65c309ed12c0beff782cfd7fddea75d09687a4aa7660a445cc5249e2d8489f4a56df2cba8ec9fd76df1390b916053cd35ab9dc19f84
7
+ data.tar.gz: 3a500080c5d44f78c1bfd0914face93c40d318eb8721d7a2e0876a7e5cfdc9cfdddded214fe0f99da2fbcb356420d1319159f085cbcbdd2d61eac3064afaf4c3
data/CHANGELOG.md CHANGED
@@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.4.0]
10
+ ### Changed
11
+ - Switch to periodic writing to the database
12
+
9
13
  ## [0.3.0] - 2019-10-27
10
14
  ### Changed
11
15
  - Changed the command-line name to match gem
@@ -0,0 +1,118 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'georuby'
4
+ require 'sequel'
5
+ require 'sequel-postgis-georuby'
6
+ require 'singleton'
7
+ require 'concurrent-ruby'
8
+
9
+ module TacScribe
10
+ class Cache
11
+ include Singleton
12
+ include GeoRuby::SimpleFeatures
13
+
14
+ @@cache = Concurrent::Hash.new
15
+
16
+ attr_accessor :reference_latitude, :reference_longitude
17
+
18
+ def data
19
+ @@cache
20
+ end
21
+
22
+ def write_object(object)
23
+ if reference_latitude != 0 || reference_longitude != 0
24
+ localize_position(object)
25
+ end
26
+
27
+ id = object[:object_id]
28
+ object[:id] = id
29
+
30
+ cache_object = @@cache[id]
31
+
32
+ object[:position] = set_position(object, cache_object)
33
+
34
+ %i[object_id latitude longitude color country].each do |key|
35
+ object.delete(key)
36
+ end
37
+
38
+ if object[:coalition]
39
+ object[:coalition] = case object[:coalition]
40
+ when 'Allies'
41
+ 0
42
+ when 'Enemies'
43
+ 1
44
+ else
45
+ 2
46
+ end
47
+ end
48
+
49
+ if cache_object
50
+ object[:heading] = calculate_heading(cache_object, object)
51
+ cache_object.merge!(object)
52
+ else
53
+ object[:heading] = -1
54
+ cache_object = object
55
+ end
56
+
57
+ if !cache_object.key?(:altitude) || !cache_object[:altitude]
58
+ cache_object[:altitude] = 0
59
+ end
60
+ if !cache_object.key?(:coalition) || !cache_object[:coalition]
61
+ cache_object[:coalition] = 2
62
+ end
63
+
64
+ cache_object[:pilot] = nil unless cache_object.key?(:pilot)
65
+
66
+ cache_object[:group] = nil unless cache_object.key?(:group)
67
+
68
+ cache_object[:deleted] = false unless cache_object.key?(:deleted)
69
+
70
+ cache_object[:updated_at] = Time.now
71
+
72
+ @@cache[id] = cache_object
73
+ end
74
+
75
+ def delete_object(id)
76
+ @@cache[id][:deleted] = true if @@cache[id]
77
+ end
78
+
79
+ private
80
+
81
+ def localize_position(object)
82
+ if reference_latitude && object.key?(:latitude)
83
+ object[:latitude] = reference_latitude + object[:latitude]
84
+ end
85
+ if reference_longitude && object.key?(:longitude)
86
+ object[:longitude] = reference_longitude + object[:longitude]
87
+ end
88
+ end
89
+
90
+ def set_position(object, cache_object)
91
+ longitude = if object.key?(:longitude)
92
+ object[:longitude]
93
+ else
94
+ cache_object[:position].y
95
+ end
96
+
97
+ latitude = if object.key?(:latitude)
98
+ object[:latitude]
99
+ else
100
+ cache_object[:position].x
101
+ end
102
+
103
+ Point.from_x_y(longitude, latitude)
104
+ end
105
+
106
+ def calculate_heading(cache_object, object)
107
+ return cache_object[:heading] if cache_object[:position] == object[:position]
108
+
109
+ begin
110
+ cache_object[:position].bearing_to(object[:position]).to_i
111
+ rescue Math::DomainError => e
112
+ puts 'Could not calculate heading: ' + e.message
113
+ puts 'Old Position: ' + cache_object[:position].inspect
114
+ puts 'New Position: ' + object[:position].inspect
115
+ end
116
+ end
117
+ end
118
+ end
@@ -4,6 +4,7 @@ require 'json'
4
4
  require 'tacview_client'
5
5
  require 'set'
6
6
  require_relative 'datastore'
7
+ require_relative 'cache'
7
8
  require_relative 'event_queue'
8
9
  require_relative 'event_processor'
9
10
 
@@ -24,11 +25,13 @@ module TacScribe
24
25
  end
25
26
  Datastore.instance.connect
26
27
 
27
- @event_queue = EventQueue.new verbose_logging: verbose_logging
28
+ @event_queue = EventQueue.new
29
+
30
+ @verbose_logging = verbose_logging
28
31
 
29
32
  @populate_airfields = populate_airfields
30
33
  @thread_count = thread_count
31
- @processing_threads = []
34
+ @threads = []
32
35
  @whitelist = Set.new(IO.read(whitelist).split) if whitelist
33
36
 
34
37
  @client = TacviewClient::Client.new(
@@ -47,10 +50,12 @@ module TacScribe
47
50
  # for example
48
51
  def start_processing
49
52
  loop do
50
- kill_processing_threads
53
+ kill_threads
51
54
  @event_queue.clear
52
55
  Datastore.instance.truncate_table
53
56
  start_processing_threads
57
+ start_db_sync_thread
58
+ start_reporting_thread
54
59
  populate_airfields if @populate_airfields
55
60
  @client.connect
56
61
  # Rescuing reliably from Net::HTTP is a complete bear so rescue
@@ -65,21 +70,55 @@ module TacScribe
65
70
  end
66
71
  end
67
72
 
68
- def kill_processing_threads
69
- @processing_threads.each do |thr|
73
+ def kill_threads
74
+ @threads.each do |thr|
70
75
  thr.kill
71
76
  thr.join
72
77
  end
73
78
  end
74
79
 
75
80
  def start_processing_threads
76
- @thread_count.times do
77
- @processing_threads << Thread.new do
78
- EventProcessor.new(datastore: Datastore.instance,
81
+ @event_processor = EventProcessor.new(cache: Cache.instance,
82
+ datastore: Datastore.instance,
79
83
  event_queue: @event_queue,
80
- whitelist: @whitelist).start
84
+ whitelist: @whitelist)
85
+ event_processor_thread = Thread.new do
86
+ @event_processor.start
87
+ end
88
+ event_processor_thread.name = "Event Processor"
89
+ @threads << event_processor_thread
90
+ end
91
+
92
+ def start_db_sync_thread
93
+ db_write_thread = Thread.new do
94
+ loop do
95
+ sleep 1
96
+ deleted = Datastore.instance.write_objects(Cache.instance.data.values)
97
+ deleted.each { |id| Cache.instance.data.delete(id) }
98
+ end
99
+ end
100
+ db_write_thread.name = "Database Writing"
101
+ @threads << db_write_thread
102
+ end
103
+
104
+ def start_reporting_thread
105
+ return unless @verbose_logging
106
+
107
+ reporting_thread = Thread.new do
108
+ loop do
109
+ puts "#{Time.now.strftime('%FT%T')}\t" +
110
+ "Events Incoming: #{@event_queue.events_written}\t" +
111
+ "Processed: #{@event_processor.events_processed}\t" +
112
+ "Ignored: #{@event_processor.events_ignored}\t" +
113
+ "Queue Size: #{@event_queue.size}"
114
+ @event_queue.events_written = 0
115
+ @event_processor.events_processed = 0
116
+ @event_processor.events_ignored = 0
117
+ sleep 1
81
118
  end
82
119
  end
120
+ reporting_thread.name = "Reporting"
121
+ @threads << reporting_thread
83
122
  end
84
123
 
85
124
  def populate_airfields
@@ -52,24 +52,19 @@ module TacScribe
52
52
  @db[:units].truncate
53
53
  end
54
54
 
55
- def write_object(event, timestamp)
56
- unit = get_unit(event[:object_id])
57
-
58
- # Tacview omits values that don't change to save
59
- # data bandwidth and storage. If something has not changed then
60
- # use the old value
61
- current_position = get_position(event, unit)
62
-
63
- if unit
64
- update_unit(event, unit, current_position, timestamp)
65
- else
66
- insert_unit(event, current_position, timestamp)
67
- end
68
- end
69
-
70
- def delete_object(object_id)
71
- count = @db[:units].where(id: object_id).delete
72
- "Deleted #{object_id} #{object_id.class} - #{count}"
55
+ def write_objects(objects)
56
+ @db[:units].insert_conflict(
57
+ constraint: :units_pkey,
58
+ update: { position: Sequel[:excluded][:position],
59
+ altitude: Sequel[:excluded][:altitude],
60
+ heading: Sequel[:excluded][:heading],
61
+ updated_at: Sequel[:excluded][:updated_at],
62
+ deleted: Sequel[:excluded][:deleted] }
63
+ )
64
+ .multi_insert(objects)
65
+ deleted_ids = @db[:units].where(deleted: true).select_map(:id)
66
+ @db[:units].where(deleted: true).delete
67
+ deleted_ids
73
68
  end
74
69
 
75
70
  private
@@ -85,56 +80,5 @@ module TacScribe
85
80
  "/#{@configuration.database}"
86
81
  end
87
82
  end
88
-
89
- def get_unit(id)
90
- @db[:units].where(id: id).first
91
- end
92
-
93
- def update_unit(event, unit, current_position, timestamp)
94
- heading = calculate_heading(unit[:position],
95
- current_position,
96
- unit[:heading])
97
-
98
- @db[:units].where(id: event[:object_id]).update(
99
- position: current_position[:lat_lon],
100
- altitude: current_position[:altitude],
101
- heading: heading,
102
- updated_at: timestamp
103
- )
104
- end
105
-
106
- def insert_unit(event, current_position, timestamp)
107
- @db[:units].insert(id: event[:object_id],
108
- position: current_position[:lat_lon],
109
- altitude: current_position[:altitude],
110
- type: event[:type],
111
- name: event[:name],
112
- group: event[:group],
113
- pilot: event[:pilot],
114
- coalition: event[:coalition] == 'Allies' ? 0 : 1,
115
- updated_at: timestamp)
116
- end
117
-
118
- def get_position(event, unit)
119
- {
120
- lat_lon: Point.from_x_y(
121
- event.fetch(:longitude) { unit ? unit[:position].y : nil },
122
- event.fetch(:latitude) { unit ? unit[:position].x : nil }
123
- ),
124
- altitude: event.fetch(:altitude) { unit ? unit[:altitude] : nil }
125
- }
126
- end
127
-
128
- def calculate_heading(old_position, current_position, current_heading)
129
- return current_heading if old_position == current_position[:lat_lon]
130
-
131
- begin
132
- old_position.bearing_to(current_position[:lat_lon]).to_i
133
- rescue Math::DomainError => e
134
- puts 'Could not calculate heading: ' + e.message
135
- puts 'Old Position: ' + old_position.inspect
136
- puts 'New Position: ' + current_position.inspect
137
- end
138
- end
139
83
  end
140
84
  end
@@ -3,17 +3,22 @@
3
3
  require 'tacview_client/base_processor'
4
4
  require 'time'
5
5
  require 'concurrent-ruby'
6
- require_relative 'datastore'
6
+ require_relative 'cache'
7
7
 
8
8
  module TacScribe
9
9
  # Processes the events emitted by the Ruby Tacview Client
10
10
  class EventProcessor
11
11
  @@ignored_units = Concurrent::Set.new
12
12
 
13
- def initialize(datastore:, event_queue:, whitelist: nil)
13
+ attr_accessor :events_processed, :events_ignored
14
+
15
+ def initialize(cache:, datastore:, event_queue:, whitelist: nil)
16
+ @cache = cache
14
17
  @datastore = datastore
15
18
  @event_queue = event_queue
16
19
  @whitelist = whitelist
20
+ self.events_processed = 0
21
+ self.events_ignored = 0
17
22
  end
18
23
 
19
24
  def start
@@ -55,45 +60,33 @@ module TacScribe
55
60
  # format.
56
61
  # @option event [BigDecimal] :altitude The object altitude above sea level
57
62
  # in meters to 1 decimal place.
58
- def update_object(event, time)
59
- return if @@ignored_units.include?(event[:object_id])
63
+ def update_object(event, _time)
64
+ if @@ignored_units.include?(event[:object_id])
65
+ self.events_ignored += 1
66
+ return
67
+ end
60
68
 
61
69
  if @whitelist && event[:type] && !@whitelist.include?(event[:type])
62
70
  @@ignored_units << event[:object_id]
71
+ self.events_ignored += 1
63
72
  return
64
73
  end
65
74
 
66
- if @event_queue.reference_latitude || @event_queue.reference_longitude
67
- localize_position(event)
68
- end
69
-
70
- @datastore.write_object(event, time)
75
+ self.events_processed += 1
76
+ @cache.write_object(event)
71
77
  end
72
78
 
73
79
  # Process a delete event for an object
74
80
  #
75
- # @param object_id [String] A hexadecimal number representing the object
76
- # ID
77
- def delete_object(object_id)
78
- return if @@ignored_units.delete?(object_id)
79
-
80
- @datastore.delete_object(object_id)
81
- end
82
-
83
- # If we have reference lat/long then use that as a base and update the event
84
- # position
85
- def localize_position(event)
86
- # There is no combination of layouts for these lines that doesn' trip
87
- # at least one rubocop cop so just ignore the guard clause. The best
88
- # one is using an inline if but that breaks the line length.
89
- # rubocop:disable Style/GuardClause
90
- if event[:latitude]
91
- event[:latitude] = @event_queue.reference_latitude + event[:latitude]
92
- end
93
- if event[:longitude]
94
- event[:longitude] = @event_queue.reference_longitude + event[:longitude]
81
+ # @param id [String] A hexadecimal number representing the object ID
82
+ def delete_object(id)
83
+ if @@ignored_units.delete?(id)
84
+ self.events_processed += 1
85
+ return
86
+ else
87
+ self.events_processed += 1
88
+ @cache.delete_object(id)
95
89
  end
96
- # rubocop:enable Style/GuardClause
97
90
  end
98
91
  end
99
92
  end
@@ -6,32 +6,23 @@ require 'time'
6
6
  module TacScribe
7
7
  # Processes the events emitted by the Ruby Tacview Client
8
8
  class EventQueue < TacviewClient::BaseProcessor
9
- attr_accessor :reference_latitude, :reference_longitude
10
9
 
11
- def initialize(verbose_logging:)
12
- @verbose_logging = verbose_logging
13
- @events = Queue.new
14
- @event_write = 0
15
- @event_read = 0
16
-
17
- return unless verbose_logging == true
10
+ attr_accessor :events_written
18
11
 
19
- Thread.new do
20
- loop do
21
- puts "#{Time.now.strftime('%FT%T')} - Queue Size: #{@events.size} \t Events Added: #{@event_write} \t Events Processed: #{@event_read}"
22
- @event_write = 0
23
- @event_read = 0
24
- sleep 1
25
- end
26
- end
12
+ def initialize
13
+ @events = Queue.new
14
+ self.events_written = 0
27
15
  end
28
16
 
29
17
  def clear
30
18
  @events.clear
31
19
  end
32
20
 
21
+ def size
22
+ @events.size
23
+ end
24
+
33
25
  def get_event
34
- @event_read += 1
35
26
  @events.shift
36
27
  end
37
28
 
@@ -53,7 +44,7 @@ module TacScribe
53
44
  # @option event [BigDecimal] :altitude The object altitude above sea level
54
45
  # in meters to 1 decimal place.
55
46
  def update_object(event)
56
- @event_write += 1
47
+ self.events_written +=1
57
48
  @events << { type: :update_object, event: event, time: @time }
58
49
  end
59
50
 
@@ -62,7 +53,7 @@ module TacScribe
62
53
  # @param object_id [String] A hexadecimal number representing the object
63
54
  # ID
64
55
  def delete_object(object_id)
65
- @event_write += 1
56
+ self.events_written +=1
66
57
  @events << { type: :delete_object, object_id: object_id }
67
58
  end
68
59
 
@@ -81,9 +72,9 @@ module TacScribe
81
72
  def set_property(property:, value:)
82
73
  case property
83
74
  when 'ReferenceLatitude'
84
- self.reference_latitude = BigDecimal(value)
75
+ Cache.instance.reference_latitude = BigDecimal(value)
85
76
  when 'ReferenceLongitude'
86
- self.reference_longitude = BigDecimal(value)
77
+ Cache.instance.reference_longitude = BigDecimal(value)
87
78
  when 'ReferenceTime'
88
79
  @reference_time = @time = Time.parse(value)
89
80
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TacScribe
4
- VERSION = '0.3.0'
4
+ VERSION = '0.4.0'
5
5
  end
data/tac_scribe.gemspec CHANGED
@@ -25,8 +25,6 @@ Gem::Specification.new do |spec|
25
25
  spec.metadata['yard.run'] = 'yri'
26
26
 
27
27
  if RUBY_PLATFORM == 'java'
28
- # TODO: Specifying a verison chokes bundler for some reason
29
- spec.platform = 'java'
30
28
  spec.add_dependency 'activerecord-jdbcpostgresql-adapter'
31
29
  else
32
30
  spec.add_dependency 'pg', '~>1.1'
metadata CHANGED
@@ -1,178 +1,178 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tac_scribe
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeffrey Jones
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-10-26 00:00:00.000000000 Z
11
+ date: 2020-03-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: pg
15
14
  requirement: !ruby/object:Gem::Requirement
16
15
  requirements:
17
- - - "~>"
16
+ - - ">="
18
17
  - !ruby/object:Gem::Version
19
- version: '1.1'
20
- type: :runtime
18
+ version: '0'
19
+ name: activerecord-jdbcpostgresql-adapter
21
20
  prerelease: false
21
+ type: :runtime
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '1.1'
26
+ version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: georuby
29
28
  requirement: !ruby/object:Gem::Requirement
30
29
  requirements:
31
30
  - - "~>"
32
31
  - !ruby/object:Gem::Version
33
32
  version: '2.5'
34
- type: :runtime
33
+ name: georuby
35
34
  prerelease: false
35
+ type: :runtime
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '2.5'
41
41
  - !ruby/object:Gem::Dependency
42
- name: sequel
43
42
  requirement: !ruby/object:Gem::Requirement
44
43
  requirements:
45
44
  - - "~>"
46
45
  - !ruby/object:Gem::Version
47
46
  version: '5.22'
48
- type: :runtime
47
+ name: sequel
49
48
  prerelease: false
49
+ type: :runtime
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '5.22'
55
55
  - !ruby/object:Gem::Dependency
56
- name: concurrent-ruby
57
56
  requirement: !ruby/object:Gem::Requirement
58
57
  requirements:
59
58
  - - "~>"
60
59
  - !ruby/object:Gem::Version
61
60
  version: 1.1.5
62
- type: :runtime
61
+ name: concurrent-ruby
63
62
  prerelease: false
63
+ type: :runtime
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: 1.1.5
69
69
  - !ruby/object:Gem::Dependency
70
- name: sequel-postgis-georuby
71
70
  requirement: !ruby/object:Gem::Requirement
72
71
  requirements:
73
72
  - - '='
74
73
  - !ruby/object:Gem::Version
75
74
  version: 0.1.2
76
- type: :runtime
75
+ name: sequel-postgis-georuby
77
76
  prerelease: false
77
+ type: :runtime
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - '='
81
81
  - !ruby/object:Gem::Version
82
82
  version: 0.1.2
83
83
  - !ruby/object:Gem::Dependency
84
- name: tacview_client
85
84
  requirement: !ruby/object:Gem::Requirement
86
85
  requirements:
87
86
  - - "~>"
88
87
  - !ruby/object:Gem::Version
89
88
  version: '0.1'
90
- type: :runtime
89
+ name: tacview_client
91
90
  prerelease: false
91
+ type: :runtime
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0.1'
97
97
  - !ruby/object:Gem::Dependency
98
- name: bundler
99
98
  requirement: !ruby/object:Gem::Requirement
100
99
  requirements:
101
100
  - - "~>"
102
101
  - !ruby/object:Gem::Version
103
102
  version: '2.0'
104
- type: :development
103
+ name: bundler
105
104
  prerelease: false
105
+ type: :development
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
110
  version: '2.0'
111
111
  - !ruby/object:Gem::Dependency
112
- name: rake
113
112
  requirement: !ruby/object:Gem::Requirement
114
113
  requirements:
115
114
  - - "~>"
116
115
  - !ruby/object:Gem::Version
117
116
  version: '10.0'
118
- type: :development
117
+ name: rake
119
118
  prerelease: false
119
+ type: :development
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
124
  version: '10.0'
125
125
  - !ruby/object:Gem::Dependency
126
- name: rspec
127
126
  requirement: !ruby/object:Gem::Requirement
128
127
  requirements:
129
128
  - - "~>"
130
129
  - !ruby/object:Gem::Version
131
130
  version: '3.8'
132
- type: :development
131
+ name: rspec
133
132
  prerelease: false
133
+ type: :development
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
136
  - - "~>"
137
137
  - !ruby/object:Gem::Version
138
138
  version: '3.8'
139
139
  - !ruby/object:Gem::Dependency
140
- name: rubocop
141
140
  requirement: !ruby/object:Gem::Requirement
142
141
  requirements:
143
142
  - - "~>"
144
143
  - !ruby/object:Gem::Version
145
144
  version: '0.73'
146
- type: :development
145
+ name: rubocop
147
146
  prerelease: false
147
+ type: :development
148
148
  version_requirements: !ruby/object:Gem::Requirement
149
149
  requirements:
150
150
  - - "~>"
151
151
  - !ruby/object:Gem::Version
152
152
  version: '0.73'
153
153
  - !ruby/object:Gem::Dependency
154
- name: simplecov
155
154
  requirement: !ruby/object:Gem::Requirement
156
155
  requirements:
157
156
  - - "~>"
158
157
  - !ruby/object:Gem::Version
159
158
  version: '0.17'
160
- type: :development
159
+ name: simplecov
161
160
  prerelease: false
161
+ type: :development
162
162
  version_requirements: !ruby/object:Gem::Requirement
163
163
  requirements:
164
164
  - - "~>"
165
165
  - !ruby/object:Gem::Version
166
166
  version: '0.17'
167
167
  - !ruby/object:Gem::Dependency
168
- name: yard
169
168
  requirement: !ruby/object:Gem::Requirement
170
169
  requirements:
171
170
  - - "~>"
172
171
  - !ruby/object:Gem::Version
173
172
  version: '0.9'
174
- type: :development
173
+ name: yard
175
174
  prerelease: false
175
+ type: :development
176
176
  version_requirements: !ruby/object:Gem::Requirement
177
177
  requirements:
178
178
  - - "~>"
@@ -205,6 +205,7 @@ files:
205
205
  - db/README.md
206
206
  - exe/tac_scribe
207
207
  - lib/tac_scribe.rb
208
+ - lib/tac_scribe/cache.rb
208
209
  - lib/tac_scribe/daemon.rb
209
210
  - lib/tac_scribe/datastore.rb
210
211
  - lib/tac_scribe/event_processor.rb
@@ -217,7 +218,7 @@ licenses:
217
218
  - AGPL-3.0-or-later
218
219
  metadata:
219
220
  yard.run: yri
220
- post_install_message:
221
+ post_install_message:
221
222
  rdoc_options: []
222
223
  require_paths:
223
224
  - lib
@@ -232,8 +233,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
232
233
  - !ruby/object:Gem::Version
233
234
  version: '0'
234
235
  requirements: []
235
- rubygems_version: 3.0.3
236
- signing_key:
236
+ rubyforge_project:
237
+ rubygems_version: 2.7.6
238
+ signing_key:
237
239
  specification_version: 4
238
240
  summary: Write Tacview data to PostGIS database
239
241
  test_files: []