OSDN Git Service

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