package logbook.gui.widgets;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.List;
import javax.annotation.CheckForNull;
import logbook.config.AppConfig;
import logbook.constants.AppConstants;
import logbook.data.context.GlobalContext;
import logbook.dto.DockDto;
import logbook.dto.ItemDto;
import logbook.dto.ShipDto;
import logbook.gui.ApplicationMain;
import logbook.gui.logic.Sound;
import logbook.internal.EvaluateExp;
import logbook.internal.SeaExp;
import logbook.util.CalcExpUtils;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CTabFolder;
import org.eclipse.swt.custom.CTabItem;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.ToolTip;
import org.eclipse.wb.swt.SWTResourceManager;
/**
* 艦隊タブのウィジェットです
*
*/
public class FleetComposite extends Composite {
/** 警告 */
private static final int WARN = 1;
/** 致命的 */
private static final int FATAL = 2;
/** 1艦隊に編成できる艦娘の数 */
private static final int MAXCHARA = 6;
/** HPゲージ幅 */
private static final int GAUGE_WIDTH = 50;
/** HPゲージ高さ */
private static final int GAUGE_HEIGHT = 10;
/** 経験値ゲージ高さ */
private static final int EXP_GAUGE_HEIGHT = 2;
/** HPゲージ最小色 */
private static final RGB GAUGE_EMPTY = new RGB(0xff, 0, 0);
/** HPゲージ中間色 */
private static final RGB GAUGE_HALF = new RGB(0xff, 0xd7, 0);
/** HPゲージ最大色 */
private static final RGB GAUGE_FULL = new RGB(0, 0xd7, 0);
/** 経験値ゲージ色 */
private static final RGB EXP_GAUGE = new RGB(0, 0x80, 0xff);
/** タブ */
private final CTabItem tab;
/** メイン画面 */
private final ApplicationMain main;
/** フォント大きい */
private final Font large;
/** フォント小さい */
private final Font small;
/** 艦隊 */
private DockDto dock;
private final Composite fleetGroup;
/** タブアイコン表示 */
private final BitSet state = new BitSet();
/** コンディション最小値(メッセージ表示用) */
private long cond;
/** 疲労回復時間(メッセージ表示用) */
private String clearDate;
/** 大破している */
private boolean badlyDamage;
/** アイコンラベル */
private final Label[] iconLabels = new Label[MAXCHARA];
/** 名前ラベル */
private final Label[] nameLabels = new Label[MAXCHARA];
/** Lvラベル */
private final Label[] lvLabels = new Label[MAXCHARA];
/** HP */
private final Label[] hpLabels = new Label[MAXCHARA];
/** HPゲージ */
private final Label[] hpgaugeLabels = new Label[MAXCHARA];
/** HPゲージイメージ */
private final Image[] hpgaugeImages = new Image[MAXCHARA];
/** HPメッセージ */
private final Label[] hpmsgLabels = new Label[MAXCHARA];
/** コンディション */
private final Label[] condLabels = new Label[MAXCHARA];
/** コンディションステータス */
private final Label[] condstLabels = new Label[MAXCHARA];
/** 弾ステータス */
private final Label[] bullstLabels = new Label[MAXCHARA];
/** 燃料ステータス */
private final Label[] fuelstLabels = new Label[MAXCHARA];
/** ダメコンステータス(要員) */
private final Label[] dmgcstyLabels = new Label[MAXCHARA];
/** ダメコンステータス(女神) */
private final Label[] dmgcstmLabels = new Label[MAXCHARA];
/** レベリングステータス */
private final Label[] nextLabels = new Label[MAXCHARA];
/** メッセージ */
private final StyledText message;
/**
* @param parent 艦隊タブの親
* @param tabItem 艦隊タブ
*/
public FleetComposite(CTabFolder parent, CTabItem tabItem, ApplicationMain main) {
super(parent, SWT.NONE);
this.tab = tabItem;
this.main = main;
this.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
GridLayout glParent = new GridLayout(1, false);
glParent.horizontalSpacing = 0;
glParent.marginTop = 0;
glParent.marginWidth = 0;
glParent.marginHeight = 0;
glParent.marginBottom = 0;
glParent.verticalSpacing = 0;
this.setLayout(glParent);
FontData normalfd = parent.getShell().getFont().getFontData()[0];
FontData largefd = new FontData(normalfd.getName(), normalfd.getHeight() + 2, normalfd.getStyle());
FontData smallfd = new FontData(normalfd.getName(), normalfd.getHeight() - 1, normalfd.getStyle());
this.large = new Font(Display.getCurrent(), largefd);
this.small = new Font(Display.getCurrent(), smallfd);
this.fleetGroup = new Composite(this, SWT.NONE);
this.fleetGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
GridLayout glShipGroup = new GridLayout(3, false);
glShipGroup.horizontalSpacing = 0;
glShipGroup.marginTop = 0;
glShipGroup.marginWidth = 1;
glShipGroup.marginHeight = 0;
glShipGroup.marginBottom = 0;
glShipGroup.verticalSpacing = 0;
this.fleetGroup.setLayout(glShipGroup);
this.init();
// セパレーター
Label separator = new Label(this, SWT.SEPARATOR | SWT.HORIZONTAL);
separator.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
// メッセージ
this.message = new StyledText(this, SWT.READ_ONLY | SWT.WRAP);
this.message.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
this.message.setWordWrap(true);
this.message.setBackground(this.getBackground());
this.fleetGroup.layout();
}
/**
* 初期化
*/
private void init() {
for (int i = 0; i < MAXCHARA; i++) {
// アイコン
Label iconlabel = new Label(this.fleetGroup, SWT.NONE);
GridData gdIconlabel = new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1);
gdIconlabel.widthHint = 16;
iconlabel.setLayoutData(gdIconlabel);
// 名前
Composite nameComposite = new Composite(this.fleetGroup, SWT.NONE);
GridLayout glName = new GridLayout(2, false);
glName.horizontalSpacing = 0;
glName.marginTop = 0;
glName.marginWidth = 1;
glName.marginHeight = 0;
glName.marginBottom = 0;
glName.verticalSpacing = 0;
nameComposite.setLayout(glName);
nameComposite.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 1, 1));
Label namelabel = new Label(nameComposite, SWT.NONE);
namelabel.setFont(this.large);
namelabel.setText("Name");
Label lvlabel = new Label(nameComposite, SWT.NONE);
lvlabel.setFont(this.small);
lvlabel.setText("Lv.0");
// HP
Composite hpComposite = new Composite(this.fleetGroup, SWT.NONE);
GridLayout glHp = new GridLayout(3, false);
glHp.horizontalSpacing = 0;
glHp.marginTop = 0;
glHp.marginWidth = 1;
glHp.marginHeight = 0;
glHp.marginBottom = 0;
glHp.verticalSpacing = 0;
hpComposite.setLayout(glHp);
hpComposite.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
Label hp = new Label(hpComposite, SWT.NONE);
hp.setFont(this.small);
Label hpgauge = new Label(hpComposite, SWT.NONE);
Label hpmsg = new Label(hpComposite, SWT.NONE);
hpmsg.setText("Good");
// ステータス
new Label(this.fleetGroup, SWT.NONE);
Composite stateComposite = new Composite(this.fleetGroup, SWT.NONE);
GridLayout glState = new GridLayout(6, false);
glState.horizontalSpacing = 0;
glState.marginTop = 0;
glState.marginWidth = 0;
glState.marginHeight = 0;
glState.marginBottom = 0;
glState.verticalSpacing = 0;
stateComposite.setLayout(glState);
stateComposite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
Label condst = new Label(stateComposite, SWT.NONE);
condst.setText("Morale ");
Label fuelst = new Label(stateComposite, SWT.NONE);
fuelst.setText("Fuel ");
Label bullst = new Label(stateComposite, SWT.NONE);
bullst.setText("Ammo");
Label dmgcsty = new Label(stateComposite, SWT.NONE);
dmgcsty.setText("ダ");
Label dmgcstm = new Label(stateComposite, SWT.NONE);
dmgcstm.setText("ダ");
Label next = new Label(stateComposite, SWT.NONE);
next.setFont(this.small);
next.setText("");
// 疲労
Label cond = new Label(this.fleetGroup, SWT.NONE);
cond.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
cond.setText("49 cond.");
this.iconLabels[i] = iconlabel;
this.nameLabels[i] = namelabel;
this.lvLabels[i] = lvlabel;
this.hpLabels[i] = hp;
this.hpgaugeLabels[i] = hpgauge;
this.hpmsgLabels[i] = hpmsg;
this.condLabels[i] = cond;
this.condstLabels[i] = condst;
this.bullstLabels[i] = bullst;
this.dmgcstyLabels[i] = dmgcsty;
this.dmgcstmLabels[i] = dmgcstm;
this.fuelstLabels[i] = fuelst;
this.nextLabels[i] = next;
}
}
/**
* 艦隊を更新します
*
* @param dock
*/
public void updateFleet(DockDto dock) {
if ((this.dock == dock) && !this.dock.isUpdate()) {
return;
}
this.getShell().setRedraw(false);
this.dock = dock;
this.dock.setUpdate(false);
this.state.set(WARN, false);
this.state.set(FATAL, false);
this.cond = 49;
this.clearDate = null;
this.badlyDamage = false;
this.message.setText("");
List<ShipDto> ships = dock.getShips();
for (int i = ships.size(); i < MAXCHARA; i++) {
this.iconLabels[i].setImage(null);
this.nameLabels[i].setText("");
this.lvLabels[i].setText("");
this.hpLabels[i].setText("");
this.hpgaugeLabels[i].setImage(null);
this.hpmsgLabels[i].setText("");
this.condLabels[i].setText("");
this.condstLabels[i].setText("");
this.bullstLabels[i].setText("");
this.dmgcstyLabels[i].setText("");
this.dmgcstmLabels[i].setText("");
this.fuelstLabels[i].setText("");
this.nextLabels[i].setText("");
}
// 艦隊合計Lv
int totallv = 0;
// 索敵値計(素)
int totalSakuteki = 0;
// 偵察機索敵値計
int totalSakutekiSurvey = 0;
// 電探索敵値計
int totalSakutekiRader = 0;
for (int i = 0; i < ships.size(); i++) {
ShipDto ship = ships.get(i);
// 艦娘のステータス
BitSet shipstatus = new BitSet();
// HP
long nowhp = ship.getNowhp();
// MaxHP
long maxhp = ship.getMaxhp();
// HP割合
float hpratio = (float) nowhp / (float) maxhp;
// 経験値ゲージの割合
float expraito = ship.getExpraito();
// 疲労
long cond = ship.getCond();
// 弾
int bull = ship.getBull();
// 弾Max
int bullmax = ship.getBullMax();
// 残弾比
float bullraito = bullmax != 0 ? (float) bull / (float) bullmax : 1f;
// 燃料
int fuel = ship.getFuel();
// 燃料Max
int fuelmax = ship.getFuelMax();
// 残燃料比
float fuelraito = fuelmax != 0 ? (float) fuel / (float) fuelmax : 1f;
// 艦隊合計Lv
totallv += ship.getLv();
// 索敵値計(素)
totalSakuteki += ship.getSakuteki();
// 偵察機索敵値計
totalSakutekiSurvey += ship.getSakutekiSurvey();
// 電探索敵値計
totalSakutekiRader += ship.getSakutekiRader();
// 疲労している艦娘がいる場合メッセージを表示
if (this.cond > cond) {
this.cond = cond;
this.clearDate = ship.getCondClearDate();
}
// 体力メッセージ
if (ship.isBadlyDamage()) {
if (AppConfig.get().isFatalBybadlyDamage()) {
// 大破で致命的アイコン
this.state.set(FATAL);
shipstatus.set(FATAL);
}
// 大破している艦娘がいる場合メッセージを表示
this.badlyDamage = true;
this.hpmsgLabels[i].setText("High");
this.hpmsgLabels[i].setBackground(SWTResourceManager.getColor(AppConstants.COND_RED_COLOR));
this.hpmsgLabels[i].setForeground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
} else if (ship.isHalfDamage()) {
if (AppConfig.get().isWarnByHalfDamage()) {
// 中破で警告アイコン
this.state.set(WARN);
shipstatus.set(WARN);
}
this.hpmsgLabels[i].setText(" Med");
this.hpmsgLabels[i].setBackground(SWTResourceManager.getColor(AppConstants.COND_ORANGE_COLOR));
this.hpmsgLabels[i].setForeground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
} else if (ship.isSlightDamage()) {
this.hpmsgLabels[i].setText(" Low");
this.hpmsgLabels[i].setBackground(null);
this.hpmsgLabels[i].setForeground(null);
} else {
this.hpmsgLabels[i].setText("Good");
this.hpmsgLabels[i].setBackground(null);
this.hpmsgLabels[i].setForeground(null);
}
// ステータス
// ステータス.疲労
this.condstLabels[i].setText("Morale ");
if (cond >= 49) {
this.condstLabels[i].setEnabled(false);
} else {
this.condstLabels[i].setEnabled(true);
}
// ステータス.燃料
this.fuelstLabels[i].setText("Fuel ");
if (fuelraito >= 1f) {
this.fuelstLabels[i].setEnabled(false);
this.fuelstLabels[i].setForeground(null);
} else {
if (AppConfig.get().isWarnByNeedSupply()) {
// 補給不足で警告アイコン
this.state.set(WARN);
shipstatus.set(WARN);
}
this.fuelstLabels[i].setEnabled(true);
if (fuelraito <= AppConstants.EMPTY_SUPPLY) {
// 補給赤
this.fuelstLabels[i].setForeground(SWTResourceManager.getColor(AppConstants.COND_RED_COLOR));
} else if (fuelraito <= AppConstants.LOW_SUPPLY) {
// 補給橙
this.fuelstLabels[i].setForeground(SWTResourceManager.getColor(AppConstants.COND_ORANGE_COLOR));
}
}
// ステータス.弾
this.bullstLabels[i].setText("Ammo");
if (bullraito >= 1f) {
this.bullstLabels[i].setEnabled(false);
this.bullstLabels[i].setBackground(null);
this.bullstLabels[i].setForeground(null);
} else {
if (AppConfig.get().isWarnByNeedSupply()) {
// 補給不足で警告アイコン
this.state.set(WARN);
shipstatus.set(WARN);
}
this.bullstLabels[i].setEnabled(true);
if (bullraito <= AppConstants.EMPTY_SUPPLY) {
this.bullstLabels[i].setForeground(SWTResourceManager.getColor(AppConstants.COND_RED_COLOR));
} else if (bullraito <= AppConstants.LOW_SUPPLY) {
this.bullstLabels[i].setForeground(SWTResourceManager.getColor(AppConstants.COND_ORANGE_COLOR));
}
}
// ステータス.ダメコン
List<ItemDto> item = ship.getItem();
int dmgcsty = 0;
int dmgcstm = 0;
for (ItemDto itemDto : item) {
if (itemDto != null) {
if (itemDto.getName().equals("応急修理要員")) {
dmgcsty++;
} else if (itemDto.getName().equals("応急修理女神")) {
dmgcstm++;
}
}
}
if (dmgcsty > 0) {
this.dmgcstyLabels[i].setText("要員x" + dmgcsty);
this.dmgcstyLabels[i].setEnabled(true);
this.dmgcstyLabels[i].setForeground(SWTResourceManager.getColor(SWT.COLOR_DARK_GREEN));
} else {
this.dmgcstyLabels[i].setText("");
this.dmgcstyLabels[i].setEnabled(false);
this.dmgcstyLabels[i].setForeground(null);
}
if (dmgcstm > 0) {
this.dmgcstmLabels[i].setText("女神x" + dmgcstm);
this.dmgcstmLabels[i].setEnabled(true);
this.dmgcstmLabels[i].setForeground(SWTResourceManager.getColor(SWT.COLOR_DARK_GREEN));
} else {
this.dmgcstmLabels[i].setText("");
this.dmgcstmLabels[i].setEnabled(false);
this.dmgcstmLabels[i].setForeground(null);
}
// ステータス.あと何回
if (AppConfig.get().isDisplayCount()) {
Integer nextcount = this.getNextCount(ship, i == 0);
if (nextcount != null) {
this.nextLabels[i].setText(MessageFormat.format("{0} remaining", nextcount));
} else {
this.nextLabels[i].setText("");
}
}
// コンディション
if (cond <= AppConstants.COND_RED) {
// 疲労19以下
if (AppConfig.get().isWarnByCondState()) {
// 疲労状態で警告アイコン
this.state.set(WARN);
shipstatus.set(WARN);
}
this.condLabels[i].setForeground(SWTResourceManager.getColor(AppConstants.COND_RED_COLOR));
this.condstLabels[i].setForeground(SWTResourceManager.getColor(AppConstants.COND_RED_COLOR));
} else if (cond <= AppConstants.COND_ORANGE) {
// 疲労29以下
if (AppConfig.get().isWarnByCondState()) {
// 疲労状態で警告アイコン
this.state.set(WARN);
shipstatus.set(WARN);
}
this.condLabels[i].setForeground(SWTResourceManager.getColor(AppConstants.COND_ORANGE_COLOR));
this.condstLabels[i].setForeground(SWTResourceManager.getColor(AppConstants.COND_ORANGE_COLOR));
} else if ((cond >= AppConstants.COND_DARK_GREEN) && (cond < AppConstants.COND_GREEN)) {
// 疲労50以上
this.condLabels[i].setForeground(SWTResourceManager.getColor(AppConstants.COND_DARK_GREEN_COLOR));
this.condstLabels[i].setForeground(SWTResourceManager.getColor(AppConstants.COND_DARK_GREEN_COLOR));
} else if (cond >= AppConstants.COND_GREEN) {
// 疲労53以上
this.condLabels[i].setForeground(SWTResourceManager.getColor(AppConstants.COND_GREEN_COLOR));
this.condstLabels[i].setForeground(SWTResourceManager.getColor(AppConstants.COND_GREEN_COLOR));
} else {
this.condLabels[i].setForeground(null);
this.condstLabels[i].setForeground(null);
}
// 艦娘の状態アイコンを更新
if (shipstatus.get(FATAL)) {
this.iconLabels[i].setImage(SWTResourceManager.getImage(FleetComposite.class,
AppConfig.get().isMonoIcon()
? AppConstants.R_ICON_EXCLAMATION_MONO
: AppConstants.R_ICON_EXCLAMATION));
} else if (shipstatus.get(WARN)) {
this.iconLabels[i].setImage(SWTResourceManager.getImage(FleetComposite.class,
AppConfig.get().isMonoIcon()
? AppConstants.R_ICON_ERROR_MONO
: AppConstants.R_ICON_ERROR));
} else {
this.iconLabels[i].setImage(null);
}
// ラベルを更新する
// 名前
this.nameLabels[i].setText(ship.getName());
this.nameLabels[i].setToolTipText(MessageFormat.format(AppConstants.TOOLTIP_FLEETTAB_SHIP, nowhp, maxhp,
fuel, fuelmax, bull, bullmax, ship.getNext()));
this.lvLabels[i].setText(MessageFormat.format("(Lv.{0})", ship.getLv()));
// HP
this.hpLabels[i].setText(MessageFormat.format("{0}/{1} ", nowhp, maxhp));
// HPゲージ
Image gauge = this.getHpGaugeImage(hpratio, expraito);
this.hpgaugeLabels[i].setImage(gauge);
if (this.hpgaugeImages[i] != null) {
// 古いイメージを破棄
this.hpgaugeImages[i].dispose();
}
this.hpgaugeImages[i] = gauge;
// コンディション
this.condLabels[i].setText(MessageFormat.format("{0} cond.", cond));
this.bullstLabels[i].getParent().layout();
}
// メッセージを更新する
// 入渠中の艦娘を探す
boolean isBathwater = false;
for (ShipDto shipDto : ships) {
if (GlobalContext.isNdock(shipDto)) {
isBathwater = true;
break;
}
}
// 制空値を計算
int seiku = 0;
for (ShipDto shipDto : ships) {
seiku += shipDto.getSeiku();
}
// 索敵値を計算
// 偵察機索敵値×2 + 電探索敵値 + √(艦隊の装備込み索敵値合計 - 偵察機索敵値 - 電探索敵値)
BigDecimal sakuteki = BigDecimal.valueOf((totalSakutekiSurvey * 2) + totalSakutekiRader
+ Math.sqrt(totalSakuteki - totalSakutekiSurvey - totalSakutekiRader));
sakuteki = sakuteki.setScale(2, RoundingMode.HALF_UP);
if (GlobalContext.isMission(this.dock.getId())) {
// 遠征中
StyleRange style = new StyleRange();
style.fontStyle = SWT.BOLD;
style.foreground = SWTResourceManager.getColor(SWT.COLOR_DARK_BLUE);
this.addStyledText(this.message, AppConstants.MESSAGE_MISSION, style);
} else if (isBathwater) {
// 入渠中
StyleRange style = new StyleRange();
style.fontStyle = SWT.BOLD;
style.foreground = SWTResourceManager.getColor(SWT.COLOR_DARK_BLUE);
this.addStyledText(this.message,
MessageFormat.format(AppConstants.MESSAGE_BAD, AppConstants.MESSAGE_BATHWATER), style);
} else if (this.badlyDamage) {
// 大破
StyleRange style = new StyleRange();
style.fontStyle = SWT.BOLD;
style.underline = true;
style.underlineStyle = SWT.UNDERLINE_SQUIGGLE;
style.underlineColor = SWTResourceManager.getColor(SWT.COLOR_RED);
style.foreground = SWTResourceManager.getColor(SWT.COLOR_RED);
this.addStyledText(this.message,
MessageFormat.format(AppConstants.MESSAGE_BAD, AppConstants.MESSAGE_BADLY_DAMAGE), style);
} else {
// 出撃可能
StyleRange style = new StyleRange();
style.fontStyle = SWT.BOLD;
style.foreground = SWTResourceManager.getColor(SWT.COLOR_DARK_GREEN);
this.addStyledText(this.message, AppConstants.MESSAGE_GOOD, style);
}
if (this.clearDate != null) {
this.addStyledText(this.message, MessageFormat.format(AppConstants.MESSAGE_COND, this.clearDate), null);
}
// 制空
this.addStyledText(this.message, MessageFormat.format(AppConstants.MESSAGE_SEIKU, seiku), null);
// 索敵
this.addStyledText(this.message, MessageFormat.format(AppConstants.MESSAGE_SAKUTEKI, sakuteki), null);
// 合計Lv
this.addStyledText(this.message, MessageFormat.format(AppConstants.MESSAGE_TOTAL_LV, totallv), null);
this.updateTabIcon();
this.postFatal();
this.fleetGroup.layout();
this.getShell().setRedraw(true);
}
/**
* 艦隊タブのアイコンを更新します
*/
private void updateTabIcon() {
if (this.state.get(FATAL)) {
this.tab.setImage(SWTResourceManager.getImage(FleetComposite.class,
AppConfig.get().isMonoIcon()
? AppConstants.R_ICON_EXCLAMATION_MONO
: AppConstants.R_ICON_EXCLAMATION));
} else if (this.state.get(WARN)) {
this.tab.setImage(SWTResourceManager.getImage(FleetComposite.class,
AppConfig.get().isMonoIcon()
? AppConstants.R_ICON_ERROR_MONO
: AppConstants.R_ICON_ERROR));
} else {
this.tab.setImage(null);
}
}
/**
* 艦隊が出撃中で大破した場合に警告を行います
*/
private void postFatal() {
if (this.badlyDamage && GlobalContext.isSortie(this.dock.getId())) {
if (AppConfig.get().isBalloonBybadlyDamage()) {
List<ShipDto> ships = this.dock.getShips();
StringBuilder sb = new StringBuilder();
sb.append(AppConstants.MESSAGE_STOP_SORTIE);
sb.append("\n");
for (ShipDto shipDto : ships) {
if (shipDto.isBadlyDamage()) {
sb.append(shipDto.getName());
sb.append("(" + shipDto.getLv() + ")");
sb.append(" : ");
List<ItemDto> items = shipDto.getItem();
List<String> names = new ArrayList<String>();
for (ItemDto itemDto : items) {
if (itemDto != null) {
names.add(itemDto.getName());
}
}
sb.append(StringUtils.join(names, ","));
sb.append("\n");
}
}
ToolTip tip = new ToolTip(this.getShell(), SWT.BALLOON
| SWT.ICON_ERROR);
tip.setText("Warning");
tip.setMessage(sb.toString());
this.main.getTrayItem().setToolTip(tip);
tip.setVisible(true);
}
// 大破時にサウンドを再生する
Sound.randomBadlySoundPlay();
}
}
/**
* HPゲージのイメージを取得します
* @param hpratio HP割合
* @return HPゲージのイメージ
*/
private Image getHpGaugeImage(float hpratio, float expraito) {
Image image = new Image(Display.getDefault(), GAUGE_WIDTH, GAUGE_HEIGHT);
GC gc = new GC(image);
gc.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
gc.fillRectangle(0, 0, GAUGE_WIDTH, GAUGE_HEIGHT);
gc.setBackground(SWTResourceManager.getColor(gradation(hpratio, GAUGE_EMPTY, GAUGE_HALF, GAUGE_FULL)));
gc.fillRectangle(0, 0, (int) (GAUGE_WIDTH * hpratio), GAUGE_HEIGHT);
gc.setBackground(SWTResourceManager.getColor(EXP_GAUGE));
gc.fillRectangle(0, GAUGE_HEIGHT - EXP_GAUGE_HEIGHT, (int) (GAUGE_WIDTH * expraito), EXP_GAUGE_HEIGHT);
gc.drawImage(image, 0, 0);
gc.dispose();
return image;
}
/**
* スタイル付きテキストを設定します
*
* @param text StyledText
* @param str 文字
* @param style スタイル
*/
private void addStyledText(StyledText text, String str, StyleRange style) {
StyleRange[] oldranges = text.getStyleRanges();
String beforeText = text.getText();
StyleRange addStyle = style;
if (addStyle == null) {
addStyle = new StyleRange();
}
addStyle.start = beforeText.length();
addStyle.length = str.length();
StyleRange[] ranges = new StyleRange[oldranges.length + 1];
for (int i = 0; i < oldranges.length; i++) {
ranges[i] = oldranges[i];
}
ranges[oldranges.length] = addStyle;
text.setText(beforeText + str);
text.setStyleRanges(ranges);
}
/**
* あと何回戦闘すればよいかを取得します
*
* @param ship 艦娘
* @param isFlagship 旗艦
* @return 回数
*/
@CheckForNull
private Integer getNextCount(ShipDto ship, boolean isFlagship) {
// 次のレベルに必要な経験値
Long nextexp = CalcExpUtils.getNextLvExp((int) ship.getLv());
if (nextexp != null) {
// 必要経験値
long needexp = nextexp - ship.getExp();
// 海域Exp
Integer baseexp = SeaExp.get().get(AppConfig.get().getDefaultSea());
// 評価倍率
Double eval = EvaluateExp.get().get(AppConfig.get().getDefaultEvaluate());
if ((baseexp != null) && (eval != null)) {
// 得られる経験値
long getexpd = CalcExpUtils.getExp(baseexp, eval, isFlagship, false);
// 戦闘回数
int count = CalcExpUtils.getCount(needexp, getexpd);
return Integer.valueOf(count);
}
}
return null;
}
@Override
public void dispose() {
super.dispose();
this.large.dispose();
this.small.dispose();
for (Image image : this.hpgaugeImages) {
if (image != null) {
image.dispose();
}
}
}
/**
* 複数の色の中間色を取得する
*
* @param raito 割合
* @param rgbs 色たち
* @return 色
*/
private static RGB gradation(float raito, RGB... rgbs) {
if (raito <= 0.0f) {
return rgbs[0];
}
if (raito >= 1.0f) {
return rgbs[rgbs.length - 1];
}
int length = rgbs.length - 1;
// 開始色
int start = (int) (length * raito);
// 終了色
int end = start + 1;
// 開始色と終了色の割合を算出
float startPer = (float) start / length;
float endPer = (float) end / length;
float subPer = (raito - startPer) / (endPer - startPer);
return gradation(subPer, rgbs[start], rgbs[end]);
}
/**
* 2つの色の中間色を取得する
*
* @param raito 割合
* @param start 開始色
* @param end 終了色
* @return 色
*/
private static RGB gradation(float raito, RGB start, RGB end) {
int r = (int) (start.red + ((end.red - start.red) * raito));
int g = (int) (start.green + ((end.green - start.green) * raito));
int b = (int) (start.blue + ((end.blue - start.blue) * raito));
return new RGB(r, g, b);
}
}