OSDN Git Service

3a7f329d9af16b71ff0a296787b812d75f9dabc0
[pettanr/pettanr.git] / app / models / story.rb
1 #ストーリー
2 class Story < ActiveRecord::Base
3   belongs_to :author
4   belongs_to :panel
5   belongs_to :comic
6   
7   validates :comic_id, :presence => true, :numericality => true, :existence => true
8   validates :panel_id, :presence => true, :numericality => true, :existence => true
9   validates :author_id, :presence => true, :numericality => true, :existence => true
10   validates :t, :presence => true, :numericality => {:greater_than_or_equal_to => 0}
11   
12   def supply_default
13     self.t = nil
14   end
15   
16   def overwrite au
17     return false unless au
18     self.author_id = au.id
19   end
20   
21   def own? au
22     return false unless au.is_a?(Author)
23     self.author_id == au.id
24   end
25   
26   def visible? au
27     if au == nil
28       return false if MagicNumber['run_mode'] == 1
29     elsif au.is_a?(Author)
30       return true if self.comic.own?(au)
31     else
32       return false
33     end
34     self.comic.visible? au
35   end
36   
37   def self.default_panel_size
38     30
39   end
40   
41   def self.max_panel_size
42     200
43   end
44   
45   def self.offset cnt, prm = nil
46     offset = prm.to_i
47     offset = cnt - 1 if offset >= cnt
48     offset = cnt - offset.abs if offset < 0
49     offset = 0 if offset < 0
50     offset
51   end
52   
53   def self.panel_count cnt, prm = self.default_panel_size
54     count = prm.to_i
55     count = self.max_panel_size if count > self.max_panel_size
56     count = self.default_panel_size if count < 1
57     count
58   end
59   
60   def self.play_list comic, author, offset = 0, limit = Story.default_panel_size
61     opt = {}
62     opt.merge!(Story.list_opt)
63     opt.merge!({:offset => offset, :limit => limit}) if limit > 0
64     opt.merge!({:conditions => ['stories.comic_id = ?', comic.id], :order => 'stories.t'})
65     Story.find(:all, opt)
66   end
67   
68   def self.list_opt
69     {:include => {
70       :author => {}, 
71       :comic => {
72         :author => {}
73       }, 
74       :panel => {
75         :author => {}, 
76         :panel_pictures => {:picture => {:artist => {}, :license => {}}}, 
77         :speech_balloons =>{:balloons => {}, :speeches => {}}
78       }
79     }}
80   end
81   
82   def self.list_json_opt
83     {:include => {
84       :author => {}, 
85       :comic => {
86         :author => {}
87       }, 
88       :panel => {
89         :author => {}, 
90         :panel_pictures => {:picture => {:artist => {}, :license => {}}}, 
91         :speech_balloons =>{:balloons => {}, :speeches => {}}
92       }
93     }}
94   end
95   
96   def self.mylist au, page = 1, page_size = Author.default_story_page_size
97     opt = {}
98     opt.merge!(Story.list_opt)
99     opt.merge!({:limit => page_size, :offset => (page -1) * page_size}) if page_size > 0
100     opt.merge!({:conditions => ['stories.author_id = ?', au.id], :order => 'stories.updated_at desc'})
101     Story.find(:all, opt)
102   end
103   
104   def self.show sid, au
105     opt = {}
106     opt.merge!(Story.show_opt)
107     res = Story.find sid, opt
108     raise ActiveRecord::Forbidden unless res.visible?(au)
109     res
110   end
111   
112   def self.edit sid, au
113     opt = {}
114     opt.merge!(Story.show_opt)
115     res = Story.find sid, opt
116     raise ActiveRecord::Forbidden unless res.own?(au)
117     res
118   end
119   
120   def self.show_opt
121     {:include => {
122       :author => {}, 
123       :comic => {
124         :author => {}
125       }, 
126       :panel => {
127         :author => {}, 
128         :panel_pictures => {:picture => {:artist => {}, :license => {}}}, 
129         :speech_balloons =>{:balloons => {}, :speeches => {}}
130       }
131     }}
132   end
133   
134   def elements
135     self.panel.elements
136   end
137   
138   def story_as_json au
139     panel_include = if self.panel and self.panel.visible?(au)
140       {:include => {:author => {}}, :methods => :elements}
141     else
142       {:include => {:author => {}}}
143     end
144     self.to_json({:include => {:comic => {:include => {:author => {}}}, :author => {}, :panel => panel_include}})
145   end
146   
147   def self.list_as_json_text ary, au
148     '[' + ary.map {|i| i.story_as_json(au) }.join(',') + ']'
149   end
150   
151   def self.licensed_pictures stories
152     r = {}
153     stories.each do |story|
154       r.merge! story.panel.licensed_pictures
155     end
156     r
157   end
158   
159   def self.new_t comic_id
160     r = Story.max_t(comic_id)
161     r.blank? ? 0 : r.to_i + 1
162   end
163   
164   def self.max_t comic_id
165     Story.maximum(:t, :conditions => ['comic_id = ?', comic_id])
166   end
167   
168   def self.find_t comic_id, t
169     Story.find(:first, :conditions => ['comic_id = ? and t = ?', comic_id, t])
170   end
171   
172   def self.collect_t story
173     r = Story.find(:all, :conditions => ['comic_id = ?', story.comic_id], :order => 't')
174     r.map {|s| s.t}
175   end
176   
177   def self.serial? ary
178     i = 0
179     ary.compact.sort.each do |t|
180       break false unless t == i
181       i += 1
182     end
183     ary.compact.size == i
184   end
185   
186   def self.validate_t story
187     Story.serial?(Story.collect_t(story))
188   end
189   
190   def insert_shift
191     Story.update_all('t = t + 1', ['comic_id = ? and t >= ?', self.comic_id, self.t])
192   end
193   
194   def lesser_shift old_t
195     self.t = 0 if self.t < 0
196     Story.update_all('t = t + 1', ['comic_id = ? and (t >= ? and t < ?)', self.comic_id, self.t, old_t])
197   end
198   
199   def higher_shift old_t
200     nf = Story.find_t(self.comic_id, self.t)
201     max_t = Story.max_t(self.comic_id).to_i
202     self.t = max_t if self.t > max_t
203     Story.update_all('t = t - 1', ['comic_id = ? and (t > ? and t <= ?)', self.comic_id, old_t, self.t])
204   end
205   
206   def update_shift old_t
207     if self.t > old_t
208       higher_shift old_t
209     else
210       lesser_shift old_t
211     end
212   end
213   
214   def rotate old_t = nil
215     if self.new_record?
216       if self.t.blank?
217         self.t = Story.new_t self.comic_id
218       else
219         self.insert_shift
220       end
221     else
222       if self.t.blank?
223       else
224         self.update_shift old_t
225       end
226     end
227   end
228   
229   def allow?
230     c = self.comic
231     pl = self.panel
232     c and c.own?(self.author) and pl and pl.usable?(self.author)
233   end
234   
235   def store old_t = nil
236     res = false
237     raise ActiveRecord::Forbidden unless self.allow?
238     Story.transaction do
239       self.rotate old_t
240       res = self.save
241       raise ActiveRecord::Rollback unless res
242       res = Story.validate_t(self) 
243       unless res
244         self.errors.add :t, 'unserialized'
245         raise ActiveRecord::Rollback 
246       end
247     end
248     res
249   end
250   
251   def destroy_and_shorten
252     Story.transaction do
253       Story.update_all('t = t - 1', ['comic_id = ? and (t > ?)', self.comic_id, self.t])
254       raise ActiveRecord::Rollback unless self.destroy
255     end
256   end
257   
258   
259 end