6 <li each={name, i in mainTabs} class={select: mainTab === i} onclick={parent.changeTab}>{name}</li>
10 /* global moment, c3, opts */
12 this.mainTab = +sessionStorage.getItem('prevTab');
13 opts.observable.trigger("mainTabChanged", this.mainTab);
15 this.changeTab = function(e) {
16 this.mainTab = e.item.i;
17 sessionStorage.setItem('prevTab', e.item.i);
18 opts.observable.trigger("mainTabChanged", e.item.i);
24 <form id="term" show={enabled}>
26 <label><input type="radio" name="term" value="0" checked="checked">直近一か月</label>
27 <label><input type="radio" name="term" value="1">期間指定: </label>
28 <input type="text" id="term_from" style="width: 7em">~<input type="text" id="term_to" style="width: 7em">
29 <input type="button" id="term_apply" value="適用">
34 this.on("mount", function() {
35 $('#term_from').datepicker({
36 defaultDate: moment().subtract(1, 'months').toDate(),
37 onClose: function() { $('input[name=term]').val(['1']); }
39 $('#term_to').datepicker({
40 onClose: function() { $('input[name=term]').val(['1']); }
42 $('#term_apply').click(function() {
43 opts.observable.trigger("termApplied");
50 opts.observable.on("mainTabChanged", function(idx) {
51 self.update({enabled: idx >= 0 && idx < self.logTables});
57 <div each={header, i in tables} show={mainTab === i}>
58 <table class="display compact cell-border" id={"log" + i}>
67 "<th>日付</th><th>海域</th><th>マス</th><th>ボス</th><th>ランク</th><th>ドロップ艦種</th><th>ドロップ艦娘", // ドロップ
68 "<th>日付</th><th style=\"min-width: 3.2em;\">海域</th><th>マス</th><th>ボス</th><th>ランク</th><th>艦隊行動</th><th>味方陣形</th><th>敵陣形</th><th style=\"min-width: 3.2em;\">敵艦隊</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>大破艦</ht><th style=\"min-width: 2.2em;\">敵艦1</th><th>敵艦1HP</th><th style=\"min-width: 2.2em;\">敵艦2</th><th>敵艦2HP</th><th style=\"min-width: 2.2em;\">敵艦3</th><th>敵艦3HP</th><th style=\"min-width: 2.2em;\">敵艦4</th><th>敵艦4HP</th><th style=\"min-width: 2.2em;\">敵艦5</th><th>敵艦5HP</th><th style=\"min-width: 2.2em;\">敵艦6</th><th>敵艦6HP</th><th>味方制空値</th><th>敵制空値</th><th>制空状態</th>", // 海戦
69 "<th>日付</th><th>結果</th><th>遠征</th><th>燃料</th><th>弾薬</th><th>鋼材</th><th>ボーキ</th><th>開発資材</th><th>高速修復材</th><th>高速建造材</th>", // 遠征
70 "<th>日付</th><th>開発装備</th><th>種別</th><th>燃料</th><th>弾薬</th><th>鋼材</th><th>ボーキ</th><th>秘書艦</th><th>司令部Lv</th>", // 開発
71 "<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>", // 建造
72 "<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>", // 改修
73 "<th>日付</th><th>燃料</th><th>弾薬</th><th>鋼材</th><th>ボーキ</th><th>高速建造材</th><th>高速修復材</th><th>開発資材</th><th>改修資材</th>" // 戦果
86 this.on("mount", function() {
87 var records = this.root.querySelectorAll("tr");
88 for (var i = 0; i < records.length; i++)
89 records[i].innerHTML = this.tables[i];
96 opts.observable.on("mainTabChanged", function(idx) {
97 self.update({mainTab: idx});
101 opts.observable.on("termApplied", function() {
105 this.init = function() {
106 for (var t = 0; t < this.tables.length; t++) {
111 order: [[0, "desc"]],
113 lengthMenu: [[50, 100, 200, -1], [50, 100, 200, "All"]],
114 drawCallback: function() {
115 $('#loading').hide();
119 opts.columns = [{ data: 0 }, { data: 1 }, { data: 2 }, { data: 3 }, { data: 4 }, { data: 9 }, { data: 10 }];
120 } else if (t === 1) {
122 for (var i = 0; i < 39; i++) {
123 if (i === 9 || i === 10)
125 entries.push({ data: i });
127 opts.columns = entries;
129 $('#log' + t).dataTable(opts);
133 this.show = function() {
134 if (this.mainTab >= this.jsons.length)
136 var query = "?from=" + moment().subtract(1, 'months').valueOf();
137 if ($('input[name=term]:eq(1)').prop('checked')) {
138 var from = $('#term_from').datepicker("getDate");
139 var to = $('#term_to').datepicker("getDate");
141 query = "?from=" + from.valueOf();
143 query += "&to=" + (to.valueOf() + this.oneDay);
145 $('#loading').show();
146 var url = this.jsons[this.mainTab] + query;
147 $('#log' + this.mainTab).DataTable().ajax.url(url).load();
153 <form id="chart_type" show={mainTabs[mainTab] === "資材グラフ"}>
154 <div style="margin: 0 0 0.5em 1em;">
155 <label><input type="radio" name="chart_type" value="0" checked={opts.chartSpec.type === 0} onchange={chartTypeChange}>連続</label>
156 <label><input type="radio" name="chart_type" value="1" checked={opts.chartSpec.type === 1} onchange={chartTypeChange}>差分</label>
162 opts.chartSpec.type = +sessionStorage.getItem('chartType');
165 this.chartTypeChange = function(e) {
166 opts.chartSpec.type = +e.target.value;
167 sessionStorage.setItem('chartType', opts.chartSpec.type);
168 opts.observable.trigger("chartTypeChanged");
169 opts.observable.trigger("chartSpecChanged");
172 opts.observable.on("mainTabChanged", function(idx) {
173 self.update({mainTab: idx});
179 <div show={mainTabs[mainTab] === "資材グラフ"}>
180 <ul class="tab tabsub" style="float: left; margin-right: 0.2em" show={chartSpec.type === 0}>
181 <li each={name, i in seqChartRanges} class={select: chartSpec.seqRange === i} onclick={parent.rangeTabChange}>{name}</li>
184 <ul class="tab tabsub" style="float: left; margin-right: 0.2em" show={chartSpec.type === 1}>
185 <li each={name, i in diffChartRanges} class={select: chartSpec.diffRange === i} onclick={parent.rangeTabChange}>{name}</li>
187 <div style="padding: 0.2em 0;">
188 <input type="text" id="chart_from" style="width: 7em">~<input type="text" id="chart_to" style="width: 7em">
189 <label><input type="checkbox" id="tooltip" value="" style="margin-left: 2em;" onchange={tooltipChange} checked={opts.chartSpec.tooltip === 1}>ツールチップ</label>
194 this.seqChartRanges = [
203 this.diffChartRanges = [
211 opts.chartSpec.seqRange = +sessionStorage.getItem('seqChartRange');
212 opts.chartSpec.diffRange = +sessionStorage.getItem('diffChartRange');
213 opts.chartSpec.tooltip = +sessionStorage.getItem('chartTooltip');
214 this.chartSpec = opts.chartSpec;
216 this.rangeTabChange = function(e) {
217 if (opts.chartSpec.type === 0) {
218 opts.chartSpec.seqRange = e.item.i;
219 sessionStorage.setItem('seqChartRange', e.item.i);
221 opts.chartSpec.diffRange = e.item.i;
222 sessionStorage.setItem('diffChartRange', e.item.i);
224 opts.observable.trigger("chartSpecChanged");
227 this.tooltipChange = function(e) {
228 opts.chartSpec.tooltip = +e.target.checked;
229 sessionStorage.setItem('chartTooltip', +e.target.checked);
230 opts.observable.trigger("chartSpecChanged");
233 this.useDatePicker = function() {
234 return opts.chartSpec.type === 0 && opts.chartSpec.seqRange === 5 ||
235 opts.chartSpec.type === 1 && opts.chartSpec.diffRange === 4;
238 this.init = function() {
239 $('#chart_from').datepicker({
240 onClose: function() {
241 if (self.useDatePicker())
242 opts.observable.trigger("chartSpecChanged");
245 $('#chart_to').datepicker({
246 onClose: function() {
247 if (self.useDatePicker())
248 opts.observable.trigger("chartSpecChanged");
253 this.on("mount", this.init);
258 opts.observable.on("mainTabChanged", function(idx) {
259 self.update({mainTab: idx});
262 opts.observable.on("chartTypeChanged", function() {
272 opts.observable.on("chartSpecChanged", function() {
273 if (opts.chartSpec.type === 0)
277 opts.observable.on("chartSizeChanged", function() {
278 if (opts.chartSpec.type === 0)
282 this.header = ["日付", "燃料", "弾薬", "鋼材", "ボーキ", "高速建造材", "高速修復材", "開発資材", "改修資材"];
284 opts.observable.on("offAllLegends", function() {
285 if (opts.chartSpec.type !== 0)
288 self.header.slice(1).forEach(function(c) {
289 self.unselected[c] = true;
293 this.resize = function() {
296 $('#loading').show();
297 setTimeout(function() {
298 self.chart.resize(self.chartSize());
302 this.drawChart = function(data) {
304 $('#loading').show();
306 url: "./資材ログ.json?number=true",
307 success: function(d) { self.drawChart(d); },
308 dataType: "json", cache: false
313 picked = this.pickChartData(data.data, opts.chartSpec.seqRange);
314 picked.data.unshift(self.header);
315 this.drawSeqChart(picked);
318 this.unselected = {};
320 this.drawSeqChart = function(picked) {
321 var size = this.chartSize();
322 this.chart = c3.generate({
330 xFormat: '%Y-%m-%d %X',
347 show: opts.chartSpec.tooltip
359 format: "%m-%d %H:%M",
369 onclick: function(id) {
370 self.unselected[id] = !self.unselected[id];
371 self.chart.toggle(id);
375 onrendered: function() {
376 $('#loading').hide();
377 opts.observable.trigger("chartRendered");
380 self.chart.hide(Object.keys(self.unselected).filter(function(e) {
381 return self.unselected[e];
385 this.pickChartData = function(data, range) {
389 var first = data[0][0];
390 var last = data[data.length - 1][0];
391 var interval, tickInterval, lastTick;
394 first = moment(last).subtract(24, 'hours').valueOf();
397 first = moment(last).subtract(7, 'days').valueOf();
400 first = moment(last).subtract(1, 'months').valueOf();
403 first = moment(last).subtract(3, 'months').valueOf();
408 var fromDate = $('#chart_from').datepicker("getDate");
409 var toDate = $('#chart_to').datepicker("getDate");
410 if (fromDate === null || toDate === null)
411 return { data: [], tick: [], grid: [] };
412 var from = fromDate.valueOf() + 3600 * 5000;
413 var to = toDate.valueOf() + this.oneDay + 3600 * 5000;
414 first = Math.max(first, from);
415 last = Math.min(last, to);
418 if (last <= first + this.oneDay) {
420 tickInterval = 3600 * 1000;
421 lastTick = last - last % tickInterval;
422 } else if (last <= first + this.oneDay * 21) {
424 tickInterval = this.oneDay;
425 lastTick = this.to5am(last);
426 } else if (last <= first + this.oneDay * 63) {
427 interval = 3600 * 1000;
428 tickInterval = this.oneDay * 7;
429 lastTick = this.to5am(moment(last).day(1).valueOf());
430 } else if (last <= first + this.oneDay * 126) {
431 interval = 3600 * 6000;
432 tickInterval = this.oneDay * 14;
433 lastTick = this.to5am(moment(last).day(1).valueOf());
435 var years = Math.floor((last - first) / (this.oneDay * 365));
436 interval = 3600 * (years > 2 ? 24000 : 12000);
437 tickInterval = this.oneDay * 28;
438 lastTick = this.to5am(moment(last).day(1).valueOf());
441 for (var i = data.length - 1; i >= 0; i--) {
446 var v = date - date % interval;
447 if (lastData !== v) {
448 newdata.unshift(row);
456 for (var tick = lastTick; tick > lastData; tick -= tickInterval) {
457 var str = self.toDateString(moment(tick));
459 grid.unshift({ value: str });
461 return { data: newdata, tick: ticks, grid: grid };
470 opts.observable.on("chartSpecChanged", function() {
471 if (opts.chartSpec.type === 1)
475 opts.observable.on("chartSizeChanged", function() {
476 if (opts.chartSpec.type === 1)
480 this.header = ["日付", "燃料", "弾薬", "鋼材", "ボーキ"];
482 opts.observable.on("offAllLegends", function() {
483 if (opts.chartSpec.type !== 1)
486 self.header.slice(1).forEach(function(c) {
487 self.unselected[c] = true;
491 this.resize = function() {
494 $('#loading').show();
495 setTimeout(function() {
496 self.chart.resize(self.chartSize());
500 this.drawChart = function(data) {
502 $('#loading').show();
504 url: "./資材ログ.json?number=true",
505 success: function(d) { self.drawChart(d); },
506 dataType: "json", cache: false
511 picked = this.pickChartData(data.data, opts.chartSpec.diffRange);
512 picked.data.unshift(self.header);
513 this.drawDiffChart(picked);
516 this.unselected = {};
518 this.drawDiffChart = function(picked) {
519 var size = this.chartSize();
520 this.chart = c3.generate({
536 groups: [["燃料", "弾薬", "鋼材", "ボーキ"]]
544 show: opts.chartSpec.tooltip
561 format: picked.monthly ? "%Y-%m" : "%m-%d %H:%M",
568 onclick: function(id) {
569 self.unselected[id] = !self.unselected[id];
570 self.chart.toggle(id);
574 onrendered: function() {
575 $('#loading').hide();
576 opts.observable.trigger("chartRendered");
579 self.chart.hide(Object.keys(self.unselected).filter(function(e) {
580 return self.unselected[e];
584 this.pickChartData = function(data, range) {
588 var first = data[0][0];
589 var last = data[data.length - 1][0];
590 var interval, tickInterval, lastTick;
593 first = moment(last).subtract(1, 'months').valueOf();
596 first = moment(last).subtract(3, 'months').valueOf();
599 first = moment(last).subtract(6, 'months').subtract(1, 'weeks').valueOf();
602 return this.pickMonthlyChartData(data);
604 var fromDate = $('#chart_from').datepicker("getDate");
605 var toDate = $('#chart_to').datepicker("getDate");
606 if (fromDate === null || toDate === null)
607 return { data: [], tick: [], grid: [] };
608 var from = fromDate.valueOf() + 3600 * 5000;
609 var to = toDate.valueOf() + this.oneDay + 3600 * 5000;
610 first = Math.max(first, from);
611 last = Math.min(last, to);
615 if (last <= first + this.oneDay * 2 * 31) {
616 interval = this.oneDay;
617 tickInterval = this.oneDay * 2;
618 lastTick = this.to5am(last);
620 } else if (last <= first + this.oneDay * 3 * 31) {
621 interval = this.oneDay;
622 tickInterval = this.oneDay * 7;
623 lastTick = this.to5am(last);
626 interval = this.oneDay * 7;
627 tickInterval = this.oneDay * 28;
628 lastTick = this.to5am(moment(last).day(1).valueOf());
630 if (last <= first + this.oneDay * 6 * 38) {
631 tickInterval = this.oneDay * 14;
635 var lastDate = lastTick;
637 for (var i = data.length - 1; i >= 0; i--) {
646 if (date <= lastDate) {
647 var newrow = [lastDate];
648 for (var r = 1; r < 5; r++) {
649 newrow.push(prevRow[r] - row[r]);
651 newdata.unshift(newrow);
652 lastDate = lastDate - interval;
660 if (tickInterval >= this.oneDay * 7)
661 lastTick = moment(lastTick).day(1).hour(5).minute(0).valueOf();
662 for (var tick = lastTick; tick > lastDate; tick -= tickInterval) {
664 grid.unshift({ value: tick });
666 return { data: newdata, tick: ticks, grid: grid, width: barWidth };
669 this.pickMonthlyChartData = function(data) {
677 for (var i = data.length - 1; i >= 0; i--) {
681 var eom = moment(row[0]).endOf('month');
682 prevRow[0] = eom.valueOf();
683 prevMonth = eom.month();
686 date = new Date(row[0]);
687 if (prevMonth !== date.getMonth()) {
688 var newrow = [prevRow[0]];
689 for (var r = 1; r < 5; r++)
690 newrow.push(prevRow[r] - row[r]);
691 newdata.unshift(newrow);
692 ticks.unshift(prevRow[0]);
693 grid.unshift({ value: prevRow[0] });
695 prevMonth = date.getMonth();
698 if (prevRow && date !== prevRow[0]) {
699 newrow = [prevRow[0]];
700 for (r = 1; r < 5; r++)
701 newrow.push(prevRow[r] - row[r]);
702 newdata.unshift(newrow);
703 ticks.unshift(prevRow[0]);
704 grid.unshift({ value: prevRow[0] });
706 return { monthly: true, data: newdata, tick: ticks, grid: grid, width: 0.5 };
709 </differential-chart>
712 <div show={mainTabs[mainTab] === "資材グラフ"}>
713 <span class="c3-legend-item" id="off-all-legends" style="text-decoration: underline; cursor: pointer; z-index: 10; position: absolute; display: none;" onclick={offAllLegends} >全解除</span>
714 <div id="chart" style="clear: both; margin: 1em;"></div>
721 opts.observable.on("mainTabChanged", function(idx) {
722 self.update({mainTab: idx});
723 if (self.mainTabs[idx] === "資材グラフ")
724 opts.observable.trigger("chartSpecChanged");
727 opts.observable.on("chartRendered", function() {
729 if (opts.chartSpec.type === 0) {
730 legend = $(".c3-legend-item-改修資材>text").offset();
733 legend = $(".c3-legend-item-ボーキ>text").offset();
737 $("#off-all-legends").offset({top: legend.top, left: legend.left + offset}).show();
740 this.offAllLegends = function() {
741 opts.observable.trigger("offAllLegends");
745 $(window).resize(function() {
747 clearTimeout(self.timer);
748 self.timer = setTimeout(function() {
749 if (self.mainTabs[self.mainTab] === "資材グラフ")
750 opts.observable.trigger("chartSizeChanged");
751 else if (self.mainTabs[self.mainTab] === "戦果")
752 opts.observable.trigger("achivementChartSizeChanged");
759 <div show={mainTabs[mainTab] === "戦果"}>
760 <span style="margin-left: 1em;">期間: </span><select style="width: 7em; margin-bottom: 1em;" name="月" onchange={monthChange}>
761 <option each={m, i in months} value={m}>{m}</option>
763 <table id="achivement_table" class="display compact cell-border">
765 <tr><th>日付</th><th>戦果</th><th>EO</th><th>月毎</th></tr>
768 <div id="achivementChart" style="margin: 1em;"></div>
772 this.on("mount", function() {
773 $("#achivement_table").dataTable({
777 order: [[0, "desc"]],
781 drawCallback: function() {
782 $('#loading').hide();
789 opts.observable.on("mainTabChanged", function(idx) {
790 self.update({mainTab: idx});
791 if (self.mainTabs[self.mainTab] === "戦果")
796 this.selectedIndex = 0;
798 this.monthChange = function(event) {
799 if (event.target.selectedIndex === 0) {
803 this.selectedIndex = event.target.selectedIndex;
804 var dt = $('#achivement_table').DataTable();
806 dt.rows.add(this.result[event.target.value]).draw();
807 this.showChart(event.target.value);
810 this.calcResult = function(data) {
812 var expPerAch = 10000 / 7.0;
814 var endOfMonth = moment(0);
817 var endOfYear = moment(0);
819 var carryOverAch = 0;
822 var lastDate = moment(0);
824 var nextDate = moment(0);
825 for (var i = 0; i < data.length; i++) {
827 var date = this.parseDate(row[0]);
828 var exp = row[1] - 0;
830 var isNewYear = date.isSameOrAfter(endOfYear);
831 var isNewMonth = date.isSameOrAfter(endOfMonth);
832 var isNewDate = date.isSameOrAfter(nextDate);
833 if (isNewDate || isNewMonth || isNewYear) {
834 if (lastDate.add(1, 'hours').isSameOrBefore(date)) {
835 // 2時を過ぎて最初のexpを戦果の計算に使うと、2時をまたいだ出撃の戦果が前日に加算される。
836 // そこで2時前のexpを使って戦果を計算するが、2時前のexpが正しく出力されていない場合は
837 // 戦果を正しく計算できない。記録の間隔が1時間以上空いているときは、2時をまたいだ出撃が
838 // 行われていない可能性が高いので計算には今のexpを使うことにする。
839 // これは5時基準で出力された過去のデータで、妥当な戦果を計算するために必要な処理である。
842 if (nextDate.valueOf() !== 0) {
843 var d = isNewDate ? nextDate.subtract(1, 'days') : endOfMonth;
844 var m = d.format("YYYY-MM");
847 this.result[m].push([
848 d.format("YYYY-MM-DD"),
849 ((lastExp - prevExp) / expPerAch).toFixed(1), dayEo,
850 ((lastExp - monthExp) / expPerAch + monthEo + carryOverAch + carryOverEo).toFixed(1)
853 prevExp = lastExp === -1 ? exp : lastExp;
855 endOfYear = date.clone().endOf('year').hour(22).startOf('hour');
856 if (endOfYear.isSameOrBefore(date))
857 endOfYear.add(1, 'year');
858 yearExp = lastExp === -1 ? exp : lastExp;
861 endOfMonth = date.clone().endOf('month');
862 if (date.date() === endOfMonth.date())
863 endOfMonth.add(1, 'months').endOf('month');
864 endOfMonth.hour(22).startOf('hour');
865 monthExp = lastExp === -1 ? exp : lastExp;
866 carryOverEo = monthEo * expPerAch / 50000;
867 carryOverAch = (monthExp - yearExp) / 50000;
869 m = endOfMonth.format("YYYY-MM");
872 this.result[m].push([endOfMonth.format("YYYY-MM 引継"),
873 carryOverAch.toFixed(1), carryOverEo.toFixed(1), (carryOverAch + carryOverEo).toFixed(1)]);
876 nextDate = date.clone().hour(2).startOf('hour');
877 if (date.hour() >= 2)
878 nextDate.add(1, 'days');
879 if (nextDate.date() === 1)
880 nextDate.add(1, 'days');
882 if (date.isBefore(date.clone().endOf('month').hour(22).startOf('hour'))) {
883 // 月末22時から翌0時までのEOのボーナス戦果は消える。
892 this.calcChartData = function() {
894 for (var month in this.result) {
895 var data = this.chartData[month] = [];
896 var result = this.result[month];
899 data.push(["日付", "戦果", "EO", "月毎"]);
900 for (var i = 0; i < result.length; i++) {
902 if (row[0].match(/引継/)) {
904 data.push([0, row[1], row[2], row[3]]);
907 d = moment(row[0], "YYYY-MM-DD").date();
909 var ach = (row[3] - eo).toFixed(1);
910 data.push([d, ach, eo, row[3]]);
912 var endOfMonth = moment(month, "YYYY-MM").endOf("month").date();
913 while (d < endOfMonth) {
915 data.push([d, null, null, null]);
920 this.chartSize = function() {
921 var width = Math.max($(window).width() - 6 * this.pxPerEm, 800);
928 opts.observable.on("achivementChartSizeChanged", function() {
931 $('#loading').show();
932 setTimeout(function() {
933 self.chart.resize(self.chartSize());
937 this.showChart = function(month) {
938 this.chart = c3.generate({
939 bindto: "#achivementChart",
940 size: this.chartSize(),
943 rows: this.chartData[month],
950 onrendered: function() { $('#loading').hide(); }
954 this.show = function(data) {
956 $('#loading').show();
959 success: function(data) {
960 self.show(data.data);
967 this.calcResult(data);
968 this.calcChartData();
969 this.months = Object.keys(this.result).sort(function(a, b) {
977 var dt = $('#achivement_table').DataTable();
979 dt.rows.add(this.result[this.months[this.selectedIndex]]).draw();
980 this.showChart(this.months[this.selectedIndex]);
986 <div show={mainTabs[mainTab] === "出撃統計"}>
988 <ul class="tab tabsub" style="float: left; margin-right: 0.2em">
989 <li each={tabs} class={select: parent.type === type} onclick={parent.changeTab}>{label}</li>
992 <div style="padding: 0.2em 0;">
993 <input type="text" id="sortie_stat_from" style="width: 7em">~<input type="text" id="sortie_stat_to" style="width: 7em">
996 <div style="clear: both;" show={type === "recent"}>
998 <table id="sortie_stat_day">
1000 <tr><th>マップ</th><th>出撃</th><th>S</th><th>A</th><th>B</th><th>C</th><th>D以下</th><th>輸送船</th></tr>
1004 <table id="sortie_stat_week">
1006 <tr><th>マップ</th><th>出撃</th><th>S</th><th>A</th><th>B</th><th>C</th><th>D以下</th><th>輸送船</th></tr>
1009 <table id="sortie_stat_month">
1011 <tr><th>マップ</th><th>出撃</th><th>S</th><th>A</th><th>B</th><th>C</th><th>D以下</th></tr>
1015 <div id="sortie_stat_all_table" show={type === "range"}>
1016 <table id="sortie_stat_all">
1018 <tr><th>マップ</th><th>出撃</th><th>S</th><th>A</th><th>B</th><th>C</th><th>D以下</th><th>輸送船</th></tr>
1036 this.type = "recent";
1037 this.changeTab = function(e) {
1038 this.type = e.item.type;
1045 this.on("mount", function() {
1046 $("[id^=sortie]").addClass('display compact cell-border');
1050 opts.observable.on("mainTabChanged", function(idx) {
1051 self.update({mainTab: idx});
1052 if (self.mainTabs[self.mainTab] === "出撃統計")
1056 this.init = function() {
1058 this.initDatePicker();
1061 this.initTable = function() {
1062 var terms = ['day', 'week', 'month', 'all'];
1063 for (var i = 0; i < terms.length; i++) {
1064 $("#sortie_stat_" + terms[i]).dataTable({
1068 columns: terms[i] !== 'month' ? [
1090 this.initDatePicker = function() {
1091 $('#sortie_stat_from').datepicker({
1092 onClose: function() { if (self.type === "range") self.show(); }
1094 $('#sortie_stat_to').datepicker({
1095 onClose: function() { if (self.type === "range") self.show(); }
1101 this.loadData = function() {
1103 if (this.type === "recent") {
1104 from = moment().subtract(1, 'months').subtract(1, 'day').valueOf();
1105 to = new Date().valueOf();
1107 var fromDate = $('#sortie_stat_from').datepicker("getDate");
1108 var toDate = $('#sortie_stat_to').datepicker("getDate");
1109 if (fromDate === null || toDate === null) {
1113 from = moment(fromDate);
1114 if (from.date() === 1)
1115 from.subtract(2, 'hours');
1116 from = from.valueOf();
1117 to = moment(toDate);
1118 if (to.date() === to.clone().endOf('month').date()) {
1126 url: "./海戦・ドロップ報告書.json?from=" + from + "&to=" + to,
1127 success: function(data) { self.show(data.data); },
1128 dataType: "json", cache: false
1132 this.initResult = function() {
1135 if (this.type === "recent") {
1141 r.day.begin = moment(now).hour(5).minute(0).second(0);
1142 if (now.hour() < 5) {
1143 r.day.begin.subtract(1, 'days');
1145 r.week.begin = moment(now).day(1).hour(5).minute(0).second(0);
1146 if (now.day() === 0 || now.day() === 1 && now.hour() < 5) {
1147 r.week.begin.subtract(1, 'weeks');
1149 if (moment(now).endOf('month').date() === now.date() &&
1150 now.hour() >= 22) { // 月末22時以降
1151 r.month.begin = moment(now).hour(22).minute(0).second(0);
1154 moment(now).date(1).subtract(1, 'days').
1155 hour(22).minute(0).second(0);
1158 r = { all: { stat: {} } };
1159 r.all.begin = moment(0);
1164 this.gatherData = function(data) {
1165 var initStat = function() {
1166 return { start: "-", S: 0, A: 0, B: 0, C: 0, D: 0, R: 0 };
1168 var r = this.initResult();
1169 for (var i = 0; i < data.length; i++) {
1171 var date = moment(row[0]);
1173 var isBoss = row[3].indexOf("ボス") !== -1;
1174 var isStart = row[3].indexOf("出撃") !== -1;
1176 for (var j = 23; j < row.length; j++) {
1177 if (/^輸送/.test(row[j]) && /^0\x2f/.test(row[j + 1]))
1183 for (var term in r) {
1184 if (!r.hasOwnProperty(term))
1187 if (to.begin.isAfter(date))
1189 for (var b = 0; b < 4; b++) {
1190 var name = b < 2 ? "合計" : map;
1191 if (b === 1 || b === 3) {
1194 name = name + " - ボス";
1196 var mo = to.stat[name];
1198 mo = to.stat[name] = initStat();
1200 to.stat["合計 - ボス"] = initStat();
1204 if ((b === 0 || b === 2) && isStart) {
1205 if (mo.start === "-")
1215 this.arrangeTable = function(r) {
1216 for (var term in r) {
1217 if (!r.hasOwnProperty(term))
1221 for (var map in r[term].stat) {
1222 if (!r[term].stat.hasOwnProperty(map))
1226 var e = r[term].stat[map];
1230 var boss = map + " - ボス";
1231 e = r[term].stat[boss];
1238 r[term].table = table;
1242 this.show = function(data) {
1244 $('#loading').show();
1248 var r = this.gatherData(data);
1249 this.arrangeTable(r);
1250 for (var term in r) {
1251 if (!r.hasOwnProperty(term))
1253 var dt = $("#sortie_stat_" + term).DataTable();
1255 dt.rows.add(r[term].table).draw();
1257 $('#loading').hide();