-
-
Save seki/40223807a88633308bc3 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'div' | |
require 'tofu/tofu' | |
require 'tofu/tofulet' | |
require 'monitor' | |
require 'rbtree' | |
require 'enumerator' | |
require 'rqr' | |
require 'time' | |
class Store | |
include MonitorMixin | |
def initialize | |
super() | |
@tree = RBTree.new | |
@enum = @tree.to_enum(:reverse_each) | |
end | |
attr_reader :tree | |
def qr_at(time) | |
_, qr = @tree[time] | |
qr || NotFoundQR | |
end | |
def each_slice(n, &blk) | |
synchronize do | |
@enum.each_slice(n, &blk) | |
nil | |
end | |
end | |
def import_string(str) | |
NKF.nkf('-sdXm0', str) | |
end | |
def self.qr_code(text) | |
tmp = Tempfile.new('hitori_koto') | |
RQR::QRCode.create do |qr| | |
qr.save(text, tmp.path, :png) | |
end | |
tmp.open | |
tmp.read | |
ensure | |
tmp.close(true) if tmp | |
end | |
def qr_code(text) | |
self.class.qr_code(text) | |
end | |
def to_qr(text) | |
qr_code(text) | |
rescue RQR::EncodeException | |
EncodeErrorQR | |
end | |
def add(str, context=nil) | |
str = import_string(str) | |
synchronize do | |
key = Time.now | |
latest, _ = @tree.last | |
while latest == key | |
key = Time.now | |
end | |
@tree[key] = [str, to_qr(str)] | |
key | |
end | |
end | |
NotFoundPNG = qr_code('not found') | |
EncodeErrorPNG = qr_code('QR encode error') | |
end | |
class HitoriKotoSession < Div::TofuSession | |
def initialize(bartender, hint=nil) | |
super | |
@content = Store.new | |
@base = BaseDiv.new(self) | |
@age = nil | |
end | |
attr_reader :content | |
def do_qr_code(context) | |
time = qr_path_to_time(context.req_path_info) | |
return false unless time | |
qr = @content.qr_at(time) | |
context.res_header('expires', expires.httpdate) | |
context.res_header('content-type', 'image/png; name="qrcode.png"') | |
context.res_body(qr) | |
return true | |
end | |
def qr_path(time) | |
"qr" + h(time_to_key(time)) + ".png" | |
end | |
def qr_path_to_time(path) | |
if /qr(.*)\.png$/ =~ path | |
key_to_time($1) | |
else | |
nil | |
end | |
end | |
def time_to_key(time) | |
(time.to_i * 1000000 + time.usec).to_s(36) | |
end | |
def key_to_time(str) | |
d = str.to_i(36) | |
i, u = d.divmod(1000000) | |
Time.at(i, u) | |
rescue | |
Time.now | |
end | |
def do_GET(context) | |
update_div(context) | |
return if do_qr_code(context) | |
context.res_header('content-type', 'text/html; charset=Shift_JIS') | |
context.res_body(@base.to_html(context)) | |
end | |
end | |
class BaseDiv < Div::Div | |
set_erb('base.erb') | |
def initialize(session) | |
super(session) | |
@enter = EnterDiv.new(session) | |
@list = ListDiv.new(session) | |
end | |
end | |
class EnterDiv < Div::Div | |
set_erb('enter.erb') | |
def do_enter(context, params) | |
str ,= params['str'] | |
str = '(nil)' if (str.nil? || str.empty?) | |
@session.content.add(str, context) | |
end | |
end | |
class ListDiv < Div::Div | |
set_erb('list.erb') | |
def initialize(session) | |
super(session) | |
@content = session.content | |
end | |
def group_header(time) | |
time.strftime("%H:%M") | |
end | |
end | |
unless $DEBUG | |
exit!(0) if fork | |
Process.setsid | |
exit!(0) if fork | |
end | |
uri = ARGV.shift || 'druby://localhost:54322' | |
tofu = Tofu::Bartender.new(HitoriKotoSession, 'hitori_' + uri.split(':').last) | |
DRb.start_service(uri, WEBrick::CGITofulet.new(tofu)) | |
unless $DEBUG | |
STDIN.reopen('/dev/null') | |
STDOUT.reopen('/dev/null', 'w') | |
STDERR.reopen('/dev/null', 'w') | |
end | |
DRb.thread.join |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<head> | |
<title>hitori-koto</title> | |
<style type="text/css" media="screen"> | |
body { | |
font-family: Helvetica; | |
background: #FFFFFF; | |
color: #000000; | |
} | |
.EnterDiv * input { | |
box-sizing: border-box; | |
width: 100%; | |
padding: 16px 6px 6px 6px; | |
font-size: 16px; | |
font-weight: normal; | |
background: #6d84a2; | |
} | |
.ListDiv > ul { | |
margin: 0; | |
padding: 0; | |
} | |
.ListDiv > ul > li { | |
border-bottom: 1px solid #E0E0E0; | |
padding: 8px 0 8px 10px; | |
font-size: 14px; | |
font-weight: bold; | |
list-style: none: | |
} | |
.ListDiv > ul > li.group { | |
top: -1px; | |
margin-bottom: -2px; | |
border-top: 1px solid #7d7d7d; | |
border-bottom: 1px solid #999999; | |
padding: 1px 5px; | |
font-size: 13px; | |
font-weight: bold; | |
text-shadow: rgba(0, 0, 0, 0.4) 0 1px 0; | |
color: #222222; | |
} | |
</style> | |
</head> | |
<body> | |
<%= @enter.to_div(context)%> | |
<%= @list.to_div(context)%> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<%=form('enter', {}, context)%> | |
<input class='enter' type='text' size='40' name='str' value=''/> | |
</form> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/local/bin/ruby | |
require 'drb/drb' | |
DRb.start_service | |
ro = DRbObject.new_with_uri('druby://localhost:54322') | |
ro.start(ENV.to_hash, $stdin, $stdout) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<ul><% | |
last_group = nil | |
@content.each_slice(30) do |ary| | |
ary.each do |time, v| | |
str, qr = v | |
group = group_header(time) | |
if group != last_group | |
%><li class="group"><%=h group %></li><% | |
last_group = group | |
end | |
png = "qr" + h(@session.time_to_key(time)) + ".png" | |
%><li><%=h str %><br /><img src="<%= png%>" /></li><% | |
end | |
break | |
end | |
%></ul> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment