trecs 0.1.11 → 0.1.12
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +13 -5
- data/Gemfile.lock +3 -1
- data/bin/trecs +27 -47
- data/bin/trecs_record +23 -27
- data/lib/trecs/frame.rb +37 -0
- data/lib/trecs/player.rb +1 -1
- data/lib/trecs/readers/json_reader.rb +18 -11
- data/lib/trecs/recorder.rb +23 -15
- data/lib/trecs/recording_strategies/config_strategy.rb +31 -0
- data/lib/trecs/recording_strategies/file_frames_strategy.rb +30 -0
- data/lib/trecs/recording_strategies/hash_strategy.rb +4 -0
- data/lib/trecs/recording_strategies/ttyrec_strategy.rb +1 -37
- data/lib/trecs/sources/tgz_source.rb +106 -0
- data/lib/trecs/version.rb +1 -1
- data/lib/trecs/writers/json_writer.rb +28 -9
- data/spec/trecs/frame_spec.rb +68 -0
- data/spec/trecs/player_spec.rb +1 -1
- data/spec/trecs/readers/json_reader_spec.rb +1 -1
- data/spec/trecs/readers/yaml_store_reader_spec.rb +1 -1
- data/spec/trecs/recorder_spec.rb +48 -29
- data/spec/trecs/recording_strategies/config_strategy_spec.rb +129 -0
- data/spec/trecs/recording_strategies/file_frames_strategy_spec.rb +10 -0
- data/spec/trecs/recording_strategies/shell_command_strategy_spec.rb +1 -1
- data/spec/trecs/sources/tgz_source_spec.rb +8 -0
- data/spec/trecs/writers/json_writer_spec.rb +8 -0
- data/trecs.gemspec +1 -0
- metadata +48 -25
- data/old_specs/player_spec.rb +0 -198
- data/old_specs/recorders/zip_file_recorder_spec.rb +0 -64
- data/old_specs/timestamps_spec.rb +0 -44
- data/old_specs/trecs_message_spec.rb +0 -125
- data/old_specs/trecs_spec.rb +0 -115
@@ -25,7 +25,7 @@ module TRecs
|
|
25
25
|
frame = data_array[-height..-1].join
|
26
26
|
|
27
27
|
frame = @prev_frame + curr_data
|
28
|
-
|
28
|
+
|
29
29
|
@first_timestamp ||= [ sec, usec ].join('.').to_f
|
30
30
|
curr_timestamp = [ sec, usec ].join('.').to_f
|
31
31
|
offset = ((curr_timestamp - @first_timestamp)*1000).to_i
|
@@ -41,39 +41,3 @@ module TRecs
|
|
41
41
|
end
|
42
42
|
end
|
43
43
|
end
|
44
|
-
|
45
|
-
# module TRecs
|
46
|
-
# class TtyrecStrategy
|
47
|
-
# attr_accessor :recorder
|
48
|
-
|
49
|
-
# def initialize(options={})
|
50
|
-
# file = options.fetch(:input_file)
|
51
|
-
# @file = File.new(file)
|
52
|
-
# @frames = []
|
53
|
-
# @full_output = ""
|
54
|
-
# @height = options.fetch(:height) { 24 }
|
55
|
-
# @width = options.fetch(:width) { 80 }
|
56
|
-
# end
|
57
|
-
|
58
|
-
# def perform
|
59
|
-
# @prev_timestamp = 0
|
60
|
-
# while !@file.eof?
|
61
|
-
# sec, usec, len = @file.read(12).unpack('VVV')
|
62
|
-
# @full_output << @file.read(len)
|
63
|
-
|
64
|
-
# data_array = @full_output.each_line.to_a
|
65
|
-
# height = data_array.size > @height ? @height : 0
|
66
|
-
# frame = data_array[-height..-1].join
|
67
|
-
|
68
|
-
# @first_timestamp ||= [ sec, usec ].join('.').to_f
|
69
|
-
# curr_timestamp = [ sec, usec ].join('.').to_f
|
70
|
-
# offset = ((curr_timestamp - @first_timestamp)*1000).to_i
|
71
|
-
|
72
|
-
# if curr_timestamp > @prev_timestamp
|
73
|
-
# recorder.current_frame(time: offset, content: frame)
|
74
|
-
# @prev_timestamp = curr_timestamp
|
75
|
-
# end
|
76
|
-
# end
|
77
|
-
# end
|
78
|
-
# end
|
79
|
-
# end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require 'json'
|
2
|
+
require "fileutils"
|
3
|
+
require "zlib"
|
4
|
+
require 'archive/tar/minitar'
|
5
|
+
require "tmpdir"
|
6
|
+
require "pathname"
|
7
|
+
require "yaml"
|
8
|
+
|
9
|
+
module TRecs
|
10
|
+
class TgzSource
|
11
|
+
include Archive::Tar
|
12
|
+
|
13
|
+
attr_reader :trecs_file
|
14
|
+
|
15
|
+
def initialize(options={})
|
16
|
+
@trecs_file = options.fetch(:trecs_file)
|
17
|
+
end
|
18
|
+
|
19
|
+
def create_recording
|
20
|
+
in_tmp_dir do
|
21
|
+
@tgz = Zlib::GzipWriter.new(File.open(trecs_file, 'wb'))
|
22
|
+
|
23
|
+
yield self
|
24
|
+
|
25
|
+
create_file('manifest.yaml') do |f|
|
26
|
+
f.write manifest.to_yaml
|
27
|
+
end
|
28
|
+
|
29
|
+
Minitar.pack(@files_to_add.flatten, @tgz)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def reader(options={})
|
34
|
+
reader = nil
|
35
|
+
options[:source] = self
|
36
|
+
read do |source|
|
37
|
+
@manifest = YAML.load(source.read_file("manifest.yaml"))
|
38
|
+
|
39
|
+
format = manifest["format"]
|
40
|
+
reader_file = "readers/#{format}_reader"
|
41
|
+
require reader_file
|
42
|
+
reader_class_name = [
|
43
|
+
"TRecs::",
|
44
|
+
format.split(/[-_\s]/).map(&:capitalize),
|
45
|
+
"Reader"
|
46
|
+
].join
|
47
|
+
reader_class = reader_class_name.split("::").reduce(Object) { |a, e| a.const_get e }
|
48
|
+
reader = reader_class.new(options)
|
49
|
+
end
|
50
|
+
reader
|
51
|
+
end
|
52
|
+
|
53
|
+
def read
|
54
|
+
in_tmp_dir do
|
55
|
+
tgz = Zlib::GzipReader.new(File.open(trecs_file, 'rb'))
|
56
|
+
Minitar.unpack(tgz, "./")
|
57
|
+
|
58
|
+
yield self
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def in_tmp_dir
|
63
|
+
Dir.mktmpdir("trecs_record") do |dir|
|
64
|
+
Dir.chdir(dir) do
|
65
|
+
yield
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def read_file(file_name)
|
71
|
+
File.read(file_name)
|
72
|
+
end
|
73
|
+
|
74
|
+
def create_file(file_name)
|
75
|
+
File.open(file_name, File::CREAT|File::TRUNC|File::RDWR, 0644) do |f|
|
76
|
+
yield f
|
77
|
+
end
|
78
|
+
add_file(file_name)
|
79
|
+
end
|
80
|
+
|
81
|
+
def add_file(file_name)
|
82
|
+
@files_to_add ||= []
|
83
|
+
@files_to_add << file_name
|
84
|
+
end
|
85
|
+
|
86
|
+
def add_audio_file(file_name)
|
87
|
+
Dir.mkdir("audio") unless File.exist? "audio"
|
88
|
+
|
89
|
+
orig_file = file_name
|
90
|
+
file_name = "./audio/" + Pathname(file_name).basename.to_s
|
91
|
+
FileUtils.symlink(orig_file, file_name)
|
92
|
+
add_file(file_name)
|
93
|
+
end
|
94
|
+
|
95
|
+
def []=(key, value)
|
96
|
+
manifest[key.to_s] = value
|
97
|
+
end
|
98
|
+
|
99
|
+
private
|
100
|
+
|
101
|
+
def manifest
|
102
|
+
@manifest ||= {}
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
end
|
data/lib/trecs/version.rb
CHANGED
@@ -1,15 +1,19 @@
|
|
1
|
-
require
|
2
|
-
require "fileutils"
|
1
|
+
require "sources/tgz_source"
|
3
2
|
|
4
3
|
module TRecs
|
5
4
|
class JsonWriter
|
6
5
|
attr_accessor :recorder
|
6
|
+
|
7
7
|
attr_reader :frames
|
8
|
-
attr_reader :
|
8
|
+
attr_reader :audio_files
|
9
|
+
attr_reader :source
|
9
10
|
|
10
11
|
def initialize(options={})
|
11
|
-
|
12
|
-
|
12
|
+
trecs_file = options.fetch(:trecs_file)
|
13
|
+
@source = TgzSource.new(trecs_file: trecs_file)
|
14
|
+
|
15
|
+
@audio_files = options.fetch(:audio_files) { [] }
|
16
|
+
@audio_files = Array(@audio_files)
|
13
17
|
end
|
14
18
|
|
15
19
|
def setup
|
@@ -23,11 +27,26 @@ module TRecs
|
|
23
27
|
end
|
24
28
|
|
25
29
|
def render
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
+
source.create_recording do |source|
|
31
|
+
source[:format] = "json"
|
32
|
+
|
33
|
+
json_string = frames.to_json
|
34
|
+
|
35
|
+
source.create_file('frames.json') do |f|
|
36
|
+
f.write json_string
|
37
|
+
end
|
38
|
+
|
39
|
+
audio_files.each do |file|
|
40
|
+
source.add_audio_file(file)
|
41
|
+
end
|
42
|
+
if audio_files.any?
|
43
|
+
source[:defailt_audio] = audio_files.first
|
44
|
+
end
|
30
45
|
end
|
31
46
|
end
|
47
|
+
|
48
|
+
def add_audio_file(file_name)
|
49
|
+
audio_files << file_name
|
50
|
+
end
|
32
51
|
end
|
33
52
|
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "frame"
|
3
|
+
|
4
|
+
module TRecs
|
5
|
+
describe Frame do
|
6
|
+
context "content" do
|
7
|
+
context "initializer" do
|
8
|
+
Given(:frame) { Frame.new("THE CONTENT") }
|
9
|
+
Then { frame.content == "THE CONTENT" }
|
10
|
+
end
|
11
|
+
context "set aftewards" do
|
12
|
+
Given(:frame) { Frame.new }
|
13
|
+
When { frame.content = "THE NEW CONTENT" }
|
14
|
+
Then { frame.content == "THE NEW CONTENT" }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
context "width" do
|
19
|
+
context "one line" do
|
20
|
+
Given(:frame) { Frame.new("123456") }
|
21
|
+
Then { frame.width == 6 }
|
22
|
+
end
|
23
|
+
context "multiple lines" do
|
24
|
+
Given(:frame) { Frame.new(<<FRAME
|
25
|
+
123
|
26
|
+
12345
|
27
|
+
12
|
28
|
+
FRAME
|
29
|
+
) }
|
30
|
+
Then { frame.width == 5 }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context "height" do
|
35
|
+
context "one line" do
|
36
|
+
Given(:frame) { Frame.new("LINE 1") }
|
37
|
+
Then { frame.height == 1 }
|
38
|
+
end
|
39
|
+
context "multiple lines" do
|
40
|
+
Given(:frame) { Frame.new(<<FRAME
|
41
|
+
LINE 1
|
42
|
+
LINE 2
|
43
|
+
LINE 3
|
44
|
+
FRAME
|
45
|
+
) }
|
46
|
+
Then { frame.height == 3 }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context "each" do
|
51
|
+
Given(:content) { "a\nb\nc\n" }
|
52
|
+
Given(:frame) { Frame.new(content) }
|
53
|
+
Then {
|
54
|
+
frame.each
|
55
|
+
.zip(content.each_line)
|
56
|
+
.all?{ |actual, expected|
|
57
|
+
actual == expected
|
58
|
+
}
|
59
|
+
}
|
60
|
+
Then { frame.is_a? Enumerable }
|
61
|
+
end
|
62
|
+
|
63
|
+
context "#to_s" do
|
64
|
+
Given(:frame) { Frame.new("FRAME CONTENT") }
|
65
|
+
Then { frame.to_s == "FRAME CONTENT" }
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
data/spec/trecs/player_spec.rb
CHANGED
@@ -76,7 +76,7 @@ module TRecs
|
|
76
76
|
context "content at time" do
|
77
77
|
Given(:screen) { double.as_null_object }
|
78
78
|
Given(:ticker) { OpenStruct.new }
|
79
|
-
Given(:reader) { CustomReader.new(
|
79
|
+
Given(:reader) { CustomReader.new(100 => "b", 0 => "a", 200 => "c") }
|
80
80
|
|
81
81
|
Given(:player) {
|
82
82
|
Player.new(reader: reader, ticker: ticker, screen: screen)
|
data/spec/trecs/recorder_spec.rb
CHANGED
@@ -207,44 +207,63 @@ module TRecs
|
|
207
207
|
end
|
208
208
|
|
209
209
|
context "Offset" do
|
210
|
+
context "initialization" do
|
211
|
+
context "from constructor" do
|
212
|
+
Given(:recorder) { Recorder.new(offset: 10, writer: OpenStruct.new, strategy: OpenStruct.new) }
|
213
|
+
Then { recorder.offset == 10 }
|
214
|
+
end
|
215
|
+
|
216
|
+
context "setter" do
|
217
|
+
Given(:recorder) { Recorder.new(offset: 10, writer: OpenStruct.new, strategy: OpenStruct.new) }
|
218
|
+
When { recorder.offset = 30 }
|
219
|
+
Then { recorder.offset == 30 }
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
210
223
|
Given { Spy.clear }
|
211
224
|
Given(:writer) { Spy.new("Writer").ignore(:recorder=, :setup, :render) }
|
212
225
|
Given(:strategy) { CustomStrategy.new }
|
213
226
|
|
214
227
|
Given(:recorder) {
|
215
|
-
Recorder.new(writer: writer, strategy: strategy,
|
228
|
+
Recorder.new(offset: 7, writer: writer, strategy: strategy, step: 10)
|
216
229
|
}
|
217
230
|
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
}
|
225
|
-
recorder.record
|
226
|
-
}
|
227
|
-
|
228
|
-
Then {
|
229
|
-
writer.calls[1] == [
|
230
|
-
:create_frame,
|
231
|
-
[ { time: 7, content: "CONTENT" } ]
|
232
|
-
]
|
233
|
-
}
|
234
|
-
Then {
|
235
|
-
writer.calls[2] == [
|
236
|
-
:create_frame,
|
237
|
-
[ { time: 17, content: "CONTENT 2" } ]
|
238
|
-
]
|
239
|
-
}
|
240
|
-
Then {
|
241
|
-
writer.calls[3] == [
|
242
|
-
:create_frame,
|
243
|
-
[ { time: 19, content: "CONTENT 3" } ]
|
244
|
-
]
|
231
|
+
When {
|
232
|
+
strategy.action = -> {
|
233
|
+
recorder.current_frame(time: 0, content: "CONTENT")
|
234
|
+
recorder.current_frame(time: 10, content: "CONTENT 2")
|
235
|
+
recorder.current_frame(time: 12, content: "CONTENT 3")
|
236
|
+
recorder.current_frame( content: "CONTENT 4")
|
245
237
|
}
|
246
|
-
|
238
|
+
recorder.record
|
239
|
+
}
|
247
240
|
|
241
|
+
Then {
|
242
|
+
writer.calls[1] == [
|
243
|
+
:create_frame,
|
244
|
+
[ { time: 7, content: "CONTENT" } ]
|
245
|
+
]
|
246
|
+
}
|
247
|
+
Then {
|
248
|
+
writer.calls[2] == [
|
249
|
+
:create_frame,
|
250
|
+
[ { time: 17, content: "CONTENT 2" } ]
|
251
|
+
]
|
252
|
+
}
|
253
|
+
Then {
|
254
|
+
writer.calls[3] == [
|
255
|
+
:create_frame,
|
256
|
+
[ { time: 19, content: "CONTENT 3" } ]
|
257
|
+
]
|
258
|
+
}
|
259
|
+
Then { recorder.current_time == 22 }
|
260
|
+
Then {
|
261
|
+
writer.calls[4] == [
|
262
|
+
:create_frame,
|
263
|
+
[ { time: 29, content: "CONTENT 4" } ]
|
264
|
+
]
|
265
|
+
}
|
248
266
|
end
|
267
|
+
|
249
268
|
end
|
250
269
|
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "recording_strategies/config_strategy"
|
3
|
+
require "recorder"
|
4
|
+
require "recording_strategies/hash_strategy"
|
5
|
+
require "writers/in_memory_writer"
|
6
|
+
|
7
|
+
module TRecs
|
8
|
+
describe ConfigStrategy do
|
9
|
+
context "options" do
|
10
|
+
|
11
|
+
context "set values" do
|
12
|
+
|
13
|
+
Given(:options) {
|
14
|
+
{
|
15
|
+
step: 40,
|
16
|
+
format: "yaml_store",
|
17
|
+
strategies: [],
|
18
|
+
spureous_option: "something spureous",
|
19
|
+
}
|
20
|
+
}
|
21
|
+
|
22
|
+
Given(:strategy) { ConfigStrategy.new(options) }
|
23
|
+
|
24
|
+
Then { strategy.step == 40 }
|
25
|
+
Then { strategy.format == "yaml_store" }
|
26
|
+
Then { strategy.strategies == [] }
|
27
|
+
end
|
28
|
+
|
29
|
+
context "default values" do
|
30
|
+
Given(:strategy) { ConfigStrategy.new }
|
31
|
+
|
32
|
+
Then { strategy.step == 100 }
|
33
|
+
Then { strategy.format == "json" }
|
34
|
+
Then { strategy.strategies == [] }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context "strategies" do
|
39
|
+
context "adding strategies" do
|
40
|
+
Given(:strategy) { ConfigStrategy.new(strategies: [first_strategy]) }
|
41
|
+
Given(:first_strategy) { Object.new }
|
42
|
+
Given(:second_strategy) { Object.new }
|
43
|
+
Given(:third_strategy) { Object.new }
|
44
|
+
|
45
|
+
context "just one" do
|
46
|
+
Then { strategy.strategies == [first_strategy] }
|
47
|
+
end
|
48
|
+
|
49
|
+
context "adding later" do
|
50
|
+
context "one by one" do
|
51
|
+
When { strategy << second_strategy }
|
52
|
+
When { strategy << third_strategy }
|
53
|
+
|
54
|
+
Then { strategy.strategies == [
|
55
|
+
first_strategy,
|
56
|
+
second_strategy,
|
57
|
+
third_strategy,
|
58
|
+
] }
|
59
|
+
end
|
60
|
+
|
61
|
+
context "in bulk" do
|
62
|
+
When { strategy << [second_strategy, third_strategy] }
|
63
|
+
|
64
|
+
Then { strategy.strategies == [
|
65
|
+
first_strategy,
|
66
|
+
second_strategy,
|
67
|
+
third_strategy,
|
68
|
+
] }
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context "#perform" do
|
73
|
+
Given(:writer) { InMemoryWriter.new }
|
74
|
+
Given(:recorder) { Recorder.new(strategy: strategy, writer: writer) }
|
75
|
+
|
76
|
+
When { strategy.recorder = recorder }
|
77
|
+
When { recorder.record }
|
78
|
+
|
79
|
+
context "one strategy" do
|
80
|
+
Given(:s) { HashStrategy.new(
|
81
|
+
{
|
82
|
+
0 => "A",
|
83
|
+
100 => "B",
|
84
|
+
200 => "C",
|
85
|
+
}
|
86
|
+
) }
|
87
|
+
|
88
|
+
Given(:strategy) { ConfigStrategy.new(strategies: [s]) }
|
89
|
+
|
90
|
+
Then { writer.frames[0] == "A" }
|
91
|
+
Then { writer.frames[100] == "B" }
|
92
|
+
Then { writer.frames[200] == "C" }
|
93
|
+
end
|
94
|
+
|
95
|
+
context "two strategies" do
|
96
|
+
Given(:s1) { HashStrategy.new(
|
97
|
+
{
|
98
|
+
0 => "A",
|
99
|
+
10 => "B",
|
100
|
+
20 => "C",
|
101
|
+
}
|
102
|
+
)
|
103
|
+
}
|
104
|
+
|
105
|
+
Given(:s2) { HashStrategy.new(
|
106
|
+
{
|
107
|
+
0 => "D",
|
108
|
+
15 => "E",
|
109
|
+
30 => "F",
|
110
|
+
}
|
111
|
+
)
|
112
|
+
}
|
113
|
+
|
114
|
+
Given(:strategy) { ConfigStrategy.new(strategies: [s1, s2]) }
|
115
|
+
|
116
|
+
Then { writer.frames[0] == "A" }
|
117
|
+
Then { writer.frames[10] == "B" }
|
118
|
+
Then { writer.frames[20] == "C" }
|
119
|
+
|
120
|
+
Then { writer.frames[120] == "D" }
|
121
|
+
Then { writer.frames[135] == "E" }
|
122
|
+
Then { writer.frames[150] == "F" }
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|