ホームに戻る
 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();
  }
}

inserted by FC2 system