ホームに戻る
TopCoder プラグインの作り方
0、はじめに
プラグインの作り方を記録しておきます。
やったこと
問題のクラス名、メソッド名を含めたテンプレート作成
エディットの色、サイズ、フォントの設定
アンドゥとリドゥ、オートインデントの実装
IDE と連動するとかの仕組みは調べてないのでわかりません。
1、使いかた
アリーナから「Options」→「Editor」→「Add」
Name:自由に決める
EntryPoint:Main (メソッド名を指定)
ClassPath:パッケージの jar ファイルを指定
問題を選択し、
「Choose your editor」でプラグインを選択
2、動作の確認
コード中にファイルへの書き出しコードを埋め込めば、
どのメソッドがどの順で使用されているかわかります。
まず、ログイン時に設定したメソッドが呼ばれます。
問題を開くと以下が順に呼ばれます。
getEditorPanel
setProblemComponent
setSource
「save」、「compile」、言語を変えると以下が呼ばれます。
getSource
ただし、言語を変えた場合はコードが保存されません。
実際には String を受け取ったり送ったりするだけです。
3、ソース
/*
以下のサイトから ContestApplet.jar を取得します。
解凍して Main.java のディレクトリに com 以下を置いておきます。
(解凍は拡張子を jar から zip に変えればできます。)
http://www.topcoder.com/contest/classes/ContestApplet.jar
コンパイルは
javac Main.java
パッケージ化は
jar cvf Main.jar *.class
次のようなコメントが出たら成功です。
マニフェストが追加されました
Language.classを追加中です(入=536)(出=266)(50%収縮されました)
Main$1.classを追加中です(入=358)(出=273)(23%収縮されました)
Main$JTextAreaA.classを追加中です(入=2278)(出=1255)(44%収縮されました)
Main.classを追加中です(入=2508)(出=1310)(47%収縮されました)
ProblemComponent.classを追加中です(入=14607)(出=5342)(63%収縮されました)
ProblemComponentModel.classを追加中です(入=1249)(出=519)(58%収縮されました)
Renderer.classを追加中です(入=266)(出=185)(30%収縮されました)
*/
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.text.Document;
import javax.swing.undo.UndoManager;
import javax.swing.event.UndoableEditEvent;
import javax.swing.event.UndoableEditListener;
import java.awt.*;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JScrollPane;
import com.topcoder.client.contestant.ProblemComponentModel;
import com.topcoder.shared.problem.ProblemComponent;
import com.topcoder.shared.language.Language;
import com.topcoder.shared.problem.Renderer;
public class Main {
private class JTextAreaA extends JTextArea implements UndoableEditListener, KeyListener{
protected UndoManager um = new UndoManager();
public JTextAreaA(){
Document doc = getDocument();
doc.addUndoableEditListener(this);
this.setTabSize(2); // タブサイズを設定
addKeyListener(this);
}
public void clearUndoEdit(){
um.discardAllEdits();
}
public void undoableEditHappened(UndoableEditEvent e){
um.addEdit(e.getEdit());
}
public void keyTyped(KeyEvent e){}
// Ctrl+Z で Undo、Ctrl+Y で Redo
public void keyPressed(KeyEvent e) {
switch(e.getKeyCode()){
case KeyEvent.VK_Z:
if(e.isControlDown() && um.canUndo()){
um.undo();
e.consume();
}
break;
case KeyEvent.VK_Y:
if(e.isControlDown() && um.canRedo()){
um.redo();
e.consume();
}
break;
}
}
public void keyReleased(KeyEvent e){
switch (e.getKeyCode()){
// オートインデント
case KeyEvent.VK_ENTER:
int n = this.getCaretPosition();
String s = this.getText();
int index = 0;
for(int i = n - 2; i >= 0; i--){
if(s.charAt(i) == '\n'){
index = i+1;
break;
}
}
int t = 0;
for(int i = index; ; i++){
if(s.charAt(i) == '\t'){
t++;
}
else{
break;
}
}
String tt = "";
for(int i = 0; i <= t; i++){
tt += "\t";
}
this.insert(tt, n);
break;
}
}
}
private JPanel nmPanel;
private JTextAreaA nmEditor;
private ProblemComponent comp;
private String cn;
private String mn;
private String pn[];
public Main(){
// エディットの色の設定
nmEditor = new JTextAreaA();
nmEditor.setForeground(Color.black);
nmEditor.setBackground(Color.white);
// フォントの設定
Font font = new Font("Monospaced",Font.PLAIN,30);
nmEditor.setFont(font);
nmPanel = new JPanel(new BorderLayout());
nmPanel.add(new JScrollPane(nmEditor), BorderLayout.CENTER);
}
public JPanel getEditorPanel() {
return nmPanel;
}
public String getSource() {
return nmEditor.getText();
}
public void setSource(String source){
// テキストが無ければテンプレートを貼り付け
if(source.isEmpty()){
// テンプレートの貼り付け
String a = "class ";
a += cn;
a += ":\n\tdef ";
a += mn;
a += "(self,";
for(int i = 0; i < pn.length; i++){
a += pn[i];
if(i != pn.length - 1){
a += ",";
}
}
a += "):\n\t\t";
nmEditor.setText(a);
}
else{
nmEditor.setText(source);
}
}
// 問題の情報を取得
public void setProblemComponent(ProblemComponentModel component, Language lang, com.topcoder.shared.problem.Renderer renderer){
ProblemComponent comp = component.getComponent();
cn = comp.getClassName();
mn = comp.getMethodName();
pn = comp.getParamNames();
}
}