Added support for GPSShogi engine
[kaya.git] / lib / plugins / engines / loader.rb
blob6bc44ae0d75e80b9eb37c9bff22d19447098fed4
1 # Copyright (c) 2009 Paolo Capriotti <p.capriotti@gmail.com>
2
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 2 of the License, or
6 # (at your option) any later version.
8 require 'toolkit'
9 require 'plugins/plugin'
10 require 'factory'
11 require_bundle 'engines', 'find_exe'
13 class EngineLoader
14   include Plugin
15   include Enumerable
16   
17   class Entry < Factory
18     AUTOLOADABLE_ENTRIES = {
19       'gnuchess' => { :name => 'GNU Chess',
20                       :game => :chess,
21                       :protocol => 'XBoard',
22                       :workdir => '/tmp' },
23       'crafty' => { :name => 'Crafty',
24                     :game => :chess,
25                     :protocol => 'XBoard',
26                     :workdir => '/tmp' },
27       'gnushogi' => { :name => 'GNU Shogi',
28                       :game => :shogi,
29                       :protocol => 'GNUShogi',
30                       :workdir => '/tmp' },
31       'gpsshogi' => { :name => 'GPSShogi',
32                       :game => :shogi,
33                       :protocol => 'GPSShogi',
34                       :workdir => '/tmp' } }
35     
36     attr_accessor :name
37     attr_accessor :game
38     attr_accessor :protocol
39     attr_accessor :workdir
40     attr_accessor :path
41     attr_accessor :arguments
42   
43     def initialize(data)
44       loader = PluginLoader.new
45       plugin = loader.get_all_matching(:engine).find do |e|
46         e.data(:protocol) == data[:protocol]
47       end
48       fact = lambda do |color, match|
49         plugin.new(@path, @name, color, match, 
50                    :workdir => @workdir,
51                    :args => @arguments)
52       end
53       super(&fact)
54       
55       @name = data[:name]
56       @game = Game.get(data[:game])
57       @protocol = data[:protocol]
58       @arguments = data[:arguments]
59       @workdir = data[:workdir]
60       @path = data[:path]
61     end
62     
63     def self.load(name, group)
64       entries = group.entry_map
65       entries['game'] ||= ''
66       new :name => name,
67           :game => entries['game'].to_sym,
68           :path => entries['path'],
69           :protocol => entries['protocol'],
70           :arguments => entries['arguments'],
71           :workdir => entries['workdir']
72     end
73     
74     def save(group)
75       group.write_entry('game', @game.class.data(:id).to_s)
76       group.write_entry('path', @path.to_s)
77       group.write_entry('protocol', @protocol.to_s)
78       group.write_entry('arguments', @arguments.to_s)
79       group.write_entry('workdir', @workdir.to_s)
80     end
81   end
82   
83   plugin :name => 'Default Engine Loader',
84          :interface => :engine_loader
86   def reload
87     @entries = { }
88     config = KDE::Global.config.group("Engines")
89     autoload unless config.exists
90     engine_groups = config.group_list
91     engine_groups.each do |engine_group|
92       entry = Entry.load(engine_group, config.group(engine_group))
93       @entries[entry.name] = entry
94     end
95   end
96   
97   def autoload
98     entries = { }
99     Entry::AUTOLOADABLE_ENTRIES.each do |keyword, data|
100       path = File.which(keyword)
101       if path
102         data = data.merge(:path => path)
103         entries[data[:name]] = Entry.new(data)
104       end
105     end
106     update_entries(entries) unless entries.empty?
107   end
108   
109   def update_entries(entries)
110     @entries = entries.dup
111     
112     config = KDE::Global.config.group("Engines")
113     config.delete_group
115     @entries.each do |name, engine|
116       group = config.group(name)
117       engine.save(group)
118     end
119     config.sync
120   end
121   
122   def [](name)
123     @entries[name]
124   end
126   def find_by_game(game)
127     @entries.select do |name, e|
128       e.game == game
129     end
130   end
131   
132   def each(&blk)
133     @entries.each(&blk)
134   end
135   
136   def size
137     @entries.size
138   end
139   
140   def engine
141     Entry
142   end