3 $logger = Logger.new('db/debug.log')
4 $logger.progname = "wtls"
8 @vildb.transaction(true) { @vildb['root'] }
17 if File.exist?('db/.dontdelete')
18 @vid = @req['vid'].to_i
19 @vildb = Store.new("db/vil/#{@vid}.db")
20 $logger = Logger.new('db/debug.log.' + @vid.to_s)
21 $logger.progname = "wtls"
22 # $logger.level = Logger::INFO
25 @head = "Content-Type: text/html; charset=utf-8\r\n"
29 raise ErrorMsg.new('ログインして下さい') if !@login.login
30 raise ErrorMsg.new('村の名前を指定して下さい') if (@req['name'].to_s == '')
31 raise ErrorMsg.new('村の名前が長すぎます') if (@req['name'].to_s.size > 60)
33 _build_village(CGI.escapeHTML(@req['name']))
37 names = IO.readlines(S[:vilnames_path])
38 name = names[rand(names.size)].chomp
43 def _build_village(vilname)
45 update_time = Time.mktime(00, 00, now.hour,
46 now.day, now.month, now.year, nil, nil, nil, nil)
49 while update_time < now
52 update_time += period / 2 if update_time - (period / 2) < now
55 vldb = Store.new('db/vil.db')
56 vid = vldb.transaction do
57 vid = vldb['recent_vid'].to_i + 1
58 vldb['recent_vid'] = vid
64 vil['start'] = update_time
65 vldb['root'].push(vil)
70 @vildb = Store.new("db/vil/#{vid}.db")
71 vil = @vildb.transaction {
72 vil = Vil.new(vilname, vid, @login.userid, update_time)
81 raise ErrorMsg.new("不正な村IDです") if (@vid == 0)
84 raise ErrorMsg.new("不正なキャラクターです") if (!pid)
87 msg = trunc(@req['message'])
90 return if (!msg || msg == '')
92 msg = CGI.escapeHTML(msg).rstrip
93 msg.gsub!(/\r\n/, '<br>')
94 msg.gsub!(/[\r\n]/, '<br>')
95 msg.gsub!(/\n/, '<br>')
96 msg.gsub!(/[\n]/, '<br>')
101 raise ErrorMsg.new('終了しています') if (vil.state == 4)
103 player = vil.players.player(@login)
104 raise ErrorMsg.new("あなた(#{@login.userid})はこの村(#{vil.vid})に参加していません(#{@login.login.inspect})") if !player
105 raise ErrorMsg.new("不正なキャラクターです") if (player.pid != pid)
107 if (!player.can_whisper && type == 'whisper')
108 raise ErrorMsg.new('あなたはささやけません')
110 if (vil.phase == Vil::Phase::Sun && type == 'night')
111 raise ErrorMsg.new('既に夜が明けています')
114 $logger.debug('post by ' + @login.userid + "(#{pid})")
115 vil.record(type, player, msg)
120 raise ErrorMsg.new("不正な村IDです") if (@vid == 0)
123 raise ErrorMsg.new("不正なキャラクターです") if (!pid)
126 msg = trunc(@req['message'])
127 raise ErrorMsg.new("発言が空です") if (!msg || msg == '')
128 raise ErrorMsg.new("発言が長すぎます") if (msg.size > 400)
133 if vil.players.has_key?(@login.userid)
134 raise ErrorMsg.new("エントリー済みです")
135 elsif (vil.state != 0 && vil.state != 1)
136 raise ErrorMsg.new('既に開始しています')
137 elsif vil.players.max == vil.players.size
138 raise ErrorMsg.new("定員に達しています")
139 elsif vil.players.player(pid)
140 raise ErrorMsg.new("既に使用されているキャラクターです")
143 @login.registaddress(@req)
146 player = Player.new(pid, @login.userid, skill)
147 m = CGI::escapeHTML(msg).gsub(/\r\n/, '<br>').gsub(/[\r\n]/, '<br>')
149 vil.add_player(player, m)
154 raise ErrorMsg.new("不正な村IDです") if (@vid == 0)
157 raise ErrorMsg.new("不正なキャラクターです") if (!pid)
162 if (!vil.players.key?(@login.userid))
163 raise ErrorMsg.new("エントリーしていません")
164 elsif (vil.date == 1)
165 raise ErrorMsg.new("既に開始しています")
168 vil.delete_player(vil.players[@login.userid])
173 move = @vildb.transaction do
180 print "Status: 302 Moved Temporary\n"
181 print "Location: log_#{@vid}_#{0}.html\n\n"
187 raise ErrorMsg.new('対象がセットされていません') if (!@req['pid'])
190 pl = vil.players.player(@login)
191 if vil.voting.first() == pl
192 if (vil.phase == Vil::Phase::Room && pl.yesterday_mate.index(@req['pid'].to_i))
193 raise ErrorMsg.new('昨日同室した相手は指定できません')
195 pl.vote = @req['pid'].to_i
196 target = vil.players.player(pl.vote)
197 raise ErrorMsg.new('相手が既に死亡しています') if target.dead?
198 $logger.debug(%Q(#{pl.name} % #{pl.vote}))
201 raise ErrorMsg.new('あなたの順番ではありません')
207 raise ErrorMsg.new('投票先がセットされていません') if (!@req['pid'])
208 yesorno = @req['pid'] =='approve' ? true : false
211 pl = vil.players.player(@login)
212 if vil.voting.first() == pl
216 raise ErrorMsg.new('あなたの順番ではありません')
222 target = (@req['pid'] != '') ? @req['pid'].to_i : nil
226 player = vil.players.player(@login)
227 player.skill_set(vil, target)
234 player = vil.players.player(@login)
235 if (vil.vtargets.index(player) && vil.voting.first == player)
243 cmds = %w(make entry post update prevote vote skill exit commit)
244 __send__('handle_' + cmd) if cmds.index(cmd)
246 comet_cmds = %w(entry post update prevote vote skill exit commit)
247 limitcheck_cmds = %w(post update exit commit)
248 if comet_cmds.index(cmd)
250 limit = (limitcheck_cmds.index(cmd)) ? S[:processlimit] : false
251 Duet::Server.dispatch(S[:ajaxdb_path] + ".#{@req['vid']}", limit)
252 $logger.debug("total time(#{cmd}):" + (Time.now() - t).to_f.to_s)
258 villages = DB::Villages.select {|v| v['state'] != 4 }
259 active_villages = DB::Villages.select {|v| v['state'] != 4}
260 if (S[:autobuildvillage] && active_villages.size < S[:autobuildlimit])
264 print Page::Index.new(@login.form, changes, villages).result()
268 print Page::MakeVillage.new(@login.form).result()
272 print Page::CharList.new(@login.form, NAMES.dup).result()
276 print Page::History.new(@login.form, HISTORY.dup).result()
280 print Page::Info.new(@login.form, INFO.dup).result()
284 #print Page::Regulation.new(@login.form).result() mod 2008/11/08 tkt: hide reg
285 raise ErrorMsg.new("編成は秘密です。")
289 print Page::Document.new(@login.form).result()
293 print Page::LogIndex.new(@login.form).result()
297 @vil = get_ronly_vil(@vid)
299 if @vil.state == Vil::State::End
300 # Vil::Sweeper.sweep(@vil)
301 url = S[:log_dir] + @vil.vid.to_s + '/0.html'
303 print %Q(<meta http-equiv="Refresh" content="0;URL=#{url}">)
304 print '</head><body>'
305 print %Q(Redirecting to <a href="#{url}">#{url}</a>)
306 print '</body></html>'
313 @vil.sync() if @vil.need_sync?
317 date = (@req.key?('date')) ? @req['date'].to_i : @vil.date
319 @player = @vil.players.player(@login)
320 if (@vil.state != Vil::State::End && @player && date == @vil.date)
321 # OK I'm foolish, too long.
322 if @req['cmd'] == 'sync'
323 sleep(S[:syncsleeptime]) unless S[:highperformance]
327 head = "Content-Type: application/x-javascript; charset=utf-8\r\n"
329 actstate = @req['ast']
330 livestate = @req['lst']
331 page = ActivePage::SyncDay.new(@vil, @player, mid, livestate)
335 if page.modified? # => not wait
336 $logger.debug('page modified, not wait')
337 if (page.nonmatch? || page.livestate_unmatch?)
342 sleep(S[:syncsleeptime]) unless S[:highperformance]
344 vil = get_ronly_vil(@vid)
346 player = vil.players.player(@login)
347 actbox = ActivePage::ActionBalloon.new(@login.form(vil.vid), player, vil)
348 page = ActivePage::SyncDay.new(vil, player, mid, livestate)
349 if page.need_actbox_resync? && (actbox.result?(actstate) || date_forward)
350 act = actbox.sync_result()
354 timeline = ActivePage::TimeLine.new(@vil).result() if date_forward
356 page_res = page.result()
357 size = page.discussions.size
358 order = ActivePage::Order.new(vil).sync_result()
359 whis = ActivePage::SkillWhisper.new(vil, player).sync_result()
361 print head + "\r\n" + \
362 [actbox.state, act, page_res, size, order, page.bgimage, timeline, whis].to_json
366 dbpath = S[:ajaxdb_path] + ".#{@vil.vid}"
367 server = Duet::Server.new(@login.userid, @req, dbpath)
368 wait_time = @vil.update_time - Time.now()
369 if wait_time > S[:reconnect_sec]
370 wait_time = S[:reconnect_sec]
374 server.wait(wait_time + 1) # +1 is helper too wide band-width
376 if server.wakeup_bysignal
379 vil = get_ronly_vil(@vid)
380 player = vil.players.player(@login)
381 page = ActivePage::SyncDay.new(vil, player, mid, livestate)
383 if (player && page.modified?)
384 # undefined player when use opera && wakeup by handle_exit
386 if (page.nonmatch? || page.livestate_unmatch?)
390 page = ActivePage::SyncDay.new(vil, player, mid, livestate)
393 actbox = ActivePage::ActionBalloon.new(@login.form(vil.vid), player, vil)
394 if page.need_actbox_resync? && \
395 (actbox.result?(actstate) || @player.dead != player.dead || date_forward)
397 act = actbox.sync_result()
401 timeline = ActivePage::TimeLine.new(@vil).result() if date_forward
403 page_res = page.result()
404 size = page.discussions.size
405 order = ActivePage::Order.new(vil).sync_result()
406 whis = ActivePage::SkillWhisper.new(vil, player).sync_result()
408 print head + "\r\n" + \
409 [actbox.state, act, page_res, size, order, page.bgimage, timeline, whis].to_json
410 $logger.debug('total time(wakeup by signal):' + (Time.now - t).to_f.to_s)
412 print page.not_modified()
415 print page.not_modified()
421 print ActivePage::VilHeader.new(@vil).result()
422 print ActivePage::ActionBalloon.new(@login.form(@vil.vid), @player, @vil).result()
423 print ActivePage::Order.new(@vil).result()
424 print ActivePage::SkillWhisper.new(@vil, @player).result()
425 print ActivePage::Day.new(@vil, @player).result()
427 elsif (@vil.state == Vil::State::End && @req['cmd'] && @req['cmd'] == 'sync')
430 head = "Content-Type: application/x-javascript; charset=utf-8\r\n"
432 print head + "\r\n" + \
433 ['', '', '', 'reload', '', '', ''].to_json
435 print Page::Day.new(@login.form(@vil.vid), @vil, date, @player).result()
437 if (@vil.date == date && @vil.state != Vil::State::End)
438 print Page::Order.new(@login, @vil).result()
442 if (@login.login && @vil.state == Vil::State::Welcome && date == @vil.date)
443 print Page::ActionBalloon.new(@player, @login, @vil).result()
444 elsif date + 1 == @vil.date
445 print "<a href=\"?vid=#{@vid}\">次の日へ</a>\n"
446 elsif date != @vil.date
447 print "<a href=\"?vid=#{@vid};date=#{date+1}\">次の日へ</a>\n"
450 print FOOT + "</div></body></html>"
455 if File.exist?('db/.dontdelete')
458 Dir.mkdir('db') unless File.exist?('db')
459 Dir.mkdir('db/vil') unless File.exist?('db/vil')
461 db = PStore.new('db/vil.db')
463 db['root'] = Array.new
467 File.open('db/.dontdelete', 'w') {|fh| fh.write '' }
476 @login = Login.new(@req)
477 @head += "Set-Cookie: #{@login.cookie}\r\n" if @login.cookie
479 if (!@login.cookie && ENV['REQUEST_METHOD'] == 'POST')
482 if %w(skill post vote prevote).index(@req['cmd'])
483 print "Status: 200 OK\n\n"
491 if @req['cmd'] != 'sync'
497 if %w(mkvil log doc history info chars reg).index(cmd)
498 __send__('handle_' + cmd)
506 print "Status: 500 Internal Server Error\n"
514 sec = rand(3) + rand()
515 $logger.debug([@login.userid, sec])
520 location = (@vid && @vid != 0) ? "?vid=#{@vid}\n\n" : ".\n\n"
522 print "Status: 302 Moved Temporary\n"
523 print "Location: #{location}"
526 def handle_error(error)
527 if error.class == ErrorMsg
529 File.open(S[:fatallog_path], 'a') {|fh| fh.write "\n#{Time.now.to_s}\n#{error}\n" }
531 er = CGI.escapeHTML("#{error.to_s}\n")
532 er << CGI.escapeHTML("#{error.backtrace.join("\n")}\n")
533 print "<pre>\n#{er}</pre>\n"
534 File.open(S[:fatallog_path], 'a') {|fh| fh.write "\n#{Time.now.to_s}\n#{er}\n" }