Logo Search packages:      
Sourcecode: jclic version File versions  Download package

Clic3.java

/*
 * File    : Clic3.java
 * Created : 30-oct-2000 20:45
 * By      : fbusquets
 *
 * JClic - Authoring and playing system for educational activities
 *
 * Copyright (C) 2000 - 2005 Francesc Busquets & Departament
 * d'Educacio de la Generalitat de Catalunya
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details (see the LICENSE file).
 */

package edu.xtec.jclic.clic3;

import edu.xtec.jclic.Activity;
import edu.xtec.jclic.bags.ActivityBag;
import edu.xtec.jclic.bags.ActivitySequenceElement;
import edu.xtec.jclic.bags.ActivitySequenceJump;
import edu.xtec.jclic.bags.ConditionalJumpInfo;
import edu.xtec.jclic.bags.JumpInfo;
import edu.xtec.jclic.bags.MediaBagElement;
import edu.xtec.jclic.fileSystem.FileSystem;
import edu.xtec.jclic.fileSystem.PCCFileSystem;
import edu.xtec.jclic.project.JClicProject;
import java.awt.Color;
import java.util.Vector;


/**
 * Constants and miscellaneous functions useful to read Clic 3.0 files and import
 * it into JClic projects.
 * @author Francesc Busquets (fbusquets@xtec.net)
 * @version 1.0
 */
00044 public abstract class Clic3 {
    
    // CONSTANTS OF CLIC 3.0
    //
    public static final int CLICVER = 120;
    public static final String CLICSTR = "CLIC120";
    
    protected static final String BLANK="";
    protected static final String COMMA=",";
    
    protected static final Color DEFAULT_BACK_COLOR=new Color(0xC0, 0xC0, 0xC0);
    protected static final Color DEFAULT_COLOR_USUARI_0=Color.blue;
    protected static final Color DEFAULT_COLOR_USUARI_1=DEFAULT_BACK_COLOR;
    protected static final Color DEFAULT_COLOR_ERROR_0=Color.white;
    protected static final Color DEFAULT_COLOR_ERROR_1=Color.red;
    protected static final TripleColor DEFAULT_TRIPLE_COLOR=new TripleColor(Color.white, Color.black, Color.gray, false);
    
    //protected static final Font DEFAULT_FONT = new Font("Helvetica", 0, 12);
    
    //Extensions
    // better a hastable?
    public static final String extName[]={"*.BMP", "*.GIF", "*.TXT", 
    "*.PUZ", "*.SOP", "*.ASS", "*.CRW", "*.TXA",
    "*.PAC", "*.PCC", "*.P?C", 
    "*.HLP", "*.MVB", "*.EXE", "*.MID", "*.WAV", "*.JPG", "*.PNG", BLANK};
    public static final int EXT_BMP=0, EXT_GIF=1, EXT_TXT=2, 
    EXT_PUZ=3, EXT_SOP=4, EXT_ASS=5, EXT_CRW=6, EXT_TXA=7, 
    EXT_PAC=8, EXT_PCC=9, EXT_PCG=10, 
    EXT_HLP=11, EXT_MVB=12, EXT_EXE=13, EXT_MID=14, EXT_WAV=15, EXT_JPG=16, EXT_PNG=17,
    UNKNOWN_EXT=18, NO_EXT=-1;
    
    //public static final int MAX_MESS_LEN = 200;
    //public static final int MAX_FULL_FILENAME = 100, MAX_DESC = 200;
    protected static final int MAXCW = 20, MAXCH = 20;
    protected static final int MAXGW = 21, MAXGH = 10;
    
    // PlayModes
    public static final int NONE=0, PUZZLE=1, SOPA=2, ASSOCIA=3, CREUATS=4, TEXTACT=5;
    
    //PuzModes
    public static final int INTERC=0, FORAT=1, DOBLE=2, MEMORY=3;
    
    //AssModes
    public static final int NORMAL=0, ESPECIAL=1, EXPLORA=2, INFO=3,
    IDENTIFICA=4, ESCRIU=5;
    
    //TxActModes
    public static final int FORATS=0, COMPTEXT=1, IDLLETRES=2, IDPARAULES=3,
    BPARAULES=4, BPARAGRAFS=5;
    
    //GraPositions
    public static final int AB=0, BA=1, AUB=2, BUA=3;
    
    public static final int DEF_TXTCASW = 140, DEF_TXTCASH = 100, DEF_CICLES = 30;
    public static final int NEGRE = 160;
    public static final char COMODI = '*';
    public static final char SEPARADOR = ';';
    public static final byte ENDDESC_BYTE = -121; //0x87
    //public static final char ENDDESC = '\u0000';
    public static final char ENDDESC = '\u2021';
    public static final char CHBLOCK = '\u008E';
    public static final char CHINC = '\u008F';
    public static final char SEP = '\u0090';
    
    
    /*
     * Constants used in Clic 3.0
     * not needed in JClic
     *
     * WM_USERIDS
     * WM_PLAYW=WM_USER, WM_HELPW, WM_CBNEXT, WM_CBPREV, WM_CBGETFOCUS,
     * WM_NOUINTENT};
     *    
     * enum USERMESSAGES {PLAYW_RESIZE, PLAYW_ENDGAME, PLAYW_INTENT,
     * PLAYW_ENCERTS, PLAYW_WAITMEIN,
     * PLAYW_SETMESS, PLAYW_SETMESSPLAY, HELPW_ITEMSEL, HELPW_MOUSE};
     *
     * public static final int WDIGIT = 13, HDIGIT = 23;
     * public static final int MARGE = 6;
     * public static final int BOTOW = 63, BOTOW2 = 30, BOTOH = 39;
     *
     * public static final int DIGITSW = 39, DIGITSH = 23;
     *
     * public static final int CTRLH = 39;   // era 41
     * public static final int CTRLW = 450;
     *
     * public static final int CLW = (3*MARGE+BOTOW+CTRLW);
     * public static final int CLH = (6*BOTOH+7*MARGE);
     *
     * public static final int PLWW = CTRLW;
     * public static final int PLWH = (CLH-CTRLH-3*MARGE);
     *
     * public static final int LMAXRFTXT = 512;
     *
     * String resources (to be revised!)
     * public static final int IDS_ERRFMT = 1;
     *
     * Common variables
     *
     * public static int passos, passos0;
     * public static int gAjVis, encertsNow;
     * public static boolean quick, quick0, arrossega, arrossega0, sonor0,
     * autoCursor, cursorGran;
     * public static boolean doReportFile, drf0, exitDirect;
     * public static boolean helponhelp, menus;
     * public static boolean allowNewUsr, allowNewGrp, showUserReports;
     * public static int caretVis, caretX, caretY, caretW, caretH, autoCursorDelay;
     * public static final Font logFont1 = new Font("Arial", 0, 12);
     * public static int gruixfil;
     *
     * public static String clicPath = "";
     * public static String ediText = "";
     * public static String ediGraf = "";
     * public static String originalPath = "";
     * public static String playerId = "";
     * public static String iniFile = "";
     * public static String dbFile = "";
     * public static String originalDbFile = "";
     * public static String fileName0 = "";
     *
     * extern char cdUnit;
     * public static String lastExt = "   ";
     */    
    
    public static int getExt(String fileName){
        int begExt;
        String ext;
        int i;
        
        //lastExt=BLANK;
        if(fileName==null || fileName.length()==0)
            return UNKNOWN_EXT;
        
        if((begExt=fileName.indexOf(' '))<0)
            begExt=fileName.length()-1;
        
        for(;begExt>0; begExt--)
            if(fileName.charAt(begExt)=='.')
                break;
        
        if(begExt==0 || fileName.length()-begExt<4)
            return UNKNOWN_EXT;
        
        ext = "*" + fileName.substring(begExt, begExt+4).toUpperCase();
        for(i=0; i<UNKNOWN_EXT; i++)
            if(ext.equals(extName[i]))
                break;
        
        //lastExt=ext.substring(2,4);        
        if(i==EXT_JPG || i==EXT_PNG)
            i=EXT_GIF;
        
        return i;
    }
    
    public static boolean isClic3Extension(int ext){
        
        return ext==EXT_PUZ || ext==EXT_ASS || ext==EXT_SOP ||
               ext==EXT_CRW || ext==EXT_TXA;
    }
    
    public static int parseIntX(String s){
        return parseIntX(s, 10);
    }
    
    public static int parseIntX(String s, int radix){
        int v;
        try {
            v=Integer.parseInt(s, radix);
        }
        catch(NumberFormatException e){
            v=0;
        }
        return v;
    }
    
    protected static int correctColor(int color){
        return (color & 0xFF)<<16 | (color & 0xFF00) | (color & 0xFF0000)>>16;
    }
    
    private static final String[] strArray={"FFFFFF", "000000", "808080", "C0C0C0", 
                                            "0000FF", "00FF00", "FF0000"};
    private static final Color[] colorArray={Color.white, Color.black, Color.gray, DEFAULT_BACK_COLOR, 
                                             Color.red, Color.green, Color.blue};
    protected static Color strToColor(String st){
        if(st==null)
            return Color.black;
        if(st.length()>6)
            st=st.substring(st.length()-6);
        for(int i=0; i<strArray.length; i++)
            if(st.equals(strArray[i]))
                return colorArray[i];
        
        return new Color(correctColor(parseIntX(st, 16)));
    }
    
    
    public static boolean copyArray(String[] dest, int indest, String[] source, 
                                    int insource, int e, boolean upper) {
        int i, d, s;
        
        for(i=0, d=indest, s=insource; i<e; i++, d++, s++) {
            //if(dest[d]!=null) delete dest[d];
            //if(source[s]==null || (dest[d]=new String(source[s]))==null) break;
            if((dest[d]=source[s])==null)
                break;
            if(upper)
                dest[d].toUpperCase();
        }
        return (i==e);
    }
    
    public static void readPccFile(JClicProject project) throws Exception {
        String name;
        byte [] bytes;
        MediaBagElement mbe;
        int i, j;
        
        if(!(project.getFileSystem() instanceof PCCFileSystem))
            throw new Exception("FileSystem is not PCCFileSystem!");
        
        PCCFileSystem pccfs=(PCCFileSystem)project.getFileSystem();
        
        //if(!pccfs.loaded) return;
        for(i=0; i<pccfs.numFiles; i++){
            name=pccfs.getEntryName(i);
            
            switch(getExt(name)){
                case EXT_PAC:
                    addPacToSequence(project, name);
                    break;
                    
                case EXT_ASS:
                case EXT_PUZ:
                case EXT_SOP:
                case EXT_CRW:
                case EXT_TXA:
                    addActivityToBag(project, name/*, pccfs*/);
                    break;
                    
                default:
                    //do nothing;
            }
        }
    }
    
    private static int gcCounter=0;
    public static void addActivityToBag(JClicProject project, String name) throws Exception {
        
        ActivityBag ab=project.activityBag;
        
        String normalizedName=FileSystem.stdFn(name);
        
        if(ab.getElementByName(normalizedName)!=null)
            return;
        
        Clic3Activity c3a=new Clic3Activity(project);
        try{
            c3a.load(normalizedName, project.getFileSystem().getBytes(normalizedName));
        } catch(Exception e){
            System.err.println("Error loading " + normalizedName + "\n"+e);
            throw e;
        }
        
        switch(c3a.actMode){
            case ASSOCIA:
                switch(c3a.puzMode){
                    case INFO:
                        c3a.className="edu.xtec.jclic.activities.panels.InformationScreen";
                        break;
                    case NORMAL:
                        c3a.className="edu.xtec.jclic.activities.associations.SimpleAssociation";
                        break;
                    case ESPECIAL:
                        c3a.className="edu.xtec.jclic.activities.associations.ComplexAssociation";
                        break;
                    case IDENTIFICA:
                        c3a.className="edu.xtec.jclic.activities.panels.Identify";
                        break;
                    case EXPLORA:
                        c3a.className="edu.xtec.jclic.activities.panels.Explore";
                        break;
                    case ESCRIU:
                        c3a.className="edu.xtec.jclic.activities.text.WrittenAnswer";
                        break;
                }
                break;
                
            case PUZZLE:
                switch(c3a.puzMode){
                    case INTERC:
                        c3a.className="edu.xtec.jclic.activities.puzzles.ExchangePuzzle";
                        break;
                    case DOBLE:
                        c3a.className="edu.xtec.jclic.activities.puzzles.DoublePuzzle";
                        break;
                    case MEMORY:
                        c3a.className="edu.xtec.jclic.activities.memory.MemoryGame";
                        break;
                    case FORAT:
                        c3a.className="edu.xtec.jclic.activities.puzzles.HolePuzzle";
                        break;
                }
                break;
                
            case SOPA:
                c3a.className="edu.xtec.jclic.activities.textGrid.WordSearch";
                break;
                
            case CREUATS:
                c3a.className="edu.xtec.jclic.activities.textGrid.CrossWord";
                break;
                
            case TEXTACT:
                switch(c3a.puzMode){
                    case FORATS:
                        c3a.className="edu.xtec.jclic.activities.text.FillInBlanks";
                        break;
                    case COMPTEXT:
                        c3a.className="edu.xtec.jclic.activities.text.Complete";
                        break;
                    case IDLLETRES:
                    case IDPARAULES:
                        c3a.className="edu.xtec.jclic.activities.text.Identify";
                        break;
                    case BPARAULES:
                    case BPARAGRAFS:
                        c3a.className="edu.xtec.jclic.activities.text.Order";
                        break;
                }
                break;
                
            default:
                throw new IllegalArgumentException("Unknown Clic3 activity!");
        }
        
        // WARNING:
        
        ab.addActivity(Activity.getActivity(c3a, project));
        // clear memory
        project.mediaBag.clearData();
        // force a gc every 50 activities
        if((++gcCounter%50)==0)
            System.gc();
    }
    
    public static void addPacToSequence(JClicProject project, String name) throws Exception {
        
        String normalizedName=FileSystem.stdFn(name);
        
        if(project.activitySequence.getElementByTag(normalizedName, false)!=null)
            return;
        
        FileSystem fs=project.getFileSystem();
        
        Clic3Pac c3p=new Clic3Pac();
        
        try{
            c3p.load(normalizedName, fs.getBytes(normalizedName));
        } catch(Exception e){
            System.err.println("Error loading " + normalizedName + "\n"+e);
            throw e;
        }
        
        for(int i=0; i<c3p.nActs; i++){
            ActivitySequenceElement ase=new ActivitySequenceElement(c3p.acts[i], 
               c3p.lapToPass, 
               c3p.noPassButtons 
               ? ActivitySequenceElement.NAV_NONE 
               : ActivitySequenceElement.NAV_BOTH);
            if(i==0){
                ase.backJump=new ActivitySequenceJump(JumpInfo.STOP);
                //if(as.getCurrentActNum()<0)
                //    as.setCurrentAct(as.size());
                ase.setTag(normalizedName);
                ase.setDescription(c3p.fileDesc!=null && c3p.fileDesc.length()>0 ? c3p.fileDesc : null);
            }
            if(i==c3p.nActs-1){
                ActivitySequenceJump asj=new ActivitySequenceJump(JumpInfo.STOP);
                if(c3p.def==true && c3p.chDef!=null && getExt(c3p.chDef)==EXT_PAC){
                    //s=fs.getRelativePathOf(relativePath+c3p.chDef)+FileSystem.getFileNameOf(c3p.chDef);
                    asj.action=JumpInfo.JUMP;
                    asj.sequence=fs.getCanonicalNameOf(c3p.chDef);
                    if(c3p.sup){
                        //s=fs.getRelativePathOf(relativePath+c3p.chSup)+FileSystem.getFileNameOf(c3p.chSup);
                        asj.setConditionalJump(
                          new ConditionalJumpInfo(JumpInfo.JUMP, 
                                                  fs.getCanonicalNameOf(c3p.chSup), 
                                                  c3p.supP, 
                                                  c3p.supTFlag ? c3p.supT : -1), 
                          true);
                    }
                    if(c3p.inf){
                        //s=fs.getRelativePathOf(relativePath+c3p.chInf)+FileSystem.getFileNameOf(c3p.chInf);
                        asj.setConditionalJump(
                          new ConditionalJumpInfo(JumpInfo.JUMP, 
                                                  fs.getCanonicalNameOf(c3p.chInf), 
                                                  c3p.infP, 
                                                  c3p.infTFlag ? c3p.infT : -1), 
                          false);
                    }
                }
                ase.fwdJump=asj;
            }
            project.activitySequence.add(ase);
        }
    }
    
    public static final String ansiChars=
    "\u20ac\u0081\u201a\u0192\u201e\u2026\u2020\u2021\u02c6\u2030\u0160\u2039\u0152"+
    "\u008d\u008e\u008f\u0090\u2018\u2019\u201c\u201d\u2022\u2013\u2014\u02dc\u2122"+
    "\u0161\u203a\u0153\u009d\u009e\u0178";
    public static final String convertFileChars=
    "e__f______s_c_z__________ts_o_zy_icl_y_s_ca___r_o_23__p__10_423_aaaaaaa"+
    "ceeeeiiiidnooooox0uuuuy_baaaaaaaceeeeiiiionooooo_0uuuuy_y";
    
    // 0x80 is Euro: 20ac
    // bytes used:
    //ENDDESC 0x87 ('\u2021')
    //CHBLOCK 0x8E (not used)
    //CHINC   0x8F (not used)
    //SEP ?   0x90 (not used)
    
    public static String bufferToString(byte[] buffer){
        if(buffer==null || buffer.length==0) return BLANK;
        char[] result=new char[buffer.length];
        int v;
        for(int i=0; i<buffer.length; i++){
            v=buffer[i]&0x00FF;
            if(v<128 || v>=160)
                // warning: direct map from int to char
                result[i]=(char)v;
            //result[i]=(char)(v==45 ? 95 : v);
            else
                result[i]=ansiChars.charAt(v-128);
        }
        return new String(result);
    }
    
    public static String[] dataToArray(byte[] data) {
        Vector v=new Vector();
        int i, j, k, l, l2;
        byte[] buffer;
        String strBuff;
        String[] array;
        int nLines=0;
        
        l=data.length;
        for(i=0, j=0; i<l;){
            for(; j<l; j++) if(data[j]==0x0D || data[j]==0x0A) break;
            l2=j-i;
            if(l2>0){
                buffer = new byte[l2];
                for(k=0;k<l2;k++) buffer[k]=data[i+k];
                v.add(bufferToString(buffer));
                //v.add(new String(buffer));
                
                //try{
                //    v.add(new String(buffer, "Cp1252"));
                //} catch(Exception ex){
                //    v.add(new String(buffer));
                //}
            }
            else v.add(BLANK);
            nLines++;
            if(j<l && data[++j]==0x0A) j++;
            i=j;
        }
        
        if(nLines>0){
            array=new String[nLines];
            try {
                array=(String[])v.toArray(array);
            }
            catch(ArrayStoreException e){
                array=null;
            }
        }
        else array=null;
        
        return array;
    }
    
    //public static final String validFileChars=".:-_!~\\0123456789abcdefghijklmnopqrstuvwxyz";
    public static final String validFileChars=".:\\_!~0123456789abcdefghijklmnopqrstuvwxyz";
    public static String validFileName(String name, boolean strict, boolean remember){
        if(name==null)
            return null;
        StringBuffer sb=new StringBuffer();
        for(int i=0; i<name.length(); i++){
            char ch=name.charAt(i);
            if(validFileChars.indexOf(ch, strict ? 3 : 0)<0){
                if(ch>='A' && ch<='Z')
                    ch=Character.toLowerCase(ch);
                else if(ch=='/')
                    ch='\\';
                else{
                    int k=ansiChars.indexOf(ch);
                    if(k>=0)
                        ch=convertFileChars.charAt(k);
                    else
                        ch='_';
                }
            }
            sb.append(ch);
        }
        String result=sb.substring(0);
        if(remember && !result.equals(name)){
            FileSystem.altFileNames.put(result, name);
        }
        return result;
    }
    
    public static String validFileName(String name){
        return validFileName(name, false, true);
    }
    
    
    public static final String pacNameToLowerCase(String s){
        String result=s;
        if(s!=null){
            String l=s.toLowerCase();
            if(l.endsWith(".pac")||l.endsWith(".pcc"))
                result=l;
        }
        return result;
    }
}


Generated by  Doxygen 1.6.0   Back to index