tv.dyndns.kishibe.qmaclone.client.creation.CreationUi.java Source code

Java tutorial

Introduction

Here is the source code for tv.dyndns.kishibe.qmaclone.client.creation.CreationUi.java

Source

//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 java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import tv.dyndns.kishibe.qmaclone.client.Service;
import tv.dyndns.kishibe.qmaclone.client.UserData;
import tv.dyndns.kishibe.qmaclone.client.bbs.PanelBbs;
import tv.dyndns.kishibe.qmaclone.client.creation.ChangeHistoryView.ChangeHistoryPresenter;
import tv.dyndns.kishibe.qmaclone.client.creation.validater.Evaluation;
import tv.dyndns.kishibe.qmaclone.client.game.ProblemGenre;
import tv.dyndns.kishibe.qmaclone.client.game.SessionData;
import tv.dyndns.kishibe.qmaclone.client.game.WidgetTimeProgressBar;
import tv.dyndns.kishibe.qmaclone.client.game.panel.QuestionPanel;
import tv.dyndns.kishibe.qmaclone.client.game.panel.QuestionPanelFactory;
import tv.dyndns.kishibe.qmaclone.client.packet.PacketProblem;
import tv.dyndns.kishibe.qmaclone.client.packet.PacketProblemCreationLog;
import tv.dyndns.kishibe.qmaclone.client.packet.PacketWrongAnswer;
import tv.dyndns.kishibe.qmaclone.client.report.ProblemReportUi;
import tv.dyndns.kishibe.qmaclone.client.util.StringUtils;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.RepeatingCommand;
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.safehtml.shared.SafeHtmlUtils;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
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.Composite;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.FocusWidget;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.SimplePanel;
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 CreationUi extends Composite implements ChangeHistoryPresenter {
    private static final Logger logger = Logger.getLogger(CreationUi.class.getName());
    private static final int MAX_SIMILER_PROBLEMS_PER_PAGE = 10;
    private static final CreationUiUiBinder uiBinder = GWT.create(CreationUiUiBinder.class);
    @VisibleForTesting
    static final String MESSAGE_UPDATE_NOTE = "????????";
    // TODO(nodchip): ??????
    @VisibleForTesting
    static boolean SUPPRESS_GET_SIMILAR_PROBLEM_FOR_TESTING = false;
    private static final int MIN_NUMBER_OF_PROBLEM_TO_SHOW_PROBLEM_FORM = 30;

    interface CreationUiUiBinder extends UiBinder<Widget, CreationUi> {
    }

    @UiField
    HTMLPanel htmlPanelSorry;
    @UiField
    HTMLPanel htmlRequireGooglePlusLogin;
    @UiField
    HTMLPanel htmlPanelMain;
    @UiField
    HTMLPanel htmlPanelDone;
    @UiField
    Button buttonNewProblem;
    @UiField
    Button buttonMoveToVerification;
    @UiField
    Button buttonSendProblem;
    @UiField
    SimplePanel panelSimilar;
    @UiField
    HTMLPanel htmlPanelWrongAnswer;
    @UiField
    SimplePanel panelWrongAnswer;
    @UiField
    HTMLPanel htmlPanelBbs;
    @UiField
    SimplePanel panelBbs;
    @UiField
    SimplePanel panelSample;
    @UiField
    TextBox textBoxGetProblem;
    @UiField
    Button buttonGetProblem;
    @UiField
    Button buttonCopyProblem;
    @UiField
    SimplePanel panelProblemForm;
    @UiField
    VerticalPanel panelWarning;
    @UiField
    HTML htmlTypeCaution;
    @UiField
    SimplePanel panelChangeHistory;
    @UiField
    Label labelProblemId;
    @UiField
    Button buttonNextProblem;

    @VisibleForTesting
    WidgetProblemForm widgetProblemForm;
    private boolean sendingProblem = false;
    private final RepeatingCommand commandCheckProblem = new RepeatingCommand() {
        @Override
        public boolean execute() {
            boolean enabled = validateProblem();
            buttonMoveToVerification.setEnabled(enabled && !sendingProblem);
            buttonSendProblem.setEnabled(enabled && !sendingProblem);
            return isAttached();
        }
    };
    private boolean copyProblem;
    private final RepeatingCommand commandCheckProblemId = new RepeatingCommand() {
        @Override
        public boolean execute() {
            boolean enabled = checkProblemId();
            buttonCopyProblem.setEnabled(enabled);
            buttonGetProblem.setEnabled(enabled);
            return isAttached();
        }
    };

    private final WrongAnswerPresenter wrongAnswerPresenter;

    public CreationUi(WrongAnswerPresenter wrongAnswerPresenter) {
        this.wrongAnswerPresenter = Preconditions.checkNotNull(wrongAnswerPresenter);
        initWidget(uiBinder.createAndBindUi(this));
        reset();
    }

    public void reset() {
        buttonSendProblem.setVisible(false);

        htmlPanelSorry.setVisible(false);
        htmlRequireGooglePlusLogin.setVisible(false);
        htmlPanelMain.setVisible(false);
        htmlPanelDone.setVisible(false);
        htmlPanelWrongAnswer.setVisible(false);
        htmlPanelBbs.setVisible(false);

        // TODO(nodchip): ???Google+?
        if (UserData.get().getPlayCount() < MIN_NUMBER_OF_PROBLEM_TO_SHOW_PROBLEM_FORM) {
            htmlPanelSorry.setVisible(true);
            // } else if (Strings.isNullOrEmpty(UserData.get().getGooglePlusId())) {
            // htmlRequireGooglePlusLogin.setVisible(true);
        } else {
            htmlPanelMain.setVisible(true);
        }

        panelSimilar.clear();
        panelWrongAnswer.clear();
        panelSample.clear();
        panelWarning.clear();
        panelChangeHistory.clear();

        widgetProblemForm = new WidgetProblemForm(this);
        panelProblemForm.setWidget(widgetProblemForm);
        textBoxGetProblem.setText(null);
        // previousProblemNote = null;
    }

    /**
     * ???
     * 
     * @param text
     *          
     */
    public void setTypeDescription(String text) {
        if (Strings.isNullOrEmpty(text)) {
            htmlTypeCaution.setHTML("");
            return;
        }

        htmlTypeCaution.setHTML(new SafeHtmlBuilder().appendEscapedLines(text).toSafeHtml());
    }

    /**
     * ??????????????
     * 
     * @return ???true
     */
    @VisibleForTesting
    boolean validateProblem() {
        clearWarnings();

        if (widgetProblemForm == null) {
            return false;
        }

        PacketProblem problem = widgetProblemForm.getProblem();
        Evaluation eval = problem.type.validate(problem);

        // ??
        // BugTrack-QMAClone/589 - QMAClone wiki
        // http://kishibe.dyndns.tv/qmaclone/wiki/wiki.cgi?page=BugTrack%2DQMAClone%2F589
        // if (previousProblemNote != null && previousProblemNote.equals(problem.note)) {
        // eval.warn.add(MESSAGE_UPDATE_NOTE);
        // }

        for (String warning : eval.warn) {
            addWarnings(warning);
        }

        for (String info : eval.info) {
            addInfo(info);
        }

        return !eval.hasWarning();
    }

    private void setProblemSample(PacketProblem problem) {
        problem.prepareShuffledAnswersAndChoices();
        WidgetTimeProgressBar widgetTimeProgressBar = new WidgetTimeProgressBar();
        QuestionPanel panelQuestion = QuestionPanelFactory.create(problem, widgetTimeProgressBar,
                new SessionData(-1, -1, false, false, false));
        panelQuestion.enableInput(false);
        panelQuestion.showCorrectRatioAndCreator();
        panelSample.setWidget(panelQuestion);
    }

    private void getSimilarProblems(PacketProblem problem) {
        if (SUPPRESS_GET_SIMILAR_PROBLEM_FOR_TESTING) {
            return;
        }
        Service.Util.getInstance().searchSimilarProblem(problem, callbackSearchSimilarProblem);
    }

    private final AsyncCallback<List<PacketProblem>> callbackSearchSimilarProblem = new AsyncCallback<List<PacketProblem>>() {
        public void onSuccess(List<PacketProblem> result) {
            panelSimilar.setWidget(new ProblemReportUi(result, true, true, MAX_SIMILER_PROBLEMS_PER_PAGE));
        }

        public void onFailure(Throwable caught) {
            logger.log(Level.WARNING, "???????", caught);
        }
    };

    public void getWrongAnswers(int problemID) {
        Service.Util.getInstance().getWrongAnswers(problemID, callbackGetWrongAnswers);
    }

    @VisibleForTesting
    final AsyncCallback<List<PacketWrongAnswer>> callbackGetWrongAnswers = new AsyncCallback<List<PacketWrongAnswer>>() {

        public void onSuccess(List<PacketWrongAnswer> result) {
            panelWrongAnswer.setWidget(wrongAnswerPresenter.asWidget());
            wrongAnswerPresenter.setWrongAnswers(result, widgetProblemForm.getProblem());
        }

        public void onFailure(Throwable caught) {
            logger.log(Level.WARNING, "???????", caught);
        }
    };

    private final AsyncCallback<Integer> callbackUploadProblem = new AsyncCallback<Integer>() {
        public void onSuccess(Integer result) {
            int userCode = UserData.get().getUserCode();

            htmlPanelMain.setVisible(false);
            htmlPanelDone.setVisible(true);
            labelProblemId.setText(Integer.toString(result));

            if (UserData.get().isRegisterCreatedProblem()) {
                Service.Util.getInstance().addProblemIdsToReport(userCode, ImmutableList.of(result),
                        callbackAddProblemIdsToReport);
            }

            sendingProblem = false;
            setEnable(true);

            // 
            PacketProblem problem = widgetProblemForm.getProblem();
            if (problem.needsResetAnswerCount) {
                Service.Util.getInstance().resetProblemCorrectCounter(UserData.get().getUserCode(), result,
                        callbackResetProblemCorrectCounter);
            }

        }

        public void onFailure(Throwable caught) {
            sendingProblem = false;
            setEnable(true);

            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);
        }
    };

    private void setEnable(boolean enabled) {
        FocusWidget[] widgets = { buttonNewProblem, buttonMoveToVerification, buttonSendProblem, textBoxGetProblem,
                buttonGetProblem, buttonCopyProblem, buttonNextProblem };
        for (FocusWidget widget : widgets) {
            widget.setEnabled(enabled);
        }
        widgetProblemForm.setEnable(enabled);
    }

    private void getProblemFromServer(boolean copy) {
        // TODO(nodchip): ??
        copyProblem = copy;

        int problemId;
        try {
            problemId = Integer.parseInt(StringUtils.toHalfWidth(textBoxGetProblem.getText()));
        } catch (NumberFormatException e) {
            logger.log(Level.WARNING, "???????????????",
                    e);
            return;
        }

        setEnable(false);

        Service.Util.getInstance().getProblemList(ImmutableList.of(problemId), callbackGetProblemList);

        if (copy) {
            panelChangeHistory.clear();
            panelBbs.clear();
            htmlPanelWrongAnswer.setVisible(false);
            htmlPanelBbs.setVisible(false);
        } else {
            panelChangeHistory.setWidget(new ChangeHistoryViewImpl(this));
            Service.Util.getInstance().getProblemCreationLog(problemId, callbackGetProblemCreationLog);

            panelBbs.setWidget(new PanelBbs(problemId));
            htmlPanelWrongAnswer.setVisible(true);
            htmlPanelBbs.setVisible(true);
        }
    }

    private final AsyncCallback<List<PacketProblem>> callbackGetProblemList = new AsyncCallback<List<PacketProblem>>() {
        public void onSuccess(List<PacketProblem> result) {
            String message = "????????";
            if (result == null || result.isEmpty()) {
                logger.log(Level.WARNING, message);
                return;
            }

            PacketProblem problem = result.get(0);
            if (problem == null) {
                logger.log(Level.WARNING, message);
                return;
            }

            if (copyProblem) {
                problem = problem.cloneForCopyingProblem();
            }
            widgetProblemForm.setProblem(problem);

            if (copyProblem) {
                panelSimilar.clear();
                panelWrongAnswer.clear();
                panelSample.clear();
                panelChangeHistory.clear();
                // previousProblemNote = null;
            } else {
                setProblemSample(problem);
                getWrongAnswers(problem.id);
                panelSimilar.clear();
                getSimilarProblems(problem);
                // previousProblemNote = problem.note;
            }

            setEnable(true);
        }

        public void onFailure(Throwable caught) {
            logger.log(Level.WARNING, "?????????", caught);
            setEnable(true);
        }
    };
    private final AsyncCallback<List<PacketProblemCreationLog>> callbackGetProblemCreationLog = new AsyncCallback<List<PacketProblemCreationLog>>() {
        @Override
        public void onSuccess(List<PacketProblemCreationLog> result) {
            ChangeHistoryView view = (ChangeHistoryView) panelChangeHistory.getWidget();
            view.setCreationLog(result);
        }

        @Override
        public void onFailure(Throwable caught) {
            logger.log(Level.WARNING, "????????", caught);
        }
    };

    private void clearWarnings() {
        panelWarning.clear();
    }

    private void addWarnings(String warning) {
        HTML w = new HTML(SafeHtmlUtils.fromString(warning));
        w.addStyleName("gwt-HTML-problemCreationWarning");
        panelWarning.add(w);
    }

    private void addInfo(String info) {
        HTML w = new HTML(SafeHtmlUtils.fromString(info));
        w.addStyleName("gwt-HTML-problemCreationInfo");
        panelWarning.add(w);
    }

    public void setProblem(int problemID) {
        textBoxGetProblem.setText(String.valueOf(problemID));
        getProblemFromServer(false);
    }

    @Override
    protected void onLoad() {
        super.onLoad();
        Scheduler.get().scheduleFixedDelay(commandCheckProblem, 1000);
        Scheduler.get().scheduleFixedDelay(commandCheckProblemId, 1000);

        // ???
        int userCode = UserData.get().getUserCode();
        Service.Util.getInstance().canUploadProblem(userCode, null, callbackCanUploadProblemOnLoad);
    }

    private final AsyncCallback<Boolean> callbackCanUploadProblemOnLoad = new AsyncCallback<Boolean>() {
        @Override
        public void onSuccess(Boolean result) {
            if (result) {
                return;
            }

            showRepeatedPostWarning();
        }

        @Override
        public void onFailure(Throwable caught) {
            logger.log(Level.WARNING, "????????", caught);

            sendingProblem = false;
            widgetProblemForm.setEnable(true);
            setEnable(true);
        }
    };

    private void showRepeatedPostWarning() {
        final DialogBox dialogBox = new DialogBox(true);

        VerticalPanel panel = new VerticalPanel();
        panel.add(
                new HTML(new SafeHtmlBuilder()
                        .appendEscapedLines(
                                "????????\n"
                                        + "???????????????\n"
                                        + "??????????")
                        .toSafeHtml()));
        panel.add(new Button("OK", new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {
                dialogBox.hide();
            }
        }));
        dialogBox.setWidget(panel);
        dialogBox.setAnimationEnabled(true);
        dialogBox.setGlassEnabled(true);
        dialogBox.setHTML(SafeHtmlUtils.fromString("?"));
        dialogBox.setPopupPosition(100, 100);
        dialogBox.show();
    }

    @UiHandler("buttonNewProblem")
    void onButtonNewProblem(ClickEvent e) {
        reset();
    }

    @UiHandler("buttonMoveToVerification")
    void onButtonMoveToVerification(ClickEvent e) {
        if (!validateProblem()) {
            return;
        }

        buttonMoveToVerification.setText("?????????");
        buttonSendProblem.setVisible(true);

        PacketProblem problem = widgetProblemForm.getProblem();
        setProblemSample(problem);
        panelSimilar.clear();
        getSimilarProblems(problem);
    }

    @UiHandler("buttonSendProblem")
    void onButtonSendProblem(ClickEvent e) {
        if (!validateProblem()) {
            return;
        }

        sendingProblem = true;
        widgetProblemForm.setEnable(false);
        setEnable(false);

        PacketProblem problem = widgetProblemForm.getProblem();
        int userCode = UserData.get().getUserCode();

        if (problem.genre == ProblemGenre.Anige) {
            // ???????????????????
            Service.Util.getInstance().canUploadProblem(userCode, problem.id == -1 ? null : problem.id,
                    callbackCanUploadProblem);
        } else {
            uploadProblem();
        }
    }

    private final AsyncCallback<Boolean> callbackCanUploadProblem = new AsyncCallback<Boolean>() {
        @Override
        public void onSuccess(Boolean result) {
            if (!result) {
                Window.alert("?: ??????????\n"
                        + "http://kishibe.dyndns.tv/QMAClone/??????\n"
                        + "http://kishibe.dyndns.tv:8080/QMAClone/??????");
                sendingProblem = false;
                widgetProblemForm.setEnable(true);
                setEnable(true);
                return;
            }

            uploadProblem();
        }

        @Override
        public void onFailure(Throwable caught) {
            logger.log(Level.WARNING, "????????", caught);

            sendingProblem = false;
            widgetProblemForm.setEnable(true);
            setEnable(true);
        }
    };

    private void uploadProblem() {
        PacketProblem problem = widgetProblemForm.getProblem();
        int userCode = UserData.get().getUserCode();
        boolean resetAnswerCount = widgetProblemForm.isReserveResetAnswerCount();

        // 
        if (problem.needsRemovePlayerAnswers) {
            Service.Util.getInstance().removePlayerAnswers(problem.id, callbackRemovePlayerAnswers);
        }

        // ??
        if (problem.needsResetVote) {
            Service.Util.getInstance().resetVote(problem.id, callbackResetVote);
        }

        Service.Util.getInstance().uploadProblem(problem, userCode, resetAnswerCount, callbackUploadProblem);
    }

    private final AsyncCallback<Void> callbackRemovePlayerAnswers = new AsyncCallback<Void>() {
        @Override
        public void onSuccess(Void result) {
        }

        @Override
        public void onFailure(Throwable caught) {
            logger.log(Level.WARNING, "??????", caught);
        }
    };
    private final AsyncCallback<Boolean> callbackResetProblemCorrectCounter = new AsyncCallback<Boolean>() {
        @Override
        public void onSuccess(Boolean result) {
            if (!result) {
                Window.alert(
                        "????????\n???????\n???????????");
            }
        }

        @Override
        public void onFailure(Throwable caught) {
            logger.log(Level.WARNING, "?????????");
        }
    };
    private final AsyncCallback<Void> callbackResetVote = new AsyncCallback<Void>() {
        @Override
        public void onSuccess(Void result) {
        }

        @Override
        public void onFailure(Throwable caught) {
            logger.log(Level.WARNING, "??????", caught);
        }
    };

    @UiHandler("buttonGetProblem")
    void onButtonGetProblem(ClickEvent e) {
        getProblemFromServer(false);
    }

    @UiHandler("buttonCopyProblem")
    void onButtonCopyProblem(ClickEvent e) {
        getProblemFromServer(true);
    }

    @UiHandler("buttonNextProblem")
    void onButtonNextProblem(ClickEvent e) {
        reset();

        // ???
        int userCode = UserData.get().getUserCode();
        Service.Util.getInstance().canUploadProblem(userCode, null, callbackCanUploadProblemOnLoad);
    }

    private boolean checkProblemId() {
        try {
            Integer.parseInt(textBoxGetProblem.getText());
        } catch (NumberFormatException e) {
            return false;
        }
        return true;
    }

    public void reloadBbs() {
        PanelBbs bbs = (PanelBbs) panelBbs.getWidget();
        if (bbs == null) {
            return;
        }
        bbs.reload();
    }

    @Override
    public void onUpdateDiffTarget(PacketProblemCreationLog before, PacketProblemCreationLog after) {
        if (before == null || after == null) {
            return;
        }

        Service.Util.getInstance().generateDiffHtml(before.summary, after.summary, callbackGenerateDiffHtml);
    }

    private final AsyncCallback<String> callbackGenerateDiffHtml = new AsyncCallback<String>() {
        @Override
        public void onSuccess(String result) {
            ChangeHistoryView view = (ChangeHistoryView) panelChangeHistory.getWidget();
            view.setDiffHtml(SafeHtmlUtils.fromSafeConstant(result));
        }

        @Override
        public void onFailure(Throwable caught) {
            logger.log(Level.WARNING, "html???????", caught);
        }
    };
}