OSDN Git Service

Merge branch 'wdoor-stable'
[shogi-server/shogi-server.git] / mk_html
1 #!/usr/bin/ruby
2 # $Id$
3 #
4 # Author:: Daigo Moriwaki
5 # Homepage:: http://sourceforge.jp/projects/shogi-server/
6 #
7 #--
8 # Copyright (C) 2006-2012 Daigo Moriwaki <daigo at debian dot org>
9 #
10 # This program is free software; you can redistribute it and/or modify
11 # it under the terms of the GNU General Public License as published by
12 # the Free Software Foundation; either version 2 of the License, or
13 # (at your option) any later version.
14 #
15 # This program is distributed in the hope that it will be useful,
16 # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 # GNU General Public License for more details.
19 #
20 # You should have received a copy of the GNU General Public License
21 # along with this program; if not, write to the Free Software
22 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23 #++
24 #
25 # == Synopsis
26 #
27 # mk_html generates an html page from a players.yaml.
28 #
29 # == Usage
30 #
31 # ./mk_html [OPTION] < players.yaml > rating.html
32 #
33 # [<tt>-h, --help</tt>]
34 #    show help
35 #
36 # [<tt>-w,--wdoor</tt>]
37 #    adpot wdoor style
38 #
39 # [<tt>--footer</tt> <i>filename</i>]
40 #    insert contents in the filename at the bottom of a genrated page.
41 #
42 # == Prerequire
43 #
44 # * Ruby 2.0.0 or later
45 #
46 #   $ sudo aptitude install ruby ruby
47 #
48 # == Example
49 #
50 #   $ ./mk_html --footer ./wdoor_1000.html < players.yaml > players.html
51 #
52 #   $ cat ./wdoor-1000.html
53 #   <p>The average of the rates in a group is always 1000. 
54 #   <p><a href="http://wdoor.c.u-tokyo.ac.jp/shogi/">BACK</a>
55 #
56
57 require 'optparse'
58 require 'yaml'
59 require 'erb'
60
61 include ERB::Util
62
63 def show_date(time)
64   if (Time.now - time < 30*60)
65     return "on line"
66   elsif (Time.now - time < 24*60*60)
67     return time.strftime("%Y-%m-%d")
68     # return "%d hours ago" % [(Time.now - time)/3600]
69   else
70     return time.strftime("%Y-%m-%d")
71   end
72 end
73
74 def remove_long_to_see_players(file)
75   return unless file["players"][999] # only for Not-Yet-Rated players
76
77   file["players"][999].delete_if do |key, value|
78     value['last_modified'] < Time.now - 24*3600*30 # 30 days
79   end
80 end
81
82 def main
83   $wdoor = false
84   $footer_content = nil
85   opts = OptionParser.new
86   opts.banner = "Usage: mk_html [OPTIONS]"
87   opts.on("--footer filename", String, "Insert contents of the filename at the bottom of a genrated page") do |filename|
88     unless File.exist?(filename)
89       $stderr.puts "File not found: %s" % [filename]
90       raise
91     end
92     $footer_content = File.open(filename).read
93   end
94   opts.on("-w","--wdoor", "adopt a wdoor style") { $wdoor=true }
95   opts.on_tail("-h", "--help", "show this message") do
96     puts opts
97     exit
98   end
99   begin
100     opts.parse(ARGV) 
101   rescue
102     puts opts
103     exit -1
104   end
105
106   lines = ""
107   while l = $stdin.gets do
108     lines << l
109   end
110   file = YAML::load(lines)
111   erb = ERB.new( DATA.read, nil, "%>" )
112   tables = []
113   group_names = []
114   file["players"].keys.sort.each do |index|
115     if index < 999
116       group_names << "#{index}"
117     else
118       group_names << "Not-Yet-Rated Players"
119     end
120   end
121   remove_long_to_see_players(file)
122
123   popup_id = 0
124
125   if $wdoor
126     yss_rate = 0
127     file["players"].keys.each do |group_index|
128       file["players"][group_index].each do |player, yaml|
129         if player == "YSS+707d4f98d9d2620cdaab58f19d02a2e4"
130           yss_rate = yaml['rate']
131         end
132       end
133     end
134   end
135         
136   file["players"].sort.each do |key, yaml| # sort groups in the order written in players.yaml
137   sorted_keys = yaml.keys.sort do |a,b| 
138     # sort players in a group by one's rate
139     if yaml[b]['rate'] == 0 && yaml[a]['rate'] == 0
140       # mainly for not-rated-yet players
141       yaml[b]['last_modified'] <=> yaml[a]['last_modified']
142     else
143       yaml[b]['rate'] <=> yaml[a]['rate']
144     end
145   end 
146   top_rate = nil  
147   table = ERB.new(<<ENDTABLE, nil, "%>")
148 % sorted_keys.each do |key|
149   <%
150     win  = yaml[key]['win']
151     loss = yaml[key]['loss']
152     win_rate = win.to_f / (win + loss)
153     last_modified = yaml[key]['last_modified']
154     
155     player_decoration = "default"
156
157     case (Time.now - last_modified)/60 # minutes
158     when (0..30)        then player_decoration = "current"
159     when (0..(1*60*24)) then player_decoration = "today"
160     when (0..(7*60*24)) then player_decoration = "this_week"
161     end
162     
163     case key
164     when "yowai_gps+95908f6c18338f5340371f71523fc5e3" then player_decoration = "yowai_gps"
165     when "gps+11648e4e66e7ed6a86cb7f1d0cf604fe"       then player_decoration = "gps"
166     end
167
168     rate = yaml[key]['rate']
169     top_rate ||= rate
170     diff_rate = rate - top_rate
171     diff_possibility = 1.0/(1.0 + 10**(-diff_rate/400.0))
172   %>
173   <tr class="<%=player_decoration%>">
174     <td class="name">
175         <a id="popup<%=popup_id+=1%>" href="/shogi/view/show-player.cgi?event=LATEST&amp;filter=floodgate&amp;show_self_play=1&amp;user=<%=u key%>"><%= h yaml[key]['name'] %></a>
176         <script type="text/javascript">
177           var tooltip<%=popup_id%> = new YAHOO.widget.Tooltip("myTooltip", {
178             context:"popup<%=popup_id%>",
179             text:"<%= h key %>" } );
180         </script>
181     </td>
182     <td class="rate">
183         <span id="popup<%=popup_id+=1%>"><%= rate != 0 ? "%5d"  % [ rate ] : "N/A" %></span>
184         <script type="text/javascript">
185           var tooltip<%=popup_id%> = new YAHOO.widget.Tooltip("myTooltip", {
186             context:"popup<%=popup_id%>",
187             text:"Behind <%= "%5d" % [ diff_rate ] %> (<%= "%.3f" % [ diff_possibility ] %>)" } );
188         </script>
189     </td>
190     <td class="ngames">
191         <%= "%5d"  % [ win ] %>  </td>
192     <td class="ngames">
193         <%= "%5d"  % [ loss ] %> </td>
194     <td class="win_rate">
195         <%= "%.3f" % [win_rate] %> </td>
196     <td class="last_modified">
197         <%= show_date(last_modified) %> </td>
198 % if $wdoor
199     <td class="rate">
200         <%= rate != 0 && yss_rate > 0 ? ("%5d"  % [2300 - yss_rate + rate]) : "N/A" %> </td>
201 % end
202   </tr>
203 % end
204 ENDTABLE
205         
206     tables << table.result(binding)
207   end
208
209   body = erb.result(binding)
210   puts body
211 end
212
213 if __FILE__ == $0
214   main
215 end
216
217 # vim: ts=2 sw=2 sts=0
218
219 __END__
220 <html>
221 <head>
222   <title>Shogi Server Rating</title>
223   <link rel="StyleSheet" type="text/css" href="http://wdoor.c.u-tokyo.ac.jp/shogi/shogi.css">
224   <!-- CSS --> 
225   <!-- License: http://developer.yahoo.com/yui/license.html -->
226   <link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/2.4.1/build/reset-fonts-grids/reset-fonts-grids.css"> 
227   <link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/2.4.1/build/base/base-min.css"> 
228   <link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/2.4.1/build/container/assets/container.css"> 
229   <!-- Dependencies --> 
230   <script type="text/javascript" src="http://yui.yahooapis.com/2.4.1/build/yahoo-dom-event/yahoo-dom-event.js"></script> 
231   <!-- OPTIONAL: Animation (only required if enabling Animation) --> 
232   <script type="text/javascript" src="http://yui.yahooapis.com/2.4.1/build/animation/animation-min.js"></script> 
233   <!-- Source file --> 
234   <script type="text/javascript" src="http://yui.yahooapis.com/2.4.1/build/container/container-min.js"></script>
235   <style type="text/css"><!--
236     TABLE {margin-left: auto;
237            margin-right: auto;}
238     CAPTION { caption-side: left;}
239     .name {text-align: center;
240            width: 180px;}
241     .rate, .ngames, .win_rate {text-align: right;}
242     .last_modified {text-align: center;}
243     .gps, .yowai_gps {background-color: lightgreen;}
244     .current   {background-color: #FFD700;}
245     .today     {background-color: #FFFF00;}
246     .this_week {background-color: #FFFFAA;}
247
248     #bd {text-align: center;}
249     #ft {text-align: right;}
250   --></style>
251 </head>
252 <body><div id="doc">
253
254 <div id="hd"></div>
255
256 <div id="bd">
257 <h1>Shogi Server Rating</h1>
258
259 % tables.each_with_index do |t, index|
260 <table>
261 <caption>Group: <%=group_names[index]%></caption>
262 <colgroup>
263   <col class="name">
264   <col class="rate">
265   <col class="ngames">
266   <col class="ngames">
267   <col class="win_rate">
268   <col class="last_modified">
269 % if $wdoor
270   <col class="rate)">
271 % end
272 </colgroup>
273 <thead>
274 <tr>
275   <th>name</th>
276   <th>rate</th> 
277   <th>win</th> 
278   <th>loss</th> 
279   <th>&#37;</th> 
280   <th>last_modified</th>
281 % if $wdoor
282   <th>(rate24)</th> 
283 % end
284 </tr>
285 </thead>
286 <tbody>
287   <%= t %>
288 </tbody>
289 </table>
290
291 <hr style="width:50%; margin:1em auto;">
292
293 % end
294
295 <p>Groups are independently rated. You can not compare rates across them.
296
297 <%= $footer_content %>
298
299 <hr/>
300 </div>
301
302
303 <div id="ft">
304   <p>Last modified at <%=Time.now%>
305   <p>$Revision$
306 </div>
307
308 </div></body>
309 </html>
310