package logbook.dto;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import javax.json.JsonArray;
import javax.json.JsonNumber;
import javax.json.JsonObject;
import javax.json.JsonValue;
import logbook.constants.AppConstants;
import logbook.data.context.GlobalContext;
import logbook.internal.ExpTable;
import logbook.internal.Ship;
/**
* 艦娘を表します
*
*/
public final class ShipDto extends AbstractDto {
/** 日時 */
private final Calendar time = Calendar.getInstance();
/** 艦娘個人を識別するID */
private final long id;
/** 鍵付き */
private final boolean locked;
/** 艦隊ID */
private String fleetid = "";
/** 名前 */
private final String name;
/** 艦種 */
private final String type;
/** Lv */
private final long lv;
/** 疲労 */
private final long cond;
/** 入渠時間 */
private final long docktime;
/** 修復資材 燃料 */
private final long dockfuel;
/** 修復資材 鋼材 */
private final long dockmetal;
/** 残弾 */
private int bull;
/** 弾Max */
private final int bullmax;
/** 残燃料 */
private int fuel;
/** 燃料Max */
private final int fuelmax;
/** 経験値 */
private final long exp;
/** 経験値ゲージの割合 */
private final float expraito;
/** HP */
private final long nowhp;
/** MaxHP */
private final long maxhp;
/** 装備 */
private final List<Long> slot;
/** 装備の搭載数 */
private final List<Integer> onslot;
/** 火力 */
private final long karyoku;
/** 火力(最大) */
private final long karyokuMax;
/** 雷装 */
private final long raisou;
/** 雷装(最大) */
private final long raisouMax;
/** 対空 */
private final long taiku;
/** 対空(最大) */
private final long taikuMax;
/** 装甲 */
private final long soukou;
/** 装甲(最大) */
private final long soukouMax;
/** 回避 */
private final long kaihi;
/** 回避(最大) */
private final long kaihiMax;
/** 対潜 */
private final long taisen;
/** 対潜(最大) */
private final long taisenMax;
/** 索敵 */
private final long sakuteki;
/** 索敵(最大) */
private final long sakutekiMax;
/** 運 */
private final long lucky;
/** 運(最大) */
private final long luckyMax;
/** 艦娘 */
private final ShipInfoDto shipInfo;
/** 出撃海域 */
private final int sallyArea;
/** */
private final int lockedEquip;
/** 空母 */
private final boolean isCarrier;
/**
* コンストラクター
*
* @param object JSON Object
*/
public ShipDto(JsonObject object) {
this.id = object.getJsonNumber("api_id").longValue();
this.locked = object.getJsonNumber("api_locked").longValue() == 1;
ShipInfoDto shipinfo = Ship.get(object.getJsonNumber("api_ship_id").toString());
this.shipInfo = shipinfo;
this.name = shipinfo.getName();
this.type = shipinfo.getType();
this.lv = object.getJsonNumber("api_lv").longValue();
this.cond = object.getJsonNumber("api_cond").longValue();
this.docktime = object.getJsonNumber("api_ndock_time").longValue();
this.dockfuel = object.getJsonArray("api_ndock_item").getJsonNumber(0).longValue();
this.dockmetal = object.getJsonArray("api_ndock_item").getJsonNumber(1).longValue();
this.bull = object.getJsonNumber("api_bull").intValue();
this.fuel = object.getJsonNumber("api_fuel").intValue();
this.bullmax = shipinfo.getMaxBull();
this.fuelmax = shipinfo.getMaxFuel();
this.exp = object.getJsonArray("api_exp").getJsonNumber(0).longValue();
this.expraito = object.getJsonArray("api_exp").getJsonNumber(2).longValue() / 100f;
this.nowhp = object.getJsonNumber("api_nowhp").longValue();
this.maxhp = object.getJsonNumber("api_maxhp").longValue();
this.slot = new ArrayList<Long>();
JsonArray slot = object.getJsonArray("api_slot");
for (JsonValue jsonValue : slot) {
JsonNumber itemid = (JsonNumber) jsonValue;
this.slot.add(Long.valueOf(itemid.longValue()));
}
this.onslot = new ArrayList<Integer>();
JsonArray onslot = object.getJsonArray("api_onslot");
for (JsonValue jsonValue : onslot) {
JsonNumber itemid = (JsonNumber) jsonValue;
this.onslot.add(Integer.valueOf(itemid.intValue()));
}
this.karyoku = ((JsonNumber) object.getJsonArray("api_karyoku").get(0)).longValue();
this.karyokuMax = ((JsonNumber) object.getJsonArray("api_karyoku").get(1)).longValue();
this.raisou = ((JsonNumber) object.getJsonArray("api_raisou").get(0)).longValue();
this.raisouMax = ((JsonNumber) object.getJsonArray("api_raisou").get(1)).longValue();
this.taiku = ((JsonNumber) object.getJsonArray("api_taiku").get(0)).longValue();
this.taikuMax = ((JsonNumber) object.getJsonArray("api_taiku").get(1)).longValue();
this.soukou = ((JsonNumber) object.getJsonArray("api_soukou").get(0)).longValue();
this.soukouMax = ((JsonNumber) object.getJsonArray("api_soukou").get(1)).longValue();
this.kaihi = ((JsonNumber) object.getJsonArray("api_kaihi").get(0)).longValue();
this.kaihiMax = ((JsonNumber) object.getJsonArray("api_kaihi").get(1)).longValue();
this.taisen = ((JsonNumber) object.getJsonArray("api_taisen").get(0)).longValue();
this.taisenMax = ((JsonNumber) object.getJsonArray("api_taisen").get(1)).longValue();
this.sakuteki = ((JsonNumber) object.getJsonArray("api_sakuteki").get(0)).longValue();
this.sakutekiMax = ((JsonNumber) object.getJsonArray("api_sakuteki").get(1)).longValue();
this.lucky = ((JsonNumber) object.getJsonArray("api_lucky").get(0)).longValue();
this.luckyMax = ((JsonNumber) object.getJsonArray("api_lucky").get(1)).longValue();
this.lockedEquip = object.getJsonNumber("api_locked_equip").intValue();
if (object.containsKey("api_sally_area")) {
this.sallyArea = object.getJsonNumber("api_sally_area").intValue();
} else {
this.sallyArea = 0;
}
// 疲労が抜ける時間を計算する
if (this.cond < 49) {
this.time.add(Calendar.MINUTE, Math.max(49 - (int) this.cond, 3));
}
this.isCarrier = "AV".equals(this.type) || "CVL".equals(this.type) || "CV".equals(this.type)
|| "CVB".equals(this.type);
}
/**
* @return 艦娘個人を識別するID
*/
public long getId() {
return this.id;
}
/**
* @return 鍵付き
*/
public boolean getLocked() {
return this.locked;
}
/**
* @return 艦隊ID
*/
public String getFleetid() {
return this.fleetid;
}
/**
* 艦隊IDを設定する
*
* @param fleetid 艦隊ID
*/
public void setFleetid(String fleetid) {
this.fleetid = fleetid;
}
/**
* @return 名前
*/
public String getName() {
return this.name;
}
/**
* @return 艦種
*/
public String getType() {
return this.type;
}
/**
* @return Lv
*/
public long getLv() {
return this.lv;
}
/**
* @return 疲労
*/
public long getCond() {
return this.cond;
}
/**
* @return 入渠時間
*/
public long getDocktime() {
return this.docktime;
}
/**
* @return 修復資材 燃料
*/
public long getDockfuel() {
return this.dockfuel;
}
/**
* @return 修復資材 鋼材
*/
public long getDockmetal() {
return this.dockmetal;
}
/**
* @return 弾
*/
public int getBull() {
return this.bull;
}
/**
* @return 弾Max
*/
public int getBullMax() {
return this.bullmax;
}
/**
* @param bull 残弾
*/
public void setBull(int bull) {
this.bull = bull;
}
/**
* @return 燃料
*/
public int getFuel() {
return this.fuel;
}
/**
* @return 燃料Max
*/
public int getFuelMax() {
return this.fuelmax;
}
/**
* @param fuel 残燃料
*/
public void setFuel(int fuel) {
this.fuel = fuel;
}
/**
* @return 経験値
*/
public long getExp() {
return this.exp;
}
/**
* @return 経験値ゲージの割合
*/
public float getExpraito() {
return this.expraito;
}
/**
* @return HP
*/
public long getNowhp() {
return this.nowhp;
}
/**
* @return MaxHP
*/
public long getMaxhp() {
return this.maxhp;
}
/**
* @return 装備
*/
public List<String> getSlot() {
List<String> itemNames = new ArrayList<String>();
Map<Long, ItemDto> itemMap = GlobalContext.getItemMap();
for (Long itemid : this.slot) {
if (-1 != itemid) {
ItemDto name = itemMap.get(itemid);
if (name != null) {
itemNames.add(name.getName());
} else {
itemNames.add("<UNKNOWN>");
}
} else {
itemNames.add("");
}
}
return itemNames;
}
/**
* @return 装備
*/
public List<ItemDto> getItem() {
List<ItemDto> items = new ArrayList<ItemDto>();
Map<Long, ItemDto> itemMap = GlobalContext.getItemMap();
for (Long itemid : this.slot) {
if (-1 != itemid) {
ItemDto item = itemMap.get(itemid);
if (item != null) {
items.add(item);
} else {
items.add(null);
}
} else {
items.add(null);
}
}
return items;
}
/**
* @return 装備ID
*/
public List<Long> getItemId() {
return Collections.unmodifiableList(this.slot);
}
/**
* @return 制空値
*/
public int getSeiku() {
List<ItemDto> items = this.getItem();
int seiku = 0;
for (int i = 0; i < items.size(); i++) {
ItemDto item = items.get(i);
if (item != null) {
if ((item.getType3() == 6)
|| (item.getType3() == 7)
|| (item.getType3() == 8)
|| ((item.getType3() == 10) && (item.getType2() == 11))) {
//6:艦上戦闘機,7:艦上爆撃機,8:艦上攻撃機,10:水上偵察機(ただし瑞雲のみ)の場合は制空値を計算する
seiku += (int) Math.floor(item.getTyku() * Math.sqrt(this.onslot.get(i)));
}
}
}
return seiku;
}
/**
* @return 火力
*/
public long getKaryoku() {
return this.karyoku;
}
/**
* @return 火力(最大)
*/
public long getKaryokuMax() {
return this.karyokuMax;
}
/**
* @return 雷装
*/
public long getRaisou() {
return this.raisou;
}
/**
* @return 雷装(最大)
*/
public long getRaisouMax() {
return this.raisouMax;
}
/**
* @return 対空
*/
public long getTaiku() {
return this.taiku;
}
/**
* @return 対空(最大)
*/
public long getTaikuMax() {
return this.taikuMax;
}
/**
* @return 装甲
*/
public long getSoukou() {
return this.soukou;
}
/**
* @return 装甲(最大)
*/
public long getSoukouMax() {
return this.soukouMax;
}
/**
* @return 回避
*/
public long getKaihi() {
return this.kaihi;
}
/**
* @return 回避(最大)
*/
public long getKaihiMax() {
return this.kaihiMax;
}
/**
* @return 対潜
*/
public long getTaisen() {
return this.taisen;
}
/**
* @return 対潜(最大)
*/
public long getTaisenMax() {
return this.taisenMax;
}
/**
* @return 索敵
*/
public long getSakuteki() {
return this.sakuteki;
}
/**
* @return 偵察機索敵値
*/
public int getSakutekiSurvey() {
int survey = 0;
List<ItemDto> items = this.getItem();
for (int i = 0; i < items.size(); i++) {
ItemDto item = items.get(i);
if (item != null) {
if ((item.getType1() == 7) && (this.onslot.get(i) > 0)) {
// 偵察機索敵値
survey += item.getSaku();
}
}
}
return survey;
}
/**
* @return 電探索敵値
*/
public int getSakutekiRader() {
int rader = 0;
List<ItemDto> items = this.getItem();
for (int i = 0; i < items.size(); i++) {
ItemDto item = items.get(i);
if (item != null) {
if (item.getType3() == 11) {
// 電探索敵値
rader += item.getSaku();
}
}
}
return rader;
}
/**
* @return 索敵(最大)
*/
public long getSakutekiMax() {
return this.sakutekiMax;
}
/**
* @return 運
*/
public long getLucky() {
return this.lucky;
}
/**
* @return 運(最大)
*/
public long getLuckyMax() {
return this.luckyMax;
}
/**
* @return 艦娘
*/
public ShipInfoDto getShipInfo() {
return this.shipInfo;
}
/**
* @return 次のレベルまでの経験値
*/
public String getNext() {
String next = "";
Long nextLvExp = ExpTable.get().get((int) this.lv + 1);
if (nextLvExp != null) {
next = Long.toString(nextLvExp - this.exp);
}
return next;
}
/**
* @return 疲労が抜けるまでの時間
*/
public String getCondClearDate() {
if (this.cond < 49) {
return new SimpleDateFormat("HH:mm").format(this.time.getTime());
}
return "";
}
/**
* 艦娘が大破しているかを調べます
* @return 大破以上の場合
*/
public boolean isBadlyDamage() {
return ((float) this.nowhp / (float) this.maxhp) <= AppConstants.BADLY_DAMAGE;
}
/**
* 艦娘が中破しているかを調べます
* @return 中破以上の場合
*/
public boolean isHalfDamage() {
return ((float) this.nowhp / (float) this.maxhp) <= AppConstants.HALF_DAMAGE;
}
/**
* 艦娘が小破しているかを調べます
* @return 小破以上の場合
*/
public boolean isSlightDamage() {
return ((float) this.nowhp / (float) this.maxhp) <= AppConstants.SLIGHT_DAMAGE;
}
/**
* 出撃海域を取得します。
* @return 出撃海域
*/
public int getSallyArea() {
return this.sallyArea;
}
/**
* lockedEquipを取得します。
* @return lockedEquip
*/
public int getLockedEquip() {
return this.lockedEquip;
}
/**
* 装備で加算された命中
*
* @return 装備の命中
*/
public long getAccuracy() {
long accuracy = 0;
for (Long itemid : this.slot) {
if (-1 != itemid) {
Map<Long, ItemDto> itemMap = GlobalContext.getItemMap();
ItemDto item = itemMap.get(itemid);
if (item != null) {
accuracy += item.getHoum();
}
}
}
return accuracy;
}
/**
* 砲撃戦火力
*
* @return 砲撃戦火力
*/
public long getHougekiPower() {
if (this.isCarrier) {
// (火力 + 雷装) × 1.5 + 爆装 × 2 + 55
long rai = 0;
long baku = 0;
Map<Long, ItemDto> itemMap = GlobalContext.getItemMap();
for (Long itemid : this.slot) {
if (-1 != itemid) {
ItemDto item = itemMap.get(itemid);
if (item != null) {
rai += item.getRaig();
baku += item.getBaku();
}
}
}
return Math.round(((this.getKaryoku() + rai) * 1.5d) + (baku * 2) + 55);
} else {
return this.getKaryoku() + 5;
}
}
/**
* 雷撃戦火力
*
* @return 雷撃戦火力
*/
public long getRaigekiPower() {
return this.getRaisou() + 5;
}
/**
* 対潜火力
*
* @return 対潜火力
*/
public long getTaisenPower() {
// [ 艦船の対潜 ÷ 5 ] + 装備の対潜 × 2 + 25
long taisenShip = this.getTaisen();
long taisenItem = 0;
Map<Long, ItemDto> itemMap = GlobalContext.getItemMap();
for (Long itemid : this.slot) {
if (-1 != itemid) {
ItemDto item = itemMap.get(itemid);
if (item != null) {
int taisen = item.getTais();
taisenShip -= taisen;
taisenItem += taisen;
}
}
}
return Math.round(Math.floor(taisenShip / 5d) + (taisenItem * 2) + 25);
}
/**
* 夜戦火力
*
* @return 夜戦火力
*/
public long getYasenPower() {
return this.getKaryoku() + this.getRaisou();
}
}