//The MIT License
//
//Copyright (c) 2009 nodchip
//
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:
//
//The above copyright notice and this permission notice shall be included in
//all copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//THE SOFTWARE.
package tv.dyndns.kishibe.qmaclone.client.creation;
import static com.google.common.base.Strings.emptyToNull;
import static com.google.common.base.Strings.nullToEmpty;
import static tv.dyndns.kishibe.qmaclone.client.constant.Constant.MAX_NUMBER_OF_ANSWERS;
import static tv.dyndns.kishibe.qmaclone.client.constant.Constant.MAX_NUMBER_OF_CHOICES;
import static tv.dyndns.kishibe.qmaclone.client.constant.Constant.MAX_PLAYER_NAME_LENGTH;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import tv.dyndns.kishibe.qmaclone.client.PlusOne;
import tv.dyndns.kishibe.qmaclone.client.Service;
import tv.dyndns.kishibe.qmaclone.client.UserData;
import tv.dyndns.kishibe.qmaclone.client.Utility;
import tv.dyndns.kishibe.qmaclone.client.game.ProblemGenre;
import tv.dyndns.kishibe.qmaclone.client.game.ProblemType;
import tv.dyndns.kishibe.qmaclone.client.game.RandomFlag;
import tv.dyndns.kishibe.qmaclone.client.packet.PacketBbsResponse;
import tv.dyndns.kishibe.qmaclone.client.packet.PacketBbsThread;
import tv.dyndns.kishibe.qmaclone.client.packet.PacketProblem;
import tv.dyndns.kishibe.qmaclone.client.packet.ProblemIndicationEligibility;
import tv.dyndns.kishibe.qmaclone.client.util.StringUtils;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Joiner;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.gwt.core.client.JavaScriptException;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.FocusWidget;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.RadioButton;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
public class WidgetProblemForm extends VerticalPanel implements ClickHandler, ChangeHandler {
private static final Logger logger = Logger.getLogger(WidgetProblemForm.class.getName());
private static final int MAX_PROBLEM_NOTE_LENGTH = 1024;
private final Label labelProblemNumber = new Label("新規問題を作成中");
private final ListBox listBoxGenre = new ListBox();
@VisibleForTesting
final ListBox listBoxType = new ListBox();
private final ListBox listBoxRandomFlag = new ListBox();
private final TextArea textAreaSentence = new TextArea();
@VisibleForTesting
final TextBox[] textBoxAnswer = new TextBox[MAX_NUMBER_OF_ANSWERS];
@VisibleForTesting
final TextBox[] textBoxChoice = new TextBox[MAX_NUMBER_OF_CHOICES];
private final RadioButton radioButtonNone = new RadioButton("external", "使用しない");
private final RadioButton radioButtonImage = new RadioButton("external", "画像");
private final RadioButton radioButtonYouTube = new RadioButton("external", "YouTube");
private final ListBox listBoxNumberOfDisplayedChoices = new ListBox();
private final TextBox textBoxExternalUrl = new TextBox();
private final HorizontalPanel panelExternalUrl = new HorizontalPanel();
private final TextBox textBoxCreator = new TextBox();
private final TextArea textAreaNote = new TextArea();
private final CreationUi creationUi;
private final Label labelAnswerCounter = new Label("0/0");
private final CheckBox checkBoxResetAnswerCount = new CheckBox("回答数をリセットする");
@VisibleForTesting
final HTML htmlPlusOne = new HTML();
private final Label labelGood = new Label("0");
private final CheckBox checkBoxResetVote = new CheckBox("良問投票をリセットする");
private final CheckBox checkBoxImageChoice = new CheckBox("画像選択肢");
private final CheckBox checkBoxImageAnswer = new CheckBox("画像回答");
private final CheckBox checkBoxRemovePlayerAnswers = new CheckBox("回答履歴を削除する");
private int problemId = PacketProblem.CREATING_PROBLEM_ID;
private final List<Button> buttonPolygonCreation = new ArrayList<Button>();
private final VerticalPanel panelProblemFeedback = new VerticalPanel();
private final Button buttonClearProblemFeedback = new Button("クリア", this);
private Date indication;
private Date indicationResolved;
private final Button buttonIndicate = new Button("問題の不備を指摘する");
@VisibleForTesting
final CheckBox checkBoxUnindicate = new CheckBox("指摘マークを消す (ページ下の掲示板の指摘内容を確認して下さい)");
private boolean reserveResetAnswerCount = false;
public WidgetProblemForm(CreationUi creationUi) {
this.creationUi = creationUi;
// 問題番号
add(labelProblemNumber);
Grid grid = new Grid(15, 2);
grid.addStyleName("gridFrame");
grid.addStyleName("gridFontNormal");
int row = 0;
// ジャンル
for (ProblemGenre genre : ProblemGenre.values()) {
String name = genre == ProblemGenre.Random ? "ジャンルを選んでください" : genre.toString();
listBoxGenre.addItem(name, Integer.toString(genre.getIndex()));
}
listBoxGenre.setWidth("200px");
grid.setText(row, 0, "ジャンル");
grid.setWidget(row++, 1, listBoxGenre);
// 出題形式
for (ProblemType type : ProblemType.values()) {
if (ProblemType.Random1.compareTo(type) <= 0) {
break;
}
String item = type == ProblemType.Random ? "出題形式を選んでください" : type.toString();
listBoxType.addItem(item, type.name());
}
listBoxType.setWidth("200px");
listBoxType.addChangeHandler(this);
grid.setText(row, 0, "出題形式");
grid.setWidget(row++, 1, listBoxType);
// ランダムフラグ
for (int i = 1; i <= 5; ++i) {
String s = Integer.toString(i);
listBoxRandomFlag.addItem(s, RandomFlag.values()[i].name());
}
listBoxRandomFlag.setSelectedIndex(4);
listBoxRandomFlag.setWidth("100px");
grid.setText(row, 0, "ランダムフラグ");
grid.setWidget(row++, 1, listBoxRandomFlag);
// 問題文
textAreaSentence.setCharacterWidth(60);
textAreaSentence.setVisibleLines(5);
grid.setText(row, 0, "問題文");
grid.setWidget(row++, 1, textAreaSentence);
// 選択肢
VerticalPanel choicePanel = new VerticalPanel();
choicePanel.setStyleName("gridNoFrame");
choicePanel.addStyleName("gridFontNormal");
for (int i = 0; i < MAX_NUMBER_OF_CHOICES; ++i) {
textBoxChoice[i] = new TextBox();
textBoxChoice[i].setWidth("400px");
choicePanel.add(textBoxChoice[i]);
}
choicePanel.add(checkBoxImageChoice);
grid.setText(row, 0, "選択肢");
grid.setWidget(row++, 1, choicePanel);
// 解答
VerticalPanel answerPanel = new VerticalPanel();
answerPanel.setStyleName("gridNoFrame");
answerPanel.addStyleName("gridFontNormal");
for (int i = 0; i < MAX_NUMBER_OF_ANSWERS; ++i) {
HorizontalPanel panel = new HorizontalPanel();
panel.setVerticalAlignment(ALIGN_MIDDLE);
answerPanel.add(panel);
textBoxAnswer[i] = new TextBox();
textBoxAnswer[i].setWidth("400px");
panel.add(textBoxAnswer[i]);
Button button = new Button("領域作成", this);
panel.add(button);
buttonPolygonCreation.add(button);
}
answerPanel.add(checkBoxImageAnswer);
grid.setText(row, 0, "解答");
grid.setWidget(row++, 1, answerPanel);
// 表示する選択肢の数
grid.setText(row, 0, "表示する選択肢の数");
grid.setWidget(row++, 1, listBoxNumberOfDisplayedChoices);
listBoxNumberOfDisplayedChoices.setWidth("50px");
listBoxNumberOfDisplayedChoices.addItem("3");
listBoxNumberOfDisplayedChoices.addItem("4");
listBoxNumberOfDisplayedChoices.setSelectedIndex(1);
// 外部コンテンツ
grid.setText(row, 0, "外部コンテンツ");
{
VerticalPanel panel = new VerticalPanel();
panel.setStyleName("gridNoFrame");
panel.addStyleName("gridFontNormal");
{
radioButtonNone.setValue(true);
radioButtonNone.addClickHandler(this);
radioButtonImage.addClickHandler(this);
radioButtonYouTube.addClickHandler(this);
HorizontalPanel panel2 = new HorizontalPanel();
panel2.add(radioButtonNone);
panel2.add(radioButtonImage);
panel2.add(radioButtonYouTube);
panel.add(panel2);
}
{
textBoxExternalUrl.setWidth("400px");
panelExternalUrl.add(new Label("URL"));
panelExternalUrl.add(textBoxExternalUrl);
panel.add(panelExternalUrl);
}
grid.setWidget(row++, 1, panel);
}
// 作成者
textBoxCreator.setWidth("200px");
textBoxCreator.setMaxLength(MAX_PLAYER_NAME_LENGTH);
textBoxCreator.setText(UserData.get().getPlayerName());
grid.setText(row, 0, "問題作成者");
grid.setWidget(row++, 1, textBoxCreator);
// 回答数
grid.setText(row, 0, "回答数");
HorizontalPanel panelAnswerCount = new HorizontalPanel();
panelAnswerCount.add(labelAnswerCounter);
panelAnswerCount.add(checkBoxResetAnswerCount);
panelAnswerCount.add(checkBoxRemovePlayerAnswers);
checkBoxResetAnswerCount.setVisible(false);
checkBoxRemovePlayerAnswers.setVisible(false);
grid.setWidget(row++, 1, panelAnswerCount);
// 回答数
grid.setText(row, 0, "+1");
HorizontalPanel panelVoteCount = new HorizontalPanel();
panelVoteCount.add(htmlPlusOne);
grid.setWidget(row++, 1, panelVoteCount);
// 評価
grid.setText(row, 0, "良問");
HorizontalPanel panelGood = new HorizontalPanel();
panelGood.add(labelGood);
panelGood.add(checkBoxResetVote);
checkBoxResetVote.setVisible(false);
grid.setWidget(row++, 1, panelGood);
// 指摘
grid.setText(row, 0, "指摘");
HorizontalPanel panelIndicate = new HorizontalPanel();
buttonIndicate.setVisible(false);
checkBoxUnindicate.setVisible(false);
panelIndicate.add(buttonIndicate);
panelIndicate.add(checkBoxUnindicate);
grid.setWidget(row++, 1, panelIndicate);
buttonIndicate.addClickHandler(this);
// 問題ノート
grid.setText(row, 0, "問題ノート");
textAreaNote.setCharacterWidth(60);
textAreaNote.setVisibleLines(5);
grid.setWidget(row++, 1, textAreaNote);
// 問題評価
grid.setText(row, 0, "問題評価");
grid.setWidget(row++, 1, panelProblemFeedback);
add(grid);
updateForm();
}
/**
* 問題を設定する
*
* @param problem
* 問題
*/
public void setProblem(PacketProblem problem) {
// TODO 範囲外の値をセットしようとしたときにJavaとブラウザで挙動が違うのを報告する
listBoxGenre.setSelectedIndex(problem.genre.getIndex());
listBoxType.setSelectedIndex(problem.type.getIndex());
listBoxRandomFlag.setSelectedIndex(problem.randomFlag.getIndex() - 1);
textAreaSentence.setText(problem.getProblemCreationSentence());
if (problem.answers != null) {
for (int i = 0; i < problem.answers.length; ++i) {
String answer = nullToEmpty(problem.answers[i]);
textBoxAnswer[i].setText(answer);
}
}
if (problem.choices != null) {
for (int i = 0; i < problem.choices.length; ++i) {
String choice = nullToEmpty(problem.choices[i]);
textBoxChoice[i].setText(choice);
}
}
if (problem.type.isNumberOfDisplayedChoicesChangeable()) {
listBoxNumberOfDisplayedChoices.setSelectedIndex(problem.numberOfDisplayedChoices - 3);
} else {
listBoxNumberOfDisplayedChoices.setSelectedIndex(1);
}
if (problem.creator != null) {
textBoxCreator.setText(problem.creator);
}
labelAnswerCounter.setText(problem.good + "/" + problem.bad);
if (problem.isCopiedProblem()) {
htmlPlusOne.setHTML("");
} else {
htmlPlusOne.setHTML(PlusOne.getButton(problem.id, true));
try {
PlusOne.render();
} catch (JavaScriptException e) {
logger.warning("+1ボタンのレンダリングに失敗しました");
}
}
textAreaNote.setText(problem.note.trim());
checkBoxImageAnswer.setValue(problem.imageAnswer);
checkBoxImageChoice.setValue(problem.imageChoice);
problemId = problem.id;
if (problemId == PacketProblem.CREATING_PROBLEM_ID) {
labelProblemNumber.setText("新規問題入力中");
checkBoxRemovePlayerAnswers.setVisible(false);
} else {
labelProblemNumber.setText("問題番号" + problemId + "の問題を修正中");
checkBoxRemovePlayerAnswers.setVisible(true);
}
checkBoxResetAnswerCount.setValue(problem.needsResetAnswerCount);
checkBoxResetVote.setValue(problem.needsResetVote);
checkBoxRemovePlayerAnswers.setValue(problem.needsRemovePlayerAnswers);
checkBoxResetAnswerCount.setVisible(!problem.isCopiedProblem());
checkBoxRemovePlayerAnswers.setVisible(!problem.isCopiedProblem());
checkBoxResetVote.setVisible(!problem.isCopiedProblem());
if (problem.imageUrl != null) {
textBoxExternalUrl.setText(problem.imageUrl);
radioButtonImage.setValue(true);
} else if (problem.movieUrl != null) {
textBoxExternalUrl.setText(problem.movieUrl);
radioButtonYouTube.setValue(true);
} else {
radioButtonNone.setValue(true);
}
// 良問
labelGood.setText(String.valueOf(problem.voteGood));
// 指摘
// BugTrack-QMAClone/595 - QMAClone wiki
// http://kishibe.dyndns.tv/qmaclone/wiki/wiki.cgi?page=BugTrack%2DQMAClone%2F595
if (problem.isCopiedProblem()) {
// 問題をコピーした場合は問題指摘フラグは折る
indication = null;
indicationResolved = null;
} else {
if (problem.indication == null) {
indication = null;
indicationResolved = problem.indicationResolved;
buttonIndicate.setVisible(true);
checkBoxUnindicate.setVisible(false);
} else {
indication = problem.indication;
indicationResolved = null;
buttonIndicate.setVisible(false);
checkBoxUnindicate.setVisible(true);
}
}
checkBoxImageAnswer.setValue(false);
// 問題評価文
panelProblemFeedback.clear();
if (problemId != PacketProblem.CREATING_PROBLEM_ID) {
Service.Util.getInstance().getProblemFeedback(problemId, callbackGetProblemFeedback);
}
updateForm();
}
private final AsyncCallback<List<String>> callbackGetProblemFeedback = new AsyncCallback<List<String>>() {
public void onSuccess(List<String> result) {
panelProblemFeedback.add(new HTML(new SafeHtmlBuilder().appendEscapedLines(
Joiner.on('\n').join(result)).toSafeHtml()));
if (!result.isEmpty()) {
panelProblemFeedback.add(buttonClearProblemFeedback);
}
}
public void onFailure(Throwable caught) {
logger.log(Level.WARNING, "問題フィードバッグの取得に失敗しました", caught);
}
};
private void updateForm() {
ProblemType type = getSelectedType();
creationUi.setTypeDescription(type.getDescription());
for (TextBox textBox : textBoxChoice) {
textBox.setEnabled(false);
textBox.setVisible(false);
}
for (TextBox textBox : textBoxAnswer) {
textBox.setEnabled(false);
textBox.setVisible(false);
}
for (int i = 0; i < type.getNumberOfAnswers(); ++i) {
textBoxAnswer[i].setEnabled(true);
textBoxAnswer[i].setVisible(true);
}
for (int i = type.getNumberOfAnswers(); i < MAX_NUMBER_OF_ANSWERS; ++i) {
textBoxAnswer[i].setText("");
}
for (int i = 0; i < type.getNumberOfChoices(); ++i) {
textBoxChoice[i].setEnabled(true);
textBoxChoice[i].setVisible(true);
}
for (int i = type.getNumberOfChoices(); i < MAX_NUMBER_OF_CHOICES; ++i) {
textBoxChoice[i].setText("");
}
checkBoxImageAnswer.setVisible(type.isImageAnswer());
checkBoxImageChoice.setVisible(type.isImageChoice());
for (Button button : buttonPolygonCreation) {
button.setVisible(type.isPolygonCreation());
}
if (radioButtonNone.getValue()) {
textBoxExternalUrl.setText("");
panelExternalUrl.setVisible(false);
} else {
panelExternalUrl.setVisible(true);
}
listBoxNumberOfDisplayedChoices.setVisible(type.isNumberOfDisplayedChoicesChangeable());
}
public void setEnable(boolean enabled) {
List<FocusWidget> focusWidgets = Lists.newArrayList(listBoxGenre, listBoxType,
listBoxRandomFlag, textAreaSentence, textBoxAnswer[0], textBoxAnswer[1], textBoxAnswer[2],
textBoxAnswer[3], textBoxChoice[0], textBoxChoice[1], textBoxChoice[2], textBoxChoice[3],
radioButtonNone, radioButtonImage, radioButtonYouTube, textBoxExternalUrl, textBoxCreator,
textAreaNote, checkBoxResetAnswerCount, checkBoxImageChoice, checkBoxImageAnswer,
checkBoxRemovePlayerAnswers, buttonClearProblemFeedback, checkBoxResetVote);
focusWidgets.addAll(buttonPolygonCreation);
for (FocusWidget focusWidget : focusWidgets) {
focusWidget.setEnabled(enabled);
}
}
/**
* 問題を取得する
*
* @return 問題
*/
public PacketProblem getProblem() {
PacketProblem problem = new PacketProblem();
// 問題番号
problem.id = problemId;
// ジャンル・出題形式
problem.genre = ProblemGenre.values()[Integer.parseInt(listBoxGenre.getValue(listBoxGenre
.getSelectedIndex()))];
problem.type = getSelectedType();
problem.randomFlag = RandomFlag.values()[listBoxRandomFlag.getSelectedIndex() + 1];
// 問題文
problem.setSentence(textAreaSentence.getText());
// 答え
problem.answers = new String[MAX_NUMBER_OF_ANSWERS];
for (int i = 0; i < MAX_NUMBER_OF_ANSWERS; ++i) {
problem.answers[i] = emptyToNull(textBoxAnswer[i].getText().replaceAll("&", "&"));
if (problem.type == ProblemType.Typing || problem.type == ProblemType.Effect
|| problem.type == ProblemType.Flash) {
problem.answers[i] = StringUtils.toFullWidth(problem.answers[i]);
}
}
// 選択肢
problem.choices = new String[MAX_NUMBER_OF_CHOICES];
for (int i = 0; i < MAX_NUMBER_OF_CHOICES; ++i) {
problem.choices[i] = emptyToNull(textBoxChoice[i].getText().replaceAll("&", "&"));
}
if (problem.type == ProblemType.YonTaku || problem.type == ProblemType.Rensou) {
problem.answers = new String[MAX_NUMBER_OF_ANSWERS];
problem.answers[0] = problem.choices[0];
}
if (radioButtonImage.getValue()) {
problem.imageUrl = textBoxExternalUrl.getText();
} else if (radioButtonYouTube.getValue()) {
problem.movieUrl = textBoxExternalUrl.getText();
}
// 表示する選択肢の数
if (problem.type.isNumberOfDisplayedChoicesChangeable()) {
problem.numberOfDisplayedChoices = Integer.valueOf(listBoxNumberOfDisplayedChoices
.getItemText(listBoxNumberOfDisplayedChoices.getSelectedIndex()));
} else {
problem.numberOfDisplayedChoices = 4;
}
// 作成者
problem.creator = textBoxCreator.getText();
// 回答数
String answerCount[] = labelAnswerCounter.getText().split("/");
problem.good = Integer.parseInt(answerCount[0]);
problem.bad = Integer.parseInt(answerCount[1]);
problem.needsResetAnswerCount = checkBoxResetAnswerCount.getValue();
problem.needsRemovePlayerAnswers = checkBoxRemovePlayerAnswers.getValue();
// 投票数
problem.voteGood = Integer.valueOf(labelGood.getText());
problem.needsResetVote = checkBoxResetVote.getValue();
// 指摘
if (indication != null) {
if (!checkBoxUnindicate.getValue()) {
problem.indication = indication;
problem.indicationResolved = null;
} else {
// 指摘を解除した場合
problem.indication = null;
problem.indicationResolved = new Date();
}
} else {
problem.indication = null;
problem.indicationResolved = indicationResolved;
}
// 問題ノート
problem.note = textAreaNote.getText().trim();
if (problem.note.length() > MAX_PROBLEM_NOTE_LENGTH) {
problem.note = problem.note.substring(0, MAX_PROBLEM_NOTE_LENGTH);
}
problem.imageAnswer = isImageAnswer();
problem.imageChoice = isImageChoice();
return problem;
}
private ProblemType getSelectedType() {
int selectedIndex = listBoxType.getSelectedIndex();
String value = listBoxType.getValue(selectedIndex);
return ProblemType.valueOf(value);
}
private void clearProblemFeedback() {
if (problemId == PacketProblem.CREATING_PROBLEM_ID) {
return;
}
panelProblemFeedback.clear();
Service.Util.getInstance().clearProblemFeedback(problemId, callbackClearProblemFeedback);
}
private final AsyncCallback<Void> callbackClearProblemFeedback = new AsyncCallback<Void>() {
@Override
public void onSuccess(Void result) {
}
@Override
public void onFailure(Throwable caught) {
logger.log(Level.WARNING, "問題フィードバックの削除に失敗しました", caught);
}
};
private boolean isImageAnswer() {
ProblemType type = getSelectedType();
return type.isImageAnswer() && checkBoxImageAnswer.getValue();
}
private boolean isImageChoice() {
ProblemType type = getSelectedType();
return type.isImageChoice() && checkBoxImageChoice.getValue();
}
@Override
public void onClick(ClickEvent event) {
Widget sender = (Widget) event.getSource();
if (buttonPolygonCreation.contains(sender)) {
final int answerIndex = buttonPolygonCreation.indexOf(sender);
final DialogBoxPolygonCreation polygonCreation = new DialogBoxPolygonCreation(
textBoxChoice[0].getText(), textBoxAnswer[answerIndex].getText());
polygonCreation.setPopupPosition(Window.getScrollLeft() + 10, Window.getScrollTop() + 10);
polygonCreation.addDialogBoxPolygonCreationListener(new DialogBoxPolygonCreationListener() {
public void onOk() {
textBoxAnswer[answerIndex].setText(polygonCreation.getPolygonDescription());
}
public void onCancel() {
}
});
polygonCreation.show();
} else if (sender == buttonClearProblemFeedback) {
clearProblemFeedback();
} else if (sender == radioButtonNone) {
updateForm();
} else if (sender == radioButtonImage) {
updateForm();
} else if (sender == radioButtonYouTube) {
updateForm();
} else if (sender == buttonIndicate) {
onButtonIndicate();
}
}
public void onButtonIndicate() {
Service.Util.getInstance().getProblemIndicationEligibility(UserData.get().getUserCode(),
callbackGetProblemIndicationEligibility);
}
private final AsyncCallback<ProblemIndicationEligibility> callbackGetProblemIndicationEligibility = new AsyncCallback<ProblemIndicationEligibility>() {
@Override
public void onSuccess(ProblemIndicationEligibility result) {
switch (result) {
case OK:
indicate();
break;
case PLAYER_NAME_UNCHANGED:
Window.alert("プレイヤー名が「未初期化です」から変更されていません\n" + "プレイヤー名を変更し一回以上プレイしてから指摘してください");
break;
case REACHED_MAX_NUMBER_OF_REQUESTS_PER_UNIT_TIME:
Window.alert("問題指摘回数の上限に達しました\n" + "時間をおいて再度お試しください。");
break;
default:
break;
}
}
@Override
public void onFailure(Throwable caught) {
logger.log(Level.WARNING, "");
}
};
private void indicate() {
String prompt = Window.prompt("指摘内容をお書きください", "(指摘内容をお書きください)");
if (prompt == null) {
return;
}
final String message = prompt.trim();
if (Strings.isNullOrEmpty(message)) {
return;
}
if (indicationResolved != null
&& System.currentTimeMillis() < indicationResolved.getTime() + 7L * 24 * 60 * 60 * 1000) {
// 指摘解除されてから7日以内の場合
AsyncCallback<List<PacketBbsThread>> callbackGetBbsThreads = new AsyncCallback<List<PacketBbsThread>>() {
@Override
public void onSuccess(List<PacketBbsThread> result) {
if (result == null || result.isEmpty()) {
logger.log(Level.WARNING, "スレッドの取得に失敗しました");
return;
}
PacketBbsThread thread = result.get(0);
PacketBbsResponse response = new PacketBbsResponse();
response.threadId = thread.id;
response.name = UserData.get().getPlayerName();
response.userCode = UserData.get().getUserCode();
response.dispInfo = 2;
response.postTime = System.currentTimeMillis();
response.body = message;
Service.Util.getInstance().writeToBbs(response, true, callbackBuildBbsThread);
}
@Override
public void onFailure(Throwable caught) {
}
};
Service.Util.getInstance().getBbsThreads(problemId, 0, 1, callbackGetBbsThreads);
} else {
// 初めて指摘する場合、または指摘解除されてから7日以上経過した場合
PacketBbsThread thread = new PacketBbsThread();
thread.title = "不具合が指摘されました (" + Utility.toDateFormat(new Date()) + ")";
PacketBbsResponse response = new PacketBbsResponse();
response.body = message;
response.dispInfo = 2; // 全て表示
response.name = UserData.get().getPlayerName();
response.userCode = UserData.get().getUserCode();
Service.Util.getInstance()
.buildBbsThread(problemId, thread, response, callbackBuildBbsThread);
}
}
private final AsyncCallback<Void> callbackBuildBbsThread = new AsyncCallback<Void>() {
@Override
public void onSuccess(Void result) {
creationUi.reloadBbs();
indication = new Date();
Service.Util.getInstance().indicateProblem(problemId, UserData.get().getUserCode(),
callbackPointOutInProblem);
}
@Override
public void onFailure(Throwable caught) {
logger.log(Level.WARNING, "BBSスレッド立てに失敗しました", caught);
}
};
private final AsyncCallback<Void> callbackPointOutInProblem = new AsyncCallback<Void>() {
@Override
public void onSuccess(Void result) {
indication = new Date();
checkBoxUnindicate.setValue(false);
setProblem(getProblem());
if (UserData.get().isRegisterIndicatedProblem()) {
Service.Util.getInstance().addProblemIdsToReport(UserData.get().getUserCode(),
ImmutableList.of(problemId), callbackAddProblemIdsToReport);
}
Window.alert("ご指摘ありがとうございました");
}
@Override
public void onFailure(Throwable caught) {
logger.log(Level.WARNING, "指摘フラグの更新に失敗しました", caught);
}
};
private final AsyncCallback<Void> callbackAddProblemIdsToReport = new AsyncCallback<Void>() {
@Override
public void onSuccess(Void result) {
}
@Override
public void onFailure(Throwable caught) {
logger.log(Level.WARNING, "正解率統計への問題追加に失敗しました", caught);
}
};
@Override
public void onChange(ChangeEvent event) {
Widget sender = (Widget) event.getSource();
if (sender == listBoxType) {
updateForm();
}
}
public boolean isReserveResetAnswerCount() {
return reserveResetAnswerCount;
}
}