/******************************************************************************
Copyright (c) Gunnar Gotshalks. All Rights Reserved.

Permission to use, copy, modify, and distribute this software
and its documentation for NON-COMMERCIAL purposes and
without fee is hereby granted. 
*******************************************************************************/
/** 
Objects that test the class Term.
<P>
@author Gunnar Gotshalks
@version 1.0 2008 June 10
*/

import java.util.ListIterator;

public class Term_test {

/*******************************************************************************
GLobal variables for test cases
*******************************************************************************/

//public String s;
Variable a_variable;
int a_coefficient;
Term a_term;

/*******************************************************************************
Test Constructor does all the work.
*******************************************************************************/

public Term_test () {
  make_is_correct();
  insert_into_ln_0();
  insert_into_ln_1_before();
  insert_into_ln_1_after();
  insert_into_ln_n_first();
  insert_into_ln_n_mid();
  insert_into_ln_n_last();
  greater_than();
  terms_variables_are_preserved();
}

/*******************************************************************************
The test cases.
*******************************************************************************/

public void make_is_correct () {
  a_term = new Term();
  if (  a_term.coefficient != 0
   || a_term.variables == null
   || !a_term.variables.isEmpty()) {
  println( "1 -- Error in new term, coefficient is " + a_term.coefficient
     + "; or variables does not exist or is not empty.");
  }
}

public void insert_into_ln_0 () {
  a_term = new Term();
  a_term = new Term();
  a_term.coefficient = 2;
  a_variable = new Variable("a", 1);
  a_term.insert(a_variable);
  if (  a_term.variables == null
     || a_term.variables.size() != 1
     || !((Variable)(a_term.variables.getFirst())).name.equals("a")) {
    println("2 -- Failed to insert a variable in an empty list");
  }
}

public void insert_into_ln_1_before () {
  a_term = new Term();
  a_term.coefficient = 2;
  a_variable = new Variable("e", 5);
  a_term.insert(a_variable);
  a_variable = new Variable("a", 1);
  a_term.insert(a_variable);
  if (  a_term.variables == null
     || a_term.variables.size() != 2
     || !((Variable)(a_term.variables.getFirst())).name.equals("a")) {
    println("3 -- Failed to insert before a single variable"
        + "First name is " + ((Variable)(a_term.variables.getFirst())).name);
  }
}

public void insert_into_ln_1_after () {
  a_term = new Term();
  a_term.coefficient = 2;
  a_variable = new Variable("e", 5);
  a_term.insert(a_variable);
  a_variable = new Variable("g", 7);
  a_term.insert(a_variable);
  if (  a_term.variables == null
     || a_term.variables.size() != 2
     || !((Variable)(a_term.variables.getLast())).name.equals("g")) {
    println("4 -- Failed to insert after a single variable. "
        + "Last name is " + ((Variable)(a_term.variables.getLast())).name);
  }
}

public void insert_into_ln_n_first () {
  a_term = create_length(8);
  a_variable = new Variable("a", 11);
  a_term.insert(a_variable);
  if (  a_term.variables == null
     || a_term.variables.size() != 9
     || !((Variable)(a_term.variables.getFirst())).name.equals("a")) {
    println("5 -- Failed to insert as first in length n list. ");
  }
}

public void insert_into_ln_n_mid () {
  a_term = create_length(8);
  a_variable = new Variable("i", 11);
  a_term.insert(a_variable);
  if (  a_term.variables == null
     || a_term.variables.size() != 9
     || !((Variable)(a_term.variables.get(4))).name.equals("i")) {
    println("6 -- Failed to insert in middle of length n list. ");
  }
}

public void insert_into_ln_n_last () {
  a_term = create_length(8);
  a_variable = new Variable("q", 11);
  a_term.insert(a_variable);
  if (  a_term.variables == null
     || a_term.variables.size() != 9
     || !((Variable)(a_term.variables.getLast())).name.equals("q")) {
    println("7 -- Failed to insert as last in length n list. ");
  }
}

public void greater_than() {
  Term term1, term2;
  term1 = new Term(); term2 = new Term();
  if (term1.greater_than(term2)) {
    println("8 -- failed greater than with no variables in both terms");
  }

  a_variable = new Variable("b", 1);
  term2.insert(a_variable);
  if (term1.greater_than(term2)) {
    println("9 -- failed greater than with object no variables, arg 1 variable");
  }
  if (!term2.greater_than(term1)) {
    println("10 -- failed greater than with object 1 variable, arg no variables");
  }

  a_variable = new Variable("a",1);
  term1.insert(a_variable);
  if (term1.greater_than(term2)) {
    println("11 -- failed greater than object 1 variable less than arg 1 variable");
  }
  if (!term2.greater_than(term1)) {
    println("12 -- failed greater than object 1 variable greater than arg 1 variable");
  }
  term2 = term1;
  if (term1.greater_than(term2)) {
    println("13 -- failed greater than object and arg have 1 equal variable");
  }

  term1 = create_length(5);
  term2 = create_length(5);
  if (term1.greater_than(term2)) {
    println("14 -- failed greater than object and arg have many equal variables");
  }

  term1 = create_length(5);
  term2 = create_length(6);
  if (term1.greater_than(term2)) {
    println("15 -- failed greater than object and arg have many equal variables");
    println("15 -- arg is 1 longer than object");
  }

  term1 = create_length(6);
  term2 = create_length(5);
  if (!term1.greater_than(term2)) {
    println("16 -- failed greater than object and arg have many equal variables");
    println("16 -- object is 1 longer than arg");
  }

  term1 = create_length(5);
  term2 = create_length(5);
  a_variable = new Variable("k",1);
  term1.insert(a_variable);
  a_variable = new Variable("l",1);
  term2.insert(a_variable);
  if (term1.greater_than(term2)) {
    println("17 -- failed greater than object has less than variable part way down");
    println("17 -- a many length list of variables.");
  }
  if (!term2.greater_than(term1)) {
    println("18 -- failed greater than object has greater than variable part way down");
    println("18 -- a many length list of variables.");
  }
}

public void terms_variables_are_preserved () {
  a_term = new Term();
  a_variable = new Variable ("a", 3);
  a_term.insert(a_variable);
  a_variable.name = "b";
  a_variable.exponent = 4;
  if (  ((Variable) a_term.variables.getFirst()).name == "b"
     || ((Variable) a_term.variables.getFirst()).exponent == 4) {
    println("19 -- Changing the first variable after adding it to a term "
           + "should not change the term.");
  }
  a_variable = new Variable ("e", 7);
  a_term.insert(a_variable);
  a_variable.name = "f";
  a_variable.exponent = 8;
  if (  ((Variable) a_term.variables.getLast()).name == "f"
     || ((Variable) a_term.variables.getLast()).exponent == 8) {
    println("20 -- Changing the last variable after adding it to a term "
           + "should not change the term.");
  }
  a_variable = new Variable ("c", 5);
  a_term.insert(a_variable);
  a_variable.name = "d";
  a_variable.exponent = 6;
  if (  ((Variable) a_term.variables.get(1)).name == "d"
     || ((Variable) a_term.variables.get(1)).exponent == 6) {
    println("21 -- Changing a middle variable after adding it to a term "
           + "should not change the term.");
  }  
}

/*******************************************************************************
Support Operations
*******************************************************************************/

// A couple of print routines to hide the call to System.out.

private static void println(String item) { System.out.println(item); }

private static void print(String item) { System.out.print(item); }

/** Create a term list of length ln variables
<PRE>
<B>Require</B> ln > 0 and ln < 13 
   -- restrict so variable names do not extend beyond lower case letters
<B>Ensure</B> Result is requested Term
*/

private Term create_length (int ln) {
  int j;        // index of the character to create, and the exponent to use
  String var_name;   // a variable name
  String base_name = new String ("x");  // Name to convert to a variable name
  char ch;           // a character
  Term Result;       // The value to return from the function

  Result = new Term();
  Result.coefficient = 8;
  j = 2 ; ch = 'b';
// Invariant
// forall k : 1..j-2 | (var : variable 
//    | name(var) = chr(ord('`')+2*k) ^ exponent(var) = 2*k
//    :: in_term(var)
  while (j <= ln + ln) {
    var_name = base_name.replace('x',ch);
    a_variable = new Variable (var_name, j);
    Result.insert(a_variable);
    j = j + 2;
    ch += 2;
  }
  return Result;
}

/** Print the variables for the term. */

public void print_variables(Term the_term) {
  Variable the_variable;
  print("Start of variables\n");

  ListIterator<Variable> list_iter = the_term.variables.listIterator(0);
// Invariant: forall var : 0..position_at(variables)-1 :: printed(var)
  while (list_iter.hasNext()) {
    the_variable = list_iter.next();
    print("   " + the_variable.name + " " + the_variable.exponent + "\n");
  }
  print("End of variables\n");
}

}