OSDN Git Service

e0f98edf40ee8d4fba46c9ccb918d062fff8eafd
[pettanr/pettanr.git] / app / models / story_sheet.rb
1 class StorySheet < Peta::Leaf
2   load_manifest
3   belongs_to :author
4   belongs_to :story
5   belongs_to :sheet
6   
7   validates :story_id, :presence => true, :numericality => true, :existence => {:both => false}
8   validates :sheet_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.story_id = nil
14     self.sheet_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_where
29     'stories.visible > 0'
30   end
31   
32   def self.list_order
33     'story_sheets.updated_at desc'
34   end
35   
36   def self.play_sheet_where sid
37     ['story_sheets.story_id = ?', sid]
38   end
39   
40  def self.page prm = nil
41     page = prm.to_i
42     page = 1 if page < 1
43     page
44   end
45   def self.play_sheet story, operators, page = 1
46     ss = StorySheet.where(self.play_sheet_where(story.id)).includes(StorySheet.list_opt).order('story_sheets.t').offset(page -1).limit(1).first
47     if ss 
48       if ss.sheet
49         Sheet.show(ss.sheet.id, operators)
50       else
51         nil
52       end
53     else
54       nil
55     end
56   end
57   
58   def self.play_paginate story, page
59     Kaminari.paginate_array(Array.new(StorySheet.where(self.play_sheet_where(story.id)).includes(StorySheet.list_opt).count, nil)).page(page).per(1)
60   end
61   
62   def self.by_author_list_includes
63     {
64       :story => {
65         :comic => {
66           :author => {}
67         }
68       }
69     }
70   end
71   
72   def self.list_opt
73     {
74       :author => {}, 
75       :story => {
76       }, 
77       :sheet => {
78         :author => {},
79       }
80     }
81   end
82   
83   def self.list_json_opt
84     {:include => {
85       :author => {}, 
86       :story => {} ,
87       :sheet => {:include => {:author => {}}} 
88     }}
89   end
90   
91   def self.show_opt
92     {:include => {
93       :author => {}, 
94       :story => {}, 
95       :sheet => {
96         :author => {} 
97       }
98     }}
99   end
100   
101   def self.show_json_opt
102     {:include => {
103       :author => {}, 
104       :story => {} ,
105       :sheet => {:include => {:author => {}}} 
106     }}
107   end
108   
109   def elements
110     self.panel.elements
111   end
112   
113   def story_sheet_as_json au
114     panel_include = if self.panel and self.panel.visible?(au)
115       {:include => {:author => {}}, :methods => :elements}
116     else
117       {:include => {:author => {}}}
118     end
119     self.to_json({:include => {:scroll => {:include => {:author => {}}}, :author => {}, :panel => panel_include}})
120   end
121   
122   def self.list_as_json_text ary, au
123     '[' + ary.map {|i| i.story_sheet_as_json(au) }.join(',') + ']'
124   end
125   
126   def self.new_t story_id
127     r = StorySheet.max_t(story_id)
128     r.blank? ? 0 : r.to_i + 1
129   end
130   
131   def self.top_sheet story, author
132     StorySheet.play_list(story, author).first
133   end
134   
135   def self.max_t story_id
136     StorySheet.maximum(:t, :conditions => ['story_id = ?', story_id])
137   end
138   
139   def self.find_t story_id, t
140     StorySheet.find(:first, :conditions => ['story_id = ? and t = ?', story_id, t])
141   end
142   
143   def self.collect_t story_sheet
144     r = StorySheet.find(:all, :conditions => ['story_id = ?', story_sheet.story_id], :order => 't')
145     r.map {|sp| sp.t}
146   end
147   
148   def self.serial? ary
149     i = 0
150     ary.compact.sort.each do |t|
151       break false unless t == i
152       i += 1
153     end
154     ary.compact.size == i
155   end
156   
157   def self.validate_t story_sheet
158     StorySheet.serial?(StorySheet.collect_t(story_sheet))
159   end
160   
161   def insert_shift
162     StorySheet.update_all('t = t + 1', ['story_id = ? and t >= ?', self.story_id, self.t])
163   end
164   
165   def lesser_shift old_t
166     self.t = 0 if self.t < 0
167     StorySheet.update_all('t = t + 1', ['story_id = ? and (t >= ? and t < ?)', self.story_id, self.t, old_t])
168   end
169   
170   def higher_shift old_t
171     nf = StorySheet.find_t(self.story_id, self.t)
172     max_t = StorySheet.max_t(self.story_id).to_i
173     self.t = max_t if self.t > max_t
174     StorySheet.update_all('t = t - 1', ['story_id = ? and (t > ? and t <= ?)', self.story_id, old_t, self.t])
175   end
176   
177   def update_shift old_t
178     if self.t > old_t
179       higher_shift old_t
180     else
181       lesser_shift old_t
182     end
183   end
184   
185   def rotate old_t = nil
186     if self.new_record?
187       if self.t.blank?
188         self.t = StorySheet.new_t self.story_id
189       else
190         self.insert_shift
191       end
192     else
193       if self.t.blank?
194       else
195         self.update_shift old_t
196       end
197     end
198   end
199   
200   def allow? operators
201     return nil if self.story_id == nil or self.sheet_id == nil
202     self.story.own?(operators) and self.sheet.usable?(operators)
203   end
204   
205   def store operators, old_t = nil
206     res = false
207     StorySheet.transaction do
208       case self.allow? operators
209       when true
210         self.rotate old_t
211       when false
212         raise ActiveRecord::Forbidden
213       else
214       end
215       res = self.save
216       raise ActiveRecord::Rollback unless res
217       res = StorySheet.validate_t(self) 
218       unless res
219         self.errors.add :t, 'unserialized'
220         raise ActiveRecord::Rollback 
221       end
222     end
223     res
224   end
225   
226   def destroy_and_shorten
227     res = false
228     StorySheet.transaction do
229       StorySheet.update_all('t = t - 1', ['story_id = ? and (t > ?)', self.story_id, self.t])
230       raise ActiveRecord::Rollback unless self.destroy
231       res = true
232     end
233     res
234   end
235   
236 end