// Example of how a megaprogram for the transportation modules could look
// CREATED: 02/18/98, D. Beringer
// UPDATED: 08/04/98, L. Melloul; 01/23/99, N. Sample
// Language Syntax as defined by July 1998
// This example shows the interaction between a Megaprogram and four
// Megamodules through the CHAIMS primitives. InputOutput (IO megamodule),
// RoutePlan, RouteCost, and RouteChoose are Megamodules whose services will be
// invoked by the Megaprogram. The aim is to retrieve information about goods
// to be transported between two cities and to find the best route between
// these two cities, considering factors such as time and cost. RoutePlan
// takes two cities, and returns a list of routes between them. RouteCost
// takes one route between two cities and the goods to be transported, and
// returns a cost for that route. RouteChoose takes a series of individual
// route costs and selects the best from among them.

Transportation
BEGINCHAIMS

// Bind to the megamodules; mmh stands for megamodule_handle
io_mmh = SETUP ("io")
RoutePlan_mmh = SETUP ("RoutePlan")
RouteCost_mmh = SETUP ("RouteCost")
RouteChoose_mmh = SETUP ("RouteChoose")
math = SETUP ("CmathS")

// Get information from the megaprogram user about the how to decide among
// possible routes; ih stands for invocation_handle
(criteria_var = Criterion) = RouteChoose_mmh.GETPARAM ()
input_criteria_ih = io_mmh.INVOKE("ask", value = criteria_var, text = "Please enter decision criteria: ")
(criteria_var = result) = input_criteria_ih.EXWDONE()

// Set default values for some parameter names of methods or global parameters
// of megamodules, specifically the decision criteria for RouteChoose
RouteChoose_mmh.SETPARAM (Criterion = criteria_var)

// Get information from the megaprogram user which cities to
// send goods in between
(cities_var = Cities) = CitiesRoutePlan_mmh.GETPARAM ()
input_cities_ih = io_mmh.INVOKE("ask", value = input_cities, text = "Please enter cities: ")
(cities_var = result) = input_cities_ih.EXDONE()
RoutePlan_mmh.SETPARAM (Cities = cities_var)

// Get information from the megaprogcitieser about the goods to be transported
(goods_var = Goods) = RouteCost_mmh.GETPARAM ()
input_goods_ih = io_mmh.INVOKE ("ask", value = input_goods, text = "Please goods to transport: ")
(goods_var = result) = input_goods_ih.EXWDONE()
RouteCost_mmh.SETPARAM (Goods = goods_var)

// Get all routes between the two cities and all city pairs in these routes
// Call the "AllRoutes" method in the RoutePlan megamodule
routes_ih = RoutePlan_mmh.INVOKE("AllRoutes")
WHILE (routes_ih.EXAMINE != DONE) {}
// better version: use partial extract with progress indicator
// instead of waiting for all routes to be computed

// Extract particular routes from RoutePlan, one at a time. Forward these
// individual routes to RouteCost.
counter = 0;
(noRoutes = NoRoutes) = routes_ih.EXTRACT()
IF (noRoutes = 0)
THEN {
    io_mmh.INVOKE("write", text = "No routes exist between these cities.") }
ELSE {
    WHILE (counter < noRoutes) {
        (city_pair_var = Route) = routes_ih.EXTRACT()
        cost_ih = RouteCost_mmh.INVOKE("OneRouteCost", city_pair_var)
        (route_cost_var = RouteCost) = cost_ih.EXWDONE()
        chooseset_ih = RouteChoose_mmh.INVOKE("AddOneRouteToSet", route_cost_var)
        (counter = res) = math_mmh.INVEX("ADD", arg1 = counter, arg2 = 1)
    }
    // Get the best route
    choose_ih = RouteChoose_mmh.INVOKE("BestRoute")
    WHILE (RouteChoose_mmh.EXAMINE != DONE) {}
    (result = BestRoute) = choose_ih.EXTRACT()

    // Return the best route to the user io_mmh.INVOKE("write", value = result,
          text = "The best route is: ")
}

RouteChoose_mmh.TERMINATE()
RoutePlan_mmh.TERMINATE()
RouteCost_mmh.TERMINATE()
io_mmh.TERMINATE()
math_mmh.TERMINATE()

ENDCHAIMS