OSDN Git Service

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