//***************************************************************
// Copyright 2008 Centre For Advanced Spatial Analysis, UCL
//
// Author: Joel Dearden, University College London
//
// Contact: j.dearden@ucl.ac.uk
//
// Joel Dearden,
// Centre for Advanced Spatial Analysis,
// University College London,
// 1-19 Torrington Place,
// London,
// WC1E 7HB
//
//
// This file is part of SLPedEvac.
//
// SLPedEvac is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// SLPedEvac is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with SLPedEvac. If not, see .
//
//***************************************************************
//CONSTANTS START=========================================
string controllerName = "ABMcontroller";
integer controllerSendChannel = -220211;
integer controllerReceiveChannel = -293321;
string tickMsg = "TiCk";
string pedInMsg = "pEdiN";
string pedOutMsg = "pedOUt";
integer rayChannel = -1;
integer rayChannelBase = 1000000;
integer rayChannelStep = 2; //band size usable by each pedestrian
integer talkToBuilder = -9292921;
integer talkToStrobeLight = -2928333;
integer talkToDisplay = -9000;
integer talkToBuildingComponents = -8927211;
float interval = 4; //seconds
integer totalModelSeconds = 0;
//CONSTANTS END=========================================
//VARIABLES START=========================================
integer totalPedestrians = 0;
integer rayChannelGenerator = 0;
integer doingUpdate = FALSE;
integer totalPedestriansDoingUpdate = 0;
integer totalPedestriansCompletedUpdate = 0;
integer buildingReady = FALSE;
//VARIABLES END=========================================
//FUNCTIONS START=========================================
startUpdate()
{
llOwnerSay("startUpdate");
//cancel timer event
llSetTimerEvent(0);
doingUpdate = TRUE;
totalPedestriansDoingUpdate = totalPedestrians;
totalPedestriansCompletedUpdate = 0;
//broadcast clock message
llShout(controllerSendChannel, tickMsg);
}
checkUpdateStatus()
{
llOwnerSay("checkStatusUpdate");
llOwnerSay("totalPedestriansDoingUpdate:" + (string)totalPedestriansDoingUpdate);
llOwnerSay("totalPedestriansCompletedUpdate:" + (string)totalPedestriansCompletedUpdate);
if(totalPedestriansCompletedUpdate >= totalPedestriansDoingUpdate)
{
llOwnerSay("completed update");
//send "register model second" HTTP message
llHTTPRequest("
/input.aspx?f=rms", [], "");
llOwnerSay("registering model second");
totalModelSeconds++;
llSetText("TOTAL MODEL SECONDS: " + (string)totalModelSeconds + "s", <1,1,1>, 1.0);
llSay(talkToDisplay, "TIME: " + (string)totalModelSeconds + "S");
doingUpdate = FALSE;
//reset timer event
//llSetTimerEvent(interval);
//wait a second before we start the next update to allow pedestrians time to process ACK and change state
llSleep(1.0);
startUpdate();
}
}
reset()
{
buildingReady = FALSE;
llOwnerSay("reset");
llSetText("", <1,1,1>, 1.0);
llSay(talkToBuilder, "clear_site");
totalPedestrians = 0;
rayChannelGenerator = 0;
totalModelSeconds = 0;
doingUpdate = FALSE;
totalPedestriansDoingUpdate = 0;
totalPedestriansCompletedUpdate = 0;
//send reset HTTP message
llOwnerSay("resetting model.");
llHTTPRequest("/input.aspx?f=r", [], "");
//give server time to reset...
llOwnerSay("giving server time to reset");
llSetTimerEvent(5);
}
load_simple_layout()
{
reset();
llSleep(2.0);
llSay(talkToBuilder, "build_simple");
}
load_complicated_layout()
{
reset();
llSleep(2.0);
llSay(talkToBuilder, "build_complicated");
}
load_multifloor_layout()
{
reset();
llSleep(2.0);
llSay(talkToBuilder, "build_multifloor");
}
//FUNCTIONS END=========================================
default
{
state_entry()
{
llOwnerSay("default state entry");
llSetText("", <1,1,1>, 1.0);
state waiting;
}
}
state waiting
{
state_entry()
{
llSay(talkToDisplay, " NO ALARM ");
llOwnerSay("waiting state entry");
llSay(talkToStrobeLight, "off");
llListen(controllerReceiveChannel, "", NULL_KEY, "");
}
listen(integer channel, string name, key id, string message)
{
if(channel == controllerReceiveChannel)
{
if(message == "builder_finished")
{
buildingReady = TRUE;
//register components with webserver
llSay(talkToBuildingComponents, "REG");
}
if(message == "fire_alarm")
{
if(buildingReady)
{
//fire alarm sounded
//tell all agents
llShout(controllerSendChannel, "alarm");
//give time for all agents to finish wandering and hear the alarm
llSleep(10.0);
//start updating agents one second at a time
state alarm_active;
}
else
{
llSay(0, "building not ready");
}
}
if(message == "reset")
{
//reset model
reset();
}
if(message == "simple_layout")
{
load_simple_layout();
}
if(message == "complicated_layout")
{
load_complicated_layout();
}
if(message == "multifloor_layout")
{
load_multifloor_layout();
}
if(message == pedInMsg)
{
llOwnerSay("PED_IN");
totalPedestrians++;
//send pedestrian its ray channel
llShout(controllerSendChannel, (string)id + ":" + (string)(rayChannelBase + rayChannelGenerator));
rayChannelGenerator += rayChannelStep;
return;
}
}
}
}
state alarm_active
{
state_entry()
{
llOwnerSay("alarm active state entry");
llSay(talkToDisplay, " ALARM ON ");
llSay(talkToStrobeLight, "on");
llListen(controllerReceiveChannel, "", NULL_KEY, "");
llSetTimerEvent(interval);
}
listen(integer channel, string name, key id, string message)
{
if(channel == controllerReceiveChannel)
{
if(message == "reset")
{
reset();
state waiting;
}
if(doingUpdate)
{
if(message == pedOutMsg)
{
llOwnerSay("PED_OUT_DURING_UPDATE");
totalPedestrians--;
//treat this as equivalent to registering a move (just out of the model)
totalPedestriansCompletedUpdate++;
checkUpdateStatus();
return;
}
if(message == "RegMoV")
{
llOwnerSay("got regmove");
llSay(controllerSendChannel, "ACK" + (string)id);
totalPedestriansCompletedUpdate++;
checkUpdateStatus();
return;
}
}
else
{
//not doing update
if(message == pedOutMsg)
{
llOwnerSay("PED_OUT");
totalPedestrians--;
return;
}
}
}
}
timer()
{
//don't start updating until we have at least one pedestrian registered
if(totalPedestrians > 0)
{
startUpdate();
}
else
{
llOwnerSay("waiting for pedestrians...");
}
}
}