poi-plugin-milk 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,24 @@
1
+ {
2
+ "Anchorage repair": "泊地修理",
3
+ "Akashi not flagship": "明石不是旗舰/野崎不是旗舰二舰",
4
+ "Not ready": "未就绪",
5
+ "Capacity: %s": "可修理数量: %s",
6
+ "Please return to HQ screen to make timer refreshed.": "请回到母港画面以重置计时器。",
7
+ "Ship": "舰娘",
8
+ "HP": "耐久",
9
+ "Akashi Time": "明石修理时间",
10
+ "Per HP": "单位修理时间",
11
+ "Estimated repaired": "预计已回复",
12
+ "fleet in expedition": "舰队远征中",
13
+ "Elapsed:": "计时器:",
14
+ "Repairing": "正在修理",
15
+ "Akashi loves you!": "明石爱你哦!",
16
+ "flagship in dock": "旗舰入渠中",
17
+ "anchorage repair completed": "泊地修理完毕",
18
+ "A plugin to help in Akashi's anchorage repair arrangement": "明石泊地修理助手",
19
+ "Docking": "入渠中",
20
+ "Total time required": "泊地修理总耗时",
21
+ "Time required for 1 HP recovery": "每回复一点耐久所用泊地修理时间",
22
+ "Estimated HP recovery since last refresh": "从上次刷新之后的预计耐久回复量",
23
+ "Candidates": "适格者"
24
+ }
@@ -0,0 +1,24 @@
1
+ {
2
+ "Anchorage repair": "泊地修理",
3
+ "Akashi not flagship": "明石不是旗艦",
4
+ "Not ready": "未就緒",
5
+ "Capacity: %s": "可修理數量: %s",
6
+ "Please return to HQ screen to make timer refreshed.": "請回到母港畫面以重置計時器。",
7
+ "Ship": "艦娘",
8
+ "HP": "耐久",
9
+ "Akashi Time": "明石修理時間",
10
+ "Per HP": "單位修理時間",
11
+ "Estimated repaired": "預計已回復",
12
+ "fleet in expedition": "艦隊遠征中",
13
+ "Elapsed:": "計時器:",
14
+ "Repairing": "正在修理",
15
+ "Akashi loves you!": "明石愛你哦!",
16
+ "flagship in dock": "旗艦入渠中",
17
+ "anchorage repair completed": "泊地修理完畢",
18
+ "A plugin to help in Akashi's anchorage repair arrangement": "明石泊地修理助手",
19
+ "Docking": "入渠中",
20
+ "Total time required": "泊地修理總耗時",
21
+ "Time required for 1 HP recovery": "每回復一點耐久所用泊地修理時間",
22
+ "Estimated HP recovery since last refresh": "從上次刷新之後的預計耐久回復量",
23
+ "Candidates": "適格者"
24
+ }
package/index.js ADDED
@@ -0,0 +1,234 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.switchPluginPath = exports.reactClass = undefined;
7
+
8
+ var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
9
+
10
+ // Import selectors defined in poi
11
+
12
+
13
+ var _react = require('react');
14
+
15
+ var _react2 = _interopRequireDefault(_react);
16
+
17
+ var _reactRedux = require('react-redux');
18
+
19
+ var _reselect = require('reselect');
20
+
21
+ var _lodash = require('lodash');
22
+
23
+ var _lodash2 = _interopRequireDefault(_lodash);
24
+
25
+ var _path = require('path');
26
+
27
+ var _reactBootstrap = require('react-bootstrap');
28
+
29
+ var _selectors = require('views/utils/selectors');
30
+
31
+ var _functions = require('./parts/functions');
32
+
33
+ var _fleetList = require('./parts/fleet-list');
34
+
35
+ var _fleetList2 = _interopRequireDefault(_fleetList);
36
+
37
+ var _candidates = require('./parts/candidates');
38
+
39
+ var _candidates2 = _interopRequireDefault(_candidates);
40
+
41
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
42
+
43
+ const { i18n, getStore } = window;
44
+ const __ = i18n['poi-plugin-anchorage-repair'].__.bind(i18n['poi-plugin-anchorage-repair']);
45
+
46
+ const AKASHI_ID = [182, 187]; // akashi and kai ID in $ships
47
+ const SRF_ID = 86; // Ship Repair Facility ID in $slotitems
48
+
49
+
50
+ // check a fleet status, returns information related to anchorage repair
51
+ const fleetAkashiConv = (fleet, $ships, ships, equips, repairId) => {
52
+ const pickKey = ['api_id', 'api_ship_id', 'api_lv', 'api_nowhp', 'api_maxhp', 'api_ndock_time','api_cond'];
53
+
54
+ let canRepair = false;
55
+ let akashiFlagship = false;
56
+ let repairCount = 0;
57
+ const inExpedition = _lodash2.default.get(fleet, 'api_mission.0') && true;
58
+ const flagShipInRepair = _lodash2.default.includes(repairId, _lodash2.default.get(fleet, 'api_ship.0', -1));
59
+ const flagship = ships[_lodash2.default.get(fleet, 'api_ship.0', -1)];
60
+
61
+ if (flagship != null) {
62
+ akashiFlagship = _lodash2.default.includes(AKASHI_ID, flagship.api_ship_id);
63
+ repairCount = _lodash2.default.filter(flagship.api_slot, item => _lodash2.default.get(equips, `${item}.api_slotitem_id`, -1) === SRF_ID).length;
64
+ repairCount += akashiFlagship ? 2 : 0;
65
+ }
66
+
67
+ canRepair = akashiFlagship && !inExpedition && !flagShipInRepair;
68
+
69
+ const repairDetail = _lodash2.default.map(_lodash2.default.filter(fleet.api_ship, shipId => shipId > 0), (shipId, index) => {
70
+ if (shipId === -1) return false; // break, LODASH ONLY
71
+
72
+ const ship = _lodash2.default.pick(ships[shipId], pickKey);
73
+
74
+ const constShip = _lodash2.default.pick($ships[ship.api_ship_id], ['api_name', 'api_stype']);
75
+
76
+ return _extends({}, ship, constShip, {
77
+ cond:ship.api_cond,
78
+ estimate: (0, _functions.akashiEstimate)(ship),
79
+ timePerHP: (0, _functions.getTimePerHP)(ship.api_lv, constShip.api_stype),
80
+ inRepair: _lodash2.default.includes(repairId, ship.api_id),
81
+ availableSRF: index < repairCount
82
+ });
83
+ });
84
+
85
+ var repairStatus = 0
86
+ if(canRepair){
87
+ repairStatus = 1;
88
+ }else{
89
+ var flagshipa = _lodash2.default.get(fleet, 'api_ship.0', -1)
90
+ var secondshipa = _lodash2.default.get(fleet, 'api_ship.1', -1)
91
+ var flagshipid = ships[flagshipa]?ships[flagshipa].api_ship_id:-1;
92
+ var secondshipid = ships[secondshipa]?ships[secondshipa].api_ship_id:-1;
93
+
94
+ if(flagshipid==996||flagshipid==1002||secondshipid==996||secondshipid==1002
95
+ //||flagshipid==357||secondshipid==357 //没有野崎,用初月改测试
96
+ ){
97
+ repairStatus = 2;
98
+ }
99
+ }
100
+ //console.log("cc:"+flagshipid)
101
+ canRepair = repairStatus;
102
+ //console.log("cc2:"+secondshipid)
103
+ return {
104
+ api_id: fleet.api_id || -1,
105
+ shipId: fleet.api_ship || [],
106
+ canRepair,
107
+ akashiFlagship,
108
+ inExpedition,
109
+ flagShipInRepair,
110
+ repairCount,
111
+ repairDetail
112
+ };
113
+ };
114
+
115
+ // selectors
116
+
117
+ const repairIdSelector = (0, _reselect.createSelector)([_selectors.repairsSelector], repair => _lodash2.default.map(repair, dock => dock.api_ship_id));
118
+
119
+ const constShipsSelector = state => state.const.$ships || {};
120
+
121
+ const fleetsAkashiSelector = (0, _reselect.createSelector)([constShipsSelector, _selectors.fleetsSelector, _selectors.shipsSelector, _selectors.equipsSelector, repairIdSelector], ($ships, fleets, ships, equips, repairId) => ({ fleets: _lodash2.default.map(fleets, fleet => fleetAkashiConv(fleet, $ships, ships, equips, repairId)) })
122
+
123
+ // React
124
+
125
+ );const reactClass = exports.reactClass = (0, _reactRedux.connect)((0, _selectors.createDeepCompareArraySelector)([fleetsAkashiSelector, _selectors.miscSelector], (data, { canNotify }) => _extends({}, data, {
126
+ canNotify
127
+ })))(class PluginAnchorageRepair extends _react.Component {
128
+
129
+ constructor(props) {
130
+ super(props);
131
+
132
+ this.handleSelectTab = key => {
133
+ this.setState({ activeTab: key });
134
+ };
135
+
136
+ this.handleSort = index => () => {
137
+ this.setState({
138
+ sortIndex: index
139
+ });
140
+ };
141
+
142
+ this.state = {
143
+ activeTab: 1,
144
+ sortIndex: 0
145
+ };
146
+ }
147
+
148
+ render() {
149
+ return _react2.default.createElement(
150
+ 'div',
151
+ { id: 'anchorage-repair' },
152
+ _react2.default.createElement('link', { rel: 'stylesheet', href: (0, _path.join)(__dirname, 'assets', 'style.css') }),
153
+ _react2.default.createElement(
154
+ _reactBootstrap.Tabs,
155
+ { activeKey: this.state.activeTab, onSelect: this.handleSelectTab, id: 'anchorage-tabs' },
156
+ _lodash2.default.map(this.props.fleets, (fleet, index) => _react2.default.createElement(
157
+ _reactBootstrap.Tab,
158
+ {
159
+ eventKey: fleet.api_id,
160
+ title: fleet.api_id,
161
+ key: `anchorage-tab-${index}`,
162
+ tabClassName: fleet.canRepair ? 'can-repair' : ''
163
+ },
164
+ _react2.default.createElement(_fleetList2.default, { fleet: fleet })
165
+ )),
166
+ _react2.default.createElement(
167
+ _reactBootstrap.Tab,
168
+ {
169
+ className: 'candidate-pane',
170
+ eventKey: -1,
171
+ title: __('Candidates')
172
+ },
173
+ _react2.default.createElement(_candidates2.default, { handleSort: this.handleSort, sortIndex: this.state.sortIndex })
174
+ )
175
+ )
176
+ );
177
+ }
178
+ }
179
+
180
+ /*
181
+
182
+ The following APIs are called in order when a fleet returns from expedition:
183
+
184
+ - api_req_mission/result
185
+ - api_port/port
186
+
187
+ As anchorage repair pops up conditionally on the latter one,
188
+ it also prevents other plugins' auto-switch mechanism on
189
+ tracking api_req_mission/result calls.
190
+
191
+ The problem is solved by applying a lock upon expedition returns
192
+ and ignoring the immediately followed api_port/port call.
193
+
194
+ */
195
+ );let expedReturnLock = null;
196
+ const clearExpedReturnLock = () => {
197
+ if (expedReturnLock !== null) {
198
+ clearTimeout(expedReturnLock);
199
+ expedReturnLock = null;
200
+ }
201
+ };
202
+
203
+ const switchPluginPath = exports.switchPluginPath = [{
204
+ path: '/kcsapi/api_port/port',
205
+ valid: () => {
206
+ if (expedReturnLock !== null) {
207
+ /*
208
+ this is the immediately followed api_port/port call
209
+ after an expedition returning event.
210
+ */
211
+ clearExpedReturnLock();
212
+ return false;
213
+ }
214
+
215
+ const { fleets = [], ships = {}, equips = {}, repairs = [] } = getStore('info') || {};
216
+ const $ships = getStore('const.$ships');
217
+ const repairId = repairs.map(dock => dock.api_ship_id);
218
+
219
+ const result = fleets.map(fleet => fleetAkashiConv(fleet, $ships, ships, equips, repairId));
220
+ return result.some(fleet => fleet.canRepair && fleet.repairDetail.some(ship => ship.estimate > 0));
221
+ }
222
+ }, {
223
+ path: '/kcsapi/api_req_mission/result',
224
+ valid: () => {
225
+ clearExpedReturnLock();
226
+ expedReturnLock = setTimeout(clearExpedReturnLock,
227
+ /*
228
+ allow a window of 5 secnds before the lock
229
+ clears itself
230
+ */
231
+ 5000);
232
+ return false;
233
+ }
234
+ }];
package/index.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["index.es"],"names":["i18n","getStore","window","__","bind","AKASHI_ID","SRF_ID","fleetAkashiConv","fleet","$ships","ships","equips","repairId","pickKey","canRepair","akashiFlagship","repairCount","inExpedition","get","flagShipInRepair","includes","flagship","api_ship_id","filter","api_slot","item","length","repairDetail","map","api_ship","shipId","index","ship","pick","constShip","estimate","timePerHP","api_lv","api_stype","inRepair","api_id","availableSRF","repairIdSelector","repair","dock","constShipsSelector","state","const","fleetsAkashiSelector","fleets","reactClass","data","canNotify","PluginAnchorageRepair","constructor","props","handleSelectTab","key","setState","activeTab","handleSort","sortIndex","render","__dirname","expedReturnLock","clearExpedReturnLock","clearTimeout","switchPluginPath","path","valid","repairs","result","some","setTimeout"],"mappings":"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","file":"index.es","sourcesContent":["import React, { Component } from 'react'\nimport { connect } from 'react-redux'\nimport { createSelector } from 'reselect'\nimport _ from 'lodash'\nimport { join } from 'path'\nimport { Tabs, Tab } from 'react-bootstrap'\n\n// Import selectors defined in poi\nimport {\n fleetsSelector,\n shipsSelector,\n equipsSelector,\n repairsSelector,\n miscSelector,\n createDeepCompareArraySelector,\n} from 'views/utils/selectors'\n\nimport {\n akashiEstimate,\n getTimePerHP,\n} from './parts/functions'\nimport FleetList from './parts/fleet-list'\nimport Candidates from './parts/candidates'\n\nconst { i18n, getStore } = window\nconst __ = i18n['poi-plugin-anchorage-repair'].__.bind(i18n['poi-plugin-anchorage-repair'])\n\nconst AKASHI_ID = [182, 187] // akashi and kai ID in $ships\nconst SRF_ID = 86 // Ship Repair Facility ID in $slotitems\n\n\n// check a fleet status, returns information related to anchorage repair\nconst fleetAkashiConv = (fleet, $ships, ships, equips, repairId) => {\n const pickKey = ['api_id', 'api_ship_id', 'api_lv', 'api_nowhp', 'api_maxhp', 'api_ndock_time']\n\n let canRepair = false\n let akashiFlagship = false\n let repairCount = 0\n const inExpedition = _.get(fleet, 'api_mission.0') && true\n const flagShipInRepair = _.includes(repairId, _.get(fleet, 'api_ship.0', -1))\n const flagship = ships[_.get(fleet, 'api_ship.0', -1)]\n\n if (flagship != null) {\n akashiFlagship = _.includes(AKASHI_ID, flagship.api_ship_id)\n repairCount = _.filter(flagship.api_slot, item => _.get(equips, `${item}.api_slotitem_id`, -1) === SRF_ID).length\n repairCount += akashiFlagship ? 2 : 0\n }\n\n canRepair = akashiFlagship && !inExpedition && !flagShipInRepair\n\n const repairDetail = _.map(_.filter(fleet.api_ship, shipId => shipId > 0), (shipId, index) => {\n if (shipId === -1) return false // break, LODASH ONLY\n\n const ship = _.pick(ships[shipId], pickKey)\n\n const constShip = _.pick($ships[ship.api_ship_id], ['api_name', 'api_stype'])\n\n return {\n ...ship,\n ...constShip,\n estimate: akashiEstimate(ship),\n timePerHP: getTimePerHP(ship.api_lv, constShip.api_stype),\n inRepair: _.includes(repairId, ship.api_id),\n availableSRF: index < repairCount,\n }\n })\n\n return {\n api_id: fleet.api_id || -1,\n shipId: fleet.api_ship || [],\n canRepair,\n akashiFlagship,\n inExpedition,\n flagShipInRepair,\n repairCount,\n repairDetail,\n }\n}\n\n// selectors\n\nconst repairIdSelector = createSelector(\n [repairsSelector],\n repair => _.map(repair, dock => dock.api_ship_id)\n)\n\nconst constShipsSelector = state => state.const.$ships || {}\n\nconst fleetsAkashiSelector = createSelector(\n [\n constShipsSelector,\n fleetsSelector,\n shipsSelector,\n equipsSelector,\n repairIdSelector,\n ],\n ($ships, fleets, ships, equips, repairId) =>\n ({ fleets: _.map(fleets, fleet => fleetAkashiConv(fleet, $ships, ships, equips, repairId)) })\n\n)\n\n\n// React\n\nexport const reactClass = connect(\n createDeepCompareArraySelector([\n fleetsAkashiSelector,\n miscSelector,\n ], (data, { canNotify }) => ({\n ...data,\n canNotify,\n }))\n)(class PluginAnchorageRepair extends Component {\n\n constructor(props) {\n super(props)\n\n this.state = {\n activeTab: 1,\n sortIndex: 0,\n }\n }\n\n handleSelectTab = (key) => {\n this.setState({ activeTab: key })\n }\n\n handleSort = index => () => {\n this.setState({\n sortIndex: index,\n })\n }\n\n render() {\n return (\n <div id=\"anchorage-repair\">\n <link rel=\"stylesheet\" href={join(__dirname, 'assets', 'style.css')} />\n <Tabs activeKey={this.state.activeTab} onSelect={this.handleSelectTab} id=\"anchorage-tabs\">\n {\n _.map(this.props.fleets, (fleet, index) => (\n <Tab\n eventKey={fleet.api_id}\n title={fleet.api_id}\n key={`anchorage-tab-${index}`}\n tabClassName={fleet.canRepair ? 'can-repair' : ''}\n >\n <FleetList fleet={fleet} />\n </Tab>\n ))\n }\n <Tab\n className=\"candidate-pane\"\n eventKey={-1}\n title={__('Candidates')}\n >\n <Candidates handleSort={this.handleSort} sortIndex={this.state.sortIndex} />\n </Tab>\n </Tabs>\n </div>\n )\n }\n})\n\n\n/*\n\n The following APIs are called in order when a fleet returns from expedition:\n\n - api_req_mission/result\n - api_port/port\n\n As anchorage repair pops up conditionally on the latter one,\n it also prevents other plugins' auto-switch mechanism on\n tracking api_req_mission/result calls.\n\n The problem is solved by applying a lock upon expedition returns\n and ignoring the immediately followed api_port/port call.\n\n */\nlet expedReturnLock = null\nconst clearExpedReturnLock = () => {\n if (expedReturnLock !== null) {\n clearTimeout(expedReturnLock)\n expedReturnLock = null\n }\n}\n\nexport const switchPluginPath = [\n {\n path: '/kcsapi/api_port/port',\n valid: () => {\n if (expedReturnLock !== null) {\n /*\n this is the immediately followed api_port/port call\n after an expedition returning event.\n */\n clearExpedReturnLock()\n return false\n }\n\n const { fleets = [], ships = {}, equips = {}, repairs = [] } = getStore('info') || {}\n const $ships = getStore('const.$ships')\n const repairId = repairs.map(dock => dock.api_ship_id)\n\n const result = fleets.map(fleet => fleetAkashiConv(fleet, $ships, ships, equips, repairId))\n return result.some(fleet =>\n fleet.canRepair && fleet.repairDetail.some(ship => ship.estimate > 0))\n },\n },\n {\n path: '/kcsapi/api_req_mission/result',\n valid: () => {\n clearExpedReturnLock()\n expedReturnLock = setTimeout(\n clearExpedReturnLock,\n /*\n allow a window of 5 secnds before the lock\n clears itself\n */\n 5000\n )\n return false\n },\n },\n]\n"]}
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "poi-plugin-milk",
3
+ "version": "1.0.0",
4
+ "description": "Anchorage repair plugin for poi",
5
+ "main": "index.es",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/KagamiChan/plugin-anchorage-repair.git"
9
+ },
10
+ "author": {
11
+ "name": "かがみ",
12
+ "link": "https://github.com/kagamichan"
13
+ },
14
+ "license": "MIT",
15
+ "bugs": {
16
+ "url": "https://github.com/KagamiChan/plugin-anchorage-repair/issues"
17
+ },
18
+ "homepage": "https://github.com/KagamiChan/plugin-anchorage-repair#readme",
19
+ "devDependencies": {
20
+ "babel-eslint": "^7.2.3",
21
+ "babel-preset-es2017": "^6.24.1",
22
+ "eslint": "^3.19.0",
23
+ "eslint-config-airbnb": "^15.0.1",
24
+ "eslint-plugin-import": "^2.3.0",
25
+ "eslint-plugin-jsx-a11y": "^5.0.3",
26
+ "eslint-plugin-react": "^7.0.1",
27
+ "poi-util-transpile": "^7.6.0"
28
+ },
29
+ "poiPlugin": {
30
+ "title": "Anchorage repair",
31
+ "description": "A plugin to help in Akashi's anchorage repair arrangement",
32
+ "icon": "ti/anchor",
33
+ "priority": 9,
34
+ "apiVer": {
35
+ "6.99.99": "0.1.0",
36
+ "7.5.99": "0.4.5",
37
+ "7.7.99": "0.4.8"
38
+ }
39
+ },
40
+ "dependencies": {
41
+ "chroma-js": "^1.3.4"
42
+ }
43
+ }
@@ -0,0 +1,169 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+
7
+ var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
8
+
9
+ var _react = require('react');
10
+
11
+ var _react2 = _interopRequireDefault(_react);
12
+
13
+ var _reselect = require('reselect');
14
+
15
+ var _reactRedux = require('react-redux');
16
+
17
+ var _fp = require('lodash/fp');
18
+
19
+ var _fp2 = _interopRequireDefault(_fp);
20
+
21
+ var _lodash = require('lodash');
22
+
23
+ var _reactVirtualized = require('react-virtualized');
24
+
25
+ var _reactBootstrap = require('react-bootstrap');
26
+
27
+ var _reactFontawesome = require('react-fontawesome');
28
+
29
+ var _reactFontawesome2 = _interopRequireDefault(_reactFontawesome);
30
+
31
+ var _chromaJs = require('chroma-js');
32
+
33
+ var _chromaJs2 = _interopRequireDefault(_chromaJs);
34
+
35
+ var _selectors = require('views/utils/selectors');
36
+
37
+ var _tools = require('views/utils/tools');
38
+
39
+ var _functions = require('./functions');
40
+
41
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
42
+
43
+ const { i18n } = window;
44
+ const __ = i18n['poi-plugin-anchorage-repair'].__.bind(i18n['poi-plugin-anchorage-repair']);
45
+
46
+ const sortable = ['HP', 'Akashi Time', 'Per HP'];
47
+
48
+ const getSortValue = sortIndex => ship => {
49
+ const direction = sortIndex % 2 ? -1 : 1;
50
+
51
+ switch (parseInt(sortIndex / 2, 10)) {
52
+ case 0:
53
+ return ship.api_nowhp / ship.api_maxhp * direction;
54
+ case 1:
55
+ return ship.akashi * direction;
56
+ case 2:
57
+ return ship.perHP * direction;
58
+ default:
59
+ return ship.api_id;
60
+ }
61
+ };
62
+
63
+ const allFleetShipIdSelector = (0, _reselect.createSelector)([...[...new Array(4).keys()].map(fleetId => (0, _selectors.fleetShipsIdSelectorFactory)(fleetId))], (id1, id2, id3, id4) => [id1, id2, id3, id4]);
64
+
65
+ const shipFleetIdMapSelector = (0, _reselect.createSelector)([state => state.info.ships, allFleetShipIdSelector], (ships, fleetIds) => (0, _lodash.mapValues)(ships, ship => (0, _lodash.findIndex)(fleetIds, fleetId => (0, _lodash.includes)(fleetId, ship.api_id))));
66
+
67
+ const repairIdSelector = (0, _reselect.createSelector)([_selectors.repairsSelector], repair => (0, _lodash.map)(repair, dock => dock.api_ship_id));
68
+
69
+ const candidateShipsSelector = sortIndex => (0, _reselect.createSelector)([state => state.info.ships, state => state.const.$ships, shipFleetIdMapSelector, repairIdSelector], (ships, $ships, shipFleetIdMap, repairIds) => _fp2.default.flow(_fp2.default.filter(ship => (0, _functions.akashiEstimate)(ship) > 0 && !(0, _lodash.includes)(repairIds, ship.api_id)), _fp2.default.map(ship => _extends({}, $ships[ship.api_ship_id], ship, {
70
+ akashi: (0, _functions.akashiEstimate)(ship),
71
+ perHP: (0, _functions.timePerHPCalc)(ship),
72
+ fleetId: shipFleetIdMap[ship.api_id]
73
+ })), _fp2.default.sortBy(ship => getSortValue(sortIndex)(ship)))(ships));
74
+
75
+ const getHPBackgroundColor = (nowhp, maxhp) => {
76
+ const percentage = nowhp / maxhp;
77
+ return percentage > 0.75 ? _chromaJs2.default.mix('rgb(253, 216, 53)', 'rgb(67, 160, 71)', (percentage - 0.75) / 0.25, 'lab').alpha(0.6).css() : _chromaJs2.default.mix('rgb(245, 124, 0)', 'rgb(253, 216, 53)', (percentage - 0.5) / 0.25, 'lab').alpha(0.6).css();
78
+ };
79
+
80
+ // console.log(
81
+ // chroma.mix('rgb(253, 216, 53)', 'rgb(67, 160, 71)', 0.5, 'lch').alpha(0.6).css(),
82
+ // chroma.mix('rgb(253, 216, 53)', 'rgb(67, 160, 71)', 0.5, 'rgb').alpha(0.6).css(),
83
+ // chroma.mix('rgb(253, 216, 53)', 'rgb(67, 160, 71)', 0.5, 'hsl').alpha(0.6).css(),
84
+ // chroma.mix('rgb(253, 216, 53)', 'rgb(67, 160, 71)', 0.5, 'lab').alpha(0.6).css(),
85
+ // )
86
+ // (nowhp / maxhp) > 0.75 ? 'rgba(67, 160, 71, 0.6)' : 'rgba(253, 216, 53, 0.6)'
87
+
88
+ const Candidates = (0, _reactRedux.connect)((state, { sortIndex = 0 }) => ({
89
+ ships: candidateShipsSelector(sortIndex)(state)
90
+ }))(class Candidates extends _react.Component {
91
+ constructor(...args) {
92
+ var _temp;
93
+
94
+ return _temp = super(...args), this.rowRenderer = ({ key, index, style }) => {
95
+ const { ships } = this.props;
96
+ const ship = ships[index];
97
+ const color = getHPBackgroundColor(ship.api_nowhp, ship.api_maxhp);
98
+ const percentage = Math.round(100 * ship.api_nowhp / ship.api_maxhp);
99
+ return _react2.default.createElement(
100
+ 'div',
101
+ {
102
+ className: 'candidate-ship-item',
103
+ style: _extends({}, style, {
104
+ background: `linear-gradient(90deg, ${color} ${percentage}%, rgba(0, 0, 0, 0) 50%)`
105
+ }),
106
+ key: key
107
+ },
108
+ _react2.default.createElement(
109
+ 'span',
110
+ { className: 'ship-name' },
111
+ `Lv.${ship.api_lv} ${window.i18n.resources.__(ship.api_name)}${ship.fleetId < 0 ? '' : `/${ship.fleetId + 1}`}`
112
+ ),
113
+ _react2.default.createElement(
114
+ 'span',
115
+ { style: { marginLeft: '1em' } },
116
+ `(${ship.api_nowhp} / ${ship.api_maxhp})`
117
+ ),
118
+ _react2.default.createElement(
119
+ 'span',
120
+ { style: { marginLeft: '2em' } },
121
+ `${(0, _tools.resolveTime)(ship.akashi / 1000)} / ${(0, _tools.resolveTime)(ship.perHP / 1000)}`
122
+ )
123
+ );
124
+ }, _temp;
125
+ }
126
+
127
+ render() {
128
+ const { ships, sortIndex } = this.props;
129
+ return _react2.default.createElement(
130
+ 'div',
131
+ {
132
+ id: 'candidate-list'
133
+ },
134
+ _react2.default.createElement(
135
+ 'div',
136
+ { style: { marginBottom: '1ex' } },
137
+ _react2.default.createElement(
138
+ _reactBootstrap.ButtonGroup,
139
+ { bsSize: 'small' },
140
+ [...new Array(6).keys()].map(index => _react2.default.createElement(
141
+ _reactBootstrap.Button,
142
+ {
143
+ key: index,
144
+ onClick: this.props.handleSort(index),
145
+ bsStyle: index === sortIndex ? 'success' : 'default'
146
+ },
147
+ __(sortable[parseInt(index / 2, 10)]),
148
+ _react2.default.createElement(_reactFontawesome2.default, { name: index % 2 === 0 ? 'arrow-up' : 'arrow-down' })
149
+ ))
150
+ )
151
+ ),
152
+ _react2.default.createElement(
153
+ _reactVirtualized.AutoSizer,
154
+ null,
155
+ ({ height, width }) => _react2.default.createElement(_reactVirtualized.List, {
156
+ sortIndex: sortIndex,
157
+ height: height,
158
+ width: width,
159
+ rowHeight: 40,
160
+ rowCount: ships.length,
161
+ rowRenderer: this.rowRenderer
162
+ })
163
+ )
164
+ );
165
+ }
166
+ });
167
+
168
+ exports.default = Candidates;
169
+ module.exports = exports['default'];
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["candidates.es"],"names":["i18n","window","__","bind","sortable","getSortValue","sortIndex","ship","direction","parseInt","api_nowhp","api_maxhp","akashi","perHP","api_id","allFleetShipIdSelector","Array","keys","map","fleetId","id1","id2","id3","id4","shipFleetIdMapSelector","state","info","ships","fleetIds","repairIdSelector","repair","dock","api_ship_id","candidateShipsSelector","const","$ships","shipFleetIdMap","repairIds","flow","filter","sortBy","getHPBackgroundColor","nowhp","maxhp","percentage","mix","alpha","css","Candidates","rowRenderer","key","index","style","props","color","Math","round","background","api_lv","resources","api_name","marginLeft","render","marginBottom","handleSort","height","width","length"],"mappings":"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","file":"candidates.es","sourcesContent":["import React, { Component } from 'react'\nimport { createSelector } from 'reselect'\nimport { connect } from 'react-redux'\nimport fp from 'lodash/fp'\nimport { mapValues, findIndex, includes, map } from 'lodash'\nimport { AutoSizer, List } from 'react-virtualized'\nimport { ButtonGroup, Button } from 'react-bootstrap'\nimport FA from 'react-fontawesome'\nimport chroma from 'chroma-js'\n\nimport { repairsSelector, fleetShipsIdSelectorFactory } from 'views/utils/selectors'\nimport { resolveTime } from 'views/utils/tools'\n\nimport { akashiEstimate, timePerHPCalc } from './functions'\n\nconst { i18n } = window\nconst __ = i18n['poi-plugin-anchorage-repair'].__.bind(i18n['poi-plugin-anchorage-repair'])\n\nconst sortable = [\n 'HP',\n 'Akashi Time',\n 'Per HP',\n]\n\nconst getSortValue = sortIndex => (ship) => {\n const direction = sortIndex % 2 ? -1 : 1\n\n switch (parseInt(sortIndex / 2, 10)) {\n case 0:\n return (ship.api_nowhp / ship.api_maxhp) * direction\n case 1:\n return ship.akashi * direction\n case 2:\n return ship.perHP * direction\n default:\n return ship.api_id\n }\n}\n\nconst allFleetShipIdSelector = createSelector(\n [\n ...[...new Array(4).keys()].map(fleetId => fleetShipsIdSelectorFactory(fleetId)),\n ],\n (id1, id2, id3, id4) => [id1, id2, id3, id4]\n)\n\nconst shipFleetIdMapSelector = createSelector(\n [\n state => state.info.ships,\n allFleetShipIdSelector,\n ], (ships, fleetIds) =>\n mapValues(ships, ship => findIndex(fleetIds, fleetId => includes(fleetId, ship.api_id)))\n)\n\nconst repairIdSelector = createSelector(\n [repairsSelector],\n repair => map(repair, dock => dock.api_ship_id)\n)\n\nconst candidateShipsSelector = sortIndex => createSelector(\n [\n state => state.info.ships,\n state => state.const.$ships,\n shipFleetIdMapSelector,\n repairIdSelector,\n ], (ships, $ships, shipFleetIdMap, repairIds) =>\n fp.flow(\n fp.filter(ship => akashiEstimate(ship) > 0 && !includes(repairIds, ship.api_id)),\n fp.map(ship => ({\n ...$ships[ship.api_ship_id],\n ...ship,\n akashi: akashiEstimate(ship),\n perHP: timePerHPCalc(ship),\n fleetId: shipFleetIdMap[ship.api_id],\n })),\n fp.sortBy(ship => getSortValue(sortIndex)(ship))\n )(ships)\n)\n\nconst getHPBackgroundColor = (nowhp, maxhp) => {\n const percentage = nowhp / maxhp\n return percentage > 0.75\n ? chroma.mix('rgb(253, 216, 53)', 'rgb(67, 160, 71)', (percentage - 0.75) / 0.25, 'lab').alpha(0.6).css()\n : chroma.mix('rgb(245, 124, 0)', 'rgb(253, 216, 53)', (percentage - 0.5) / 0.25, 'lab').alpha(0.6).css()\n}\n\n// console.log(\n// chroma.mix('rgb(253, 216, 53)', 'rgb(67, 160, 71)', 0.5, 'lch').alpha(0.6).css(),\n// chroma.mix('rgb(253, 216, 53)', 'rgb(67, 160, 71)', 0.5, 'rgb').alpha(0.6).css(),\n// chroma.mix('rgb(253, 216, 53)', 'rgb(67, 160, 71)', 0.5, 'hsl').alpha(0.6).css(),\n// chroma.mix('rgb(253, 216, 53)', 'rgb(67, 160, 71)', 0.5, 'lab').alpha(0.6).css(),\n// )\n // (nowhp / maxhp) > 0.75 ? 'rgba(67, 160, 71, 0.6)' : 'rgba(253, 216, 53, 0.6)'\n\nconst Candidates = connect(\n (state, { sortIndex = 0 }) => ({\n ships: candidateShipsSelector(sortIndex)(state),\n })\n)(class Candidates extends Component {\n\n rowRenderer = ({ key, index, style }) => {\n const { ships } = this.props\n const ship = ships[index]\n const color = getHPBackgroundColor(ship.api_nowhp, ship.api_maxhp)\n const percentage = Math.round((100 * ship.api_nowhp) / ship.api_maxhp)\n return (\n <div\n className=\"candidate-ship-item\"\n style={{\n ...style,\n background: `linear-gradient(90deg, ${color} ${percentage}%, rgba(0, 0, 0, 0) 50%)`,\n }}\n key={key}\n >\n <span className=\"ship-name\">\n { `Lv.${ship.api_lv} ${window.i18n.resources.__(ship.api_name)}${ship.fleetId < 0 ? '' : `/${ship.fleetId + 1}`}` }\n </span>\n <span style={{ marginLeft: '1em' }}>{`(${ship.api_nowhp} / ${ship.api_maxhp})`}</span>\n <span style={{ marginLeft: '2em' }}>{ `${resolveTime(ship.akashi / 1000)} / ${resolveTime(ship.perHP / 1000)}` }</span>\n </div>\n )\n }\n\n render() {\n const { ships, sortIndex } = this.props\n return (\n <div\n id=\"candidate-list\"\n >\n <div style={{ marginBottom: '1ex' }}>\n <ButtonGroup bsSize=\"small\">\n {\n [...new Array(6).keys()].map(index => (\n <Button\n key={index}\n onClick={this.props.handleSort(index)}\n bsStyle={index === sortIndex ? 'success' : 'default'}\n >\n {__(sortable[parseInt(index / 2, 10)])}<FA name={index % 2 === 0 ? 'arrow-up' : 'arrow-down'} />\n </Button>\n ))\n }\n </ButtonGroup>\n </div>\n <AutoSizer>\n {\n ({ height, width }) => (\n <List\n sortIndex={sortIndex}\n height={height}\n width={width}\n rowHeight={40}\n rowCount={ships.length}\n rowRenderer={this.rowRenderer}\n />\n )\n }\n </AutoSizer>\n </div>\n )\n }\n})\n\nexport default Candidates\n"]}
@@ -0,0 +1,122 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+
7
+ var _react = require('react');
8
+
9
+ var _react2 = _interopRequireDefault(_react);
10
+
11
+ var _propTypes = require('prop-types');
12
+
13
+ var _propTypes2 = _interopRequireDefault(_propTypes);
14
+
15
+ var _tools = require('views/utils/tools');
16
+
17
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
18
+
19
+ class CountupTimer extends _react.Component {
20
+ constructor(props) {
21
+ super(props);
22
+ this.state = {
23
+ startTime: this.props.startTime
24
+ };
25
+
26
+ this.componentDidMount = () => {
27
+ this.startTick();
28
+ };
29
+
30
+ this.componentWillReceiveProps = nextProps => {
31
+ if (nextProps.countdownId !== this.props.countdownId) {
32
+ this.stopTick();
33
+ }
34
+ if (nextProps.startTime !== this.state.startTime) {
35
+ this.setState({ startTime: nextProps.startTime });
36
+ this.timeElapsed = this.constructor.getTimeElapsed(nextProps.startTime);
37
+ }
38
+ };
39
+
40
+ this.shouldComponentUpdate = (nextProps, nextState) => nextProps.countdownId !== this.props.countdownId || nextState.startTime !== this.state.startTime;
41
+
42
+ this.componentDidUpdate = () => {
43
+ this.startTick // Doesn't matter if it didn't stop
44
+ ();
45
+ };
46
+
47
+ this.componentWillUnmount = () => {
48
+ this.stopTick();
49
+ };
50
+
51
+ this.startTick = () => {
52
+ window.ticker.reg(this.props.countdownId, this.tick);
53
+ };
54
+
55
+ this.stopTick = () => {
56
+ window.ticker.unreg(this.props.countdownId);
57
+ };
58
+
59
+ this.tick = currentTime => {
60
+ // const actualElapsed = this.constructor.getTimeElapsed(this.state.startTime, currentTime)
61
+ // if (Math.abs(this.timeElapsed - actualElapsed) > 2) {
62
+ // this.timeElapsed = actualElapsed
63
+ // }
64
+ this.timeElapsed = this.constructor.getTimeElapsed(this.state.startTime, currentTime);
65
+ if (this.timeElapsed < 0) {
66
+ this.stopTick();
67
+ }
68
+ if (this.state.startTime >= 0) {
69
+ try {
70
+ if (this.textLabel) {
71
+ this.textLabel.textContent = (0, _tools.resolveTime)(this.timeElapsed) || (0, _tools.resolveTime)(0);
72
+ }
73
+ if (this.props.tickCallback) {
74
+ this.props.tickCallback(this.timeElapsed);
75
+ }
76
+ if (this.timeElapsed < 1 && this.props.startCallback) {
77
+ this.props.startCallback();
78
+ }
79
+ } catch (error) {
80
+ console.error(error.stack);
81
+ }
82
+ }
83
+ this.timeElapsed += 1;
84
+ };
85
+
86
+ this.timeElapsed = this.constructor.getTimeElapsed(this.props.startTime);
87
+ }
88
+
89
+ render() {
90
+ return _react2.default.createElement(
91
+ 'span',
92
+ { ref: ref => {
93
+ this.textLabel = ref;
94
+ } },
95
+ (0, _tools.resolveTime)(this.timeElapsed)
96
+ );
97
+ }
98
+ }
99
+ exports.default = CountupTimer; // similar to CountdownTimer in 'views/components/main/parts/countdown-timer.es', but it counts up
100
+
101
+ CountupTimer.propTypes = {
102
+ countdownId: _propTypes2.default.string.isRequired, // UNIQUE ID to register to window.ticker
103
+ startTime: _propTypes2.default.number, // startTime in ms
104
+ tickCallback: _propTypes2.default.func, // callback function for each second
105
+ startCallback: _propTypes2.default.func // callback function when starting to count up
106
+ };
107
+
108
+ CountupTimer.getTimeElapsed = (startTime, currentTime = Date.now()) => {
109
+ if (startTime <= 0) {
110
+ return -1;
111
+ } else if (startTime > currentTime) {
112
+ return 0;
113
+ }
114
+ return Math.round((currentTime - startTime) / 1000);
115
+ };
116
+
117
+ CountupTimer.defaultProps = {
118
+ startTime: -1,
119
+ tickCallback: null,
120
+ startCallback: null
121
+ };
122
+ module.exports = exports['default'];