package logbook.gui; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import logbook.config.AppConfig; import logbook.data.context.GlobalContext; import logbook.dto.ShipDto; import logbook.internal.EvaluateExp; import logbook.internal.ExpTable; import logbook.internal.SeaExp; import logbook.util.CalcExpUtils; import org.apache.commons.lang3.StringUtils; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.layout.RowLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Dialog; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Spinner; import org.eclipse.swt.widgets.Text; /** * 経験値計算機 * */ public final class CalcExpDialog extends Dialog { /** 旗艦 */ private static boolean flag = true; /** MVP */ private static boolean mvp; private final Map<String, ShipDto> shipmap = new HashMap<String, ShipDto>(); private Shell shell; private Combo shipcombo; private Spinner beforelv; private Text beforexp; private Spinner afterlv; private Text afterexp; private Combo seacombo; private Combo evalcombo; private Button flagbtn; private Button mvpbtn; private Text getexp; private Text needexp; private Text battlecount; /** * Create the dialog. * @param parent */ public CalcExpDialog(Shell parent) { super(parent, SWT.CLOSE | SWT.TITLE | SWT.MIN | SWT.RESIZE); this.setText("Exp Calculator"); } /** * Open the dialog. */ public void open() { this.createContents(); this.shell.open(); this.shell.layout(); Display display = this.getParent().getDisplay(); while (!this.shell.isDisposed()) { if (!display.readAndDispatch()) { display.sleep(); } } } /** * Create contents of the dialog. */ private void createContents() { this.shell = new Shell(this.getParent(), this.getStyle()); this.shell.setText(this.getText()); this.shell.setLayout(new GridLayout(1, false)); Composite select = new Composite(this.shell, SWT.NONE); select.setLayout(new RowLayout()); select.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); this.shipcombo = new Combo(select, SWT.READ_ONLY); Button reload = new Button(select, SWT.NONE); reload.setText("Calculate"); Composite plan = new Composite(this.shell, SWT.NONE); plan.setLayout(new GridLayout(5, false)); plan.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); Label label1 = new Label(plan, SWT.NONE); label1.setText("Current"); this.beforelv = new Spinner(plan, SWT.BORDER); GridData gdBeforelv = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1); gdBeforelv.widthHint = 45; this.beforelv.setLayoutData(gdBeforelv); this.beforelv.setMaximum(150); this.beforelv.setMinimum(1); Label label2 = new Label(plan, SWT.NONE); label2.setText("Lv"); this.beforexp = new Text(plan, SWT.BORDER | SWT.READ_ONLY); GridData gdBeforexp = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1); gdBeforexp.widthHint = 60; this.beforexp.setLayoutData(gdBeforexp); this.beforexp.setText("0"); Label label3 = new Label(plan, SWT.NONE); label3.setText("Exp"); Label label4 = new Label(plan, SWT.NONE); label4.setText("Target"); this.afterlv = new Spinner(plan, SWT.BORDER); GridData gdAfterlv = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1); gdAfterlv.widthHint = 45; this.afterlv.setLayoutData(gdAfterlv); this.afterlv.setMaximum(150); this.afterlv.setMinimum(1); Label label5 = new Label(plan, SWT.NONE); label5.setText("Lv"); this.afterexp = new Text(plan, SWT.BORDER | SWT.READ_ONLY); GridData gdAfterexp = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1); gdAfterexp.widthHint = 60; this.afterexp.setLayoutData(gdAfterexp); this.afterexp.setText("0"); Label label6 = new Label(plan, SWT.NONE); label6.setText("Exp"); Composite plan2 = new Composite(this.shell, SWT.NONE); plan2.setLayout(new RowLayout()); plan2.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); Label label7 = new Label(plan2, SWT.NONE); label7.setText("Map"); this.seacombo = new Combo(plan2, SWT.READ_ONLY); for (Entry<String, Integer> entry : SeaExp.get().entrySet()) { this.seacombo.add(entry.getKey()); } Label label8 = new Label(plan2, SWT.NONE); label8.setText("Rank"); this.evalcombo = new Combo(plan2, SWT.READ_ONLY); for (Entry<String, Double> entry : EvaluateExp.get().entrySet()) { this.evalcombo.add(entry.getKey()); } Composite plan3 = new Composite(this.shell, SWT.NONE); plan3.setLayout(new RowLayout()); plan3.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); this.flagbtn = new Button(plan3, SWT.CHECK); this.flagbtn.setText("Flagship"); this.mvpbtn = new Button(plan3, SWT.CHECK); this.mvpbtn.setText("MVP"); Composite plan4 = new Composite(this.shell, SWT.NONE); plan4.setLayout(new FillLayout()); plan4.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); new Label(plan4, SWT.SEPARATOR | SWT.HORIZONTAL); Composite result = new Composite(this.shell, SWT.NONE); result.setLayout(new GridLayout(4, false)); result.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); Label label10 = new Label(result, SWT.NONE); label10.setText("Per-sortie"); this.getexp = new Text(result, SWT.BORDER | SWT.READ_ONLY); GridData gdGetexp = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1); gdGetexp.widthHint = 55; this.getexp.setLayoutData(gdGetexp); new Label(result, SWT.NONE); new Label(result, SWT.NONE); Label label11 = new Label(result, SWT.NONE); label11.setText("Required"); this.needexp = new Text(result, SWT.BORDER | SWT.READ_ONLY); GridData gdNeedexp = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1); gdNeedexp.widthHint = 55; this.needexp.setLayoutData(gdNeedexp); Label label12 = new Label(result, SWT.NONE); label12.setText("Times"); this.battlecount = new Text(result, SWT.BORDER | SWT.READ_ONLY); GridData gdBattlecount = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1); gdBattlecount.widthHint = 55; this.battlecount.setLayoutData(gdBattlecount); // 海域のインデックス値を復元 for (int i = 0; i < this.seacombo.getItemCount(); i++) { if (this.seacombo.getItem(i).equals(AppConfig.get().getDefaultSea())) { this.seacombo.select(i); } } // 評価のインデックス値を復元 for (int i = 0; i < this.evalcombo.getItemCount(); i++) { if (this.evalcombo.getItem(i).equals(AppConfig.get().getDefaultEvaluate())) { this.evalcombo.select(i); } } // 旗艦チェックを復元 this.flagbtn.setSelection(flag); // MVPチェックを復元 this.mvpbtn.setSelection(mvp); this.shipcombo.addSelectionListener(new PresetListener()); reload.addSelectionListener(new ReloadListener()); this.beforelv.addSelectionListener(new BeforeLvListener(this.beforexp, this.beforelv)); this.afterlv.addSelectionListener(new AfterLvListener(this.afterexp, this.afterlv)); this.seacombo.addSelectionListener(new UpdateListener()); this.evalcombo.addSelectionListener(new UpdateListener()); this.flagbtn.addSelectionListener(new UpdateListener()); this.mvpbtn.addSelectionListener(new UpdateListener()); this.shell.pack(); this.setShipComboData(); this.preset(); this.calc(); } /** * プリセットを行う */ public void preset() { if (this.shipcombo.getSelectionIndex() > -1) { ShipDto ship = CalcExpDialog.this.shipmap .get(this.shipcombo.getItem(this.shipcombo.getSelectionIndex())); if (ship != null) { int before = (int) ship.getLv(); int after = this.afterlv.getSelection(); // 改造Lv int afterlv = ship.getShipInfo().getAfterlv(); if (before < afterlv) { after = afterlv; } if (before > after) { after = before + 1; } // 目標レベルが150を超える場合は150に設定 after = Math.min(after, 150); String beforeexpstr = Long.toString(ship.getExp()); String afterexpstr = Long.toString(ExpTable.get().get(after)); this.beforelv.setSelection(before); this.afterlv.setSelection(after); this.beforexp.setText(beforeexpstr); this.afterexp.setText(afterexpstr); } } } /** * 計算を行う */ private void calc() { if ((this.seacombo.getSelectionIndex() < 0) || (this.evalcombo.getSelectionIndex() < 0)) { return; } // 必要経験値 int needexpint = Integer.parseInt(this.afterexp.getText()) - Integer.parseInt(this.beforexp.getText()); // 基礎経験値 int baseexp = SeaExp.get().get(this.seacombo.getItem(this.seacombo.getSelectionIndex())); // 評価 double eval = EvaluateExp.get().get(this.evalcombo.getItem(this.evalcombo.getSelectionIndex())); // 得られる経験値 long getexp = CalcExpUtils.getExp(baseexp, eval, this.flagbtn.getSelection(), this.mvpbtn.getSelection()); // 戦闘回数 int count = BigDecimal.valueOf(needexpint).divide(BigDecimal.valueOf(getexp), RoundingMode.CEILING).intValue(); // 1回の戦闘 this.getexp.setText(Long.toString(getexp)); // 必要経験値 this.needexp.setText(Integer.toString(needexpint)); // 戦闘回数 this.battlecount.setText(Integer.toString(count)); // 旗艦チェックを保存 CalcExpDialog.flag = this.flagbtn.getSelection(); // MVPチェックを保存 CalcExpDialog.mvp = this.mvpbtn.getSelection(); } /** * コンボボックスに艦娘をセットします * * @param combo */ private void setShipComboData() { // 選択していた艦娘を取得 long select = 0; if (this.shipcombo.getSelectionIndex() >= 0) { ShipDto ship = this.shipmap.get(this.shipcombo.getItem(this.shipcombo.getSelectionIndex())); select = ship.getId(); } else { // 誰も選択されてない状態の場合は秘書艦を選択する ShipDto ship = GlobalContext.getSecretary(); if (ship != null) { select = ship.getId(); } } // コンボボックスから全ての艦娘を削除 this.shipcombo.removeAll(); // 表示用文字列と艦娘の紐付けを削除 this.shipmap.clear(); // 艦娘IDの最大を取得してゼロ埋め長さを算出 long maxshipid = 0; for (ShipDto ship : GlobalContext.getShipMap().values()) { maxshipid = Math.max(ship.getId(), maxshipid); } int padlength = Long.toString(maxshipid).length(); // 表示用文字列と艦娘の紐付けを追加 for (ShipDto ship : GlobalContext.getShipMap().values()) { this.shipmap.put(this.getShipLabel(ship, padlength), ship); } // 艦娘を経験値順でソート List<ShipDto> ships = new ArrayList<ShipDto>(this.shipmap.values()); Collections.sort(ships, new Comparator<ShipDto>() { @Override public int compare(ShipDto o1, ShipDto o2) { return Long.compare(o2.getExp(), o1.getExp()); } }); // コンボボックスに追加 for (int i = 0; i < ships.size(); i++) { String key = this.getShipLabel(ships.get(i), padlength); this.shipcombo.add(key); if (ships.get(i).getId() == select) { this.shipcombo.select(i); } } // コントロールを再配置 this.shipcombo.pack(); this.shipcombo.getParent().pack(); } /** * 艦娘のプルダウン表示用文字列を作成します * * @param ship * @param padlength * @return */ private String getShipLabel(ShipDto ship, int padlength) { return new StringBuilder().append(StringUtils.leftPad(Long.toString(ship.getId()), padlength, '0')) .append(": ").append(ship.getName()).append(" (Lv").append(ship.getLv() + ")").toString(); } /** * 艦娘の状態を更新する * */ private final class ReloadListener extends SelectionAdapter { @Override public void widgetSelected(SelectionEvent e) { CalcExpDialog.this.setShipComboData(); CalcExpDialog.this.preset(); CalcExpDialog.this.calc(); } } /** * 計算結果を更新する * */ private final class UpdateListener extends SelectionAdapter { @Override public void widgetSelected(SelectionEvent e) { CalcExpDialog.this.calc(); } } /** * プリセットを行う * */ private final class PresetListener extends SelectionAdapter { @Override public void widgetSelected(SelectionEvent e) { CalcExpDialog.this.preset(); CalcExpDialog.this.calc(); } } /** * 今のレベルが変更された * */ private final class BeforeLvListener extends SelectionAdapter { private final Text beforexp; private final Spinner beforelv; /** * @param beforexp * @param beforelv */ private BeforeLvListener(Text beforexp, Spinner beforelv) { this.beforexp = beforexp; this.beforelv = beforelv; } @Override public void widgetSelected(SelectionEvent e) { String beforeexpstr = Long.toString(ExpTable.get().get(this.beforelv.getSelection())); this.beforexp.setText(beforeexpstr); CalcExpDialog.this.calc(); } } /** * 目標レベルが変更された * */ private final class AfterLvListener extends SelectionAdapter { private final Text afterexp; private final Spinner afterlv; /** * @param afterexp * @param afterlv */ private AfterLvListener(Text afterexp, Spinner afterlv) { this.afterexp = afterexp; this.afterlv = afterlv; } @Override public void widgetSelected(SelectionEvent e) { String afterexpstr = Long.toString(ExpTable.get().get(this.afterlv.getSelection())); this.afterexp.setText(afterexpstr); CalcExpDialog.this.calc(); } } }