OSDN Git Service

改修報告書を実装する
[kancollesniffer/KancolleSniffer.git] / LogViewer / index.html
1 <!DOCTYPE html>
2 <html lang="ja">
3 <head>
4 <meta charset="utf-8">
5 <title>各種報告書 - KancolleSniffer</title>
6
7 <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
8 <script src="//cdnjs.cloudflare.com/ajax/libs/datatables/1.10.7/js/jquery.dataTables.min.js"></script>
9 <link rel="stylesheet" type="text/css" href="//cdnjs.cloudflare.com/ajax/libs/datatables/1.10.7/css/jquery.dataTables.min.css">
10 <script src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.min.js"></script>
11 <script src="//cdnjs.cloudflare.com/ajax/libs/c3/0.4.10/c3.min.js"></script>
12 <link rel="stylesheet" type="text/css" href="//cdnjs.cloudflare.com/ajax/libs/c3/0.4.10/c3.min.css">
13 <script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.9.0/moment.min.js"></script>
14 <script src="//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
15 <link rel="stylesheet" type="text/css" href="//ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css">
16 <script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/i18n/datepicker-ja.min.js"></script>
17 <style>
18 body {
19     font-family:'Lucida Grande','Hiragino Kaku Gothic ProN', Meiryo, sans-serif;
20     line-height: 1.5;
21     font-size: 14px;
22 }
23 .tab {overflow: hidden; list-style-type: none; margin: 0em 2em 2em 1em; padding: 0em;}
24 .tab li {background: #eee; padding: 0.3em 2.0em; float: left; margin-right: 2px;}
25 .tab li.select {background: #ccc;}
26 .contents {list-style-type: none; margin: 0em; padding: 0em;}
27 .hide {display: none;}
28 #loading {
29     width: 48px;
30     height: 48px;
31     display: none;
32     position: fixed;
33     top: 50%;
34     left: 50%;
35     margin-top: -24px;
36     margin-left: -24px;
37     z-index: 100;
38 }
39 </style>
40
41 </head>
42 <body>
43 <script>
44 function showLog()
45 {
46     var query = "?from=" + moment().subtract(1, 'months').valueOf();
47     if ($('input[name=term]:eq(1)').prop('checked')) {
48         from = $('#term_from').datepicker("getDate");
49         to = $('#term_to').datepicker("getDate");
50         if (from != null)
51             query = "?from=" + from.valueOf();
52         if (to != null)
53             query += "&to=" + (to.valueOf() + 3600 * 24 * 1000);
54     }
55     var jsons = [
56         "海戦・ドロップ報告書.json",
57         "海戦・ドロップ報告書.json",
58         "遠征報告書.json",
59         "開発報告書.json",
60         "建造報告書.json",
61         "改修報告書.json",
62         "資材ログ.json"
63     ];
64     $('#loading').show();
65     var url = jsons[selectedTable] + query;
66     $('#log' + selectedTable).DataTable().ajax.url(url).load();
67 }
68
69 var tables = 7;
70
71 function initTables()
72 {
73     for (var t = 0; t < tables; t++) {
74         var opts = {
75             destroy: true,
76             deferRender: true,
77             stateSave: true,
78             order: [[0, "desc"]],
79             pageLength: 50,
80             lengthMenu: [[50, 100, 200, -1],[50, 100, 200, "All"]],
81             drawCallback: function () {
82                 $('#loading').hide();
83             }
84         };
85         if (t == 0) {
86             opts.columns = [{data: 0}, {data: 1}, {data: 2}, {data: 3}, {data: 4}, {data: 9}, {data: 10}];
87         } else if (t == 1) {
88             var entries = [];
89             for (i = 0; i < 35; i++) {
90                 if (i == 9 || i == 10)
91                     continue;
92                 entries.push({data: i})
93             }
94             opts.columns = entries;
95         }
96         $('#log' + t).dataTable(opts);
97     }
98 }
99
100 const timeFormat = "YYYY-MM-DD HH:mm:ss";
101 function parseDate(d)
102 {
103     return moment(d, timeFormat);
104 }
105
106 function toString(d)
107 {
108     return d.format(timeFormat);
109 }
110
111 function pickChartData(data, range)
112 {
113     var newdata = [];
114     var ticks = [];
115     var grid = [];
116     var last = moment(data[data.length - 1][0]).valueOf();
117     var first, interval, tickInterval;
118     const oneDay = 3600 * 24 * 1000;
119     switch (range) {
120     case 0:
121         first = moment(last).subtract(24, 'hours').valueOf();
122         interval = 1000;
123         tickInterval = 3600 * 1000;
124         last -= last % tickInterval;
125         break;
126     case 1:
127         first = moment(last).subtract(7, 'days').valueOf();
128         interval = 1000;
129         tickInterval = oneDay;
130         last -= last % tickInterval + 3600 * 4000;
131         break;
132     case 2:
133         first = moment(last).subtract(1, 'months').valueOf();
134         last = moment(last).day(1).valueOf();
135         interval = 3600 * 2000;
136         tickInterval = oneDay * 7;
137         last -= last % oneDay + 3600 * 4000;
138         break;
139     case 3:
140         first = moment(data[0][0]).valueOf();
141         last = moment(last).day(1).valueOf();
142         interval = 3600 * 6000;
143         tickInterval = oneDay * 7;
144         last -= last % oneDay + 3600 * 4000;
145         break;
146     }
147     for (var tick = last; tick > first; tick -= tickInterval)
148     {
149         var str = toString(moment(tick));
150         ticks.unshift(str);
151         grid.unshift({value: str});
152     }
153     var last_data;
154     for (var i = data.length - 1; i >= 0; i--) {
155         var row = data[i];
156         var date = parseDate(row[0]).valueOf();
157         if (date > first) {
158             var v = date - date % interval;
159             if (last_data != v) {
160                 newdata.unshift(row);
161                 last_data = v;
162             }
163         } else {
164             break;
165         }
166     }
167     return { data: newdata, tick: ticks, grid: grid };
168 }
169
170 var selectedTable = 0;
171 var selectedRange = 0;
172
173 function drawChart(data)
174 {
175     if (data == null) {
176         $('#loading').show();
177         $.get("./資材ログ.json?time=" + Date.now(), function (data) { drawChart(data);}, "json");
178         return;
179     }
180     picked = pickChartData(data.data, selectedRange);
181     var header = ["日付","燃料","弾薬","鋼材","ボーキ","高速建造材","高速修復材","開発資材","改修資材"];
182     picked.data.unshift(header);
183     var chart = c3.generate({
184         bindto: '#chart',
185         size: {
186             height: 400,
187             width: 800
188         },
189         data: {
190             x: '日付',
191             xFormat: '%Y-%m-%d %X',
192             rows: picked.data,
193             axes: {
194                 燃料: 'y',
195                 弾薬: 'y',
196                 鋼材: 'y',
197                 ボーキ: 'y',
198                 高速建造材: 'y2',
199                 高速修復材: 'y2',
200                 開発資材: 'y2',
201                 改修資材: 'y2'
202             }
203         },
204         point: {
205             show: false
206         },
207         tooltip: {
208             show: $('#tooltip').prop('checked')
209         },
210         grid: {
211             x: {
212                 lines: picked.grid
213             }
214         },
215         axis: {
216             x: {
217                 type: 'timeseries',
218                 tick: {
219                     rotate: 30,
220                     format: function (x) { return moment(x).format("MM-DD HH:mm"); },
221                     values: picked.tick
222                 },
223                 height: 60
224             },
225             y2: {
226                 show: true
227             }
228         },
229         onrendered: function () { $('#loading').hide(); }
230     });
231 }
232
233 function setSortieStat(data) {
234     if (!data) {
235         $('#loading').show();
236         var from = moment().subtract(1, 'months').valueOf();
237         $.get("./海戦・ドロップ報告書.json?time=" + Date.now() + "&from=" + from, function (data) { setSortieStat(data.data);}, "json");
238         return;
239     }
240     var r = {
241         day: {stat: {}},
242         week: {stat: {}},
243         month: {stat: {}}
244     };
245     var initStat = function () { return {start:"-", S:0, A:0, B:0, C:0, D:0} };
246     now = moment();
247     r.day.begin = moment(now).hour(5).minute(0);
248     if (now.hour() < 5) {
249         r.day.begin.subtract(1, 'days');
250     }
251     r.week.begin = moment(now).day(1).hour(5).minute(0);
252     if (now.day() == 0 || now.day() == 1 && now.hour() < 5) {
253         r.week.begin.subtract(1, 'weeks');
254     }
255     r.month.begin = moment(now).date(1).hour(5).minute(0);
256     if (now.date() == 1 && now.hours() < 5) {
257         r.month.begin.subtract(1, 'months');
258     }
259     for (var i = 0; i < data.length; i++) {
260         var row = data[i];
261         var date = moment(row[0]);
262         var map = row[1];
263         var isBoss = row[3].indexOf("ボス") != -1;
264         var isStart = row[3].indexOf("出撃") != -1;
265         var res = row[4];
266         if (res == "E")
267             res = "D";
268         for (var term in r) {
269             to = r[term];
270             if (to.begin.isAfter(date))
271                 continue;
272             for (var b = 0; b < 4; b++) {
273                 var name = b < 2 ? "合計" : map;
274                 if (b == 1 || b == 3) {
275                     if (!isBoss)
276                         continue;
277                     name = name + " - ボス";
278                 }
279                 var mo = to.stat[name];
280                 if (!mo) {
281                     mo = to.stat[name] = initStat();
282                     if (name == "合計")
283                         to.stat["合計 - ボス"] = initStat();
284                 }
285                 mo[res]++;
286                 if ((b == 0 || b == 2) && isStart)
287                 {
288                     if (mo.start == "-")
289                         mo.start = 0;
290                     mo.start++
291                 }
292             }
293         }
294     }
295     for (term in r) {
296         var table = [];
297         for (map in r[term].stat)
298         {
299             var e = r[term].stat[map];
300             e.map = map;
301             table.push(e);
302         }
303         var dt = $("#sortie_stat_" + term).DataTable();
304         dt.clear();
305         dt.rows.add(table).draw();
306     }
307     $('#loading').hide();
308 }
309
310 function initSortieStat()
311 {
312     var terms = ['day', 'week', 'month'];
313     for (var i = 0; i < terms.length; i++) {
314         $("#sortie_stat_" + terms[i]).dataTable({
315             paging: false,
316             searching: false,
317             ordering: false,
318             columns: [
319                 { data: "map" },
320                 { data: "start" },
321                 { data: "S" },
322                 { data: "A" },
323                 { data: "B" },
324                 { data: "C" },
325                 { data: "D" }
326             ]
327         });
328     }
329 }
330
331 function selectTopTab(i)
332 {
333     var chart = tables;
334     if (i < tables) {
335         selectedTable = i;
336         showLog();
337     } else if (i == chart) {
338         drawChart();
339     } else if (i == chart + 1) {
340         setSortieStat();
341     }
342     if (i < tables)
343         $('#term').show();
344     else
345         $('#term').hide();
346     var tab = $('.tab0 li');
347     tab.removeClass('select');
348     tab.eq(i).addClass('select');
349     $('.contents .hide').hide();
350     $('.contents .hide').eq(i).show();
351 }
352
353 $(function() {
354     $.fn.dataTable.ext.errMode = 'throw';
355     $('.tab0 li').click(function() {
356         var tab = $('.tab0 li');
357         var i = tab.index(this)
358         selectTopTab(i);
359         sessionStorage.setItem('prevTab', i);
360     });
361     $('.tab1 li').click(function() {
362         var tab = $('.tab1 li');
363         var i = tab.index(this);
364         selectedRange = i;
365         drawChart();
366         tab.removeClass('select');
367         tab.eq(i).addClass('select');
368         sessionStorage.setItem('prevRange', i);
369     });
370     $('#tooltip').change(function() {
371         drawChart();
372     });
373     $('table').addClass('display compact cell-border');
374     initTables();
375     initSortieStat();
376     var range = sessionStorage.getItem('prevRange');
377     selectedRange = range == null ? 0 : +range;
378     $('.tab1 li').eq(range).addClass('select');
379     $('#term_from').datepicker({
380         defaultDate: moment().subtract(1, 'months').toDate()
381     });
382     $('#term_to').datepicker();
383     $('#term_apply').click(showLog);
384     var prev = sessionStorage.getItem('prevTab');
385     selectTopTab(prev == null ? 0 : +prev);
386 });
387 </script>
388
389 <div id="loading"><img src="http://kancollesniffer.osdn.jp/ajax-loader.gif" alt="読み込み中..."></div>
390
391 <ul class="tab tab0">
392 <li>ドロップ</li>
393 <li>海戦</li>
394 <li>遠征</li>
395 <li>開発</li>
396 <li>建造</li>
397 <li>改修</li>
398 <li>資材</li>
399 <li>資材グラフ</li>
400 <li>出撃統計</li>
401 </ul>
402
403 <form id="term">
404 <p>
405 <label><input type="radio" name="term" value="0" checked="checked">直近一か月</label>
406 <label><input type="radio" name="term" value="1">指定の期間: </label>
407 <input type="text" id="term_from" style="width: 8em">~<input type="text" id="term_to" style="width: 8em">
408 <input type="button" id="term_apply" value="適用">
409 </p>
410 </form>
411
412 <ul class="contents">
413 <li class="hide">
414 <table id="log0">
415 <thead>
416 <tr><th>日付</th><th>海域</th><th>マス</th><th>ボス</th><th>ランク</th><th>ドロップ艦種</th><th>ドロップ艦娘</th></tr>
417 </thead>
418 </table>
419
420 <li class="hide">
421 <table id="log1">
422 <thead>
423 <tr><th>日付</th><th>海域</th><th>マス</th><th>ボス</th><th>ランク</th><th>艦隊行動</th><th>味方陣形</th><th>敵陣形</th><th>敵艦隊</th><th>味方艦1</th><th>味方艦1HP</th><th>味方艦2</th><th>味方艦2HP</th><th>味方艦3</th><th>味方艦3HP</th><th>味方艦4</th><th>味方艦4HP</th><th>味方艦5</th><th>味方艦5HP</th><th>味方艦6</th><th>味方艦6HP</th><th>敵艦1</th><th>敵艦1HP</th><th>敵艦2</th><th>敵艦2HP</th><th>敵艦3</th><th>敵艦3HP</th><th>敵艦4</th><th>敵艦4HP</th><th>敵艦5</th><th>敵艦5HP</th><th>敵艦6</th><th>敵艦6HP</th></tr>
424 </thead>
425 </table>
426
427 <li class="hide">
428 <table id="log2">
429 <thead>
430 <tr><th>日付</th><th>結果</th><th>遠征</th><th>燃料</th><th>弾薬</th><th>鋼材</th><th>ボーキ</th><th>開発資材</th><th>高速修復材</th><th>高速建造材</th></tr>
431 </thead>
432 </table>
433
434 <li class="hide">
435 <table id="log3">
436 <thead>
437 <tr><th>日付</th><th>開発装備</th><th>種別</th><th>燃料</th><th>弾薬</th><th>鋼材</th><th>ボーキ</th><th>秘書艦</th><th>司令部Lv</th></tr>
438 </thead>
439 </table>
440
441 <li class="hide">
442 <table id="log4">
443 <thead>
444 <tr><th>日付</th><th>種類</th><th>名前</th><th>艦種</th><th>燃料</th><th>弾薬</th><th>鋼材</th><th>ボーキ</th><th>開発資材</th><th>空きドック</th><th>秘書艦</th><th>司令部Lv</th></tr>
445 </thead>
446 </table>
447
448 <li class="hide">
449 <table id="log5">
450 <thead>
451 <tr><th>日付</th><th>改修装備</th><th>レベル</th><th>成功</th><th>確実化</th><th>消費装備</th><th>消費数</th><th>燃料</th><th>弾薬</th><th>鋼材</th><th>ボーキ</th><th>開発資材</th><th>改修資材</th><th>秘書艦</th><th>二番艦</th></tr>
452 </thead>
453 </table>
454
455 <li class="hide">
456 <table id="log6">
457 <thead>
458 <tr><th>日付</th><th>燃料</th><th>弾薬</th><th>鋼材</th><th>ボーキ</th><th>高速建造材</th><th>高速修復材</th><th>開発資材</th><th>改修資材</th></tr>
459 </thead>
460 </table>
461
462 <li class="hide">
463 <ul class="tab tab1" style="float: left">
464 <li>一日</li>
465 <li>一週間</li>
466 <li>一か月</li>
467 <li>すべて</li>
468 </ul>
469 <label><input type="checkbox" id="tooltip" value="">ツールチップ</label>
470 <div id="chart" style="clear: both; width: 800px; margin: 1em;"></div>
471
472 <li class="hide">
473 <h3>今日</h3>
474 <table id="sortie_stat_day">
475 <thead>
476 <tr><th>マップ</th><th>出撃</th><th>S</th><th>A</th><th>B</th><th>C</th><th>D以下</th></tr>
477 </thead>
478 </table>
479
480 <h3>今週</h3>
481 <table id="sortie_stat_week">
482 <thead>
483 <tr><th>マップ</th><th>出撃</th><th>S</th><th>A</th><th>B</th><th>C</th><th>D以下</th></tr>
484 </table>
485
486 <h3>今月</h3>
487 <table id="sortie_stat_month">
488 <thead>
489 <tr><th>マップ</th><th>出撃</th><th>S</th><th>A</th><th>B</th><th>C</th><th>D以下</th></tr>
490 </table>
491 </ul>
492 </body>
493 </html>