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="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
8 <script src="https://cdnjs.cloudflare.com/ajax/libs/datatables/1.10.7/js/jquery.dataTables.min.js"></script>
9 <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/datatables/1.10.7/css/jquery.dataTables.min.css">
10 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.min.js"></script>
11 <script src="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.11/c3.min.js"></script>
12 <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.11/c3.min.css">
13 <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>
14 <script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
15 <link rel="stylesheet" type="text/css" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css">
16 <script src="https://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: 0 0 2em 1em; padding: 0;}
24 .tab li {background: #eee; padding: 0.3em 1.5em; float: left; margin-right: 2px;}
25 .tab1 li {padding: 0.3em 1em;}
26 .tab li.select {background: #ccc;}
27 .contents {list-style-type: none; margin: 0; padding: 0;}
28 .hide {display: none;}
29 .c3 .tick {font-family:'Lucida Grande','Hiragino Kaku Gothic ProN', Meiryo, sans-serif; font-size: 12px;}
30 .c3-legend-item {font-family:'Lucida Grande','Hiragino Kaku Gothic ProN', Meiryo, sans-serif; font-size: 14px;}
31 #loading {
32     width: 48px;
33     height: 48px;
34     display: none;
35     position: fixed;
36     top: 50%;
37     left: 50%;
38     margin-top: -24px;
39     margin-left: -24px;
40     z-index: 100;
41 }
42 </style>
43 </head>
44 <body>
45 <script>
46 /* global moment, c3, $ */
47
48 var oneDay = 3600 * 24 * 1000;
49
50 function showLog() {
51     var query = "?from=" + moment().subtract(1, 'months').valueOf();
52     if ($('input[name=term]:eq(1)').prop('checked')) {
53         var from = $('#term_from').datepicker("getDate");
54         var to = $('#term_to').datepicker("getDate");
55         if (from != null)
56             query = "?from=" + from.valueOf();
57         if (to != null)
58             query += "&to=" + (to.valueOf() + oneDay);
59     }
60     var jsons = [
61         "海戦・ドロップ報告書.json",
62         "海戦・ドロップ報告書.json",
63         "遠征報告書.json",
64         "開発報告書.json",
65         "建造報告書.json",
66         "改修報告書.json",
67         "資材ログ.json"
68     ];
69     $('#loading').show();
70     var url = jsons[selectedTable] + query;
71     $('#log' + selectedTable).DataTable().ajax.url(url).load();
72 }
73
74 var tables = 7;
75
76 function initTables() {
77     for (var t = 0; t < tables; t++) {
78         var opts = {
79             destroy: true,
80             deferRender: true,
81             stateSave: true,
82             order: [[0, "desc"]],
83             pageLength: 50,
84             lengthMenu: [[50, 100, 200, -1], [50, 100, 200, "All"]],
85             drawCallback: function () {
86                 $('#loading').hide();
87             }
88         };
89         if (t === 0) {
90             opts.columns = [{ data: 0 }, { data: 1 }, { data: 2 }, { data: 3 }, { data: 4 }, { data: 9 }, { data: 10 }];
91         } else if (t === 1) {
92             var entries = [];
93             for (var i = 0; i < 38; i++) {
94                 if (i === 9 || i === 10)
95                     continue;
96                 entries.push({ data: i });
97             }
98             opts.columns = entries;
99         }
100         $('#log' + t).dataTable(opts);
101     }
102 }
103
104 var timeFormat = "YYYY-MM-DD HH:mm:ss";
105 function parseDate(d) {
106     return moment(d, timeFormat);
107 }
108
109 function toString(d) {
110     return d.format(timeFormat);
111 }
112
113 function to5am(tick) {
114     return tick - tick % (3600 * 24000) - 3600 * 4000;
115 }
116
117 var selectedTable = 0;
118 var seqChartRange = 0;
119 var diffChartRange = 0;
120 var chartType = 0;
121 var showChart = false;
122 var currentPickedData;
123
124 function drawChart(data) {
125     if (data == null) {
126         $('#loading').show();
127         $.get("./資材ログ.json?time=" + Date.now(), function (d) { drawChart(d); }, "json");
128         return;
129     }
130     var picked, header;
131     if (chartType === 0) {
132         picked = pickChartData(data.data, seqChartRange);
133         header = ["日付", "燃料", "弾薬", "鋼材", "ボーキ", "高速建造材", "高速修復材", "開発資材", "改修資材"];
134         picked.data.unshift(header);
135         drawSeqChart(picked);
136         currentPickedData = picked;
137     } else {
138         picked = pickDiffChartData(data.data, diffChartRange);
139         header = ["日付", "燃料", "弾薬", "鋼材", "ボーキ"];
140         picked.data.unshift(header);
141         drawDiffChart(picked);
142         currentPickedData = picked;
143     }
144 }
145
146 var chartSeq, chartDiff;
147
148 function redrawChart() {
149     if (!currentPickedData)
150         return;
151     $('#loading').show();
152     setTimeout(function () {
153         if (chartType === 0)
154             chartSeq.resize(chartSize());
155         if (chartType === 1)
156             chartDiff.resize(chartSize());
157     });
158 }
159
160 var timer;
161 $(window).resize(function () {
162     if (timer)
163         clearTimeout(timer);
164     timer = setTimeout(function () {
165         if (showChart)
166             redrawChart();
167     }, 200);
168 });
169
170 function chartSize() {
171     var pxPerEm = Number($('#chart').css('fontSize').match(/(\d*(\.\d*)?)px/)[1]);
172     return {
173         height: Math.max($(document).height() - 15 * pxPerEm, 400),
174         width: Math.max($(document).width() - 6 * pxPerEm, 800)
175     };
176 }
177
178 var seqChartUnselected = {};
179
180 function drawSeqChart(picked) {
181     var size = chartSize();
182     chartSeq = c3.generate({
183         bindto: '#chart',
184         size: {
185             height: size.height,
186             width: size.width
187         },
188         data: {
189             x: '日付',
190             xFormat: '%Y-%m-%d %X',
191             rows: picked.data,
192             axes: {
193                 燃料: 'y',
194                 弾薬: 'y',
195                 鋼材: 'y',
196                 ボーキ: 'y',
197                 高速建造材: 'y2',
198                 高速修復材: 'y2',
199                 開発資材: 'y2',
200                 改修資材: 'y2'
201             }
202         },
203         point: {
204             show: false
205         },
206         tooltip: {
207             show: $('#tooltip').prop('checked')
208         },
209         grid: {
210             x: {
211                 lines: picked.grid
212             }
213         },
214         axis: {
215             x: {
216                 type: 'timeseries',
217                 tick: {
218                     rotate: 30,
219                     format: function (x) { return moment(x).format("MM-DD HH:mm"); },
220                     values: picked.tick
221                 }
222             },
223             y2: {
224                 show: true
225             }
226         },
227         legend: {
228             item: {
229                 onclick: function(id) {
230                     seqChartUnselected[id] = !seqChartUnselected[id];
231                     chartSeq.toggle(id);
232                 }
233             }
234         },
235         onrendered: function () { $('#loading').hide(); }
236     });
237     for (var id in seqChartUnselected) {
238         if (seqChartUnselected.hasOwnProperty(id) && seqChartUnselected[id])
239             chartSeq.toggle(id);
240     }
241 }
242
243 function pickChartData(data, range) {
244     var newdata = [];
245     var ticks = [];
246     var grid = [];
247     var first = moment(data[0][0]).valueOf();
248     var last = moment(data[data.length - 1][0]).valueOf();
249     var interval, tickInterval, lastTick;
250     switch (range) {
251         case 0:
252             first = moment(last).subtract(24, 'hours').valueOf();
253             break;
254         case 1:
255             first = moment(last).subtract(7, 'days').valueOf();
256             break;
257         case 2:
258             first = moment(last).subtract(1, 'months').valueOf();
259             break;
260         case 3:
261             first = moment(last).subtract(3, 'months').valueOf();
262             break;
263         case 4:
264             first = moment(data[0][0]).valueOf();
265             break;
266         case 5:
267             var fromDate = $('#chart_from').datepicker("getDate");
268             var toDate = $('#chart_to').datepicker("getDate");
269             if (fromDate == null || toDate == null)
270                 return { data: [], tick: [], grid: [] };
271             var from = fromDate.valueOf() + 3600 * 5000;
272             var to = toDate.valueOf() + oneDay + 3600 * 5000;
273             first = Math.max(first, from);
274             last = Math.min(last, to);
275             break;
276     }
277     if (last <= first + oneDay) {
278         interval = 1000;
279         tickInterval = 3600 * 1000;
280         lastTick = last - last % tickInterval;
281     } else if (last <= first + oneDay * 21) {
282         interval = 1000;
283         tickInterval = oneDay;
284         lastTick = to5am(last);
285     } else if (last <= first + oneDay * 63) {
286         interval = 3600 * 1000;
287         tickInterval = oneDay * 7;
288         lastTick = to5am(moment(last).day(1).valueOf());
289     } else if (last <= first + oneDay * 126) {
290         interval = 3600 * 6000;
291         tickInterval = oneDay * 14;
292         lastTick = to5am(moment(last).day(1).valueOf());
293     } else {
294         interval = 3600 * 12000;
295         tickInterval = oneDay * 28;
296         lastTick = to5am(moment(last).day(1).valueOf());
297     }
298     var lastData;
299     for (var i = data.length - 1; i >= 0; i--) {
300         var row = data[i];
301         var date = parseDate(row[0]).valueOf();
302         if (date > first) {
303             if (date <= last) {
304                 var v = date - date % interval;
305                 if (lastData !== v) {
306                     newdata.unshift(row);
307                     lastData = v;
308                 }
309             }
310         } else {
311             break;
312         }
313     }
314     for (var tick = lastTick; tick > lastData; tick -= tickInterval) {
315         var str = toString(moment(tick));
316         ticks.unshift(str);
317         grid.unshift({ value: str });
318     }
319     return { data: newdata, tick: ticks, grid: grid };
320 }
321
322 var diffChartUnselected = {};
323
324 function drawDiffChart(picked) {
325     var size = chartSize();
326     chartDiff = c3.generate({
327         bindto: '#chart',
328         size: {
329             height: size.height,
330             width: size.width
331         },
332         data: {
333             x: '日付',
334             xFormat: '%Y-%m-%d %X',
335             rows: picked.data,
336             axes: {
337                 燃料: 'y',
338                 弾薬: 'y',
339                 鋼材: 'y',
340                 ボーキ: 'y'
341             },
342             type: 'bar',
343             groups: [["燃料", "弾薬", "鋼材", "ボーキ"]]
344         },
345         bar: {
346             width: {
347                 ratio: picked.width
348             }
349         },
350         tooltip: {
351             show: $('#tooltip').prop('checked')
352         },
353         grid: {
354             x: {
355                 lines: picked.grid
356             },
357             y: {
358                 lines: [
359                     { value: 0 }
360                 ]
361             }
362         },
363         axis: {
364             x: {
365                 type: 'timeseries',
366                 tick: {
367                     rotate: 30,
368                     format: function (x) { return moment(x).format("MM-DD HH:mm"); },
369                     values: picked.tick
370                 }
371             }
372         },
373         legend: {
374             item: {
375                 onclick: function(id) {
376                     diffChartUnselected[id] = !diffChartUnselected[id];
377                     chartDiff.toggle(id);
378                 }
379             }
380         },
381         onrendered: function () { $('#loading').hide(); }
382     });
383     for (var id in diffChartUnselected) {
384         if (diffChartUnselected.hasOwnProperty(id) && diffChartUnselected[id])
385             chartDiff.toggle(id);
386     }
387 }
388
389 function pickDiffChartData(data, range) {
390     var newdata = [];
391     var ticks = [];
392     var grid = [];
393     var first = moment(data[0][0]).valueOf();
394     var last = moment(data[data.length - 1][0]).valueOf();
395     var interval, tickInterval, lastTick;
396     var oneDay = 3600 * 24 * 1000;
397     switch (range) {
398         case 0:
399             first = moment(last).subtract(1, 'months').valueOf();
400             break;
401         case 1:
402             first = moment(last).subtract(3, 'months').valueOf();
403             break;
404         case 2:
405             first = moment(last).subtract(6, 'months').subtract(1, 'weeks').valueOf();
406             break;
407         case 3:
408             first = moment(data[0][0]).valueOf();
409             break;
410         case 4:
411             var fromDate = $('#chart_from').datepicker("getDate");
412             var toDate = $('#chart_to').datepicker("getDate");
413             if (fromDate == null || toDate == null)
414                 return { data: [], tick: [], grid: [] };
415             var from = fromDate.valueOf() + 3600 * 5000;
416             var to = toDate.valueOf() + oneDay + 3600 * 5000;
417             first = Math.max(first, from);
418             last = Math.min(last, to);
419             break;
420     }
421     var barWidth;
422     if (last <= first + oneDay * 2 * 31) {
423         interval = oneDay;
424         tickInterval = oneDay * 2;
425         lastTick = to5am(last);
426         barWidth = 0.3;
427     } else if (last <= first + oneDay * 3 * 31) {
428         interval = oneDay;
429         tickInterval = oneDay * 7;
430         lastTick = to5am(last);
431         barWidth = 0.1;
432     } else {
433         interval = oneDay * 7;
434         tickInterval = oneDay * 28;
435         lastTick = to5am(moment(last).day(1).valueOf());
436         barWidth = 0.1;
437         if (last <= first + oneDay * 6 * 38) {
438             tickInterval = oneDay * 14;
439             barWidth = 0.3;
440         }
441     }
442     var lastDate = lastTick;
443     var prevRow;
444     for (var i = data.length - 1; i >= 0; i--) {
445         var row = data[i];
446         var date = parseDate(row[0]).valueOf();
447         if (date > first && date <= last) {
448             if (!prevRow) {
449                 prevRow = row;
450                 continue;
451             }
452             if (date <= lastDate) {
453                 var newrow = [prevRow[0]];
454                 for (var r = 1; r < 5; r++) {
455                     newrow.push(prevRow[r] - row[r]);
456                 }
457                 newdata.unshift(newrow);
458                 lastDate = lastDate - interval;
459                 prevRow = row;
460             }
461         } else {
462             break;
463         }
464     }
465     if (tickInterval >= oneDay * 7)
466         lastTick = moment(lastTick).day(1).hour(5).minute(0).valueOf();
467     for (var tick = lastTick; tick > lastDate; tick -= tickInterval) {
468         var str = toString(moment(tick));
469         ticks.unshift(str);
470         grid.unshift({ value: str });
471     }
472     return { data: newdata, tick: ticks, grid: grid, width: barWidth };
473 }
474
475 var sortieStatRange = 0;
476
477 function loadSortieData() {
478     var from, to;
479     if (sortieStatRange === 0) {
480         from = moment().subtract(1, 'months').subtract(1, 'day').valueOf();
481         to = new Date().valueOf();
482     } else {
483         var fromDate = $('#sortie_stat_from').datepicker("getDate");
484         var toDate = $('#sortie_stat_to').datepicker("getDate");
485         if (fromDate == null || toDate == null) {
486             setSortieStat([]);
487             return;
488         }
489         from = fromDate.valueOf();
490         to = toDate.valueOf() + oneDay;
491     }
492     $.ajax({
493         url: "./海戦・ドロップ報告書.json?from=" + from + "&to=" + to,
494         success: function (data) { setSortieStat(data.data); },
495         dataType: "json", cache: false
496     });
497 }
498
499 function initSortieStatResult() {
500     var now = moment();
501     var r;
502     if (sortieStatRange === 0) {
503         r = {
504             day: { stat: {} },
505             week: { stat: {} },
506             month: { stat: {} }
507         };
508         r.day.begin = moment(now).hour(5).minute(0).second(0);
509         if (now.hour() < 5) {
510             r.day.begin.subtract(1, 'days');
511         }
512         r.week.begin = moment(now).day(1).hour(5).minute(0).second(0);
513         if (now.day() === 0 || now.day() === 1 && now.hour() < 5) {
514             r.week.begin.subtract(1, 'weeks');
515         }
516         if (moment(now).endOf('month').date() === now.date() &&
517             now.hour() >= 22) { // 月末22時以降
518             r.month.begin = moment(now).hour(22).minute(0).second(0);
519         } else {
520             r.month.begin =
521                 moment(now).date(1).subtract(1, 'days').
522                     hour(22).minute(0).second(0);
523         }
524     } else {
525         r = { all: { stat: {} } };
526         r.all.begin = moment(0);
527     }
528     return r;
529 }
530
531 function gatherSortieStat(data) {
532     var initStat = function () {
533         return { start: "-", S: 0, A: 0, B: 0, C: 0, D: 0, R: 0 }
534     };
535     var r = initSortieStatResult();
536     for (var i = 0; i < data.length; i++) {
537         var row = data[i];
538         var date = moment(row[0]);
539         var map = row[1];
540         var isBoss = row[3].indexOf("ボス") !== -1;
541         var isStart = row[3].indexOf("出撃") !== -1;
542         var resR = 0;
543         for (var j = 23; j < row.length; j++) {
544             if (/^輸送/.test(row[j]) && /^0\//.test(row[j + 1]))
545                 resR++;
546         }
547         var res = row[4];
548         if (res === "E")
549             res = "D";
550         for (var term in r) {
551             if (!r.hasOwnProperty(term))
552                 continue;
553             var to = r[term];
554             if (to.begin.isAfter(date))
555                 continue;
556             for (var b = 0; b < 4; b++) {
557                 var name = b < 2 ? "合計" : map;
558                 if (b === 1 || b === 3) {
559                     if (!isBoss)
560                         continue;
561                     name = name + " - ボス";
562                 }
563                 var mo = to.stat[name];
564                 if (!mo) {
565                     mo = to.stat[name] = initStat();
566                     if (name === "合計")
567                         to.stat["合計 - ボス"] = initStat();
568                 }
569                 mo["R"] += resR;
570                 mo[res]++;
571                 if ((b === 0 || b === 2) && isStart) {
572                     if (mo.start === "-")
573                         mo.start = 0;
574                     mo.start++;
575                 }
576             }
577         }
578     }
579     return r;
580 }
581
582 function arrangeSortieStatTable(r) {
583     for (var term in r) {
584         if (!r.hasOwnProperty(term))
585             continue;
586         var table = [];
587         var pushed = {};
588         for (var map in r[term].stat) {
589             if (!r[term].stat.hasOwnProperty(map))
590                 continue;
591             if (pushed[map])
592                 continue;
593             var e = r[term].stat[map];
594             e.map = map;
595             table.push(e);
596             pushed[map] = 1;
597             var boss = map + " - ボス";
598             e = r[term].stat[boss];
599             if (!e)
600                 continue;
601             e.map = boss;
602             table.push(e);
603             pushed[boss] = 1;
604         }
605         r[term].table = table;
606     }
607 }
608
609 function setSortieStat(data) {
610     if (!data) {
611         $('#loading').show();
612         loadSortieData();
613         return;
614     }
615     var r = gatherSortieStat(data);
616     arrangeSortieStatTable(r);
617     for (var term in r) {
618         if (!r.hasOwnProperty(term))
619             continue;
620         var dt = $("#sortie_stat_" + term).DataTable();
621         dt.clear();
622         dt.rows.add(r[term].table).draw();
623     }
624     $('#loading').hide();
625 }
626
627 function initSortieStatTables() {
628     var terms = ['day', 'week', 'month', 'all'];
629     for (var i = 0; i < terms.length; i++) {
630         $("#sortie_stat_" + terms[i]).dataTable({
631             paging: false,
632             searching: false,
633             ordering: false,
634             columns: terms[i] !== 'month' ? [
635                 { data: "map" },
636                 { data: "start" },
637                 { data: "S" },
638                 { data: "A" },
639                 { data: "B" },
640                 { data: "C" },
641                 { data: "D" },
642                 { data: "R" }
643             ] : [
644                     { data: "map" },
645                     { data: "start" },
646                     { data: "S" },
647                     { data: "A" },
648                     { data: "B" },
649                     { data: "C" },
650                     { data: "D" }
651                 ]
652         });
653     }
654 }
655
656 function showAchivementTable(data) {
657     var expPerAch = 10000 / 7.0;
658     if (!data) {
659         $('#loading').show();
660         $.ajax({
661             url: "./戦果.json",
662             success: function (data) {
663                 showAchivementTable(data.data);
664             },
665             dataType: 'json',
666             cache: false
667         });
668         return;
669     }
670     var result = [];
671     var dayEo = 0;
672     var endOfMonth = null;
673     var monthExp = 0;
674     var monthEo = 0;
675     var endOfYear = null;
676     var yearExp = 0;
677     var carryOverAch = 0;
678     var carryOverEo = 0;
679     var prevExp = null;
680     var lastExp = -1;
681     var nextDate = null;
682     for (var i = 0; i < data.length; i++) {
683         var row = data[i];
684         var date = parseDate(row[0]);
685         var exp = row[1] - 0;
686         var eo = row[2] - 0;
687         var isNewYear = endOfYear == null || date.isSameOrAfter(endOfYear);
688         var isNewMonth = endOfMonth == null || date.isSameOrAfter(endOfMonth);
689         var isNewDate = nextDate == null || date.isSameOrAfter(nextDate);
690         if (isNewDate || isNewMonth || isNewYear) {
691             if (nextDate != null) {
692                 result.push([
693                     (isNewDate ? nextDate.subtract(1, 'days') : endOfMonth).format("YYYY-MM-DD"),
694                     new Number((lastExp - prevExp) / expPerAch).toFixed(1), dayEo,
695                     new Number((lastExp - monthExp) / expPerAch + monthEo + carryOverAch + carryOverEo).toFixed(1)
696                 ]);
697             }
698             prevExp = lastExp === -1 ? exp : lastExp;
699             if (isNewYear) {
700                 endOfYear = date.clone().endOf('year').hour(22).startOf('hour');
701                 if (endOfYear.isSameOrBefore(date))
702                     endOfYear.add(1, 'year').endOf('year');
703                 yearExp = lastExp === -1 ? exp : lastExp;
704             }
705             if (isNewMonth) {
706                 endOfMonth = date.clone().endOf('month').hour(22).startOf('hour');
707                 if (endOfMonth.isSameOrBefore(date))
708                     endOfMonth.add(1, 'month').endOf('month');
709                 monthExp = lastExp === -1 ? exp : lastExp;
710                 carryOverEo = monthEo * expPerAch / 50000;
711                 carryOverAch = (monthExp - yearExp) / 50000;
712                 monthEo = 0;
713                 result.push([endOfMonth.format("YYYY-MM 引継"),
714                     carryOverAch.toFixed(1), carryOverEo.toFixed(1), (carryOverAch + carryOverEo).toFixed(1)]);
715             }
716             dayEo = 0;
717             nextDate = date.clone().hour(5).startOf('hour');
718             if (date.hour() >= 5)
719                 nextDate.add(1, 'days');
720             if (nextDate.date() === 1)
721                 nextDate.add(1, 'days');
722         }
723         dayEo += eo;
724         monthEo += eo;
725         lastExp = exp;
726     }
727     var dt = $('#achivement_table').DataTable();
728     dt.clear();
729     dt.rows.add(result).draw();
730     $('#loading').hide();
731 }
732
733 function initAchievementTable() {
734     $("#achivement_table").dataTable({
735         destroy: true,
736         deferRener: true,
737         stateSave: true,
738         order: [[0, "desc"]],
739         pageLength: 50,
740         lengthMenu: [[50, 100, 200, -1], [50, 100, 200, "All"]],
741         drawCallback: function () {
742             $('#loading').hide();
743         }
744     });
745 }
746
747 function selectTopTab(i) {
748     var chart = tables;
749     showChart = false;
750     if (i < tables) {
751         selectedTable = i;
752         showLog();
753     } else if (i === chart) {
754         showChart = true;
755         drawChart();
756     } else if (i === chart + 1) {
757         showAchivementTable();
758     } else if (i === chart + 2) {
759         setSortieStat();
760     }
761     if (i < tables)
762         $('#term').show();
763     else
764         $('#term').hide();
765     var tab = $('.tab0 li');
766     tab.removeClass('select');
767     tab.eq(i).addClass('select');
768     $('#main_contents .hide').hide();
769     $('#main_contents .hide').eq(i).show();
770 }
771
772 function initAction() {
773     $('.tab0 li').click(function () {
774         var tab = $('.tab0 li');
775         var i = tab.index(this);
776         selectTopTab(i);
777         sessionStorage.setItem('prevTab', i);
778     });
779     $('#range_seq li').click(function () {
780         var tab = $('#range_seq li');
781         var i = tab.index(this);
782         seqChartRange = i;
783         chartType = 0;
784         drawChart();
785         tab.removeClass('select');
786         tab.eq(i).addClass('select');
787         sessionStorage.setItem('prevSeqRange', i);
788     });
789     $('#range_diff li').click(function () {
790         var tab = $('#range_diff li');
791         var i = tab.index(this);
792         diffChartRange = i;
793         chartType = 1;
794         drawChart();
795         tab.removeClass('select');
796         tab.eq(i).addClass('select');
797         sessionStorage.setItem('prevDiffRange', i);
798     });
799     $('input[name="chart_type"]:radio').change(function () {
800         if ($(this).val() === "0") {
801             $("#range_seq").show();
802             $("#range_diff").hide();
803             chartType = 0;
804         } else {
805             $("#range_seq").hide();
806             $("#range_diff").show();
807             chartType = 1;
808         }
809         drawChart();
810         sessionStorage.setItem('chartType', $(this).val());
811     });
812     $('#tooltip').change(function () {
813         drawChart();
814         sessionStorage.setItem('chartTooltip', $(this).prop("checked"));
815     });
816     $('#range_sortie_stat li').click(function () {
817         var tab = $('#range_sortie_stat li');
818         var i = tab.index(this);
819         sortieStatRange = i;
820         tab.removeClass('select');
821         tab.eq(i).addClass('select');
822         if (sortieStatRange === 0) {
823             $('#sortie_stat_recent_tables').show();
824             $('#sortie_stat_all_table').hide();
825         } else {
826             $('#sortie_stat_recent_tables').hide();
827             $('#sortie_stat_all_table').show();
828         }
829         setSortieStat();
830     });
831 }
832
833 function initTableDatePicker() {
834     $('#term_from').datepicker({
835         defaultDate: moment().subtract(1, 'months').toDate(),
836         onClose: function () { $('input[name=term]').val(['1']) }
837     });
838     $('#term_to').datepicker({
839         onClose: function () { $('input[name=term]').val(['1']) }
840     });
841     $('#term_apply').click(showLog);
842 }
843
844 function initChartDatePicker() {
845     $('#chart_from').datepicker({
846         onClose: function () { if (useChartDatePicker()) drawChart(); }
847     });
848     $('#chart_to').datepicker({
849         onClose: function () { if (useChartDatePicker()) drawChart(); }
850     });
851 }
852
853 function useChartDatePicker() {
854     return (chartType === 0 && seqChartRange === 5) ||
855         (chartType === 1 && diffChartRange === 4);
856 }
857
858 function initSortieStatDatePicker() {
859     $('#sortie_stat_from').datepicker({
860         onClose: function () { if (sortieStatRange === 1) setSortieStat(); }
861     });
862     $('#sortie_stat_to').datepicker({
863         onClose: function () { if (sortieStatRange === 1) setSortieStat(); }
864     });
865 }
866
867 function restoreChartSettings() {
868     var type = sessionStorage.getItem('chartType');
869     chartType = type == null ? 0 : +type;
870     var tooltip = sessionStorage.getItem('chartTooltip');
871     $('#tooltip').prop('checked', tooltip === "true");
872     var range = sessionStorage.getItem('prevSeqRange');
873     seqChartRange = range == null ? 0 : +range;
874     range = sessionStorage.getItem('prevDiffRange');
875     diffChartRange = range == null ? 0 : +range;
876     $('input[name="chart_type"]:radio').eq(chartType).prop('checked', true);
877     if (chartType === 0) {
878         $('#range_seq').show();
879         $('#range_diff').hide();
880     } else {
881         $('#range_seq').hide();
882         $('#range_diff').show();
883     }
884     $('#range_diff li').removeClass('select');
885     $('#range_diff li').eq(diffChartRange).addClass('select');
886     $('#range_seq li').removeClass('select');
887     $('#range_seq li').eq(seqChartRange).addClass('select');
888 }
889
890 $(function () {
891     $.fn.dataTable.ext.errMode = 'throw';
892     initAction();
893     initTableDatePicker();
894     initChartDatePicker();
895     initSortieStatDatePicker();
896     $('table').addClass('display compact cell-border');
897     initTables();
898     initAchievementTable();
899     initSortieStatTables();
900     $('#range_sortie_stat li').removeClass('select');
901     $('#range_sortie_stat li').eq(sortieStatRange).addClass('select');
902     restoreChartSettings();
903     var prev = sessionStorage.getItem('prevTab');
904     selectTopTab(prev == null ? 0 : +prev);
905 });
906 </script>
907
908 <div id="loading"><img src="https://kancollesniffer.osdn.jp/ajax-loader.gif" alt="読み込み中..."></div>
909
910 <ul class="tab tab0">
911 <li>ドロップ</li>
912 <li>海戦</li>
913 <li>遠征</li>
914 <li>開発</li>
915 <li>建造</li>
916 <li>改修</li>
917 <li>資材</li>
918 <li>資材グラフ</li>
919 <li>戦果</li>
920 <li>出撃統計</li>
921 </ul>
922
923 <form id="term">
924 <p>
925 <label><input type="radio" name="term" value="0" checked="checked">直近一か月</label>
926 <label><input type="radio" name="term" value="1">期間指定: </label>
927 <input type="text" id="term_from" style="width: 7em">~<input type="text" id="term_to" style="width: 7em">
928 <input type="button" id="term_apply" value="適用">
929 </p>
930 </form>
931
932 <ul class="contents" id="main_contents">
933 <li class="hide">
934 <table id="log0">
935 <thead>
936 <tr><th>日付</th><th>海域</th><th>マス</th><th>ボス</th><th>ランク</th><th>ドロップ艦種</th><th>ドロップ艦娘</th></tr>
937 </thead>
938 </table>
939
940 <li class="hide">
941 <table id="log1">
942 <thead>
943 <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><th>味方制空値</th><th>敵制空値</th><th>制空状態</th></tr>
944 </thead>
945 </table>
946
947 <li class="hide">
948 <table id="log2">
949 <thead>
950 <tr><th>日付</th><th>結果</th><th>遠征</th><th>燃料</th><th>弾薬</th><th>鋼材</th><th>ボーキ</th><th>開発資材</th><th>高速修復材</th><th>高速建造材</th></tr>
951 </thead>
952 </table>
953
954 <li class="hide">
955 <table id="log3">
956 <thead>
957 <tr><th>日付</th><th>開発装備</th><th>種別</th><th>燃料</th><th>弾薬</th><th>鋼材</th><th>ボーキ</th><th>秘書艦</th><th>司令部Lv</th></tr>
958 </thead>
959 </table>
960
961 <li class="hide">
962 <table id="log4">
963 <thead>
964 <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>
965 </thead>
966 </table>
967
968 <li class="hide">
969 <table id="log5">
970 <thead>
971 <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>
972 </thead>
973 </table>
974
975 <li class="hide">
976 <table id="log6">
977 <thead>
978 <tr><th>日付</th><th>燃料</th><th>弾薬</th><th>鋼材</th><th>ボーキ</th><th>高速建造材</th><th>高速修復材</th><th>開発資材</th><th>改修資材</th></tr>
979 </thead>
980 </table>
981
982 <li class="hide">
983 <form id="chart_type">
984 <div style="margin: 0 0 0.5em 1em;">
985 <label><input type="radio" name="chart_type" value="0" checked="checked">連続</label>
986 <label><input type="radio" name="chart_type" value="1">差分</label>
987 </div>
988 </form>
989 <ul class="tab tab1" id="range_seq" style="float: left; margin-right: 0.2em">
990 <li>一日</li>
991 <li>一週間</li>
992 <li>一か月</li>
993 <li>三か月</li>
994 <li>すべて</li>
995 <li>期間指定</li>
996 </ul>
997 <ul class="tab tab1" id="range_diff" style="float: left; margin-right: 0.2em">
998 <li>一か月(日)</li>
999 <li>三か月(日)</li>
1000 <li>半年(週)</li>
1001 <li>すべて(週)</li>
1002 <li>期間指定</li>
1003 </ul>
1004 <div style="padding: 0.2em 0;">
1005 <input type="text" id="chart_from" style="width: 7em">~<input type="text" id="chart_to" style="width: 7em">
1006 <label><input type="checkbox" id="tooltip" value="" style="margin-left: 2em;">ツールチップ</label>
1007 </div>
1008 <div id="chart" style="clear: both; margin: 1em;"></div>
1009
1010 <li class="hide">
1011 <table id="achivement_table">
1012 <thead>
1013 <tr><th>日付</th><th>戦果</th><th>EO</th><th>月毎</th></tr>
1014 </thead>
1015 </table>
1016
1017 <li class="hide">
1018 <ul class="tab tab1" id="range_sortie_stat" style="float: left; margin-right: 0.2em">
1019 <li>直近</li>
1020 <li>期間指定</li>
1021 </ul>
1022 <div style="padding: 0.2em 0;">
1023 <input type="text" id="sortie_stat_from" style="width: 7em">~<input type="text" id="sortie_stat_to" style="width: 7em">
1024 </div>
1025
1026 <div id="sortie_stat_recent_tables" style="clear: both;">
1027
1028 <h3>今日</h3>
1029 <table id="sortie_stat_day">
1030 <thead>
1031 <tr><th>マップ</th><th>出撃</th><th>S</th><th>A</th><th>B</th><th>C</th><th>D以下</th><th>輸送船</th></tr>
1032 </thead>
1033 </table>
1034
1035 <h3>今週</h3>
1036 <table id="sortie_stat_week">
1037 <thead>
1038 <tr><th>マップ</th><th>出撃</th><th>S</th><th>A</th><th>B</th><th>C</th><th>D以下</th><th>輸送船</th></tr>
1039 </table>
1040
1041 <h3>今月</h3>
1042 <table id="sortie_stat_month">
1043 <thead>
1044 <tr><th>マップ</th><th>出撃</th><th>S</th><th>A</th><th>B</th><th>C</th><th>D以下</th></tr>
1045 </table>
1046 </div>
1047
1048 <div id="sortie_stat_all_table" style="display: none;">
1049 <table id="sortie_stat_all">
1050 <thead>
1051 <tr><th>マップ</th><th>出撃</th><th>S</th><th>A</th><th>B</th><th>C</th><th>D以下</th><th>輸送船</th></tr>
1052 </thead>
1053 </table>
1054 </div>
1055
1056 </ul>
1057 </body>
1058 </html>