package tv.dyndns.kishibe.qmaclone.client.report;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import tv.dyndns.kishibe.qmaclone.client.Controller;
import tv.dyndns.kishibe.qmaclone.client.Service;
import tv.dyndns.kishibe.qmaclone.client.UserData;
import tv.dyndns.kishibe.qmaclone.client.packet.PacketProblem;
import com.google.common.base.Strings;
import com.google.common.collect.ComparisonChain;
import com.google.common.collect.Ordering;
import com.google.gwt.cell.client.FieldUpdater;
import com.google.gwt.core.client.GWT;
import com.google.gwt.safehtml.client.SafeHtmlTemplates;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.safehtml.shared.SafeUri;
import com.google.gwt.safehtml.shared.UriUtils;
import com.google.gwt.user.cellview.client.CellTable;
import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.user.cellview.client.ColumnSortEvent.ListHandler;
import com.google.gwt.user.cellview.client.RowStyles;
import com.google.gwt.user.cellview.client.TextColumn;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.view.client.ListDataProvider;
import com.google.gwt.view.client.ProvidesKey;
public class CellTableProblem extends CellTable<PacketProblem> {
private static final long RESOLVED_CHECK_PERIOD = 7L * 24 * 60 * 60 * 1000;
private static final long INDICATION_PERIOD = 30L * 24 * 60 * 60 * 1000;
private static final Logger logger = Logger.getLogger(CellTableProblem.class.getName());
private static final String STYLE_ACCURACY_RATE = "accuracyRate";
private static final String STYLE_NEW_PROBLEM = "newProblem";
private final ListDataProvider<PacketProblem> dataProvider = new ListDataProvider<PacketProblem>();
public interface CellTableProblemTemplates extends SafeHtmlTemplates {
@Template("<div class='gridFontSmall'>{0}</div>")
SafeHtml smallFont(String text);
@Template("")
SafeHtml empty();
@Template("<img src=\"{0}\" title=\"{1}\">")
SafeHtml indication(SafeUri fileName, String title);
}
private static final CellTableProblemTemplates TEMPLATES = GWT
.create(CellTableProblemTemplates.class);
private static final SafeHtml SAFE_HTML_EXISTS = TEMPLATES.smallFont("有");
private final ListHandler<PacketProblem> columnSortHandler;
public CellTableProblem(List<PacketProblem> problems, final boolean regist, int pageSize) {
super(pageSize, CellTableProblemResources.Factory.get(), new ProvidesKey<PacketProblem>() {
@Override
public Object getKey(PacketProblem item) {
return item.id;
}
});
dataProvider.setList(problems);
dataProvider.addDataDisplay(this);
columnSortHandler = new ListHandler<PacketProblem>(dataProvider.getList());
addColumnSortHandler(columnSortHandler);
// 問題番号
addColumn("問題番号", new Comparator<PacketProblem>() {
@Override
public int compare(PacketProblem o1, PacketProblem o2) {
return o1.id - o2.id;
}
}, new LinkColumn<PacketProblem>() {
@Override
public String getValue(PacketProblem object) {
return object.testing ? "(出題中)" : Integer.toString(object.id);
}
}, new FieldUpdater<PacketProblem, String>() {
@Override
public void update(int index, PacketProblem object, String value) {
if (object.testing) {
return;
}
Controller.getInstance().showCreationProblem(object.id);
}
});
// ジャンル
addColumn("ジャンル", new Comparator<PacketProblem>() {
@Override
public int compare(PacketProblem o1, PacketProblem o2) {
return o1.genre.compareTo(o2.genre);
}
}, new SafeHtmlColumn<PacketProblem>() {
@Override
public SafeHtml getValue(PacketProblem object) {
return TEMPLATES.smallFont(object.genre.toString());
}
}, null);
// 出題形式
addColumn("出題形式", new Comparator<PacketProblem>() {
@Override
public int compare(PacketProblem o1, PacketProblem o2) {
return o1.type.compareTo(o2.type);
}
}, new SafeHtmlColumn<PacketProblem>() {
@Override
public SafeHtml getValue(PacketProblem object) {
return TEMPLATES.smallFont(object.type.toString());
}
}, null);
// ランダムフラグ
addColumn("ランダム", new Comparator<PacketProblem>() {
@Override
public int compare(PacketProblem o1, PacketProblem o2) {
return o1.randomFlag.compareTo(o2.randomFlag);
}
}, new TextColumn<PacketProblem>() {
@Override
public String getValue(PacketProblem object) {
return Integer.toString(object.randomFlag.getIndex());
}
}, null);
// 問題文
addColumn("問題文", new Comparator<PacketProblem>() {
@Override
public int compare(PacketProblem o1, PacketProblem o2) {
return o1.sentence.compareTo(o2.sentence);
}
}, new SafeHtmlColumn<PacketProblem>() {
@Override
public SafeHtml getValue(PacketProblem object) {
return TEMPLATES.smallFont(object.getProblemReportSentence());
}
}, null);
// 問題ノート
addColumn("問題ノート", new Comparator<PacketProblem>() {
@Override
public int compare(PacketProblem o1, PacketProblem o2) {
return o1.note.compareTo(o2.note);
}
}, new SafeHtmlColumn<PacketProblem>() {
@Override
public SafeHtml getValue(PacketProblem object) {
if (Strings.isNullOrEmpty(object.note)) {
return null;
}
return TEMPLATES.smallFont(object.note);
}
}, null);
// 作問者
addColumn("作問者", new Comparator<PacketProblem>() {
@Override
public int compare(PacketProblem o1, PacketProblem o2) {
return o1.creator.compareTo(o2.creator);
}
}, new SafeHtmlColumn<PacketProblem>() {
@Override
public SafeHtml getValue(PacketProblem object) {
if (Strings.isNullOrEmpty(object.creator)) {
return null;
}
return TEMPLATES.smallFont(object.creator);
}
}, null);
// 画像
addColumn("画像", new Comparator<PacketProblem>() {
@Override
public int compare(PacketProblem o1, PacketProblem o2) {
return -((Boolean) o1.hasImage()).compareTo(o2.hasImage());
}
}, new SafeHtmlColumn<PacketProblem>() {
@Override
public SafeHtml getValue(PacketProblem object) {
if (object.hasImage()) {
return SAFE_HTML_EXISTS;
} else {
return null;
}
}
}, null);
// 動画
addColumn("動画", new Comparator<PacketProblem>() {
@Override
public int compare(PacketProblem o1, PacketProblem o2) {
return -((Boolean) o1.hasMovie()).compareTo(o2.hasMovie());
}
}, new SafeHtmlColumn<PacketProblem>() {
@Override
public SafeHtml getValue(PacketProblem object) {
if (object.hasMovie()) {
return SAFE_HTML_EXISTS;
} else {
return null;
}
}
}, null);
// 正解数
addColumn("正解数", new Comparator<PacketProblem>() {
@Override
public int compare(PacketProblem o1, PacketProblem o2) {
return o1.good - o2.good;
}
}, new TextColumn<PacketProblem>() {
@Override
public String getValue(PacketProblem object) {
return Integer.toString(object.good);
}
}, null);
// 誤答数
addColumn("誤答数", new Comparator<PacketProblem>() {
@Override
public int compare(PacketProblem o1, PacketProblem o2) {
return o1.bad - o2.bad;
}
}, new TextColumn<PacketProblem>() {
@Override
public String getValue(PacketProblem object) {
return Integer.toString(object.bad);
}
}, null);
// 回答数
addColumn("回答数", new Comparator<PacketProblem>() {
@Override
public int compare(PacketProblem o1, PacketProblem o2) {
return (o1.good + o1.bad) - (o2.good + o2.bad);
}
}, new TextColumn<PacketProblem>() {
@Override
public String getValue(PacketProblem object) {
return Integer.toString(object.good + object.bad);
}
}, null);
// 正答率
addColumn("正答率", new Comparator<PacketProblem>() {
public int compare(PacketProblem o1, PacketProblem o2) {
return o1.getAccuracyRate() - o2.getAccuracyRate();
}
}, new TextColumn<PacketProblem>() {
@Override
public String getValue(PacketProblem object) {
int ratio = object.getAccuracyRate();
if (ratio == -1) {
return "-%";
} else {
return ratio + "%";
}
}
}, null);
// // +1ボタン
// addColumn("+1", null, new SafeHtmlColumn<PacketProblem>() {
// @Override
// public SafeHtml getValue(PacketProblem object) {
// return PlusOne.getButton(object.id, false);
// }
// }, null);
// 良問
addColumn("良問", new Comparator<PacketProblem>() {
@Override
public int compare(PacketProblem o1, PacketProblem o2) {
return o1.voteGood - o2.voteGood;
}
}, new GwtButtonColumn<PacketProblem>() {
@Override
public String getValue(PacketProblem object) {
return Integer.toString(object.voteGood);
}
}, new FieldUpdater<PacketProblem, String>() {
@Override
public void update(int index, final PacketProblem object, String value) {
new ProblemFeedbackDialogBox(dataProvider, object).center();
}
});
// 指摘
addColumn("指摘", new Comparator<PacketProblem>() {
public int compare(PacketProblem o1, PacketProblem o2) {
return ComparisonChain
.start()
.compare(o1.indication, o2.indication, Ordering.natural().nullsLast())
.compare(o1.indicationResolved, o2.indicationResolved,
Ordering.natural().nullsLast()).result();
}
}, new SafeHtmlColumn<PacketProblem>() {
@Override
public SafeHtml getValue(PacketProblem object) {
if (object.indication != null) {
if (object.indication.getTime() + INDICATION_PERIOD < System
.currentTimeMillis()) {
return TEMPLATES.indication(UriUtils.fromString("notification_error.png"),
"指摘から30日以上経過しています。\n問題作成者以外の方も書き換えることができます。");
} else {
return TEMPLATES.indication(
UriUtils.fromString("notification_warning.png"),
"他の問題作成者により指摘がありました。\n速やかに内容を確認してください。");
}
} else if (object.indicationResolved != null) {
if (System.currentTimeMillis() < object.indicationResolved.getTime()
+ RESOLVED_CHECK_PERIOD) {
return TEMPLATES.indication(
UriUtils.fromString("notification_resolved.png"),
"問題が修正されました。\n指摘した方は内容を確認して下さい。");
}
}
return TEMPLATES.empty();
}
}, null);
// // 悪問
// addColumn("悪問", new Comparator<PacketProblem>() {
// @Override
// public int compare(PacketProblem o1, PacketProblem o2) {
// return o1.voteBad - o2.voteBad;
// }
// }, new GwtButtonColumn<PacketProblem>() {
// @Override
// public String getValue(PacketProblem object) {
// return Integer.toString(object.voteBad);
// }
// }, new FieldUpdater<PacketProblem, String>() {
// @Override
// public void update(int index, final PacketProblem object, String value) {
// String feedback = Window.prompt("投票理由をお書き下さい", "");
// if (Strings.isNullOrEmpty(feedback)) {
// return;
// }
//
// int userCode = UserData.get().getUserCode();
// String playerName = UserData.get().getPlayerName();
// Service.Util.getInstance().voteToProblem(userCode, object.id, false, feedback,
// playerName, new AsyncCallback<Void>() {
// @Override
// public void onSuccess(Void result) {
// ++object.voteBad;
// dataProvider.refresh();
// }
//
// @Override
// public void onFailure(Throwable caught) {
// logger.log(Level.WARNING, "問題への投票に失敗しました", caught);
// }
// });
// }
// });
// 問題登録・解除
addColumn("登録", null, new LinkColumn<PacketProblem>() {
@Override
public String getValue(PacketProblem object) {
return regist ? "追加" : "削除";
}
}, new FieldUpdater<PacketProblem, String>() {
public void update(int index, PacketProblem object, String value) {
final int problemId = object.id;
final int userCode = UserData.get().getUserCode();
if (regist) {
final List<Integer> problemIds = new ArrayList<Integer>();
problemIds.add(problemId);
Service.Util.getInstance().addProblemIdsToReport(userCode, problemIds,
callbackReport);
} else {
Service.Util.getInstance().removeProblemIDFromReport(userCode, problemId,
callbackReport);
}
}
});
// 各行の表示色設定
final RowStyles<PacketProblem> rowStyles = new RowStyles<PacketProblem>() {
@Override
public String getStyleNames(PacketProblem row, int rowIndex) {
if (row == null) {
return null;
}
if (row.isNew()) {
return STYLE_NEW_PROBLEM;
} else {
return STYLE_ACCURACY_RATE + row.getAccuracyRate();
}
}
};
setRowStyles(rowStyles);
}
private final AsyncCallback<Void> callbackReport = new AsyncCallback<Void>() {
@Override
public void onSuccess(Void result) {
dataProvider.refresh();
}
@Override
public void onFailure(Throwable caught) {
logger.log(Level.WARNING, "問題の追加・削除に失敗しました", caught);
}
};
private <C, S> void addColumn(String header, Comparator<PacketProblem> comparator,
Column<PacketProblem, S> column, FieldUpdater<PacketProblem, S> fieldUpdater) {
if (comparator != null) {
column.setSortable(true);
columnSortHandler.setComparator(column, comparator);
}
if (fieldUpdater != null) {
column.setFieldUpdater(fieldUpdater);
}
addColumn(column, header);
}
}