/**
*
*/
package logbook.gui.logic;
import java.util.List;
import logbook.config.AppConfig;
import logbook.dto.ItemDto;
import logbook.dto.ShipBaseDto;
/**
* @author Nekopanda
*
*/
public class SeikuString implements Comparable<SeikuString> {
private static int[][] alevelBonusTable = new int[][] {
{ 0, 0, 2, 5, 9, 14, 14, 22 }, // 艦上戦闘機、水上戦闘機
{ 0, 0, 0, 0, 0, 0, 0, 0 }, // 艦上爆撃機、艦上攻撃機
{ 0, 0, 1, 1, 1, 3, 3, 6 }, // 水上爆撃機
};
private static int[] internalAlevelTable = new int[] {
0, 10, 25, 40, 55, 70, 85, 100, 121
};
// 従来の数値
private int seikuBase;
// 熟練度ボーナス込み
private int seikuToalMin;
private int seikuToalMid;
private int seikuTotalMax;
// 情報が不足してて計算できなかった
private boolean seikuFailed = false;
public <SHIP extends ShipBaseDto> SeikuString(List<SHIP> ships) {
for (SHIP ship : ships) {
this.add(ship);
}
}
public SeikuString(ShipBaseDto ship) {
this.add(ship);
}
private static double calcBonusSeiku(int type, int alv, double internal) {
return alevelBonusTable[type][alv] + Math.sqrt(internal / 10);
}
private void add(ShipBaseDto ship) {
List<ItemDto> items = ship.getItem2();
for (int i = 0; i < items.size(); i++) {
ItemDto item = items.get(i);
if (item != null) {
int type;
switch (item.getType2()) {
case 6: // 艦上戦闘機
case 45: // 水上戦闘機
type = 0;
break;
case 7: // 艦上爆撃機
case 8: // 艦上攻撃機
type = 1;
break;
case 11: // 水上爆撃機
type = 2;
break;
default:
type = -1;
break;
}
if (type != -1) {
// スロット数が分からないと計算できない
if (ship.getOnSlot() == null) {
this.seikuFailed = true;
return;
}
double tyku = item.getParam().getTyku();
// 改修効果 艦戦は★×0.2、爆戦は★×0.25
switch (type) {
case 0: // 艦上戦闘機 (水上戦闘機は不明だけど一応入れておく)
tyku += item.getLevel() * 0.2;
break;
case 1: // 爆戦(爆戦でない艦上爆撃機や艦上攻撃機は不明だけど一応入れておく)
tyku += item.getLevel() * 0.25;
break;
}
double basePart = tyku * Math.sqrt(ship.getOnSlot()[i]);
double ialvMin = internalAlevelTable[item.getAlv()];
double ialvMax = internalAlevelTable[item.getAlv() + 1] - 1;
double ialvMid = (ialvMin + ialvMax) / 2;
double totalMin = basePart + calcBonusSeiku(type, item.getAlv(), ialvMin);
double totalMid = basePart + calcBonusSeiku(type, item.getAlv(), ialvMid);
double totalMax = basePart + calcBonusSeiku(type, item.getAlv(), ialvMax);
this.seikuBase += (int) Math.floor(basePart);
this.seikuToalMin += (int) Math.floor(totalMin);
this.seikuToalMid += (int) Math.floor(totalMid);
this.seikuTotalMax += (int) Math.floor(totalMax);
}
}
}
}
public int getValue() {
int method = AppConfig.get().getSeikuMethod();
switch (method) {
case 0:
return this.seikuBase;
case 1:
case 2:
case 3:
case 4:
return this.seikuToalMid;
default:
return 0;
}
}
private String seikuTotalString() {
if (this.seikuToalMin == this.seikuTotalMax) {
return Integer.toString(this.seikuToalMin);
}
else {
return String.format("%d-%d", this.seikuToalMin, this.seikuTotalMax);
}
}
@Override
public String toString() {
int method = AppConfig.get().getSeikuMethod();
if (this.seikuFailed) {
return "?";
}
switch (method) {
case 0: // 艦載機素の制空値
return Integer.toString(this.seikuBase);
case 1: // 制空推定値範囲
return this.seikuTotalString();
case 2: // 制空推定値範囲(艦載機素の制空値 + 熟練度ボーナス推定値)
return String.format("%s (%d+%d)",
this.seikuTotalString(), this.seikuBase, this.seikuToalMid - this.seikuBase);
case 3: // 制空推定値中央
return Integer.toString(this.seikuToalMid);
case 4: // 制空推定値中央(艦載機素の制空値 + 熟練度ボーナス推定値)
return String.format("%d (%d+%d)",
this.seikuToalMid, this.seikuBase, this.seikuToalMid - this.seikuBase);
}
return Integer.toString(this.seikuBase);
}
@Override
public int compareTo(SeikuString o) {
return Double.compare(this.getValue(), o.getValue());
}
}