OSDN Git Service

d1a3961ae6f8ebcce4d7ba71d2d3f0fc8dab3a42
[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.list_opt
63     {
64       :author => {}, 
65       :story => {
66       }, 
67       :sheet => {
68         :author => {},
69       }
70     }
71   end
72   
73   def self.list_json_opt
74     {:include => {
75       :author => {}, 
76       :story => {} ,
77       :sheet => {:include => {:author => {}}} 
78     }}
79   end
80   
81   def self.show_opt
82     {:include => {
83       :author => {}, 
84       :story => {}, 
85       :sheet => {
86         :author => {} 
87       }
88     }}
89   end
90   
91   def self.show_json_opt
92     {:include => {
93       :author => {}, 
94       :story => {} ,
95       :sheet => {:include => {:author => {}}} 
96     }}
97   end
98   
99   def elements
100     self.panel.elements
101   end
102   
103   def story_sheet_as_json au
104     panel_include = if self.panel and self.panel.visible?(au)
105       {:include => {:author => {}}, :methods => :elements}
106     else
107       {:include => {:author => {}}}
108     end
109     self.to_json({:include => {:scroll => {:include => {:author => {}}}, :author => {}, :panel => panel_include}})
110   end
111   
112   def self.list_as_json_text ary, au
113     '[' + ary.map {|i| i.story_sheet_as_json(au) }.join(',') + ']'
114   end
115   
116   def self.new_t story_id
117     r = StorySheet.max_t(story_id)
118     r.blank? ? 0 : r.to_i + 1
119   end
120   
121   def self.top_sheet story, author
122     StorySheet.play_list(story, author).first
123   end
124   
125   def self.max_t story_id
126     StorySheet.maximum(:t, :conditions => ['story_id = ?', story_id])
127   end
128   
129   def self.find_t story_id, t
130     StorySheet.find(:first, :conditions => ['story_id = ? and t = ?', story_id, t])
131   end
132   
133   def self.collect_t story_sheet
134     r = StorySheet.find(:all, :conditions => ['story_id = ?', story_sheet.story_id], :order => 't')
135     r.map {|sp| sp.t}
136   end
137   
138   def self.serial? ary
139     i = 0
140     ary.compact.sort.each do |t|
141       break false unless t == i
142       i += 1
143     end
144     ary.compact.size == i
145   end
146   
147   def self.validate_t story_sheet
148     StorySheet.serial?(StorySheet.collect_t(story_sheet))
149   end
150   
151   def insert_shift
152     StorySheet.update_all('t = t + 1', ['story_id = ? and t >= ?', self.story_id, self.t])
153   end
154   
155   def lesser_shift old_t
156     self.t = 0 if self.t < 0
157     StorySheet.update_all('t = t + 1', ['story_id = ? and (t >= ? and t < ?)', self.story_id, self.t, old_t])
158   end
159   
160   def higher_shift old_t
161     nf = StorySheet.find_t(self.story_id, self.t)
162     max_t = StorySheet.max_t(self.story_id).to_i
163     self.t = max_t if self.t > max_t
164     StorySheet.update_all('t = t - 1', ['story_id = ? and (t > ? and t <= ?)', self.story_id, old_t, self.t])
165   end
166   
167   def update_shift old_t
168     if self.t > old_t
169       higher_shift old_t
170     else
171       lesser_shift old_t
172     end
173   end
174   
175   def rotate old_t = nil
176     if self.new_record?
177       if self.t.blank?
178         self.t = StorySheet.new_t self.story_id
179       else
180         self.insert_shift
181       end
182     else
183       if self.t.blank?
184       else
185         self.update_shift old_t
186       end
187     end
188   end
189   
190   def allow? operators
191     return nil if self.story_id == nil or self.sheet_id == nil
192     self.story.own?(operators) and self.sheet.usable?(operators)
193   end
194   
195   def store operators, old_t = nil
196     res = false
197     StorySheet.transaction do
198       case self.allow? operators
199       when true
200         self.rotate old_t
201       when false
202         raise ActiveRecord::Forbidden
203       else
204       end
205       res = self.save
206       raise ActiveRecord::Rollback unless res
207       res = StorySheet.validate_t(self) 
208       unless res
209         self.errors.add :t, 'unserialized'
210         raise ActiveRecord::Rollback 
211       end
212     end
213     res
214   end
215   
216   def destroy_and_shorten
217     res = false
218     StorySheet.transaction do
219       StorySheet.update_all('t = t - 1', ['story_id = ? and (t > ?)', self.story_id, self.t])
220       raise ActiveRecord::Rollback unless self.destroy
221       res = true
222     end
223     res
224   end
225   
226 end