OSDN Git Service

add binder
[pettanr/pettanr.git] / app / models / scroll_panel.rb
1 class ScrollPanel < Peta::Leaf
2   load_manifest
3   belongs_to :author
4   belongs_to :panel
5   belongs_to :scroll
6   
7   validates :scroll_id, :presence => true, :numericality => true, :existence => {:both => false}
8   validates :panel_id, :presence => true, :numericality => true, :existence => {:both => false}
9   validates :author_id, :presence => true, :numericality => true, :existence => {:both => false}
10   validates :t, :presence => true, :numericality => {:greater_than_or_equal_to => 0}
11   
12   def supply_default
13     self.scroll_id = nil
14     self.panel_id = nil
15     self.t = nil
16   end
17   
18   def overwrite operators
19     return false unless operators.author
20     self.author_id = operators.author.id
21   end
22   
23   def visible? operators
24     return false unless super
25     self.owner_model.visible? operators
26   end
27   
28   def self.list_order
29     'scroll_panels.updated_at desc'
30   end
31   
32   def self.list_where
33     'scrolls.visible > 0'
34   end
35   
36   def self.play_list_where cid
37     ['scroll_panels.scroll_id = ?', cid]
38   end
39   
40   def self.play_list scroll, author, offset = 0, limit = ScrollPanel.default_panel_size
41     ScrollPanel.where(self.play_list_where(scroll.id)).includes(ScrollPanel.list_opt).order('scroll_panels.t').offset(offset).limit(limit)
42   end
43   
44   def self.list_opt
45     {
46       :author => {}, 
47       :scroll => {
48         :author => {}
49       }, 
50       :panel => {
51         :author => {}, 
52         :panel_pictures => {:picture => {:artist => {}, :license => {}}}, 
53         :speech_balloons =>{:balloon => {}, :speech => {}}
54       }
55     }
56   end
57   
58   def self.list_json_opt
59     {:include => {
60       :author => {}, 
61       :scroll => {
62         :author => {}
63       }, 
64       :panel => {
65         :author => {}, 
66         :panel_pictures => {:picture => {:artist => {}, :license => {}}}, 
67         :speech_balloons =>{:balloon => {}, :speech => {}}
68       }
69     }}
70   end
71   
72   def self.show_opt
73     {:include => {
74       :author => {}, 
75       :scroll => {
76         :author => {}
77       }, 
78       :panel => {
79         :author => {}, 
80         :panel_pictures => {:picture => {:artist => {}, :license => {}}}, 
81         :speech_balloons =>{:balloon => {}, :speech => {}}
82       }
83     }}
84   end
85   
86   def elements
87     self.panel.elements
88   end
89   
90   def scroll_panel_as_json au
91     panel_include = if self.panel and self.panel.visible?(au)
92       {:include => {:author => {}}, :methods => :elements}
93     else
94       {:include => {:author => {}}}
95     end
96     self.to_json({:include => {:scroll => {:include => {:author => {}}}, :author => {}, :panel => panel_include}})
97   end
98   
99   def self.list_as_json_text ary, au
100     '[' + ary.map {|i| i.scroll_panel_as_json(au) }.join(',') + ']'
101   end
102   
103   def self.licensed_pictures scroll_panels
104     r = {}
105     scroll_panels.each do |scroll_panel|
106       r.merge!(scroll_panel.panel.licensed_pictures) if scroll_panel.panel
107     end
108     r
109   end
110   
111   def self.new_t scroll_id
112     r = ScrollPanel.max_t(scroll_id)
113     r.blank? ? 0 : r.to_i + 1
114   end
115   
116   def self.max_t scroll_id
117     ScrollPanel.maximum(:t, :conditions => ['scroll_id = ?', scroll_id])
118   end
119   
120   def self.find_t scroll_id, t
121     ScrollPanel.find(:first, :conditions => ['scroll_id = ? and t = ?', scroll_id, t])
122   end
123   
124   def self.collect_t scroll_panel
125     r = ScrollPanel.find(:all, :conditions => ['scroll_id = ?', scroll_panel.scroll_id], :order => 't')
126     r.map {|sp| sp.t}
127   end
128   
129   def self.serial? ary
130     i = 0
131     ary.compact.sort.each do |t|
132       break false unless t == i
133       i += 1
134     end
135     ary.compact.size == i
136   end
137   
138   def self.validate_t scroll_panel
139     ScrollPanel.serial?(ScrollPanel.collect_t(scroll_panel))
140   end
141   
142   def insert_shift
143     ScrollPanel.update_all('t = t + 1', ['scroll_id = ? and t >= ?', self.scroll_id, self.t])
144   end
145   
146   def lesser_shift old_t
147     self.t = 0 if self.t < 0
148     ScrollPanel.update_all('t = t + 1', ['scroll_id = ? and (t >= ? and t < ?)', self.scroll_id, self.t, old_t])
149   end
150   
151   def higher_shift old_t
152     nf = ScrollPanel.find_t(self.scroll_id, self.t)
153     max_t = ScrollPanel.max_t(self.scroll_id).to_i
154     self.t = max_t if self.t > max_t
155     ScrollPanel.update_all('t = t - 1', ['scroll_id = ? and (t > ? and t <= ?)', self.scroll_id, old_t, self.t])
156   end
157   
158   def update_shift old_t
159     if self.t > old_t
160       higher_shift old_t
161     else
162       lesser_shift old_t
163     end
164   end
165   
166   def rotate old_t = nil
167     if self.new_record?
168       if self.t.blank?
169         self.t = ScrollPanel.new_t self.scroll_id
170       else
171         self.insert_shift
172       end
173     else
174       if self.t.blank?
175       else
176         self.update_shift old_t
177       end
178     end
179   end
180   
181   def allow? operators
182     return nil if self.scroll_id == nil or self.panel_id == nil
183     self.scroll.own?(operators) and self.panel.usable?(operators)
184   end
185   
186   def store operators, old_t = nil
187     res = false
188     ScrollPanel.transaction do
189       case self.allow? operators
190       when true
191         self.rotate old_t
192       when false
193         raise ActiveRecord::Forbidden
194       else
195       end
196       res = self.save
197       raise ActiveRecord::Rollback unless res
198       res = ScrollPanel.validate_t(self) 
199       unless res
200         self.errors.add :t, 'unserialized'
201         raise ActiveRecord::Rollback 
202       end
203     end
204     res
205   end
206   
207   def destroy_and_shorten
208     res = false
209     ScrollPanel.transaction do
210       ScrollPanel.update_all('t = t - 1', ['scroll_id = ? and (t > ?)', self.scroll_id, self.t])
211       raise ActiveRecord::Rollback unless self.destroy
212       res = true
213     end
214     res
215   end
216   
217 end