// file: $isip/doc/examples/class/dstr/dstr_example_03/example.cc
// version: $Id: example.cc 6023 2000-12-20 04:06:28Z duncan $
//

// isip include files
//
#include <DiGraph.h>

// main program starts here:
//  this example demonstrates reading and writing data structures to a
//  text sof file. the output file will not be deleted so that the user
//  may examine the output upon exiting.
//
int main () {

  // we will write the grammar to this file
  //
  String file(L"graph_grammar.sof");
  
  // create a Graph of our simple grammar
  //
  DiGraph<String> grammar;

  // graphs are difficult to build by hand. One way to do it is to
  // keep a pointer to every vertex in the graph so that the arcs can
  // be directly added at the end.
  //
  String word;
  word.assign(L"See");
  GraphVertex<String>* v_See = grammar.insertVertex(&word);
  
  word.assign(L"Jane");
  GraphVertex<String>* v_Jane = grammar.insertVertex(&word);

  word.assign(L"John");
  GraphVertex<String>* v_John = grammar.insertVertex(&word);

  word.assign(L"run");
  GraphVertex<String>* v_run = grammar.insertVertex(&word);

  word.assign(L"walk");
  GraphVertex<String>* v_walk = grammar.insertVertex(&word);

  word.assign(L"get");
  GraphVertex<String>* v_get = grammar.insertVertex(&word);

  word.assign(L"buy");
  GraphVertex<String>* v_buy = grammar.insertVertex(&word);

  word.assign(L"to");
  GraphVertex<String>* v_to = grammar.insertVertex(&word);

  word.assign(L"the");
  GraphVertex<String>* v_the = grammar.insertVertex(&word);

  word.assign(L"store");
  GraphVertex<String>* v_store = grammar.insertVertex(&word);

  word.assign(L"library");
  GraphVertex<String>* v_library = grammar.insertVertex(&word);

  word.assign(L"a");
  GraphVertex<String>* v_a = grammar.insertVertex(&word);

  word.assign(L"book");
  GraphVertex<String>* v_book = grammar.insertVertex(&word);

  word.assign(L"lunch");
  GraphVertex<String>* v_lunch = grammar.insertVertex(&word);

  // add an arc from the start node to the word See
  //
  grammar.insertArc(grammar.getStart(), v_See, true);

  // add arcs between words
  //
  grammar.insertArc(v_See, v_Jane);
  grammar.insertArc(v_See, v_John);

  // create a dummy node to collapse the Jane and John paths
  // arcs will come into this node with epsilon transitions
  //
  word.clear();
  GraphVertex<String>* dummy = grammar.insertVertex(&word);
  grammar.insertArc(v_John, dummy, true);
  grammar.insertArc(v_Jane, dummy, true);

  // branch on the verb
  //
  grammar.insertArc(dummy, v_run);
  grammar.insertArc(dummy, v_walk);
  grammar.insertArc(dummy, v_get);
  grammar.insertArc(dummy, v_buy);

  grammar.insertArc(v_run, v_to);
  grammar.insertArc(v_walk, v_to);

  dummy = grammar.insertVertex(&word);
  grammar.insertArc(v_get, dummy, true);
  grammar.insertArc(v_buy, dummy, true);

  grammar.insertArc(dummy, v_a);
  grammar.insertArc(dummy, v_lunch);

  grammar.insertArc(v_to, v_the);
  grammar.insertArc(v_the, v_store);
  grammar.insertArc(v_the, v_library);

  grammar.insertArc(v_a, v_book);

  // add paths from the ending words to the terminal node to signify
  // they are terminal nodes.
  //
  grammar.insertArc(v_run, grammar.getTerm(), true);
  grammar.insertArc(v_walk, grammar.getTerm(), true);
  grammar.insertArc(v_store, grammar.getTerm(), true);
  grammar.insertArc(v_library, grammar.getTerm(), true);
  grammar.insertArc(v_book, grammar.getTerm(), true);
  grammar.insertArc(v_lunch, grammar.getTerm(), true);

  // write the Graph to a text Sof file
  //
  Sof text_file;
  text_file.open(file, File::WRITE_ONLY, File::TEXT);
  grammar.write(text_file, 0);
  text_file.close();

  // now generate some random strings
  //
  for (long i = 0; i < 20; i++) {
  
    // now make some random strings with the language
    //
    GraphVertex<String>* node = grammar.getStart();
    
    String sentence;
    while (node != grammar.getTerm()) {
      
      // concatenate this word to the sentence
      //
      sentence.concat(*(node->getItem()));

      // randomly select a path to traverse
      //
      long num_choices = node->length();
      long choice = (long)((Random::GLOBAL_UNIFORM.get() - 0.1) * num_choices);
      node->gotoPosition(choice);
      
      // node->getCurr() returns a GraphArc. we don't print spaces for
      // epsilon transitions.
      //
      if (!node->getCurr()->getEpsilon()) {
	sentence.concat(L" ");
      }
      
      // follow the node
      //
      node = node->getCurr()->getVertex();
    }

    // print the sentence
    //
    sentence.concat(L".\n");
    Console::put(sentence);
  }
  
  // exit gracefully
  //
  Integral::exit();
}
