frypan 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: fb8a7b23f1048487bc5ab065783383c02ce47b1d
4
+ data.tar.gz: 93c85039222d259ad54acab69dadb06e653811f6
5
+ SHA512:
6
+ metadata.gz: 7af33ae5164675458049fd5be4bc2c7ca67333ca1ca4dd6e525e6575074c905367d092383a5c4bdde9d53269494c76ff8335aa2f86215a86accc1f0152df47df
7
+ data.tar.gz: c52cf2274ac18309bf4ecbc09164511dcba3ec2149fb5fd118713f1e66828d78631be153de21a29516920cb1bd1a3d4857e23b581b34bc2b4fbb542fa88adc1a
data/.gitignore ADDED
@@ -0,0 +1,16 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ *~
15
+ *#
16
+ mkmf.log
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in frypan.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 TODO: Write your name
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new do |test|
5
+ test.test_files = Dir["unit_test/**/test_*.rb"]
6
+ test.verbose = true
7
+ end
8
+
data/_README.md ADDED
@@ -0,0 +1,31 @@
1
+ # Frypan
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'frypan'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install frypan
20
+
21
+ ## Usage
22
+
23
+ TODO: Write usage instructions here
24
+
25
+ ## Contributing
26
+
27
+ 1. Fork it ( https://github.com/[my-github-username]/frypan/fork )
28
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
29
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
30
+ 4. Push to the branch (`git push origin my-new-feature`)
31
+ 5. Create a new Pull Request
data/bin/frypan ADDED
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+ # -*- mode: ruby -*-
4
+
5
+ require 'mongo'
6
+
7
+ def install(home_path)
8
+ # 1. mongodbのバイナリを落として [homepath]/mongodb.tarに保存
9
+ # 2. 解凍する。[homepath]/mongodb/bin/mongodってな具合になる
10
+ # 3. [homepath]/db/作る
11
+ end
12
+
13
+ def fork_db(home_path, port=27017)
14
+ mongod = "#{home_path}/mongodb/bin/mongod"
15
+ db = "#{home_path}/db/"
16
+ log = "#{home_path}/db/server.log"
17
+ status = `#{mongod} --dbpath #{db} --logpath #{log} --port #{port} --fork`
18
+ pid = status.lines.map{|ln| ln.match(/forked process: (\d+)/)}.select{|a| a}.first[1].to_i
19
+ success = status.lines.any?{|ln| ln.match(/successfully/)}
20
+ if success then pid else nil end
21
+ end
22
+
23
+ def connect_db(port=27017, host="localhost")
24
+ Mongo::Connection.new(host, port).db("frypan_core")
25
+ end
26
+
27
+ begin
28
+ pid = fork_db("~/Workspace/")
29
+ TinyFRP::Runtime.new(main_signal(connect_db)).run(:loop)
30
+ ensure
31
+ Process.kill("TERM", pid) if pid
32
+ end
33
+
34
+
35
+
36
+ db = hoge
37
+ api_server = APIServer.new(db) # fork webrick. only op-command throw.
38
+ epg = hoge
39
+ tuner = [fuga]
40
+
41
+ command = TinyFRP.lift{ api_server.get_next_command } # one-unit-command OR nil
42
+ current_time = TinyFRP.lift{ Time.now.strftime("%Y%m%d%H%M%S") }
43
+ epg_flag = hoge
44
+ tuners_flag = [fuga]
45
+
46
+ main = TinyFRP::Bundle.new(command, current_time, epg_flag, tuners_flag) >> Node.top(setting)
47
+
48
+ TinyFRP.loop(main) do |out|
49
+ out[:reserve1].action(db)
50
+ out[:reserve2].action(db)
51
+ out[:reserve3].action(db)
52
+ out[:reserve4].action(db)
53
+ out[:epg].action(epg)
54
+ out[:tuner1].action(tuner1)
55
+ end
data/frypan.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ # -*- mode: ruby -*-
2
+ # coding: utf-8
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'frypan/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = "frypan"
9
+ spec.version = Frypan::VERSION
10
+ spec.authors = ["sawaken"]
11
+ spec.email = ["sasasawada@gmail.com"]
12
+ spec.summary = %q{Yet another recording scheduler.}
13
+ spec.description = %q{}
14
+ spec.homepage = ""
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0")
18
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_development_dependency "bundler", "~> 1.7"
23
+ spec.add_development_dependency "rake", "~> 10.0"
24
+ end
@@ -0,0 +1,30 @@
1
+ module Frypan
2
+ class DBSyncList
3
+ def initialize(name, db)
4
+ @coll = db.collection(name)
5
+ end
6
+
7
+ def +(list)
8
+ list.each{|a| @coll.insert(a)}
9
+ self
10
+ end
11
+
12
+ def update(alt_list)
13
+ @coll.remove
14
+ alt_list.each{|a| @coll.insert(a)}
15
+ self
16
+ end
17
+
18
+ def update_elements(elements, ident_key)
19
+ elements.each do |a|
20
+ @coll.update({ident_key => a[ident_key]}, {"$set" => a}, true)
21
+ end
22
+ self
23
+ end
24
+
25
+ def to_a
26
+ @coll.find.to_a
27
+ end
28
+ end
29
+ end
30
+
@@ -0,0 +1,23 @@
1
+ module Frypan
2
+ class EpgParser
3
+ require 'm2ts_parser'
4
+ class ParserProcess
5
+ def initialize(file_path)
6
+
7
+ end
8
+
9
+ def finished?
10
+
11
+ end
12
+
13
+ def get_parsed
14
+
15
+ end
16
+ end
17
+
18
+ def parse(file_path)
19
+ ParserProcess.new(file_path)
20
+ end
21
+ end
22
+ end
23
+
@@ -0,0 +1,150 @@
1
+ module Frypan
2
+ require 'tiny_frp'
3
+ module Node
4
+ def self.overlaped?(list_of_range)
5
+ !list_of_range.sort{|a, b| a.begin <=> b.begin}.each_cons(2).all?{|a, b| a.end <= b.begin}
6
+ end
7
+
8
+ def self.apply_operations(list, ops)
9
+ case
10
+ when ops == []
11
+ [list, ""]
12
+ when ops.first[:kind] == :add
13
+ added_list = list + [ops.first[:target]]
14
+ if overlaped?(added_list.map{|a| a[:start_time]..a[:end_time]})
15
+ [nil, "cannot add reservation: #{ops.first[:target]}"]
16
+ else
17
+ apply_operations(added_list, ops.drop(1))
18
+ end
19
+ when ops.first[:kind] == :remove
20
+ if list.find{|a| a[:start_time] == ops.first[:target][:start_time]}
21
+ apply_operations(list.reject{|a| a[:start_time] == ops.first[:target][:start_time]}, ops.drop(1))
22
+ else
23
+ [nil, "unexist remove reservation id: #{ops.first[:target][:id]}"]
24
+ end
25
+ else
26
+ [nil, "unknown operation '#{ops.first[:kind]}'"]
27
+ end
28
+ end
29
+
30
+ def self.ReserveListFoldp(tuner_id, initial_list=[])
31
+ TinyFRP.foldp(launch: nil, list: initial_list, ack: nil) do |acc, command, current_time|
32
+ case
33
+ when command && command[:target_tuner] == tuner_id
34
+ new_list, status = *apply_operations(acc[:list], command[:operations])
35
+ ack = command.merge({
36
+ timestamp: current_time,
37
+ succeeded: !!new_list,
38
+ status: status
39
+ })
40
+ if new_list
41
+ {launch: nil, list: new_list.sort{|a, b| a[:start_time] <=> b[:start_time]}, ack: ack}
42
+ else
43
+ {launch: nil, ack: ack}
44
+ end
45
+ when acc[:list] != [] && acc[:list].first[:start_time] <= current_time
46
+ {launch: acc[:list].first, list: acc[:list].drop(1), ack: nil}
47
+ else
48
+ {launch: nil, ack: nil}
49
+ end
50
+ end
51
+ end
52
+
53
+ def self.PersistantReserveListFoldp(tuner_id, dbsync_reserve)
54
+ TinyFRP.foldp(last_list: nil, list: dbsync_reserve) do |acc, rlist|
55
+ if !acc[:last_list] || acc[:last_list] != rlist[:list]
56
+ {last_list: rlist[:list], list: acc[:list].update(rlist[:list])}
57
+ else
58
+ {}
59
+ end
60
+ end
61
+ end
62
+
63
+ def self.RecordingAsyncFoldp(tuner)
64
+ TinyFRP.foldp(busy: false, rec_process: nil, waiting: [], log: []) do |acc, rlist|
65
+ case
66
+ when rlist[:launch]
67
+ {waiting: acc[:waiting] + [rlist[:launch]], log: []}
68
+ when acc[:busy]
69
+ {busy: !acc[:rec_process].finished?, log: acc[:rec_process].get_log}
70
+ when acc[:waiting] != []
71
+ {
72
+ busy: true,
73
+ rec_process: tuner.rec(acc[:waiting].first),
74
+ waiting: acc[:waiting].drop(1),
75
+ log: []
76
+ }
77
+ else
78
+ {log: []}
79
+ end
80
+ end
81
+ end
82
+
83
+ def self.RecordingLogFoldp(initial_log=[])
84
+ TinyFRP.foldp(log: initial_log, epg_order: [], recorded: []) do |acc, *log_inputs|
85
+ if log_inputs.any?{|a| a != []}
86
+ new_logs = log_inputs.select{|a| a != []}.flatten
87
+ {
88
+ log: acc[:log] + new_logs,
89
+ epg_order: Fnc.find_epg_order(new_logs),
90
+ recorded: Fnc.find_recorded(new_logs)
91
+ }
92
+ else
93
+ {epg_order: [], recorded: []}
94
+ end
95
+ end
96
+ end
97
+
98
+ def self.EpgExtractAsyncFoldp(epg_parser)
99
+ TinyFRP.foldp(busy: false, parser_process: nil, waiting: [], extracted: []) do |acc, log|
100
+ case
101
+ when log[:epg_order]
102
+ {waiting: acc[:waiting] + [log[:epg_order]], extracted: []}
103
+ when acc[:busy]
104
+ {busy: !acc[:parser_process].finished?, extracted: acc[:parser_process].get_parsed}
105
+ when acc[:waiting] != []
106
+ {
107
+ busy: true,
108
+ parser_process: epg_parser.parse(acc[:waiting].first[:file_path]),
109
+ waiting: acc[:waiting].drop(1),
110
+ extracted: []
111
+ }
112
+ else
113
+ {extracted: []}
114
+ end
115
+ end
116
+ end
117
+
118
+ def self.ProgramListFoldp(initial_list=[])
119
+ TinyFRP.foldp(list: initial_list) do |acc, epg|
120
+ if epg[:extracted] != []
121
+ # epg[:extracted] := list of {program_id: [service_id, event_id], ...}
122
+ {list: acc[:list].update_elements(epg[:extracted], :program_id)}
123
+ else
124
+ {}
125
+ end
126
+ end
127
+ end
128
+
129
+ def self.RecordedListFoldp(initial_list=[])
130
+ TinyFRP.foldp(list: initial_list) do |acc, log|
131
+ if log[:recorded] != []
132
+ {list: acc[:list] + log[:recorded]}
133
+ else
134
+ {}
135
+ end
136
+ end
137
+ end
138
+
139
+ def self.UIresponseFoldp(initial_list=[])
140
+ TinyFRP.foldp(list: initial_list) do |acc, current_time, *acks|
141
+ if acks.any?{|a| a}
142
+ {list: acc[:list] + acks.select{|a| a}}
143
+ else
144
+ {}
145
+ end
146
+ end
147
+ end
148
+ end
149
+ end
150
+
@@ -0,0 +1,47 @@
1
+ module Frypan
2
+ class Tuner
3
+ class RecordingProcess
4
+ def initialize(command)
5
+ @reader, writer = IO.pipe
6
+ @pid = Process.spawn(command, :err => writer, :out => writer)
7
+ @mutex = Mutex.new
8
+ @logs = []
9
+ Thread.new{
10
+ while IO::select([@reader])
11
+ @mutex.synchronize{
12
+ @logs << @reader.gets.chomp
13
+ }
14
+ end
15
+ }
16
+ end
17
+
18
+ def finished?
19
+ @finished ||= Process.waitpid2(@pid, Process::WNOHANG)
20
+ end
21
+
22
+ def get_log
23
+ res = []
24
+ @mutex.synchronize{
25
+ res = @logs.dup
26
+ @logs = []
27
+ }
28
+ res
29
+ end
30
+ end
31
+
32
+ def initialize(format_str)
33
+ @format_str = format_str
34
+ end
35
+
36
+ def rec(setting)
37
+ RecordingProcess.new(Tuner.make_command(@format_str, setting))
38
+ end
39
+
40
+ def self.make_command(format_str, setting)
41
+ setting.keys.inject(format_str) do |str, key|
42
+ str.gsub("<#{key}>", setting[key].to_s)
43
+ end
44
+ end
45
+ end
46
+ end
47
+
@@ -0,0 +1,3 @@
1
+ module Frypan
2
+ VERSION = "0.0.1"
3
+ end
data/lib/frypan.rb ADDED
@@ -0,0 +1,57 @@
1
+ require "frypan/version"
2
+
3
+ module Frypan
4
+ # TODO
5
+ # imp APIServer
6
+ # imp EpgParser
7
+
8
+ def self.main_signal(db, tuner_config=nil)
9
+ dbsync_ui_res = DBSyncList.new("ui_response", db)
10
+ dbsync_recording_log = DBSyncList.new("recording_log", db)
11
+ dbsync_program = DBSyncList.new("program", db)
12
+ dbsync_recorded = DBSyncList.new("recorded", db)
13
+
14
+ dbsync_reserve1 = DBSyncList.new("reserve1", db)
15
+ dbsync_reserve2 = DBSyncList.new("reserve2", db)
16
+ dbsync_reserve3 = DBSyncList.new("reserve3", db)
17
+ dbsync_reserve4 = DBSyncList.new("reserve4", db)
18
+
19
+ api_server = APIServer.new(db) # fork webrick. only op-command throw.
20
+
21
+ command = TinyFRP.lift{ api_server.get_next_command } # one-unit-command OR nil
22
+ #com = {
23
+ # command_id: 1024,
24
+ # target_tuner: 1
25
+ # operations: [
26
+ # {:kind => :remove, ::target => {reserve data (something including start_time)}},
27
+ # {:kind => :add, :target => {reserve data}}
28
+ # ]
29
+ #}
30
+
31
+ current_time = TinyFRP.lift{ Time.now.strftime("%Y%m%d%H%M%S") }
32
+
33
+ s1 = TinyFRP.bundle(command, current_time) >> Node.ReserveListFoldp("tuner1", dbsync_reserve1.to_a)
34
+ s2 = TinyFRP.bundle(command, current_time) >> Node.ReserveListFoldp("tuner2", dbsync_reserve2.to_a)
35
+ s3 = TinyFRP.bundle(command, current_time) >> Node.ReserveListFoldp("tuner3", dbsync_reserve3.to_a)
36
+ s4 = TinyFRP.bundle(command, current_time) >> Node.ReserveListFoldp("tuner4", dbsync_reserve4.to_a)
37
+
38
+ ui_res = Node.UIresponseFoldp(dbsync_ui_res) << TinyFRP.bundle(s1, s2, s3, s4)
39
+
40
+ ps1 = s1 >> Node.PersistantReserveListFoldp("tuner1", dbsync_reserve1)
41
+ ps2 = s2 >> Node.PersistantReserveListFoldp("tuner2", dbsync_reserve2)
42
+ ps3 = s3 >> Node.PersistantReserveListFoldp("tuner3", dbsync_reserve3)
43
+ ps4 = s4 >> Node.PersistantReserveListFoldp("tuner4", dbsync_reserve4)
44
+
45
+ t1 = s1 >> Node.RecordingAsyncFoldp(Tuner.new("fmt1"))
46
+ t2 = s2 >> Node.RecordingAsyncFoldp(Tuner.new("fmt2"))
47
+ t3 = s3 >> Node.RecordingAsyncFoldp(Tuner.new("fmt2"))
48
+ t4 = s4 >> Node.RecordingAsyncFoldp(Tuner.new("fmt2"))
49
+
50
+ recording_log = TinyFRP.bundle(t1, t2, t3, t4) >> Node.RecordingLogFoldp(dbsync_recording_log)
51
+ epg_extract = recording_log >> Node.EpgExtractAsyncFoldp(EpgParser.new)
52
+ program_list = epg_extract >> Node.ProgramListFoldp(dbsync_program)
53
+ recorded_list = recording_log >> Node.RecordedListFoldp(dbsync_recorded)
54
+
55
+ return TinyFRP.bundle(ui_res, ps1, ps2, ps3, ps4, program_list, recorded_list) >> TinyFRP.bottom
56
+ end
57
+ end
@@ -0,0 +1,171 @@
1
+ $LIBRARY_ROOT_PATH = File.dirname(File.expand_path(File.dirname(__FILE__)))
2
+
3
+ module Frypan
4
+ module UnitTest
5
+ require 'test/unit'
6
+ require $LIBRARY_ROOT_PATH + '/lib/frypan/node.rb'
7
+
8
+ class DummyList
9
+ attr_reader :array
10
+ def initialize(init=[])
11
+ @array = []
12
+ end
13
+
14
+ def +(list)
15
+ DummyList.new(@array + list)
16
+ end
17
+
18
+ def update(alt_list)
19
+ DummyList.new(alt_list)
20
+ end
21
+
22
+ def update_elements(elements, ident_key)
23
+ if elements == []
24
+ self
25
+ else
26
+ update_element(elements.first, ident_key).update_elements(elements.drop(1), ident_key)
27
+ end
28
+ end
29
+
30
+ def update_element(element, ident_key)
31
+ if @array.find{|a| a[ident_key] == element[ident_key]}
32
+ DummyList.new(@array.map{|a| a[ident_key] == element[ident_key] ? element : a})
33
+ else
34
+ DummyList.new(@array + [element])
35
+ end
36
+ end
37
+ end
38
+
39
+ class DummyTuner
40
+ class DummyRecordingProcess
41
+ def initialize(logs)
42
+ @logs = logs.dup
43
+ end
44
+
45
+ def finished?
46
+ @logs.empty?
47
+ end
48
+
49
+ def get_log
50
+ @logs.shift || []
51
+ end
52
+ end
53
+
54
+ def initialize(logs)
55
+ @logs = logs
56
+ end
57
+
58
+ def rec(setting)
59
+ DummyRecordingProcess.new(@logs)
60
+ end
61
+ end
62
+
63
+ class DummyEpgParser
64
+ class DummyParserProcess
65
+ def initialize(parseds)
66
+ @parseds = parseds.dup
67
+ end
68
+
69
+ def finished?
70
+ @parseds.empty?
71
+ end
72
+
73
+ def get_parsed
74
+ @parseds.shift || []
75
+ end
76
+ end
77
+
78
+ def initialize(parseds)
79
+ @parseds = parseds
80
+ end
81
+
82
+ def parse(file_path)
83
+ DummyParserProcess.new(@parseds)
84
+ end
85
+ end
86
+
87
+ module Util
88
+ def mkcom(command_id, target_tuner, *ops)
89
+ {command_id: command_id, target_tuner: target_tuner, operations: ops}
90
+ end
91
+
92
+ def mkop(kind, target)
93
+ {kind: kind, target: target}
94
+ end
95
+
96
+ def mkres(id, start_time, end_time)
97
+ {id: id, start_time: start_time, end_time: end_time}
98
+ end
99
+ end
100
+
101
+ class NodeTest < Test::Unit::TestCase
102
+ include Util
103
+
104
+ def test_ReserveListFoldp
105
+ n = Node.ReserveListFoldp(:test_tuner, [])
106
+ vals = [
107
+ nil,
108
+ com1 = mkcom(0, :test_tuner, mkop(:add, res1 = mkres(0, 2, 5))),
109
+ com2 = mkcom(1, :test_tuner, mkop(:add, res2 = mkres(1, 5, 7))),
110
+ nil,
111
+ com3 = mkcom(2, :test_tuner, mkop(:add, res3 = mkres(2, 6, 10)))
112
+ ].each_with_index.map{|a, i| n.call(a, i)}
113
+
114
+ assert_equal({launch: nil, list: [], ack: nil}, vals[0])
115
+
116
+ expect_ack1 = com1.merge(timestamp: 1, succeeded: true, status: "")
117
+ assert_equal({launch: nil, list: [res1], ack: expect_ack1}, vals[1])
118
+
119
+ expect_ack2 = com2.merge(timestamp: 2, succeeded: true, status: "")
120
+ assert_equal({launch: nil, list: [res1, res2], ack: expect_ack2}, vals[2])
121
+
122
+ assert_equal({launch: res1, list: [res2], ack: nil}, vals[3])
123
+
124
+ expect_ack3 = com3.merge(timestamp: 4, succeeded: false, status: vals[4][:ack][:status])
125
+ assert_equal({launch: nil, list: [res2], ack: expect_ack3}, vals[4])
126
+ end
127
+
128
+ def test_PersistantReserveListFoldp
129
+ n = Node.PersistantReserveListFoldp(:tuner_tuner, DummyList.new([]))
130
+ vals = [
131
+ {list: [:a]},
132
+ {list: [:a]},
133
+ {list: [:a, :b]},
134
+ ].map{|a| n.call(a)}
135
+
136
+ assert_equal(vals[0], vals[1])
137
+ assert_not_equal(vals[1], vals[2])
138
+ end
139
+
140
+ def test_RecordingAsyncFoldp
141
+ n = Node.RecordingAsyncFoldp(DummyTuner.new([[0, 1], [2]]))
142
+ v = [
143
+ {launch: nil},
144
+ {launch: :a},
145
+ {launch: nil},
146
+ {launch: :b},
147
+ {launch: nil},
148
+ {launch: nil},
149
+ {launch: nil},
150
+ {launch: nil},
151
+ {launch: nil},
152
+ {launch: nil},
153
+ {launch: nil},
154
+ ].map{|a| n.call(a)}
155
+
156
+ assert_equal({busy: false, rec_process: v[0][:rec_process], waiting: [], log: []}, v[0])
157
+ assert_equal({busy: false, rec_process: v[1][:rec_process], waiting: [:a], log: []}, v[1])
158
+ assert_equal({busy: true, rec_process: v[2][:rec_process], waiting: [], log: []}, v[2])
159
+ assert_equal({busy: true, rec_process: v[3][:rec_process], waiting: [:b], log: []}, v[3])
160
+ assert_equal({busy: true, rec_process: v[4][:rec_process], waiting: [:b], log: [0, 1]}, v[4])
161
+ assert_equal({busy: true, rec_process: v[5][:rec_process], waiting: [:b], log: [2]}, v[5])
162
+ assert_equal({busy: false, rec_process: v[6][:rec_process], waiting: [:b], log: []}, v[6])
163
+ assert_equal({busy: true, rec_process: v[7][:rec_process], waiting: [], log: []}, v[7])
164
+ assert_equal({busy: true, rec_process: v[8][:rec_process], waiting: [], log: [0, 1]}, v[8])
165
+ assert_equal({busy: true, rec_process: v[9][:rec_process], waiting: [], log: [2]}, v[9])
166
+ assert_equal({busy: false, rec_process: v[10][:rec_process], waiting: [], log: []}, v[10])
167
+ end
168
+ end
169
+ end
170
+ end
171
+
metadata ADDED
@@ -0,0 +1,87 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: frypan
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - sawaken
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-02-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ description: ''
42
+ email:
43
+ - sasasawada@gmail.com
44
+ executables:
45
+ - frypan
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - ".gitignore"
50
+ - Gemfile
51
+ - LICENSE.txt
52
+ - Rakefile
53
+ - _README.md
54
+ - bin/frypan
55
+ - frypan.gemspec
56
+ - lib/frypan.rb
57
+ - lib/frypan/database_sync_list.rb
58
+ - lib/frypan/epg_parser.rb
59
+ - lib/frypan/node.rb
60
+ - lib/frypan/tuner.rb
61
+ - lib/frypan/version.rb
62
+ - unit_test/test_node.rb
63
+ homepage: ''
64
+ licenses:
65
+ - MIT
66
+ metadata: {}
67
+ post_install_message:
68
+ rdoc_options: []
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ requirements: []
82
+ rubyforge_project:
83
+ rubygems_version: 2.2.2
84
+ signing_key:
85
+ specification_version: 4
86
+ summary: Yet another recording scheduler.
87
+ test_files: []