global gen_table


# set the default for Children_R
procedure children_default()

   return Children_R(50, 3, table(), table())

end

# generates children
procedure children_generation(children)

   local parent_id
   local delete_id
   local max
   local id
   local child
   local parents
   local num

   # set up the first child
   max := ?children.max_children
   children.all[0] := Child_Node_R(0, set(), &null, 0, 2 * &pi)

   # give child(ren) to the first node
   every insert(children.all[0].children_id, 1 to max)   

   # add the new children to the children list and set the children 
   # to be ready as parents
   parents := set()
   every insert(parents, id := !children.all[0].children_id) do
      children.all[id] := Child_Node_R(0, set())
     
   # generate children for each child created, some children may not have children

   every id := max+1 to children.num_children do
   {
      num := 0;

      # get a parent and give it a child
      parent_id := ?parents
      children.all[id] := Child_Node_R(parent_id, set())
      insert(children.all[parent_id].children_id, id)
      insert(parents, id)

      # delete the parent from the parents set of has max number of children
      if *children.all[parent_id].children_id >= children.max_children then 
         delete(parents, parent_id)

      # randomly delete a parent
      delete_id := ?[1, &null]
      if \delete_id & *parents ~== 0 then 
      {
         until *children.all[id := ?parents].children_id ~== 0 do
              if (num +:= 1) > (2 * *parents) then break; 
         delete(parents, id)
      }
    }

    count_children( children, 0 )
    # get the base and the bound for each child
    assign_base_and_bound( children )
    # find the generation for each child
    count_gen( children, 0, 0 )
    # print out children
    # print_out(children)
    # count number of children per generation
    num_children_per_generation(children)
    get_gen_id(children, 0)

end


# for inputted data
procedure parse_text()

   local parent_id, text, intext, id, input_file, text_list
   local text_info, part_child, left_b, child, children_new

   if Dialog(["Data File:"], [""], 
             [], [20]) == "Okay" then input_file := get(dialog_value)
   else return fail

   children_new := Children_R(0, 0, table(), table())
   id := 1
   parent_id := 0

   intext := open(input_file) | return fail
   text := ""
   while text ||:= read(intext) 
   text_list := [[text, 0]]
   close(intext)

   # start the root
   children_new.all[0] := Child_Node_R(0, set(), &null, 0, 2 * &pi, 0, 0)

   # build the tree
   while text_info := get(text_list) do {

      text := text_info[1]
      parent_id := text_info[2]

      text ? {
         tab(upto('[') + 1) | return fail
         part_child := ""
         left_b := 0
         while child := tab(upto('[]') + 1) do {

              find("[", child) & part_child ||:= child & left_b +:= 1 & next
              find("]", child) & part_child ||:= child & left_b -:= 1 & left_b > 0  & next

              child := part_child
              if not find("[", child) then break

              # set up the new child
              children_new.all[id] := Child_Node_R(parent_id, set())
              insert(children_new.all[parent_id].children_id, id)

              # check if the new child is also a parent
              if child[-2:0] ~== "[]" then put(text_list, [child,id])
              id +:= 1  

              part_child := ""
              left_b := 0
              child := ""
         }
      }
   }

   children_new.num_children := id - 1;
   
   children_new.max_children := 0
   every id := 0 to children_new.num_children  do
      if *children_new.all[id].children_id > children_new.max_children then 
          children_new.max_children := *children_new.all[id].children_id
      
   count_children( children_new, 0 )
   # get the base and the bound  for each child
   assign_base_and_bound( children_new )
   # find the generation for each child
   count_gen(children_new, 0, 0 )
   # count number of children per generation
   num_children_per_generation(children_new)
   get_gen_id(children_new, 0)

   return(children_new)

end

         

# for directory data
procedure children_directory()

   local dir_string
   local children, text, intext

   children := Children_R(0, 0, table(), table())
   dir_string := begin_root()
   system("ls -p " || dir_string || " > file") 
   intext := open("file")
   text := read(intext) 
   if find("No such file or directory", text) then return fail
   close(intext)
   system("rm file")

   /dir_string & return fail
   set_up_children_directory(children, dir_string)

   return children

end



# 
procedure set_up_children_directory(children, dir_string)

   local parent_id
   local count
   local directory_table
   local dir_list
   local new_dir

   parent_id := count := 0
   directory_table := table()

   # set up the root (dir_string)
   children.all[count] := Child_Node_R(0, set(), &null, 0, 2 * &pi)
   directory_table[count] := [dir_string, 0]
   count +:= 1
   dir_list := get_directory_list(dir_string)
   if /dir_list then return;
   children.max_children := *dir_list;

   # assign id number for each new child and record
   while new_dir := get(dir_list) do {
      directory_table[count] := [new_dir, parent_id]
      insert(children.all[parent_id].children_id, count)
      count +:= 1
   }
   parent_id +:= 1;

   # initailize each new child
   until parent_id = count do {

      # set up the new parent and get the children
      children.all[parent_id] := Child_Node_R(directory_table[parent_id][2],
                                              set())
      dir_list := get_directory_list(directory_table[parent_id][1])
      if *dir_list > children.max_children then 
         children.max_children := *dir_list

      # assign id number for each new child and record
      while new_dir := get(dir_list) do {
         directory_table[count] := [new_dir, parent_id]
         insert(children.all[parent_id].children_id, count)
         count +:= 1
      }

      parent_id +:= 1;

   }

   children.num_children := count - 1  

   count_children( children, 0 )
   # get the bas and the bound  for each child
   assign_base_and_bound( children )
   # find the generation for each child
   count_gen(children, 0, 0 )
   # count number of children per generation
   num_children_per_generation(children)
   get_gen_id(children, 0)

end


# get all the directory names that live in a certain directory
procedure get_directory_list(dir_string)
   
   local intext
   local text
   local dir_list

   dir_list := list()

   system("ls -p " || dir_string || " > file")
   intext := open("file")

   while text := read(intext) do {
      if find("/", text) then {
         text ? {
            push(dir_list, dir_string || "/" || tab(upto('/'))) }
      }
   }

   close(intext)
   system("rm file")
   return dir_list

end


procedure begin_root()

   if Dialog(["Enter a directory:"], [""], 
             [], [20]) == "Okay" then  return get(dialog_value)
   else return fail

end


# count the number of children 
procedure count_children( children, id )

   children.all[id].children_num := *children.all[id].children_id
   every children.all[id].children_num +:= count_children(children, !children.all[id].children_id)

   return children.all[id].children_num

end


# find the generation for each child
procedure count_gen( children, id, generation )

   children.all[id].generation := generation
   every count_gen(children, !children.all[id].children_id, generation + 1)

   return

end


# get the base and the bound for each child
procedure assign_base_and_bound(children)

   local id, range, base,  bound, num, child, base_s, bound_s

   # get the base and the bound
   every id := 0 to children.num_children do
   {
      # get the base and the bound of its parent
      bound_s := bound := children.all[id].bound
      base_s := base  := children.all[id].base 

      # find the range and calulate its own base and bound
      range := bound - base 
      every child := !children.all[id].children_id do
      {
         num := (children.all[child].children_num + 1)* range / children.all[id].children_num 
         bound_s := num + base_s
         children.all[child].base  := base_s
         children.all[child].bound := bound_s
         base_s := bound_s
      }
    }

end
         

# find the number of children per generation
procedure num_children_per_generation(children)

   local id, num_of_children

   children.num_gen := table()

   every id := 0 to children.num_children do
      children.num_gen[id] := 0

   every id := 0 to children.num_children do {
      num_of_children := *children.all[id].children_id      
      children.num_gen[children.all[id].generation + 1] +:= num_of_children
   }
  children.num_gen[0] := 1

end


# get the id number for each child for its generation starting at 1
procedure get_gen_id(children, child)

   gen_table := table()
   every gen_table[0 to children.num_children] := 1
   N_get_gen_id(children, child)

end
 

procedure N_get_gen_id(children, child)

   local gen, new_child

   gen := children.all[child].generation
   children.all[child].gen_id := gen_table[gen]
   gen_table[gen] +:= 1
   every new_child := !children.all[child].children_id do
       N_get_gen_id(children, new_child)
   
end


