csstats 1.1.0 → 1.2.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.
Files changed (41) hide show
  1. checksums.yaml +5 -5
  2. data/.rubocop.yml +33 -0
  3. data/.travis.yml +23 -7
  4. data/Gemfile +3 -7
  5. data/LICENSE +1 -1
  6. data/README.md +12 -9
  7. data/bin/console +1 -1
  8. data/csstats.gemspec +3 -4
  9. data/lib/csstats.rb +5 -3
  10. data/lib/csstats/client.rb +23 -0
  11. data/lib/csstats/columns.rb +28 -0
  12. data/lib/csstats/parser.rb +13 -4
  13. data/lib/csstats/parser/reader.rb +11 -0
  14. data/lib/csstats/parser/reader/file_reader.rb +45 -0
  15. data/lib/csstats/parser/{file_reader/handler.rb → reader/file_streamer.rb} +8 -8
  16. data/lib/csstats/parser/reader/player.rb +41 -0
  17. data/lib/csstats/parser/reader/players.rb +41 -0
  18. data/lib/csstats/{writer.rb → parser/writer.rb} +4 -2
  19. data/lib/csstats/{writer/file_writer/handler.rb → parser/writer/file_streamer.rb} +9 -10
  20. data/lib/csstats/parser/writer/player.rb +34 -0
  21. data/lib/csstats/parser/writer/players.rb +29 -0
  22. data/lib/csstats/player.rb +34 -0
  23. data/lib/csstats/players.rb +52 -0
  24. data/lib/csstats/version.rb +1 -1
  25. data/spec/csstats/client_spec.rb +13 -0
  26. data/spec/csstats/parser/reader/player_spec.rb +17 -0
  27. data/spec/csstats/parser/writer/players_spec.rb +30 -0
  28. data/spec/csstats/player_spec.rb +109 -0
  29. data/spec/csstats/players_spec.rb +30 -0
  30. data/spec/csstats_spec.rb +2 -2
  31. data/spec/spec_helper.rb +3 -7
  32. metadata +29 -21
  33. data/lib/csstats/handler.rb +0 -50
  34. data/lib/csstats/parser/file_reader.rb +0 -39
  35. data/lib/csstats/parser/player.rb +0 -82
  36. data/lib/csstats/parser/players.rb +0 -42
  37. data/lib/csstats/writer/player.rb +0 -39
  38. data/lib/csstats/writer/players.rb +0 -24
  39. data/spec/csstats/handler_spec.rb +0 -113
  40. data/spec/csstats/parser/player_spec.rb +0 -17
  41. data/spec/csstats/writer/players_spec.rb +0 -26
@@ -0,0 +1,41 @@
1
+ module CSstats
2
+ module Parser
3
+ module Reader
4
+ class Players
5
+ attr_reader :file_path, :max_players
6
+
7
+ def initialize(file_path, options = {})
8
+ @file_path = file_path
9
+ @max_players = options[:max_players] || 0
10
+ end
11
+
12
+ def parse
13
+ players = []
14
+
15
+ file_reader.read do |streamer, index|
16
+ parse_player(streamer, index, players)
17
+ end
18
+
19
+ players
20
+ end
21
+
22
+ private
23
+
24
+ def parse_player(streamer, index, players)
25
+ player_parser = CSstats::Parser::Reader::Player.new(streamer)
26
+ player = player_parser.parse
27
+ return unless player
28
+
29
+ player.rank = index + 1
30
+ players[index] = player
31
+ end
32
+
33
+ def file_reader
34
+ @file_reader ||= CSstats::Parser::Reader::FileReader.new(
35
+ file_path, limit: max_players
36
+ )
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -1,8 +1,10 @@
1
- require_relative 'writer/file_writer/handler'
1
+ require_relative 'writer/file_streamer'
2
2
  require_relative 'writer/player'
3
3
  require_relative 'writer/players'
4
4
 
5
5
  module CSstats
6
- module Writer
6
+ module Parser
7
+ module Writer
8
+ end
7
9
  end
8
10
  end
@@ -1,26 +1,25 @@
1
1
  module CSstats
2
- module Writer
3
- class FileWriter
4
- class Handler
5
- attr_reader :handle
2
+ module Parser
3
+ module Writer
4
+ class FileStreamer
5
+ attr_reader :stream
6
6
 
7
- def initialize(handle)
8
- @handle = handle
7
+ def initialize(stream)
8
+ @stream = stream
9
9
  end
10
10
 
11
11
  def write_int_data(int)
12
12
  data = [int].pack('V')
13
- handle.write(data)
13
+ stream.write(data)
14
14
  end
15
15
 
16
16
  def write_short_data(int)
17
17
  data = [int].pack('v')
18
- handle.write(data)
18
+ stream.write(data)
19
19
  end
20
20
 
21
21
  def write_string_data(string)
22
- data = "#{string}\x00"
23
- handle.write(data)
22
+ stream.write(string)
24
23
  end
25
24
  end
26
25
  end
@@ -0,0 +1,34 @@
1
+ module CSstats
2
+ module Parser
3
+ module Writer
4
+ class Player
5
+ attr_reader :streamer, :player
6
+
7
+ def initialize(streamer, player)
8
+ @streamer = streamer
9
+ @player = player
10
+ end
11
+
12
+ def write
13
+ CSstats::COLUMNS.each do |column|
14
+ next streamer.write_int_data(0) if column.empty?
15
+
16
+ value = player.send(column[:name])
17
+ send("write_#{column[:type]}", value)
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ def write_string(value)
24
+ streamer.write_short_data(value.length + 1)
25
+ streamer.write_string_data("#{value}\x00")
26
+ end
27
+
28
+ def write_integer(value)
29
+ streamer.write_int_data(value)
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,29 @@
1
+ module CSstats
2
+ module Parser
3
+ module Writer
4
+ class Players
5
+ attr_reader :file_path
6
+
7
+ def initialize(file_path)
8
+ @file_path = file_path
9
+ end
10
+
11
+ def write(players)
12
+ file = File.new(file_path, 'w')
13
+
14
+ streamer(file).write_short_data(11) # File version
15
+
16
+ players.each do |player|
17
+ CSstats::Parser::Writer::Player.new(streamer(file), player).write
18
+ end
19
+
20
+ file.close
21
+ end
22
+
23
+ def streamer(file)
24
+ CSstats::Parser::Writer::FileStreamer.new(file)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,34 @@
1
+ module CSstats
2
+ class Player
3
+ attr_accessor :rank
4
+
5
+ def initialize(attributes = {})
6
+ CSstats::COLUMN_KEYS.each do |column|
7
+ self.class.send(:attr_accessor, column)
8
+ end
9
+
10
+ attributes.each do |key, value|
11
+ instance_variable_set("@#{key}", value)
12
+ end
13
+ end
14
+
15
+ def efficiency
16
+ kills_and_deaths = kills.to_f + deaths.to_f
17
+ return 0.0 if kills_and_deaths.zero?
18
+
19
+ (kills.to_f / kills_and_deaths * 100).round(2)
20
+ end
21
+
22
+ def accuracy
23
+ return 0.0 if shots.to_f.zero?
24
+
25
+ (hits.to_f / shots.to_f * 100).round(2)
26
+ end
27
+
28
+ def as_json
29
+ CSstats::COLUMN_KEYS.each_with_object({}) do |column, object|
30
+ object[column] = send(column)
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,52 @@
1
+ module CSstats
2
+ class Players
3
+ attr_reader :client
4
+
5
+ def initialize(client)
6
+ @client = client
7
+ end
8
+
9
+ def all
10
+ players
11
+ end
12
+
13
+ def find(id)
14
+ players[id - 1]
15
+ end
16
+
17
+ def find_by(attributes = {})
18
+ players.find do |player|
19
+ attributes.all? do |column, value|
20
+ player.send(column) == value
21
+ end
22
+ end
23
+ end
24
+
25
+ def where(attributes = {})
26
+ players.select do |player|
27
+ attributes.all? do |column, value|
28
+ player.send(column) == value
29
+ end
30
+ end
31
+ end
32
+
33
+ # def save
34
+ # CSstats::Parser.write_players(client, players)
35
+ # end
36
+
37
+ def method_missing(method_name, *args, &block)
38
+ return super unless respond_to?(method_name)
39
+ players.send(method_name, *args, &block)
40
+ end
41
+
42
+ def respond_to_missing?(method_name, include_private = false)
43
+ players.respond_to?(method_name, include_private)
44
+ end
45
+
46
+ private
47
+
48
+ def players
49
+ @players ||= CSstats::Parser.get_players(client)
50
+ end
51
+ end
52
+ end
@@ -1,3 +1,3 @@
1
1
  module CSstats
2
- VERSION = '1.1.0'.freeze
2
+ VERSION = '1.2.0'.freeze
3
3
  end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ describe CSstats::Client do
4
+ let(:client) { CSstats::Client.new(path: csstats_file, max_players: 5) }
5
+
6
+ it 'has correct file path' do
7
+ expect(client.file_path).to eq(csstats_file)
8
+ end
9
+
10
+ it 'has correct max players value' do
11
+ expect(client.max_players).to eq(5)
12
+ end
13
+ end
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ describe CSstats::Parser::Reader::Player do
4
+ let(:file_stream) { File.new(csstats_file) }
5
+ let(:streamer) { CSstats::Parser::Reader::FileStreamer.new(file_stream) }
6
+ subject { described_class.new(streamer) }
7
+ let(:player_data) { subject.parse }
8
+
9
+ before do
10
+ # We need to read first bytes, because it's file version.
11
+ streamer.read_short_data
12
+ end
13
+
14
+ it 'has correct head' do
15
+ expect(player_data.head).to eq(402)
16
+ end
17
+ end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+
3
+ describe CSstats::Parser::Writer::Players do
4
+ let(:old_players) { CSstats.new(path: csstats_file).players }
5
+ let(:file_path) { tmp_file('test.dat') }
6
+ let(:new_players) { CSstats.new(path: file_path).players }
7
+
8
+ it 'has correct players count in main file' do
9
+ expect(old_players.length).to eq(208)
10
+ end
11
+
12
+ context 'new file' do
13
+ before do
14
+ described_class.new(file_path).write(old_players)
15
+ end
16
+
17
+ after do
18
+ FileUtils.rm(file_path)
19
+ end
20
+
21
+ it 'has correct players count' do
22
+ described_class.new(file_path).write(old_players)
23
+ expect(new_players.length).to eq(208)
24
+ end
25
+
26
+ it 'has same players data' do
27
+ expect(old_players.map(&:as_json)).to eq(new_players.map(&:as_json))
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,109 @@
1
+ require 'spec_helper'
2
+
3
+ describe CSstats::Player do
4
+ let(:client) { CSstats::Client.new(path: csstats_file, max_players: 10) }
5
+ let(:players) { client.players }
6
+
7
+ it 'sets attributes from options' do
8
+ player = CSstats::Player.new(nick: 'Test')
9
+ expect(player.nick).to eq('Test')
10
+ end
11
+
12
+ it 'has ability to rewrite attribute' do
13
+ player = CSstats::Player.new
14
+ player.nick = 'Test'
15
+ expect(player.nick).to eq('Test')
16
+ end
17
+
18
+ context 'data' do
19
+ let(:player) { players.find_by(nick: 'CHMARSON') }
20
+
21
+ it 'has correct nick' do
22
+ expect(player.nick).to eq 'CHMARSON'
23
+ end
24
+
25
+ it 'has correct rank' do
26
+ expect(player.rank).to eq 2
27
+ end
28
+
29
+ it 'has correct teamkill' do
30
+ expect(player.teamkill).to eq 7
31
+ end
32
+
33
+ it 'has correct damage' do
34
+ expect(player.damage).to eq 101_543
35
+ end
36
+
37
+ it 'has correct deaths' do
38
+ expect(player.deaths).to eq 511
39
+ end
40
+
41
+ it 'has correct kills' do
42
+ expect(player.kills).to eq 759
43
+ end
44
+
45
+ it 'has correct shots' do
46
+ expect(player.shots).to eq 9421
47
+ end
48
+
49
+ it 'has correct hits' do
50
+ expect(player.hits).to eq 2885
51
+ end
52
+
53
+ it 'has correct headshots' do
54
+ expect(player.headshots).to eq 225
55
+ end
56
+
57
+ it 'has correct defusions' do
58
+ expect(player.defusions).to eq 15
59
+ end
60
+
61
+ it 'has correct defused' do
62
+ expect(player.defused).to eq 9
63
+ end
64
+
65
+ it 'has correct plants' do
66
+ expect(player.plants).to eq 33
67
+ end
68
+
69
+ it 'has correct explosions' do
70
+ expect(player.explosions).to eq 7
71
+ end
72
+
73
+ it 'has correct head' do
74
+ expect(player.head).to eq 275
75
+ end
76
+
77
+ it 'has correct chest' do
78
+ expect(player.chest).to eq 407
79
+ end
80
+
81
+ it 'has correct stomach' do
82
+ expect(player.stomach).to eq 376
83
+ end
84
+
85
+ it 'has correct leftarm' do
86
+ expect(player.leftarm).to eq 1126
87
+ end
88
+
89
+ it 'has correct rightarm' do
90
+ expect(player.rightarm).to eq 283
91
+ end
92
+
93
+ it 'has correct leftleg' do
94
+ expect(player.leftleg).to eq 202
95
+ end
96
+
97
+ it 'has correct rightleg' do
98
+ expect(player.rightleg).to eq 214
99
+ end
100
+
101
+ it 'has correct accuracy' do
102
+ expect(player.accuracy).to eq 30.62
103
+ end
104
+
105
+ it 'has correct efficiency' do
106
+ expect(player.efficiency).to eq 59.76
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+
3
+ describe CSstats::Players do
4
+ let(:client) { CSstats::Client.new(path: csstats_file, max_players: 30) }
5
+ let(:players) { client.players }
6
+
7
+ it 'has correct players count' do
8
+ expect(players.count).to eq(30)
9
+ end
10
+
11
+ it 'returns players with all' do
12
+ expect(players.all.length).to eq(30)
13
+ end
14
+
15
+ it 'has array of Player class' do
16
+ expect(players.first).to be_a(CSstats::Player)
17
+ end
18
+
19
+ it 'has correct player data' do
20
+ expect(players.find(2).nick).to eq('CHMARSON')
21
+ end
22
+
23
+ it 'has correct count with where' do
24
+ expect(players.where(head: 102).count).to eq(2)
25
+ end
26
+
27
+ it 'has correct count with find_by' do
28
+ expect(players.find_by(head: 102).nick).to eq('LBM')
29
+ end
30
+ end