openra 1.8.2 → 2.0.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 +4 -4
- data/CHANGELOG.md +9 -1
- data/lib/openra/cli.rb +1 -2
- data/lib/openra/cli/command_registry.rb +0 -1
- data/lib/openra/cli/formatters.rb +33 -0
- data/lib/openra/cli/utils.rb +1 -1
- data/lib/openra/replays/file.rb +5 -3
- data/lib/openra/version.rb +1 -1
- data/openra.gemspec +11 -9
- metadata +5 -23
- data/.gitignore +0 -50
- data/Gemfile +0 -5
- data/Rakefile +0 -3
- data/lib/openra/cli/commands/detect_production_macros.rb +0 -141
- data/lib/openra/cli/commands/formatters.rb +0 -35
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4d50772fdfb058a097600d6739787d971d4181ea94f889f463f5790d87cae0df
|
4
|
+
data.tar.gz: 325f6d9fae9516003c127b7ea580e69d4fdb45c70183a30e4b2ab35598ff2996
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4b7591e6daa6aa379d36f990a01f873826e133a9c5cffacb7bcf63f935148410c67e2936a875da5507b7c14ad1c7c1f4389136fbfb19672fb8028306a3500ade
|
7
|
+
data.tar.gz: 2304fa6ca53e18438a18c213fff87157a7835b4937e391af64cabd4202a2b9aa974e208cda17bbbf7bc2a51dba29585bcfd68c6f973d9fbc671b6ebd4bc758da
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,14 @@
|
|
1
1
|
## Unreleased
|
2
2
|
|
3
|
-
[Compare
|
3
|
+
[Compare v2.0.0...HEAD](https://github.com/AMHOL/openra-ruby/compare/v2.0.0...HEAD)
|
4
|
+
|
5
|
+
## v2.0.0
|
6
|
+
|
7
|
+
### Removed
|
8
|
+
|
9
|
+
* [detect-production-macros] Remove command because it's garbage ([AMHOL](https://github.com/AMHOL))
|
10
|
+
|
11
|
+
[Compare v1.8.2...v2.0.0](https://github.com/AMHOL/openra-ruby/compare/v1.8.2...v2.0.0)
|
4
12
|
|
5
13
|
## v1.8.2
|
6
14
|
|
data/lib/openra/cli.rb
CHANGED
@@ -8,8 +8,7 @@ require 'openra/version'
|
|
8
8
|
require 'openra/constants'
|
9
9
|
require 'openra/replays'
|
10
10
|
require 'openra/cli/utils'
|
11
|
-
require 'openra/cli/
|
12
|
-
require 'openra/cli/commands/detect_production_macros'
|
11
|
+
require 'openra/cli/formatters'
|
13
12
|
require 'openra/cli/commands/replay_data'
|
14
13
|
require 'openra/cli/commands/version'
|
15
14
|
require 'openra/cli/command_registry'
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Openra
|
4
|
+
class CLI
|
5
|
+
module Formatters
|
6
|
+
class JSON
|
7
|
+
def call(data)
|
8
|
+
::JSON.dump(data)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class PrettyJSON
|
13
|
+
def call(data)
|
14
|
+
::JSON.pretty_generate(data)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class YAML
|
19
|
+
def call(data)
|
20
|
+
::YAML.dump(
|
21
|
+
Openra::Struct::Functions[:deep_stringify_keys].(data)
|
22
|
+
)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
FORMATTERS = {
|
28
|
+
'json' => Formatters::JSON.new,
|
29
|
+
'pretty-json' => Formatters::PrettyJSON.new,
|
30
|
+
'yaml' => Formatters::YAML.new,
|
31
|
+
}.freeze
|
32
|
+
end
|
33
|
+
end
|
data/lib/openra/cli/utils.rb
CHANGED
data/lib/openra/replays/file.rb
CHANGED
@@ -16,9 +16,11 @@ module Openra
|
|
16
16
|
template = Packet.new(fields: Packet.fields)
|
17
17
|
|
18
18
|
loop do
|
19
|
-
|
20
|
-
|
21
|
-
|
19
|
+
begin
|
20
|
+
template.new.read(file).orders.each(&block)
|
21
|
+
rescue EOFError, IOError
|
22
|
+
break
|
23
|
+
end
|
22
24
|
end
|
23
25
|
end
|
24
26
|
|
data/lib/openra/version.rb
CHANGED
data/openra.gemspec
CHANGED
@@ -10,13 +10,16 @@ Gem::Specification.new do |spec|
|
|
10
10
|
spec.homepage = 'https://github.com/AMHOL/openra-ruby'
|
11
11
|
spec.license = 'MIT'
|
12
12
|
|
13
|
-
spec.files =
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
13
|
+
spec.files = Dir[
|
14
|
+
'CHANGELOG.md',
|
15
|
+
'LICENSE',
|
16
|
+
'README.md',
|
17
|
+
'openra.gemspec',
|
18
|
+
'lib/**/*',
|
19
|
+
'bin/openra'
|
20
|
+
]
|
21
|
+
spec.bindir = 'bin'
|
22
|
+
spec.executables = ['openra']
|
20
23
|
spec.require_paths = ['lib']
|
21
24
|
|
22
25
|
spec.add_dependency 'bundler'
|
@@ -27,7 +30,6 @@ Gem::Specification.new do |spec|
|
|
27
30
|
spec.add_dependency 'dry-cli'
|
28
31
|
|
29
32
|
spec.add_development_dependency 'rake'
|
33
|
+
spec.add_development_dependency 'rspec'
|
30
34
|
spec.add_development_dependency 'pry'
|
31
|
-
spec.add_development_dependency 'memory_profiler'
|
32
|
-
spec.add_development_dependency 'stackprof'
|
33
35
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: openra
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andy Holland
|
@@ -109,7 +109,7 @@ dependencies:
|
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '0'
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
|
-
name:
|
112
|
+
name: rspec
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
115
|
- - ">="
|
@@ -123,21 +123,7 @@ dependencies:
|
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: '0'
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
|
-
name:
|
127
|
-
requirement: !ruby/object:Gem::Requirement
|
128
|
-
requirements:
|
129
|
-
- - ">="
|
130
|
-
- !ruby/object:Gem::Version
|
131
|
-
version: '0'
|
132
|
-
type: :development
|
133
|
-
prerelease: false
|
134
|
-
version_requirements: !ruby/object:Gem::Requirement
|
135
|
-
requirements:
|
136
|
-
- - ">="
|
137
|
-
- !ruby/object:Gem::Version
|
138
|
-
version: '0'
|
139
|
-
- !ruby/object:Gem::Dependency
|
140
|
-
name: stackprof
|
126
|
+
name: pry
|
141
127
|
requirement: !ruby/object:Gem::Requirement
|
142
128
|
requirements:
|
143
129
|
- - ">="
|
@@ -158,12 +144,9 @@ executables:
|
|
158
144
|
extensions: []
|
159
145
|
extra_rdoc_files: []
|
160
146
|
files:
|
161
|
-
- ".gitignore"
|
162
147
|
- CHANGELOG.md
|
163
|
-
- Gemfile
|
164
148
|
- LICENSE
|
165
149
|
- README.md
|
166
|
-
- Rakefile
|
167
150
|
- bin/openra
|
168
151
|
- lib/bindata/big_integer.rb
|
169
152
|
- lib/bindata/pascal_string.rb
|
@@ -175,10 +158,9 @@ files:
|
|
175
158
|
- lib/openra.rb
|
176
159
|
- lib/openra/cli.rb
|
177
160
|
- lib/openra/cli/command_registry.rb
|
178
|
-
- lib/openra/cli/commands/detect_production_macros.rb
|
179
|
-
- lib/openra/cli/commands/formatters.rb
|
180
161
|
- lib/openra/cli/commands/replay_data.rb
|
181
162
|
- lib/openra/cli/commands/version.rb
|
163
|
+
- lib/openra/cli/formatters.rb
|
182
164
|
- lib/openra/cli/utils.rb
|
183
165
|
- lib/openra/constants.rb
|
184
166
|
- lib/openra/replays.rb
|
@@ -226,7 +208,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
226
208
|
- !ruby/object:Gem::Version
|
227
209
|
version: '0'
|
228
210
|
requirements: []
|
229
|
-
rubygems_version: 3.
|
211
|
+
rubygems_version: 3.1.2
|
230
212
|
signing_key:
|
231
213
|
specification_version: 4
|
232
214
|
summary: Openra Rubygem
|
data/.gitignore
DELETED
@@ -1,50 +0,0 @@
|
|
1
|
-
*.gem
|
2
|
-
*.rbc
|
3
|
-
/.config
|
4
|
-
/coverage/
|
5
|
-
/InstalledFiles
|
6
|
-
/pkg/
|
7
|
-
/spec/reports/
|
8
|
-
/spec/examples.txt
|
9
|
-
/test/tmp/
|
10
|
-
/test/version_tmp/
|
11
|
-
/tmp/
|
12
|
-
|
13
|
-
# Used by dotenv library to load environment variables.
|
14
|
-
# .env
|
15
|
-
|
16
|
-
## Specific to RubyMotion:
|
17
|
-
.dat*
|
18
|
-
.repl_history
|
19
|
-
build/
|
20
|
-
*.bridgesupport
|
21
|
-
build-iPhoneOS/
|
22
|
-
build-iPhoneSimulator/
|
23
|
-
|
24
|
-
## Specific to RubyMotion (use of CocoaPods):
|
25
|
-
#
|
26
|
-
# We recommend against adding the Pods directory to your .gitignore. However
|
27
|
-
# you should judge for yourself, the pros and cons are mentioned at:
|
28
|
-
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
|
29
|
-
#
|
30
|
-
# vendor/Pods/
|
31
|
-
|
32
|
-
## Documentation cache and generated files:
|
33
|
-
/.yardoc/
|
34
|
-
/_yardoc/
|
35
|
-
/doc/
|
36
|
-
/rdoc/
|
37
|
-
|
38
|
-
## Environment normalization:
|
39
|
-
/.bundle/
|
40
|
-
/vendor/bundle
|
41
|
-
/lib/bundler/man/
|
42
|
-
|
43
|
-
# for a library or gem, you might want to ignore these files since the code is
|
44
|
-
# intended to run in multiple environments; otherwise, check them in:
|
45
|
-
Gemfile.lock
|
46
|
-
.ruby-version
|
47
|
-
.ruby-gemset
|
48
|
-
|
49
|
-
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
50
|
-
.rvmrc
|
data/Gemfile
DELETED
data/Rakefile
DELETED
@@ -1,141 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Openra
|
4
|
-
class CLI
|
5
|
-
module Commands
|
6
|
-
class DetectProductionMacros < Dry::CLI::Command
|
7
|
-
ARRAY_HASH = ->(hash, key) { hash[key] = [] }
|
8
|
-
|
9
|
-
desc 'Detect whether players are using production macros'
|
10
|
-
|
11
|
-
argument :replay, required: true, desc: 'Path of the replay file to read data from'
|
12
|
-
option :format, default: 'json', values: %w(json pretty-json yaml), desc: 'Output format'
|
13
|
-
|
14
|
-
def call(replay:, **options)
|
15
|
-
replay = Openra::Replays::Replay.new(replay)
|
16
|
-
commands = Hash.new(&ARRAY_HASH)
|
17
|
-
sync_info = nil
|
18
|
-
|
19
|
-
replay.each_order do |order|
|
20
|
-
case order.command
|
21
|
-
when 'StartGame'
|
22
|
-
game_started = true
|
23
|
-
when 'SyncInfo'
|
24
|
-
sync_info = Openra::Struct::SyncInfo.new(
|
25
|
-
Openra::YAML.load(order.target)
|
26
|
-
) unless game_started
|
27
|
-
when 'StartProduction'
|
28
|
-
commands[order.client_index.to_s] << {
|
29
|
-
target: utf8(order.target),
|
30
|
-
msec: order.frame * sync_info.global_settings.frametime_multiplier
|
31
|
-
}
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
data = {
|
36
|
-
players: replay.players.select(&:is_human).map { |player|
|
37
|
-
player_commands = commands_with_delay(commands[player.index])
|
38
|
-
production_stats = production_stats(player_commands)
|
39
|
-
sequences = detect_sequences(player_commands)
|
40
|
-
|
41
|
-
{
|
42
|
-
index: player.index,
|
43
|
-
name: utf8(player.name),
|
44
|
-
team: player.team,
|
45
|
-
outcome: player.outcome,
|
46
|
-
production_stats: production_stats,
|
47
|
-
sequences: sequences,
|
48
|
-
suspected_macros: suspected_macros(production_stats, sequences)
|
49
|
-
}
|
50
|
-
}
|
51
|
-
}
|
52
|
-
|
53
|
-
puts FORMATTERS.fetch(options[:format]).call(data)
|
54
|
-
end
|
55
|
-
|
56
|
-
private
|
57
|
-
|
58
|
-
def commands_with_delay(commands)
|
59
|
-
commands.inject do |last_command, command|
|
60
|
-
command[:delay] = command[:msec] - last_command[:msec]
|
61
|
-
command
|
62
|
-
end
|
63
|
-
|
64
|
-
# Drop the first command, as we don't have a delay for that
|
65
|
-
commands.drop(1)
|
66
|
-
end
|
67
|
-
|
68
|
-
def detect_sequences(player_commands)
|
69
|
-
sequences = []
|
70
|
-
groups = player_commands.each_with_object(
|
71
|
-
Hash.new(&ARRAY_HASH)
|
72
|
-
).with_index do |(command, hash), index|
|
73
|
-
hash[command[:delay]] << command.merge(index: index)
|
74
|
-
end
|
75
|
-
|
76
|
-
groups.each_pair do |delay, commands|
|
77
|
-
sequence = []
|
78
|
-
|
79
|
-
commands.inject do |last_command, command|
|
80
|
-
if last_command[:index].next == command[:index]
|
81
|
-
sequence << command
|
82
|
-
elsif sequence.length > 1
|
83
|
-
sequences << {
|
84
|
-
delay: delay,
|
85
|
-
sequence: sequence.map { |c| c[:target] }
|
86
|
-
}
|
87
|
-
sequence = []
|
88
|
-
end
|
89
|
-
|
90
|
-
command
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
sequences = sequences.uniq.map do |sequence|
|
95
|
-
sequence.merge(
|
96
|
-
occurences: sequences.count { |current| current == sequence }
|
97
|
-
)
|
98
|
-
end
|
99
|
-
|
100
|
-
sequences.select { |sequence| sequence[:occurences] > 1 }.sort do |a, b|
|
101
|
-
b[:occurences] <=> a[:occurences]
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
def production_stats(player_commands)
|
106
|
-
order_delays = player_commands.map { |command| command[:delay] }
|
107
|
-
|
108
|
-
{
|
109
|
-
order_delay: {
|
110
|
-
min: order_delays.min,
|
111
|
-
max: order_delays.max,
|
112
|
-
mean: mean(order_delays),
|
113
|
-
median: median(order_delays)
|
114
|
-
}
|
115
|
-
}
|
116
|
-
end
|
117
|
-
|
118
|
-
def suspected_macros(production_stats, sequences)
|
119
|
-
suspicious_sequences = sequences.count do |sequence|
|
120
|
-
sequence[:delay] < 100 &&
|
121
|
-
sequence[:sequence].length > 3 &&
|
122
|
-
sequence[:sequence].uniq.length > 2
|
123
|
-
end
|
124
|
-
|
125
|
-
production_stats[:order_delay][:min] < 50 || suspicious_sequences > 0
|
126
|
-
end
|
127
|
-
|
128
|
-
def mean(ints)
|
129
|
-
ints.sum / ints.length
|
130
|
-
end
|
131
|
-
|
132
|
-
def median(ints)
|
133
|
-
ints = ints.sort
|
134
|
-
middle_index = (ints.length - 1) / 2.0
|
135
|
-
|
136
|
-
(ints[middle_index.floor] + ints[middle_index.ceil]) / 2
|
137
|
-
end
|
138
|
-
end
|
139
|
-
end
|
140
|
-
end
|
141
|
-
end
|
@@ -1,35 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Openra
|
4
|
-
class CLI
|
5
|
-
module Commands
|
6
|
-
module Formatters
|
7
|
-
class JSON
|
8
|
-
def call(data)
|
9
|
-
::JSON.dump(data)
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
class PrettyJSON
|
14
|
-
def call(data)
|
15
|
-
::JSON.pretty_generate(data)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
class YAML
|
20
|
-
def call(data)
|
21
|
-
::YAML.dump(
|
22
|
-
Openra::Struct::Functions[:deep_stringify_keys].(data)
|
23
|
-
)
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
FORMATTERS = {
|
29
|
-
'json' => Formatters::JSON.new,
|
30
|
-
'pretty-json' => Formatters::PrettyJSON.new,
|
31
|
-
'yaml' => Formatters::YAML.new,
|
32
|
-
}.freeze
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|