ruby + win32ole で、iTunesのプレイリストを自動生成するプログラム (その2)

少しづつ機能を拡張している最中です。
ファイル名をtodays_itunes.rbにしました。

●追加機能

  • 再生回数の多いアルバム1〜100位をランダムで1つピックアップ
  • 再生回数の多いアーティスト1〜100位をランダム1つピックアップ
  • レーティングプレイリスト、★〜★★★★★を追加
  • 追加日、再生日は現在時間では無く全曲で一番最近の時間を参考にするように(今までは実行時の時間を使っていた)
  • テスト用実行機能を追加 -t オプション
#! ruby

require 'win32ole'
require 'parsedate'

class TodaysITunes
  module ITunes
  end

  # コンストラクタ
  def initialize
    message("初期化中です...")
    
    @itunes = WIN32OLE.new("iTunes.application")
    WIN32OLE.const_load(@itunes,ITunes)

    # 不要なジャンルを除外する
    @tracks = []
    @itunes.LibraryPlaylist.Tracks.each do |track|
      @tracks << track if (validTrack(track))
    end
  end

  # 全て作成
  def createAll
    createFolder
    createRandom100
    createPlayCount
    createHighRate
    createPlay0
    createRecentAdd
    createPlayedDate
    createBestArtist
    createBestAlbum
  end

  def createTest
    createFolder
    createBestArtist
    createBestAlbum
  end

  private

  # 含めるべきトラックか?
  def validTrack(track)
    case track.Genre
    when 'Books & Spoken', 'Podcast', 'Movies'
      return false
    end

    if (track.Kind != 1)        # ITTrackKindFile
      return false
    end

    return true
  end

  # トラック数を得る
  def trackNum()
    @itunes.LibraryPlaylist.Tracks.Count
  end

  # デバッグメッセージ
  def message(msg)
    puts msg
    STDOUT.flush
  end

  # フォルダ作成
  def createFolder
    message("フォルダ作成...")

    folderName = '【今I】今日のiTunes'
    
    # 古いフォルダがあったら削除
    playlist = @itunes.LibrarySource.Playlists.ItemByName(folderName)
    playlist.Delete if (playlist)

    # フォルダ作成
    @folder = @itunes.CreateFolder(folderName)
  end

  # プレイリスト作成
  def createPlayList(name)
    message("'#{name}'を作成中...")
    playlist = @itunes.CreatePlaylist('【今I】' + name)
    playlist.Parent = @folder
    playlist
  end

  # ランダムプレイリストを作成
  def createRandom100
    playlist = createPlayList('ランダム100')

    (1..100).each do
      playlist.AddTrack(@tracks[rand(@tracks.size)])
    end
  end

  # 再生回数を利用したプレイリストを作成
  def createPlayCount
    playlist = createPlayList('再生回数が多い100')

    sorted = @tracks.sort_by do |track|
      track.PlayedCount
    end

    sorted.reverse!

    (1..100).each do |i|
      playlist.AddTrack(sorted[i])
    end
  end

  # レートの高いものを取得
  def createHighRate
    playlist1 = createPlayList('')
    playlist2 = createPlayList('★★')
    playlist3 = createPlayList('★★★')
    playlist4 = createPlayList('★★★★')
    playlist5 = createPlayList('★★★★★')

    @tracks.each do |track|
      playlist1.AddTrack(track) if (track.Rating >= 20)
      playlist2.AddTrack(track) if (track.Rating >= 40)
      playlist3.AddTrack(track) if (track.Rating >= 60)
      playlist4.AddTrack(track) if (track.Rating >= 80)
      playlist5.AddTrack(track) if (track.Rating >= 100)
    end
  end

  # 未再生
  def createPlay0
    playlist = createPlayList('未再生')

    @tracks.each do |track|
      playlist.AddTrack(track) if (track.PlayedCount == 0)
    end
  end

  # 最近一ヶ月で追加
  def createRecentAdd
    # 一番最近の追加時間
    recentAdded = Time::at(0)
      
    @tracks.each do |track|
      trackDate = Time::local(*ParseDate::parsedate(track.DateAdded)[0..-3])
      recentAdded = trackDate if (recentAdded < trackDate)
    end

    # プレイリスト作成
    playlist1 = createPlayList('一日以内に追加')
    playlist2 = createPlayList('一週間以内に追加')
    playlist3 = createPlayList('一ヶ月以内に追加')
    dayTime = 60 * 60 * 24

    @tracks.each do |track|
      trackDate = Time::local(*ParseDate::parsedate(track.DateAdded)[0..-3])
      playlist1.AddTrack(track) if (recentAdded - trackDate < dayTime * 1)
      playlist2.AddTrack(track) if (recentAdded - trackDate < dayTime * 7)
      playlist3.AddTrack(track) if (recentAdded - trackDate < dayTime * 30)
    end
  end

  # 最近一ヶ月で聞いた
  def createPlayedDate
    # 一番最近の追加時間
    recentPlayed = Time::at(0)
      
    @tracks.each do |track|
      if (track.PlayedCount > 0)
        trackDate = Time::local(*ParseDate::parsedate(track.PlayedDate)[0..-3])
        recentPlayed = trackDate if (recentPlayed < trackDate)
      end
    end

    # プレイリスト作成
    playlist1 = createPlayList('一日以内に聞いた')
    playlist2 = createPlayList('一週間以内に聞いた')
    playlist3 = createPlayList('一ヶ月以内に聞いた')
    dayTime = 60 * 60 * 24

    @tracks.each do |track|
      if (track.PlayedCount > 0)
        trackDate = Time::local(*ParseDate::parsedate(track.PlayedDate)[0..-3])
        playlist1.AddTrack(track) if (recentPlayed - trackDate < dayTime * 1)
        playlist2.AddTrack(track) if (recentPlayed - trackDate < dayTime * 7)
        playlist3.AddTrack(track) if (recentPlayed - trackDate < dayTime * 30)
      end
    end
  end

  # よく聞くアーティスト Best5
  def createBestArtist
    artist = Hash.new

    @tracks.each do |track|
      addHash(artist, track.Artist, track.PlayedCount)
    end

    artist = artist.to_a.sort_by { |a| a[1] }.reverse

    # 一番よく聞く
    playlist = createPlayList("一番よく聞くアーティスト #{artist[0][0]}")

    @tracks.each do |track|
      playlist.AddTrack(track) if (track.Artist == artist[0][0])
    end

    # Best5
    playlist = createPlayList('よく聞くアーティスト Best5')

    (0..4).each do |index|
      @tracks.each do |track|
        playlist.AddTrack(track) if (track.Artist == artist[index][0])
      end
    end

    # 一枚ピックアップ
    size = 100
    size = artist.size if (artist.size < 100)
    targetRank = rand(size)
    targetArtist = artist[targetRank][0]
    playlist = createPlayList("#{targetRank}番目によく聞くアーティスト #{targetArtist}")

    @tracks.each do |track|
      playlist.AddTrack(track) if (track.Artist == targetArtist)
    end
  end

  # よく聞くアルバム Best5
  def createBestAlbum
    album = Hash.new

    @tracks.each do |track|
      addHash(album, track.Album, track.PlayedCount)
    end

    album = album.to_a.sort_by { |a| a[1] }.reverse

    # 一番よく聞く
    playlist = createPlayList("一番よく聞くアルバム #{album[0][0]}")

    @tracks.each do |track|
      playlist.AddTrack(track) if (track.Album == album[0][0])
    end

    # Best5
    playlist = createPlayList('よく聞くアルバム Best5')

    (0..4).each do |index|
      @tracks.each do |track|
        playlist.AddTrack(track) if (track.Album == album[index][0])
      end
    end

    # 一枚ピックアップ
    size = 100
    size = album.size if (album.size < 100)
    targetRank = rand(size)
    targetAlbum = album[targetRank][0]
    playlist = createPlayList("#{targetRank}番目によく聞くアルバム #{targetAlbum}")

    @tracks.each do |track|
      playlist.AddTrack(track) if (track.Album == targetAlbum)
    end
  end

  # ハッシュに加算
  def addHash(hash, key, value)
    if (key == '')
      return
    end

    if (hash.has_key? key)
      hash[key] += value
    else
      hash[key] = value
    end
  end

  # ipodの更新
  def update_iPod
    ipod = @itunes.Sources.Item(2)
    ipod.UpdateIPod
  end
end

obj = TodaysITunes.new

if (ARGV[0] == '-t')
  obj.createTest
else
  obj.createAll
end