OSDN Git Service

t#32046:
[pettanr/pettanr.git] / app / models / sheet_panel.rb
1 class SheetPanel < ActiveRecord::Base
2   belongs_to :author
3   belongs_to :panel
4   belongs_to :sheet
5   
6   validates :sheet_id, :presence => true, :numericality => true, :existence => {:both => false}
7   validates :panel_id, :presence => true, :numericality => true, :existence => {:both => false}
8   validates :author_id, :presence => true, :numericality => true, :existence => {:both => false}
9   validates :x, :presence => true, :numericality => true
10   validates :y, :presence => true, :numericality => true
11   validates :z, :presence => true, :numericality => {:greater_than => 0}
12   validates :t, :presence => true, :numericality => {:greater_than_or_equal_to => 0}
13   
14   def supply_default
15     self.sheet_id = nil
16     self.panel_id = nil
17     self.x = 15
18     self.y = 15
19     self.z = 1
20     self.t = nil
21   end
22   
23   def overwrite au
24     return false unless au
25     self.author_id = au.id
26   end
27   
28   def own? roles
29     roles = [roles] unless roles.respond_to?(:each)
30     au = SheetPanel.get_author_from_roles roles
31     return false unless au
32     self.author_id == au.id
33   end
34   
35   def visible? roles
36     if MagicNumber['run_mode'] == 0
37       return false unless guest_role_check(roles)
38     else
39       return false unless reader_role_check(roles)
40     end
41     return true if self.sheet.own?(roles)
42     self.sheet.visible? roles
43   end
44   
45   def self.default_panel_size
46     30
47   end
48   
49   def self.max_panel_size
50     200
51   end
52   
53   def self.offset cnt, prm = nil
54     offset = prm.to_i
55     offset = cnt - 1 if offset >= cnt
56     offset = cnt - offset.abs if offset < 0
57     offset = 0 if offset < 0
58     offset
59   end
60   
61   def self.panel_count cnt, prm = self.default_panel_size
62     count = prm.to_i
63     count = self.max_panel_size if count > self.max_panel_size
64     count = self.default_panel_size if count < 1
65     count
66   end
67   
68   def self.default_page_size
69     25
70   end
71   
72   def self.max_page_size
73     100
74   end
75   
76   def self.page prm = nil
77     page = prm.to_i
78     page = 1 if page < 1
79     page
80   end
81   
82   def self.page_size prm = self.default_page_size
83     page_size = prm.to_i
84     page_size = self.max_page_size if page_size > self.max_page_size
85     page_size = self.default_page_size if page_size < 1
86     page_size
87   end
88   
89   def self.play_list_where cid
90     ['sheet_panels.sheet_id = ?', cid]
91   end
92   
93   def self.list_where
94     'sheets.visible > 0'
95   end
96   
97   def self.mylist_where au
98     ['sheet_panels.author_id = ?', au.id]
99   end
100   
101   def self.himlist_where au
102     ['sheet_panels.author_id = ? and sheets.visible > 0', au.id]
103   end
104   
105   def self.play_list sheet, author, offset = 0, limit = SheetPanel.default_panel_size
106     SheetPanel.where(self.play_list_where(sheet.id)).includes(SheetPanel.list_opt).order('sheet_panels.t').offset(offset).limit(limit)
107   end
108   
109   def self.list page = 1, page_size = self.default_page_size
110     SheetPanel.where(self.list_where()).includes(SheetPanel.list_opt).order('sheet_panels.updated_at desc').offset((page -1) * page_size).limit(page_size)
111   end
112   
113   def self.mylist au, page = 1, page_size = Author.default_sheet_panel_page_size
114     SheetPanel.where(self.mylist_where(au)).includes(SheetPanel.list_opt).order('sheet_panels.updated_at desc').offset((page -1) * page_size).limit(page_size)
115   end
116   
117   def self.himlist au, page = 1, page_size = Author.default_sheet_panel_page_size
118     SheetPanel.where(self.himlist_where(au)).includes(SheetPanel.list_opt).order('sheet_panels.updated_at desc').offset((page -1) * page_size).limit(page_size)
119   end
120   
121   def self.list_paginate page = 1, page_size = self.default_page_size
122     Kaminari.paginate_array(Array.new(SheetPanel.where(self.list_where()).includes(SheetPanel.list_opt).count, nil)).page(page).per(page_size)
123   end
124   
125   def self.mylist_paginate au, page = 1, page_size = Author.default_sheet_panel_page_size
126     Kaminari.paginate_array(Array.new(SheetPanel.where(self.mylist_where(au)).includes(SheetPanel.list_opt).count, nil)).page(page).per(page_size)
127   end
128   
129   def self.himlist_paginate au, page = 1, page_size = Author.default_sheet_panel_page_size
130     Kaminari.paginate_array(Array.new(SheetPanel.where(self.himlist_where(au)).includes(SheetPanel.list_opt).count, nil)).page(page).per(page_size)
131   end
132   
133   def self.list_opt
134     {
135       :author => {}, 
136       :sheet => {
137         :author => {}
138       }, 
139       :panel => {
140         :author => {}, 
141         :panel_pictures => {:picture => {:artist => {}, :license => {}}}, 
142         :speech_balloons =>{:balloon => {}, :speech => {}}
143       }
144     }
145   end
146   
147   def self.list_json_opt
148     {:include => {
149       :author => {}, 
150       :sheet => {
151         :author => {}
152       }, 
153       :panel => {
154         :author => {}, 
155         :panel_pictures => {:picture => {:artist => {}, :license => {}}}, 
156         :speech_balloons =>{:balloon => {}, :speech => {}}
157       }
158     }}
159   end
160   
161   def self.show spid, roles
162     opt = {}
163     opt.merge!(SheetPanel.show_opt)
164     res = SheetPanel.find spid, opt
165     raise ActiveRecord::Forbidden unless res.visible?(roles)
166     res
167   end
168   
169   def self.edit spid, au
170     opt = {}
171     opt.merge!(SheetPanel.show_opt)
172     res = SheetPanel.find spid, opt
173     raise ActiveRecord::Forbidden unless res.own?(au)
174     res
175   end
176   
177   def self.show_opt
178     {:include => {
179       :author => {}, 
180       :sheet => {
181         :author => {}
182       }, 
183       :panel => {
184         :author => {}, 
185         :panel_pictures => {:picture => {:artist => {}, :license => {}}}, 
186         :speech_balloons =>{:balloon => {}, :speech => {}}
187       }
188     }}
189   end
190   
191   def elements
192     self.panel.elements
193   end
194   
195   def sheet_panel_as_json au
196     panel_include = if self.panel and self.panel.visible?(au)
197       {:include => {:author => {}}, :methods => :elements}
198     else
199       {:include => {:author => {}}}
200     end
201     self.to_json({:include => {:sheet => {:include => {:author => {}}}, :author => {}, :panel => panel_include}})
202   end
203   
204   def self.list_as_json_text ary, au
205     '[' + ary.map {|i| i.sheet_panel_as_json(au) }.join(',') + ']'
206   end
207   
208   def self.licensed_pictures sheet_panels
209     r = {}
210     sheet_panels.each do |sheet_panel|
211       r.merge!(sheet_panel.panel.licensed_pictures) if sheet_panel.panel
212     end
213     r
214   end
215   
216   def self.new_t sheet_id
217     r = SheetPanel.max_t(sheet_id)
218     r.blank? ? 0 : r.to_i + 1
219   end
220   
221   def self.max_t sheet_id
222     SheetPanel.maximum(:t, :conditions => ['sheet_id = ?', sheet_id])
223   end
224   
225   def self.find_t sheet_id, t
226     SheetPanel.find(:first, :conditions => ['sheet_id = ? and t = ?', sheet_id, t])
227   end
228   
229   def self.collect_t sheet_panel
230     r = SheetPanel.find(:all, :conditions => ['sheet_id = ?', sheet_panel.sheet_id], :order => 't')
231     r.map {|sp| sp.t}
232   end
233   
234   def self.serial? ary
235     i = 0
236     ary.compact.sort.each do |t|
237       break false unless t == i
238       i += 1
239     end
240     ary.compact.size == i
241   end
242   
243   def self.validate_t sheet_panel
244     SheetPanel.serial?(SheetPanel.collect_t(sheet_panel))
245   end
246   
247   def insert_shift
248     SheetPanel.update_all('t = t + 1', ['sheet_id = ? and t >= ?', self.sheet_id, self.t])
249   end
250   
251   def lesser_shift old_t
252     self.t = 0 if self.t < 0
253     SheetPanel.update_all('t = t + 1', ['sheet_id = ? and (t >= ? and t < ?)', self.sheet_id, self.t, old_t])
254   end
255   
256   def higher_shift old_t
257     nf = SheetPanel.find_t(self.sheet_id, self.t)
258     max_t = SheetPanel.max_t(self.sheet_id).to_i
259     self.t = max_t if self.t > max_t
260     SheetPanel.update_all('t = t - 1', ['sheet_id = ? and (t > ? and t <= ?)', self.sheet_id, old_t, self.t])
261   end
262   
263   def update_shift old_t
264     if self.t > old_t
265       higher_shift old_t
266     else
267       lesser_shift old_t
268     end
269   end
270   
271   def rotate old_t = nil
272     if self.new_record?
273       if self.t.blank?
274         self.t = SheetPanel.new_t self.sheet_id
275       else
276         self.insert_shift
277       end
278     else
279       if self.t.blank?
280       else
281         self.update_shift old_t
282       end
283     end
284   end
285   
286   def allow?
287     return nil if self.sheet_id == nil or self.panel_id == nil
288     self.sheet.own?(self.author) and self.panel.usable?(self.author)
289   end
290   
291   def store old_t = nil
292     res = false
293     SheetPanel.transaction do
294       case self.allow?
295       when true
296         self.rotate old_t
297       when false
298         raise ActiveRecord::Forbidden
299       else
300       end
301       res = self.save
302       raise ActiveRecord::Rollback unless res
303       res = SheetPanel.validate_t(self) 
304       unless res
305         self.errors.add :t, 'unserialized'
306         raise ActiveRecord::Rollback 
307       end
308     end
309     res
310   end
311   
312   def destroy_and_shorten
313     res = false
314     SheetPanel.transaction do
315       SheetPanel.update_all('t = t - 1', ['sheet_id = ? and (t > ?)', self.sheet_id, self.t])
316       raise ActiveRecord::Rollback unless self.destroy
317       res = true
318     end
319     res
320   end
321   
322 end