OSDN Git Service

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