2012年9月14日金曜日

予約の衝突とデバイス選択

皆さんこんにちは。レコーダーネタです。
予約をした際、その時間は録画が実行可能なのかを判断する仕組みについて。

判断材料は対応放送波のデバイスの数、録画開始/終了時間、優先度。
予約登録時に使用するデバイスを決めておくのが大前提。

時間についてはきっとこうなる。
衝突候補は「開始時間Sと終了時間Eの間に他予約の開始時間S'若しくは終了時間E'がある」「EとS'あるいはSとE'は同時(連続した番組)」は許容する。

  ( ss >= s ) & ( ss < e )  or ( ee > s ) & ( ee <= e )

衝突する例

A|     S-----------E
B| S'-----E'
C|           S'-------E'

この例では、BとCは衝突してないのでデバイスが2つあれば全部録画できるが、仮にBとCが衝突しているとデバイスは3つ必要になる。

衝突していたらデバイスの空きを調べる。

# 対応デバイスのリスト
devices = Groonga['Devices'].select do |dev|
  # type は放送波種別
  dev.type == program.channel.type
end.sort(['number'])

# 予約時間がかぶってるのを探す
reserves = Groonga['Reserves'].select do |res|
  (
    ( res.start >= program.start ) & ( res.start < program.stop )
  ) |
  (
    ( res.stop >  program.start ) & ( res.stop <= program.stop )
  )
end

if reserves.size > 0
  # 予約したい時間に使用中のデバイスを除外する
  reserves.each do |res|
    devices.reject! do |dev| dev._id == res.device._id end
  end
end

return devices.first

ちなみに、Groonga の select で使う expression は右辺にブロック変数をもってくることができない
わざわざ_idでデバイスの同一チェックしてるのは select で返ってくるオブジェクトはレコードの実体ではないから。

あと、この一連の操作(チェックから予約を登録するまで)は完全に排他でやらないと破滅する。

さて、このあと予約優先度を考慮してもし低めの予約と衝突したら入れ替えるよにしなきゃならなのだけどまだ実装してないので今度。ハードスケジュールなタイミングではいろいろ面倒くさそうである。

一番楽なのは衝突していようがとりあえず登録して、録画開始時にデバイスが一杯だったら優先度低い奴止めるみたいな仕組みだと思うけど、それはわりと怖いし、この記事の意味がなくなる。

0 件のコメント:

コメントを投稿