Sindbad~EG File Manager
package org.dynamicgeometry.scripts;
import sun.reflect.Reflection;
import java.util.ArrayList;
import org.dynamicgeometry.diagrammer.GeometricObject;
import org.dynamicgeometry.diagrammer.Point;
// 11.5.06 made Euclid public, provided Earlier and earlier, put in code to deal with PackagePath so that it should look twice for the class.
// 12.18.06 added ActiveLine
// 12.21.06 added ReturnTypes and getReturnTypes
// 12.24.06 added Purpose
// 12.25.06 added setCommands
/**
* author: Michael Beeson. This code is in the public domain.
*/
class IllegalScriptException extends Exception{
public IllegalScriptException(){}
public IllegalScriptException(String msg) { super(msg);}
}
public class Scripts
{
String Name;
String ReturnType;
String[] ReturnTypes; // for scripts with multiple returns
String[] ParameterNames;
String[] ParameterTypes;
String[] Script;
public String Purpose; // for pedagogic use
public String EuclidReference; // for pedagogic use, e.g. "Book I, Prop. 2"
public int ActiveLine;
private static final String PackagePath = "org.dynamicgeometry.scripts.";
private static Class getScriptClass(String CommandName)
// return the class formed by adding "Script" to ScriptName, finding it using the PackagePath.
{ try{
return Class.forName(CommandName + "Script");
}
catch (ClassNotFoundException e)
{ //System.out.println("Class " + CommandName + "Script not found, probably the package path is wrong.");
// so try it again with no package path
try{
return Class.forName(PackagePath + CommandName + "Script");
}
catch(ClassNotFoundException e2)
{ System.out.println("Senor, you reeeally have a problem with " + CommandName);
}
}
return null;
}
public Scripts(String n, String ret, String[] p, String[] q, String[] s)
{
Name = n;
ReturnType = ret;
ReturnTypes = null;
ParameterNames = p;
ParameterTypes = q;
Script = s;
}
public Scripts(String _Name, String _ReturnType, String[] _ParameterNames, String[] _ParameterTypes, String[] _Script, String[] _ReturnTypes)
{
Name = _Name;
ReturnType = _ReturnType;
ParameterNames = _ParameterNames;
ParameterTypes = _ParameterTypes;
Script = _Script;
ReturnTypes = _ReturnTypes;
}
/**
* @return The name of this script
*/
public static final String[] Euclid = {
"EquilateralTriangle", // Book I, prop. 1
"CopySegment", // Book I, prop. 2
"CopySegmentOntoLine", // Book I, prop. 3
"CopySegmentOntoLine2", // done
"BisectAngle2", // Book I, prop. 9 --uses EquilateralTriangle
"BisectAngle", // continuous solution, using BisectSegment
"BisectSegment", // Book I, prop. 10
"BisectSegment2", // Book I, prop. 10
"ErectPerpendicular", // Book I, prop. 11
"DropPerpendicular", // Book I, prop. 12
"TriangleFromSegments", // Book I, Prop. 22
"ConstructTriangle", // Book I, prop. 22 (alternate)
"CircleFromCenterAndRadius", // not directly in Euclid
"CopyAngleToSegment", // Book I, prop. 23
"ParallelThroughPoint", // Book I, prop. 31
"ParallelogramEqualToTriangle", // Book I, prop. 42. This works only in Euclidean geometry
"ParallelogramOfGivenWidthEqualToTriangle", // Book I, prop. 44
// "ParallelogramEqualToQuadrilateral", // Book I, prop. 45. This requires accessing the points of a quadrilateral,
// and that is not in the specs.
"SquareOnGivenSide", // Book I, prop. 46
"SquareOnGivenSide2", // shorter method
"CutSegmentInGoldenSection", // Book II, prop. 11
//"SquareEqualToConvexPolygon",
"FindCenterOfCircle",
"TangentToCircle",
"CircleFromArc",
"BisectCircumference",
"GivenSegmentAndAngleConstructCircle",
"GivenCircleAndAngleConstructArc",
"FitSegmentInCircle",
"TriangleInCircle",
"TriangleAroundCircle",
"CircleInTriangle",
"CircleAroundTriangle",
"SquareInCircle",
"SquareAroundCircle",
"CircleInSquare",
"CircleAroundSquare",
"ConstructGoldenTriangle",
"PentagonInCircle",
"PentagonAroundCircle",
"CircleInPentagon",
"CircleAroundPentagon",
"HexagonInCircle",
"FifteenGonInCircle",
"DivideSegmentIntoParts",
"SegmentOnLine",
"ThirdProportional",
"FourthProportional",
"MeanProportional",
"SimilarConvexPolygonWithGivenSide"}; // not finished yet
private static final boolean done(String ScriptName)
// return true if it's been implemented
{ return earlier(ScriptName, "FindCenterOfCircle");
}
/**
* @return The name of the script
*/
public String getName()
{
return Name;
}
/**
* @return The return type of the script
*/
public String getReturnType()
{
return ReturnType;
}
/**
* @return The purpose of the script, i.e. its postcondition
*/
public String getPurpose()
{
return Purpose;
}
/**
* @return The variables used to name the points, lines, segments, arcs,
* circles, etc. that are the inputs to this script.
*/
public String[] getParameters()
{
return ParameterNames;
}
/**
* @return The types of the variables used to name the points, lines,
* segments, arcs, circles, etc. that are the inputs to this script.
*/
public String[] getParameterNames()
{
return ParameterNames;
}
/**
* @return The types of the variables used to name the points, lines,
* segments, arcs, circles, etc. that are the inputs to this script.
*/
public String[] getParameterTypes()
{
return ParameterTypes;
}
/**
* @return The Geoscript commands making up the script.
*/
public String[] getScript()
{
return Script;
}
/**
* @return The Geoscript commands making up the script.
*/
public void setScript(String[] newCommands)
{
Script = newCommands;
}
/**
* @param CommandName
* The name of a supported construction.
* @return The Geoscript for the construction named in the parameter. A
* construction "Foo" is supported if class FooScript exists
* extending Scripts.
*/
static public String[] getScript(String CommandName)
throws ClassNotFoundException, InstantiationException,
IllegalAccessException
{
Class C = getScriptClass(CommandName);
Scripts X = (Scripts)C.newInstance();
return X.getScript();
}
static public Scripts getScriptObject(String CommandName)
{
Class C = getScriptClass(CommandName);
Scripts ans;
try{ ans = (Scripts)C.newInstance();}
catch(Exception ex) { ex.printStackTrace(); return null;}
return ans;
}
/**
* @return The return types of a script with multiple returns
*/
static public String[] getReturnTypes(String CommandName)
throws ClassNotFoundException, InstantiationException,
IllegalAccessException
{
Class C = getScriptClass(CommandName);
Scripts X = (Scripts)C.newInstance();
return X.ReturnTypes;
}
/**
* @param CommandName
* The name of a supported construction.
* @return the list of variables used in the script to name the input
* parameters. A construction "Foo" is supported if class FooScript
* exists extending Scripts. Deprecated way to call
* getParameterNames--use that method instead.
*/
static public String[] getParameters(String CommandName)
throws ClassNotFoundException, InstantiationException,
IllegalAccessException
{
Class C = getScriptClass(CommandName);
Scripts X = (Scripts)C.newInstance();
return X.getParameterNames();
}
/**
* @param CommandName
* The name of a supported construction.
* @return the list of variables used in the script to name the input
* parameters. A construction "Foo" is supported if class FooScript
* exists extending Scripts.
*/
static public String[] getParameterNames(String CommandName) throws
ClassNotFoundException, InstantiationException, IllegalAccessException
{
Class C = getScriptClass(CommandName);
Scripts X = (Scripts)C.newInstance();
return X.getParameterNames();
}
/** Get the return type of any command, whether it is primitive or defined by a script.
*/
static public String getReturnType(String CommandName) throws
ClassNotFoundException, InstantiationException, IllegalAccessException
{ String t = primitiveReturnType(CommandName);
if(t != null)
return t;
Class C = getScriptClass(CommandName);
Scripts X = (Scripts)C.newInstance();
return X.ReturnType;
}
/**
* @param CommandName
* The name of a supported construction.
* @return the list of types of the parameters of this command. Example:
* since the Midpoint command takes two Points,
* getParameterTypes("Midpoint") returns {"Point", "Point"}. A
* construction "Foo" is supported if class FooScript exists
* extending Scripts.
*/
static public String[] getParameterTypes(String CommandName)
throws ClassNotFoundException, InstantiationException, IllegalAccessException
{
Class C = getScriptClass(CommandName);
Scripts X = (Scripts)C.newInstance();
return X.getParameterTypes();
}
public static final boolean Earlier(String FirstScript, String SecondScript)
// it's in the specs with a capital E
{ return earlier(FirstScript, SecondScript);
}
public static final boolean earlier(String FirstScript, String SecondScript)
// it's in the specs with a capital E, but Java methods should begin with lowercase, so here it is both ways.
// returns true if FirstScript is a member of Euclid and SecondScript is not listed in Euclid before FirstScript.
// Otherwise, returns false. In particular it returns false if SecondScript is listed in Euclide before FirstScript
// or is not listed at all. It also returns false in the special case when the two inputs are equal.
{ for(String s: Euclid)
{ if(s == FirstScript && s != SecondScript)
return true;
if(s != SecondScript)
return false;
}
return false;
}
// Returns a new instance of the Script
public static Scripts finalScript(String scriptName)
throws ClassNotFoundException, InstantiationException, IllegalAccessException
{
Scripts X = null;
try
{
Class C = getScriptClass(scriptName);
X = (Scripts)C.newInstance();
}
catch(Exception ioe)
{
System.out.println("Class " + scriptName + " not found.");
ioe.printStackTrace();
}
return X;
}
/**
* This provides a unit test for the class Scripts
*/
public static void main(String args[])
{
for (String CommandName : Euclid)
{ if(!done(CommandName))
continue;
try
{
String[] Script = getScript(CommandName);
String[] ParameterNames = getParameterNames(CommandName);
String[] ParameterTypes = getParameterTypes(CommandName);
String ReturnType = getReturnType(CommandName);
System.out.print(ReturnType + " " + CommandName + "(");
if (ParameterNames.length > 0)
{
System.out.print(ParameterTypes[0]);
System.out.print(" " + ParameterNames[0]);
}
int i;
for (i = 1; i < ParameterNames.length; ++i)
{
System.out.print("," + ParameterTypes[i]);
System.out.print(" " + ParameterNames[i]);
}
System.out.println(")");
for (String s : Script)
System.out.println(s);
}
catch (Exception e)
{ System.out.println( e.getMessage());
// System.out.println("Oops! " + CommandName + " hasn't been programmed yet.");
}
}
}
/**
* Return true if the given command is primitive, false otherwise
*/
public static boolean isPrimitiveCommand( String cmdName ) {
if( cmdName.equalsIgnoreCase( "line" )) return true;
else if( cmdName.equalsIgnoreCase( "segment" )) return true;
else if( cmdName.equalsIgnoreCase( "circle" )) return true;
else if( cmdName.equalsIgnoreCase( "ray" )) return true;
else if( cmdName.equalsIgnoreCase( "arc" )) return true;
else if( cmdName.equalsIgnoreCase( "triangle" )) return true;
else if( cmdName.equalsIgnoreCase( "quadrilateral" )) return true;
else if( cmdName.equalsIgnoreCase( "vertex" )) return true;
else if( cmdName.equalsIgnoreCase( "intersectLines" )) return true;
else if( cmdName.equalsIgnoreCase( "intersectLineCircle1" )) return true;
else if( cmdName.equalsIgnoreCase( "intersectLineCircle2" )) return true;
else if( cmdName.equalsIgnoreCase( "intersectLineCircle3" )) return true;
else if( cmdName.equalsIgnoreCase( "intersectCircles1" )) return true;
else if( cmdName.equalsIgnoreCase( "intersectCircles2" )) return true;
else if( cmdName.equalsIgnoreCase( "extend" )) return true;
return false;
}
/**
* Return the return type of a primitive command.
* Returns null if cmdName is not a primitive command.
*/
private static String primitiveReturnType(String cmdName)
{
if( cmdName.equalsIgnoreCase( "line" )) return "Line";
else if( cmdName.equalsIgnoreCase( "segment" )) return "Segment";
else if( cmdName.equalsIgnoreCase( "circle" )) return "Circle";
else if( cmdName.equalsIgnoreCase( "ray" )) return "Ray";
else if( cmdName.equalsIgnoreCase( "arc" )) return "Arc";
else if( cmdName.equalsIgnoreCase( "triangle" )) return "Triangle";
else if( cmdName.equalsIgnoreCase( "quadrilateral" )) return "Quadrilateral";
else if( cmdName.equalsIgnoreCase( "vertex" )) return "Point";
else if( cmdName.equalsIgnoreCase( "intersectLines" )) return "Point";
else if( cmdName.equalsIgnoreCase( "intersectLineCircle1" )) return "Point";
else if( cmdName.equalsIgnoreCase( "intersectLineCircle2" )) return "Point";
else if( cmdName.equalsIgnoreCase( "intersectLineCircle3" )) return "Point";
else if( cmdName.equalsIgnoreCase( "intersectCircles1" )) return "Point";
else if( cmdName.equalsIgnoreCase( "intersectCircles2" )) return "Point";
else if( cmdName.equalsIgnoreCase( "extend" )) return "Point";
return null; // command is not primitive
}
/** Produces initial data for the script commandName.
* The members of the returned ArrayList must match the parameters
* of commandName in label and type. They must also satisfy the
* preconditions (hypotheses) of commandName, and they should ideally
* look nice on the screen as well, in particular allowing the whole
* construction to complete visibly in the applet window.
*/
public ArrayList<GeometricObject> startData(int width, int height)
throws IllegalScriptException
{
int minDistance = 50;
int n = ParameterTypes.length;
if(n != ParameterNames.length)
throw(new IllegalScriptException("Parameter names and types have different length in " + Name));
ArrayList<GeometricObject> ans = new ArrayList(n);
// prepare the arguments for the construction
for(int i = 0; i < n; ++i)
{
GeometricObject nextarg = null;
try {
Class cls = Class.forName("org.dynamicgeometry.diagrammer." + ParameterTypes[i]);
nextarg = (GeometricObject) cls.newInstance();
if(nextarg == null)
throw new IllegalScriptException("Illegal parameter type in script " + Name);
ans.add(nextarg);
}
catch(Exception ex)
{ ex.printStackTrace();
}
nextarg.setVisible(true);
nextarg.setIsInput(0); // strangely, 0 means it IS in an input.
nextarg.setLabelFromString(ParameterNames[i]);
nextarg.setSelected(true);
if(ParameterTypes[i].equals("Point"))
{
double dMin = 0.0;
double d;
boolean ok = false;
do
{ d = 2* Math.max(width,height);
ok = true;
double margin = 0.35;
double x = Math.random()*(width - 2*margin *width) + margin*width;
double y = Math.random()*(height - 2*margin *height) + margin*height;
boolean firstFlag = false;
for(int j = 0;j<i;j++)
{ if(!ParameterTypes[j].equals("Point"))
continue;
d = Math.hypot(x- ((Point) ans.get(j)).getX(), y - ((Point) ans.get(j)).getY());
if(d < minDistance)
{ // this x and y won't do
ok = false;
break;
}
}
if(ok)
{ // this x and y are OK
((Point) ans.get(i)).setX((int)x);
((Point) ans.get(i)).setY((int)y);
}
} while(!ok);
}
}
return ans;
}
}
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists