Operating the timetable generator by JSON_RPC v. 1.1 API

Now you can use simple remote procedure calls to contact generator engine and your timetables. To do it you need a special rpc account created by service administrator. Timetables data exchanged with the timetable engine comply XSD format defined at: http://www.school-timetable.eu/t4s_v10.xsd
Below there are simple examples in Ruby & Java how you can operate the timetable generator by using rpc calls:

Code in Ruby

require 'rubygems'
require 'cgi'
require 'json'
require 'zlib'
require 'stringio'
require 'json_rpc_client'

class RpcClient < JsonRpcClient
    json_rpc_service 'http://www.school-timetable.eu/api'
end

def compress(term)
    zm=StringIO.new
    gz = Zlib::GzipWriter.new(zm)
    gz.write term
    gz.close
    zm.string
end

def decompress(term)
    zr=Zlib::GzipReader.new(StringIO.new(term))
    zr.read
end

def rpctest

# Logs into service. Args: version, user, password
    ses=RpcClient.login 1,'user','password'
    puts "Session:"+ses


# Runs the generator
# Args: session, plan_id, maxtime[min], base[0,1], find_close[0,1], teacher_gaps_mode, room_mode, room_count_only[0,1], optym_mode, optym_from
# a)teacher_gaps_mode:
# -2: Default
# -1: Do not take into account
# 0: Selected teachers - No gaps
# 1: Selected teachers - One a day (one hour)
# 2: Selected teachers - One break a day (several hours)
# b) room_mode
# 0: Priority:min displacements and pref room for st.body,then for a teacher,pref room for a subject">Minimize student bodies displacement
# 1: Priority:min displacements and pref room for a teacher,then for st.body,pref room for a subject">Minimize teachers displacement
# 2: Priority:pref room for a subject,then minimize displacements and pref room for st.body and a teacher">Pref rooms for subj,student body shift
# 3: Priority:pref room for a subject,then min displacements and pref room for a teacher and st.body">Pref rooms for subj,teacher shift
# 4: Priority:pref room and displacements for st.body,then for a teacher,pref room for a subject">Prefered rooms for student bodies
# 5: Priority:pref room and displacements for a teacher,then for st.body,pref room for a subject">Prefered rooms for teachers
# 6: Priority:pref room for a subject,then pref room and min displacements for st.body and a teacher" selected>Pref rooms for subj,student body
# 7: Priority:pref room for a subject,then pref room and min displacements for a teacher and st.body">Pref rooms for subj, teachers
# c) optym_mode
# None
# Fast
# Normal
# Iterative - big step
# Iterative - small step

    str=RpcClient.run ses,697,10,0,1,-2,2,1,1,3
    puts "Timetables:"+str

# Status of generator execution
# Returns: off=>0,:scheduled=>1,:running=>2,:done=>3,stopped=>4,:waiting=>5
    str=RpcClient.status ses,697
    puts "Status:"+str

# Stops execution of generator
    str=RpcClient.stop ses,697
    puts "Status:"+str

# Loads a timetable from XML
    timXML=File.read("tim.xml")
    tim_id=RpcClient.putT4s ses,CGI.escape(compress(timXML))
    puts "ID of Timetable:"+tim_id

# Remove timetable
    str=RpcClient.remove ses,712
    puts "Status:"+str

# Returns list of timetable ids. Example 100, 101, 321,
    str=RpcClient.list ses
    puts "Timetables:"+str

# Gets timetable with results
    tim_xml=RpcClient.getT4s ses,711
    puts "Timetable XML:"+decompress(CGI.unescape(tim_xml))
end



Code in Java


import java.io.IOException;
import java.util.Arrays;
import java.util.ArrayList;
import java.io.FileOutputStream;
import java.io.*;
import java.util.zip.*;
import java.io.ByteArrayOutputStream;
import org.codebistro.jsonrpc.Client;
import org.codebistro.jsonrpc.TransportRegistry;

public class TestClient{

  public void test() throws Exception{
    Client client= new Client(TransportRegistry.i().createSession("http://www.school-timetable.eu/api"));
    Test tester= client.openProxy("",Test.class);
    String session=tester.login(1,"user","password");
    String ls=tester.list(session);
    ls=tester.run(session,734,10,0,1,-2,2,1,1,3);
    ls=tester.status(session,734);
    ls=tester.stop(session,734);
    ls=tester.status(session,734);
    ls=tester.getT4s(session,734);
    byte[] bt=unescape(ls);
    ls=gzipDecompress(bt);

    BufferedReader fin = new BufferedReader(new FileReader("myTimetable.xml"));

    String tim="";
    String s = fin.readLine();
    while (s != null) {
      tim+=s;
      s = fin.readLine();
    }
    bt=gzipCompress(tim);
    tim=escape(bt);
    System.out.println(tim);
    tester.putT4s(session,tim);
  }

  public static void main(String args[]) throws Exception{
    (new TestClient()).test();
  }

  private byte[] gzipCompress(String from) throws Exception {

    InputStream in = new ByteArrayInputStream( from.getBytes() );

    ByteArrayOutputStream bt=new ByteArrayOutputStream();
    BufferedOutputStream out = new BufferedOutputStream(new GZIPOutputStream(bt));

    int c;
    while ((c = in.read()) != -1) out.write(c);
    in.close();
    out.close();

    return bt.toByteArray();
  }

  private String gzipDecompress(byte[] from) throws Exception {
    BufferedReader in = new BufferedReader(new InputStreamReader(
      new GZIPInputStream(new ByteArrayInputStream(from))));
    String tim="";
    String s = in.readLine();
    while (s != null) {
      tim+=s;
      s = in.readLine();
    }

    return tim;
  }

  private String escape(byte[] bt) throws UnsupportedEncodingException{
    String res="";
    /*def CGI::escape(string)
      string.gsub(/([^ a-zA-Z0-9_.-]+)/n) do
        '%' + $1.unpack('H2' * $1.size).join('%').upcase
      end.tr(' ', '+')
    end
    */
    int i=0;
    while (i<bt.length) {
      int code=bt[i];
      if ((code>=97 && code <=122) || (code>=65 && code <=90) || (code>=48 && code <=57) || (code==32) || (code==95) || (code==46) || (code==45)) {
        if (code==32) res+="+";
        else res+=(char)code;
      }
      else {
        res+="%"+String.format("%02X", (byte)code);
      }
      i++;
    }
    return res;
  }

  private byte[] unescape(String str) throws Exception{
    ArrayList al = new ArrayList();

    /*def CGI::unescape(string)
      string.tr('+', ' ').gsub(/((?:%[0-9a-fA-F]{2})+)/n) do
        [$1.delete('%')].pack('H*')
    end*/
    int i=0;
    while (i<str.length()) {
      if (str.charAt(i)=='%') {
        byte code= (byte)Integer.parseInt(str.substring(i+1,i+3),16);
        al.add(code);
        i+=3;
      }
      else {
        if ((byte)(str.charAt(i))==43) {al.add((byte)32);}
        else {al.add((byte)(str.charAt(i) & 0xFF));}
        i++;     }  
    }
    Byte[] b=new Byte[al.size()];
    b=al.toArray(b);
    byte[] c=new byte[b.length];
    for (int j=0; j<b.length; j++) {
      c[j]=b[j];
    }
    return c;
  }

}


public interface Test {
  String login(int version, String user, String password);
  String list(String session);
  String getT4s(String session, int timId);
  String remove(String session, int timId);
  String stop(String session, int timId);
  String status(String session, int timId);
  String run(String session, int timId, int maxTim, int base, int findClose, int teacherGapsMode, int roomMode, int roomCountOnly, int optymMode, int optymFrom);
  int putT4s(String session, String timXML);
}