function Activity (
			DatabaseId,
			ScormObjectDatabaseId, 
			ActivityProgressStatus, 
			ActivityAbsoluteDuration, 
			ActivityExperiencedDuration, 
			ActivityAttemptCount,
			AttemptProgressStatus,
			AttemptCompletionAmount,
			AttemptCompletionStatus,
			AttemptAbsoluteDuration,
			AttemptExperiencedDuration,
			Active,
			Suspended,
			Included,
			Ordinal,
			SelectedChildren,
			RandomizedChildren,
			ActivityObjectives,
			RunTime,
			PrevAttemptProgressStatus,
			PrevAttemptCompletionStatus,
			AttemptedDuringThisAttempt,
			FirstCompletionTimestampUtc){
	
	//this is here purely to make this object easier to identify in the Quick Watch debugger window. It is initialized by the activity repository.
	this.StringIdentifier = null;
	
	//data initialized from server
	this.DatabaseId = DatabaseId; 
	this.ScormObjectDatabaseId = ScormObjectDatabaseId; 
	
	this.ActivityProgressStatus = ActivityProgressStatus; 
	this.ActivityAbsoluteDuration = ActivityAbsoluteDuration; 
	this.ActivityExperiencedDuration = ActivityExperiencedDuration; 
	this.ActivityAttemptCount = ActivityAttemptCount;
	this.AttemptProgressStatus = AttemptProgressStatus;
	this.AttemptCompletionAmount = AttemptCompletionAmount;
	this.AttemptCompletionStatus = AttemptCompletionStatus;
	this.AttemptAbsoluteDuration = AttemptAbsoluteDuration;
	this.AttemptExperiencedDuration = AttemptExperiencedDuration;
	this.Active = Active;
	this.Suspended = Suspended;
	this.Included = Included;
	this.Ordinal = Ordinal;
	this.SelectedChildren = SelectedChildren;
	this.RandomizedChildren = RandomizedChildren;
	
	this.ActivityObjectives = ActivityObjectives;
	this.RunTime = RunTime;
	
	this.PrevAttemptProgressStatus = PrevAttemptProgressStatus;
	this.PrevAttemptCompletionStatus = PrevAttemptCompletionStatus;
	this.AttemptedDuringThisAttempt = false;
	
	this.FirstCompletionTimestampUtc = FirstCompletionTimestampUtc;
	
	//data initialized on client side
	this.Sequencer = null;
	this.LookAheadActivity = false;
	this.LearningObject = null;
	this.ParentActivity = null;
	this.ChildActivities = new Array();			//maintain as an array indexed by integers, int indicies are used by selection and randomization
	this.AvailableChildren = null;
	
	this.DataState = DATA_STATE_CLEAN;
	
	this.MenuItem = null;
	
	this.CachedPrimaryObjective = null;
	this.HiddenFromChoice = false;
	
	//used by the scorm 2004 look ahead sequencer
	this.HasSeqRulesRelevantToChoice = null;			
	this.HasChildActivitiesDeliverableViaFlow = false;

	//indicates whether this activity has been shown to the end user, i.e, the sco/asset's initial html page has been shown
	this.LaunchedThisSession = false;

}

Activity.prototype.GetXml = Activity_GetXml;
Activity.prototype.toString = Activity_toString;

Activity.prototype.GetTitle = Activity_GetTitle;
Activity.prototype.GetItemIdentifier = Activity_GetItemIdentifier;
Activity.prototype.GetDatabaseIdentifier = Activity_GetDatabaseIdentifier;
Activity.prototype.GetLaunchPath = Activity_GetLaunchPath;
Activity.prototype.IsDeliverable = Activity_IsDeliverable;

Activity.prototype.TransferRteDataToActivity = Activity_TransferRteDataToActivity;

Activity.prototype.IsTheRoot = Activity_IsTheRoot;
Activity.prototype.IsALeaf = Activity_IsALeaf;

Activity.prototype.IsActive = Activity_IsActive;
Activity.prototype.IsSuspended = Activity_IsSuspended;
Activity.prototype.HasSuspendedChildren = Activity_HasSuspendedChildren;

Activity.prototype.SetActive = Activity_SetActive;
Activity.prototype.SetSuspended = Activity_SetSuspended;

Activity.prototype.IsTracked = Activity_IsTracked;
Activity.prototype.IsCompletionSetByContent = Activity_IsCompletionSetByContent;
Activity.prototype.IsObjectiveSetByContent = Activity_IsObjectiveSetByContent;

Activity.prototype.GetAttemptProgressStatus = Activity_GetAttemptProgressStatus;
Activity.prototype.SetAttemptProgressStatus = Activity_SetAttemptProgressStatus;

Activity.prototype.SetAttemptCompletionStatus = Activity_SetAttemptCompletionStatus;
Activity.prototype.GetAttemptCompletionStatus = Activity_GetAttemptCompletionStatus;

Activity.prototype.GetChildren = Activity_GetChildren;

Activity.prototype.GetSequencingControlFlow = Activity_GetSequencingControlFlow;
Activity.prototype.GetSequencingControlChoice = Activity_GetSequencingControlChoice;
Activity.prototype.GetSequencingControlChoiceExit = Activity_GetSequencingControlChoiceExit;
Activity.prototype.GetSequencingControlForwardOnly = Activity_GetSequencingControlForwardOnly;

Activity.prototype.GetPreventActivation = Activity_GetPreventActivation;
Activity.prototype.GetConstrainedChoice = Activity_GetConstrainedChoice;

Activity.prototype.GetSelectionTiming = Activity_GetSelectionTiming;
Activity.prototype.GetSelectionCountStatus = Activity_GetSelectionCountStatus;
Activity.prototype.GetSelectionCount = Activity_GetSelectionCount;

Activity.prototype.GetRandomizationTiming = Activity_GetRandomizationTiming;
Activity.prototype.GetRandomizeChildren = Activity_GetRandomizeChildren;

Activity.prototype.GetLimitConditionAttemptControl = Activity_GetLimitConditionAttemptControl;
Activity.prototype.GetActivityProgressStatus = Activity_GetActivityProgressStatus;
Activity.prototype.SetActivityProgressStatus = Activity_SetActivityProgressStatus;
Activity.prototype.GetAttemptCount = Activity_GetAttemptCount;
Activity.prototype.GetLimitConditionAttemptLimit = Activity_GetLimitConditionAttemptLimit;

Activity.prototype.GetPreConditionRules = Activity_GetPreConditionRules;
Activity.prototype.GetPostConditionRules = Activity_GetPostConditionRules;
Activity.prototype.GetExitRules = Activity_GetExitRules;

Activity.prototype.IsSatisfied = Activity_IsSatisfied;
Activity.prototype.IsObjectiveStatusKnown = Activity_IsObjectiveStatusKnown;
Activity.prototype.IsObjectiveMeasureKnown = Activity_IsObjectiveMeasureKnown;
Activity.prototype.IsObjectiveMeasureGreaterThan = Activity_IsObjectiveMeasureGreaterThan;
Activity.prototype.IsObjectiveMeasureLessThan = Activity_IsObjectiveMeasureLessThan;
Activity.prototype.GetObjectiveMeasure = Activity_GetObjectiveMeasure;

Activity.prototype.IsCompleted = Activity_IsCompleted;
Activity.prototype.IsActivityProgressKnown = Activity_IsActivityProgressKnown;
Activity.prototype.IsAttempted = Activity_IsAttempted;
Activity.prototype.IsAttemptLimitExceeded = Activity_IsAttemptLimitExceeded;

Activity.prototype.GetObjectives = Activity_GetObjectives;
Activity.prototype.FindObjective = Activity_FindObjective;
Activity.prototype.GetPrimaryObjective = Activity_GetPrimaryObjective;

Activity.prototype.GetRollupObjectiveMeasureWeight = Activity_GetRollupObjectiveMeasureWeight;
Activity.prototype.GetMeasureSatisfactionIfActive = Activity_GetMeasureSatisfactionIfActive;

Activity.prototype.GetRollupRules = Activity_GetRollupRules;

Activity.prototype.GetRollupObjectiveSatisfied = Activity_GetRollupObjectiveSatisfied;
Activity.prototype.GetRequiredForSatisfied = Activity_GetRequiredForSatisfied;
Activity.prototype.GetRequiredForNotSatisfied = Activity_GetRequiredForNotSatisfied;
Activity.prototype.RollupProgressCompletion = Activity_RollupProgressCompletion;
Activity.prototype.GetRequiredForCompleted = Activity_GetRequiredForCompleted;
Activity.prototype.GetRequiredForIncomplete = Activity_GetRequiredForIncomplete;

Activity.prototype.IncrementAttemptCount = Activity_IncrementAttemptCount;

Activity.prototype.SetRandomizedChildren = Activity_SetRandomizedChildren;
Activity.prototype.SetSelectedChildren = Activity_SetSelectedChildren;
Activity.prototype.GetRandomizedChildren = Activity_GetRandomizedChildren;
Activity.prototype.GetSelectedChildren = Activity_GetSelectedChildren;

Activity.prototype.GetActivityListBetweenChildren = Activity_GetActivityListBetweenChildren;

Activity.prototype.IsActivityAnAvailableChild = Activity_IsActivityAnAvailableChild;
Activity.prototype.IsActivityAnAvailableDescendent = Activity_IsActivityAnAvailableDescendent;

Activity.prototype.IsActivityTheLastAvailableChild = Activity_IsActivityTheLastAvailableChild;
Activity.prototype.IsActivityTheFirstAvailableChild = Activity_IsActivityTheFirstAvailableChild;

Activity.prototype.GetFirstAvailableChild = Activity_GetFirstAvailableChild;

Activity.prototype.GetNextActivity = Activity_GetNextActivity;
Activity.prototype.GetPreviousActivity = Actvity_GetPreviousActivity;


Activity.prototype.InitializeAvailableChildren = Activity_InitializeAvailableChildren;
Activity.prototype.GetAvailableChildren = Activity_GetAvailableChildren;
//Activity.prototype.GetUnAvailableChildren = Activity_GetUnAvailableChildren;
Activity.prototype.SetAvailableChildren = Activity_SetAvailableChildren;
Activity.prototype.IsAvailable = Activity_IsAvailable;

//Activity.prototype.InitializeObjectives = Activity_InitializeObjectives;
Activity.prototype.InitializeForNewAttempt = Activity_InitializeForNewAttempt;

Activity.prototype.ResetAttemptState = Activity_ResetAttemptState;
Activity.prototype.SetDirtyData = Activity_SetDirtyData;
Activity.prototype.IsAnythingDirty = Activity_IsAnythingDirty;

Activity.prototype.MarkPostedObjectiveDataDirty = Activity_MarkPostedObjectiveDataDirty;
Activity.prototype.MarkPostedObjectiveDataClean = Activity_MarkPostedObjectiveDataClean;
Activity.prototype.MarkDirtyObjectiveDataPosted = Activity_MarkDirtyObjectiveDataPosted;

Activity.prototype.SetSequencer = Activity_SetSequencer;
Activity.prototype.Clone = Activity_Clone;
Activity.prototype.TearDown = Activity_TearDown;

Activity.prototype.DisplayInChoice = Activity_DisplayInChoice;
Activity.prototype.SetHiddenFromChoice = Activity_SetHiddenFromChoice;

Activity.prototype.SetLaunchedThisSession = Activity_SetLaunchedThisSession;
Activity.prototype.WasLaunchedThisSession = Activity_WasLaunchedThisSession;

Activity.prototype.SetAttemptedDuringThisAttempt = Activity_SetAttemptedDuringThisAttempt;
Activity.prototype.WasAttemptedDuringThisAttempt = Activity_WasAttemptedDuringThisAttempt;

function Activity_GetXml(){
	
	var ServerFormat = new ServerFormater();
	
	var xml = new XmlElement("Activity");
		
	xml.AddAttribute("dbid", this.DatabaseId);
	
	xml.AddAttribute("ActivityProgressStatus", ServerFormat.ConvertBoolean(this.ActivityProgressStatus));
	
	xml.AddAttribute("ActivityAbsoluteDuration", this.ActivityAbsoluteDuration);
	xml.AddAttribute("ActivityExperiencedDuration", this.ActivityExperiencedDuration);
	
	xml.AddAttribute("ActivityAttemptCount", this.ActivityAttemptCount);
	
	xml.AddAttribute("AttemptProgressStatus", ServerFormat.ConvertBoolean(this.AttemptProgressStatus));
	xml.AddAttribute("AttemptCompletionAmount", this.AttemptCompletionAmount);
	
	xml.AddAttribute("AttemptCompletionStatus", ServerFormat.ConvertBoolean(this.AttemptCompletionStatus));
	
	xml.AddAttribute("AttemptAbsoluteDuration", this.AttemptAbsoluteDuration);
	xml.AddAttribute("AttemptExperiencedDuration", this.AttemptExperiencedDuration);
	
	xml.AddAttribute("Active", ServerFormat.ConvertBoolean(this.Active));
	xml.AddAttribute("Suspended", ServerFormat.ConvertBoolean(this.Suspended));
	xml.AddAttribute("Included", ServerFormat.ConvertBoolean(this.Included));
	xml.AddAttribute("Ordinal", this.Ordinal);
	xml.AddAttribute("SelectedChildren", ServerFormat.ConvertBoolean(this.SelectedChildren));
	xml.AddAttribute("RandomizedChildren", ServerFormat.ConvertBoolean(this.RandomizedChildren));
	
	xml.AddAttribute("PrevAttemptProgressStatus", ServerFormat.ConvertBoolean(this.PrevAttemptProgressStatus));	
	xml.AddAttribute("PrevAttemptCompletionStatus", ServerFormat.ConvertBoolean(this.PrevAttemptCompletionStatus));
	xml.AddAttribute("AttemptedDuringThisAttempt", ServerFormat.ConvertBoolean(this.AttemptedDuringThisAttempt));
	
	if (this.FirstCompletionTimestampUtc !== null) {
		xml.AddAttribute("FirstCompletionTimestampUtc", ServerFormat.ConvertTime(this.FirstCompletionTimestampUtc));	
	}
	
	for (var i=0; i < this.ActivityObjectives.length; i++){
		xml.AddElement(this.ActivityObjectives[i].GetXml(this.DatabaseId, i));
	}
	
	if (this.RunTime !== null){
		xml.AddElement(this.RunTime.GetXml(this.DatabaseId));
	}
	
	//we're intentionally not getting the XML for all the child activities...only want to submit what is dirty and no more
	
	return xml.toString();
}

function Activity_toString(){
	var str = this.GetTitle() + " (" + this.GetItemIdentifier() + ")";
	return str;
}

function Activity_GetTitle(){
	return this.LearningObject.Title;
}

function Activity_GetItemIdentifier(){

	//In SCORM 1.1 / 1.2 if the item identifier is null or "" or something...we need this to be intelligent enough
	//to return the DB id or something to ensure that other functionality which depends on this (such as DIV names) doesn't break
	
	if (this.LearningObject.ItemIdentifier !== null && this.LearningObject.ItemIdentifier !== ""){
		return this.LearningObject.ItemIdentifier;
	}
	else{
		return this.DatabaseId;
	}
	
}

function Activity_GetDatabaseIdentifier(){
	return this.DatabaseId;
}

function Activity_GetLaunchPath(){
	
	return MergeQueryStringParameters(this.LearningObject.Href, this.LearningObject.Parameters);
	
	//return this.LearningObject.Href + this.LearningObject.Parameters;
}

function Activity_IsDeliverable(){

	return (this.RunTime !== null);
}


function Activity_TransferRteDataToActivity(){

	var objectives = this.GetObjectives();
	var rtObjective;
	var primaryObjective;
	var id;

	if (this.IsTracked()){
		
		for (var i=0; i < objectives.length; i++){
			
			id = objectives[i].GetIdentifier();
			
			rtObjective = this.RunTime.FindObjectiveWithId(id);
			
			//rt.objective.success_status goes to seq.objective.objective satisfied status / seq.objective.objective progress status
			if (rtObjective !== null){
				
				//only save data to the activity tree if it was changed during this runtime session
				//we don't want to resave this data to the activity tree if it doens't change at runtime, that would give a
				//local objective known status, even though it was populated from a global objective
				
				if (rtObjective.SuccessStatusChangedDuringRuntime === true){
					if (rtObjective.SuccessStatus == SCORM_STATUS_UNKNOWN){
						objectives[i].SetProgressStatus(false, false, this);
					}
					else if (rtObjective.SuccessStatus == SCORM_STATUS_PASSED){
						objectives[i].SetProgressStatus(true, false, this);
						objectives[i].SetSatisfiedStatus(true);
					}
					else if (rtObjective.SuccessStatus == SCORM_STATUS_FAILED){
						objectives[i].SetProgressStatus(true, false, this);
						objectives[i].SetSatisfiedStatus(false);
					}
					else{
						Debug.AssertError("Invalid success status (" + rtObjective.SuccessStatus + ") encountered in a RTE objective at position " + i);
					}
				}
				
				if (rtObjective.MeasureChangedDuringRuntime === true) {
					//objectives.score.scaled -> seq.objective measure status / seq.objective.normalized measure
					if (rtObjective.ScoreScaled === null){
						objectives[i].SetMeasureStatus(false, this);
					}
					else{
						objectives[i].SetMeasureStatus(true, this);
						objectives[i].SetNormalizedMeasure(rtObjective.ScoreScaled, this);
					}
				}
			}
			else{
				if (id.length > 0){		//there might be a primary objective with no id in here
					Debug.AssertError("Sequencing objective not found in runtime, id=" + objectives[i].GetIdentifier());
				}
			}
		}
		
		primaryObjective = this.GetPrimaryObjective();
		
		
		//rt.success status goes to objective progress status, objective satisfied status
	
		var successStatus;
		var completionStatus;
		
		if (this.Sequencer.LookAhead === true){
			successStatus = this.RunTime.LookAheadSuccessStatus;
			completionStatus = this.RunTime.LookAheadCompletionStatus;
		}
		else{
			successStatus = this.RunTime.SuccessStatus;
			completionStatus = this.RunTime.CompletionStatus;
		}
		
		if (successStatus == SCORM_STATUS_UNKNOWN){
			primaryObjective.SetProgressStatus(false, false, this);
		}
		else if (successStatus == SCORM_STATUS_PASSED){	
			primaryObjective.SetProgressStatus(true, false, this);
			primaryObjective.SetSatisfiedStatus(true);
		}
		else if (successStatus == SCORM_STATUS_FAILED){
			primaryObjective.SetProgressStatus(true, false, this);
			primaryObjective.SetSatisfiedStatus(false);
		}
		else{
			Debug.LogSeq("ERROR - invalid success status-" + successStatus);
		}
		
		//rt.score.scaled goes to objective measure status / objective normalized measure
		if (this.RunTime.ScoreScaled === null){
			primaryObjective.SetMeasureStatus(false, this);
		}
		else{
			primaryObjective.SetMeasureStatus(true, this);
			primaryObjective.SetNormalizedMeasure(this.RunTime.ScoreScaled, this);
		}	
		
		
		//completion status -> attempt progress / attempt completion
		if (completionStatus == SCORM_STATUS_UNKNOWN){
			this.SetAttemptProgressStatus(false);
		}
		else if (completionStatus == SCORM_STATUS_NOT_ATTEMPTED){
			this.SetAttemptProgressStatus(true);
			this.SetAttemptCompletionStatus(false);
		}
		else if (completionStatus == SCORM_STATUS_COMPLETED){
			this.SetAttemptProgressStatus(true);
			this.SetAttemptCompletionStatus(true);
		}
		else if (completionStatus == SCORM_STATUS_INCOMPLETE){
			this.SetAttemptProgressStatus(true);
			this.SetAttemptCompletionStatus(false);
		}
		else if (completionStatus == SCORM_STATUS_BROWSED){
			this.SetAttemptProgressStatus(true);
			this.SetAttemptCompletionStatus(false);
		}
		else{
			Debug.AssertError("Invalid completeion status-" + completionStatus);
		}
		
		if (this.LookAheadActivity === false){
			//make sure that all this get committed
			this.SetDirtyData();
		}
	}
	else{
		//TODO - check that everything should not be transferred rather than just some data "[DB.2]7.1.1. The Objective and Attempt Progress information for the activity should not be recorded during delivery "
		//this.LogSeq("Not tracked...not transfering RTE data");
	}
}

function Activity_IsTheRoot(){
	
	var parentActivity = this.ParentActivity;
	
	var activityIsRoot = (parentActivity === null);
	
	return activityIsRoot;
}

function Activity_IsALeaf(){
	if (this.ChildActivities.length === 0){
		return true;
	}
	else{
		return false;
	}
}

function Activity_IsActive(){
	var active;
	
	active = this.Active;
	
	return active;
}

function Activity_IsSuspended(){
	var suspended;
	
	suspended = this.Suspended;
	
	return suspended;
}

function Activity_HasSuspendedChildren(){
	
	var children = this.GetChildren();
	
	for (var i=0; i < children.length; i++){
		if (children[i].IsSuspended()){
			return true;
		}
	}
	
	return false;
}

function Activity_SetActive(active){
	this.Active = active;
	this.SetDirtyData();
}

function Activity_SetSuspended(suspended){
	this.Suspended = suspended;
	this.SetDirtyData();
}

function Activity_IsTracked(){
	var tracked = this.LearningObject.SequencingData.Tracked;
	
	return tracked;
}

function Activity_IsCompletionSetByContent(){
	var completionSet = this.LearningObject.SequencingData.CompletionSetByContent;
	
	return completionSet;
}

function Activity_IsObjectiveSetByContent(){
	var objectiveSet = this.LearningObject.SequencingData.ObjectiveSetByContent;
	
	return objectiveSet;
}

function Activity_GetAttemptProgressStatus(){
	
	if (this.IsTracked() === false){
		return false;
	}
	
	var attemptProgressStatus = this.AttemptProgressStatus;
	return attemptProgressStatus;
}

function Activity_SetAttemptProgressStatus(value){
	this.AttemptProgressStatus = value;
	
	if (value === true){
		this.SetAttemptedDuringThisAttempt();
	}
	
	this.SetDirtyData();
}
	
function Activity_SetAttemptCompletionStatus(value){
	if (this.FirstCompletionTimestampUtc === null && value === true) {
		this.FirstCompletionTimestampUtc = ConvertDateToIso8601String(new Date());
	}
	
	this.AttemptCompletionStatus = value;
	
	this.SetDirtyData();
}
function Activity_GetAttemptCompletionStatus(){
	if (this.IsTracked() === false){
		return false;
	}
	
	var attemptCompletionStatus = this.AttemptCompletionStatus;
	return attemptCompletionStatus;
}

function Activity_GetChildren(){
	return this.ChildActivities;
}

function Activity_GetSequencingControlFlow(){
	var controlFlow = this.LearningObject.SequencingData.ControlFlow;
	return controlFlow;
}

function Activity_GetSequencingControlChoice(){
	var controlChoice = this.LearningObject.SequencingData.ControlChoice;
	return controlChoice;
}


function Activity_GetSequencingControlChoiceExit(){
	var controlChoiceExit = this.LearningObject.SequencingData.ControlChoiceExit;
	return controlChoiceExit;
}

function Activity_GetSequencingControlForwardOnly(){
	var controlForwardOnly = this.LearningObject.SequencingData.ControlForwardOnly;
	return controlForwardOnly;
}

function Activity_GetPreventActivation(){
	var preventActivation = this.LearningObject.SequencingData.PreventActivation;
	return preventActivation;
}

function Activity_GetConstrainedChoice(){
	var constrainedChoice = this.LearningObject.SequencingData.ConstrainChoice;
	return constrainedChoice;
}

function Activity_GetSelectionTiming(){
	var timing = this.LearningObject.SequencingData.SelectionTiming;
	return timing;
}

function Activity_GetSelectionCountStatus(){
	var status = this.LearningObject.SequencingData.SelectionCountStatus;
	return status;
}

function Activity_GetSelectionCount(){
	var count = this.LearningObject.SequencingData.SelectionCount;
	return count;
}

function Activity_GetRandomizationTiming(){
	var timing = this.LearningObject.SequencingData.RandomizationTiming;
	return timing;
}

function Activity_GetRandomizeChildren(){
	var randomize = this.LearningObject.SequencingData.RandomizeChildren;
	return randomize;
}


function Activity_GetLimitConditionAttemptControl(){
	var control = this.LearningObject.SequencingData.LimitConditionAttemptControl;
	return control;
}

function Activity_GetActivityProgressStatus(){
	if (this.IsTracked() === false){
		return false;
	}
	
	var progressData = this.ActivityProgressStatus;
	return progressData;
}

function Activity_SetActivityProgressStatus(status){
	this.ActivityProgressStatus = status;
	this.SetDirtyData();
}

function Activity_GetAttemptCount(){
	var attemptCount = this.ActivityAttemptCount;
	return attemptCount;
}

function Activity_GetLimitConditionAttemptLimit(){
	var attemptLimit = this.LearningObject.SequencingData.LimitConditionAttemptLimit;
	return attemptLimit;
}

function Activity_GetPreConditionRules(){
	var rules = this.LearningObject.SequencingData.PreConditionSequencingRules;
	return rules;
}

function Activity_GetPostConditionRules(){
	var rules = this.LearningObject.SequencingData.PostConditionSequencingRules;
	return rules;
}

function Activity_GetExitRules(){
	var rules = this.LearningObject.SequencingData.ExitSequencingRules;
	return rules;
}

function Activity_IsSatisfied(referencedObjective, canLookAtPreviousAttempt){
	
	if (canLookAtPreviousAttempt === null || canLookAtPreviousAttempt === undefined){
		//Debug.AssertError("ERROR - canLookAtPreviousAttempt must be passed into IsSatisfied");
		canLookAtPreviousAttempt = false;	//don't throw an error because this is called from integrations that were in place before we added this parameter for 3rd Edition
	}
	
	if (this.IsTracked() === false){
		return RESULT_UNKNOWN;
	}
	
	var objective;
	
	if (referencedObjective === undefined || referencedObjective === null){
		objective = this.GetPrimaryObjective();
	}
	else{
		objective = this.FindObjective(referencedObjective);
	}
	
	if (objective === null || objective === undefined){
		Debug.AssertError("Sequencing rule references a bad objective.");
	}
	
	if (objective.GetProgressStatus(this, canLookAtPreviousAttempt) === true){
		
		if (objective.GetSatisfiedStatus(this, canLookAtPreviousAttempt) === true){
			return true;
		}
		else{
			return false;
		}
		
	}
	else{
		return RESULT_UNKNOWN;
	}

}

function Activity_IsObjectiveStatusKnown(referencedObjective, canLookAtPreviousAttempt){
	
	if (canLookAtPreviousAttempt === null || canLookAtPreviousAttempt === undefined){
		Debug.AssertError("ERROR - canLookAtPreviousAttempt must be passed into IsObjectiveStatusKnown");
	}
	
	if (this.IsTracked() === false){
		return false;
	}
	
	var objective = this.FindObjective(referencedObjective);
	
	if (objective.GetProgressStatus(this, canLookAtPreviousAttempt) === true){
		return true;
	}
	else{
		return false;
	}
}

function Activity_IsObjectiveMeasureKnown(referencedObjective, canLookAtPreviousAttempt){

	if (canLookAtPreviousAttempt === null || canLookAtPreviousAttempt === undefined){
		Debug.AssertError("ERROR - canLookAtPreviousAttempt must be passed into IsObjectiveMeasureKnown");
	}
	
	if (this.IsTracked() === false){
		return false;
	}
	
	var objective = this.FindObjective(referencedObjective);
	
	//change made to be consistent with Addendum 3.4 of SCORM 2004 2nd Edition
	//if (objective.GetProgressStatus(this) === true && objective.GetMeasureStatus() === true){
	if (objective.GetMeasureStatus(this, canLookAtPreviousAttempt) === true){
		return true;
	}
	else{
		return false;
	}
}


function Activity_IsObjectiveMeasureGreaterThan(referencedObjective, measureThreshold, canLookAtPreviousAttempt){

	if (canLookAtPreviousAttempt === null || canLookAtPreviousAttempt === undefined){
		Debug.AssertError("ERROR - canLookAtPreviousAttempt must be passed into IsObjectiveMeasureGreaterThan");
	}

	if (this.IsTracked() === false){
		return RESULT_UNKNOWN;
	}
	
	var objective = this.FindObjective(referencedObjective);
	
	if (objective.GetMeasureStatus(this, canLookAtPreviousAttempt) === true){
		if (objective.GetNormalizedMeasure(this, canLookAtPreviousAttempt) > measureThreshold){
			return true;
		}
		else{
			return false;
		}
	}
	else{
		return RESULT_UNKNOWN;
	}
}

function Activity_IsObjectiveMeasureLessThan(referencedObjective, measureThreshold, canLookAtPreviousAttempt){

	if (canLookAtPreviousAttempt === null || canLookAtPreviousAttempt === undefined){
		Debug.AssertError("ERROR - canLookAtPreviousAttempt must be passed into IsObjectiveMeasureLessThan");
	}
		
	if (this.IsTracked() === false){
		return RESULT_UNKNOWN;
	}
	
	var objective = this.FindObjective(referencedObjective);
	
	Debug.AssertError("The objective referenced by a sequencing rule was not found. Does the definition of the sequencing rule in the manifest erroneously reference the name of the global objective instead of the local name of the objective? Problematic reference=" + referencedObjective, (objective === null));
	
	if (objective.GetMeasureStatus(this, canLookAtPreviousAttempt) === true){
		if (objective.GetNormalizedMeasure(this, canLookAtPreviousAttempt) < measureThreshold){
			return true;
		}
		else{
			return false;
		}
	}
	else{
		return RESULT_UNKNOWN;
	}
}

function Activity_GetObjectiveMeasure(canLookAtPreviousAttempt){
	
	if (canLookAtPreviousAttempt === null || canLookAtPreviousAttempt === undefined){
		Debug.AssertError("ERROR - canLookAtPreviousAttempt must be passed into GetObjectiveMeasure");
	}
	
	if (this.IsTracked() === false){
		return RESULT_UNKNOWN;
	}
	
	var objective = this.GetPrimaryObjective();
	
	if (objective.GetMeasureStatus(this, canLookAtPreviousAttempt) === true){
		 return objective.GetNormalizedMeasure(this, canLookAtPreviousAttempt);
	}
	else{
		return RESULT_UNKNOWN;
	}
}

function Activity_IsCompleted(canLookAtPreviousAttempt){
	
	if (canLookAtPreviousAttempt === null || canLookAtPreviousAttempt === undefined){
		//Debug.AssertError("ERROR - canLookAtPreviousAttempt must be passed into IsSatisfied");
		canLookAtPreviousAttempt = false;	//don't throw an error because this is called from integrations that were in place before we added this parameter for 3rd Edition
	}
	
	if (this.IsTracked() === false){
		return RESULT_UNKNOWN;
	}
	
	
	var attemptProgressStatus;
	var attemptCompletionStatus;
	
	//when evaluating sequencing rules, if there was a previous attempt, and the current activity hasn't been
	//attempted during the current attempt on the parent, use the previous attempt's data
	if (canLookAtPreviousAttempt === true && this.WasAttemptedDuringThisAttempt() === false){
		attemptProgressStatus = this.PrevAttemptProgressStatus;
		attemptCompletionStatus = this.PrevAttemptCompletionStatus;
	}
	else{
		attemptProgressStatus = this.AttemptProgressStatus;
		attemptCompletionStatus = this.AttemptCompletionStatus;
	}
	
	if (attemptProgressStatus === true){
		if (attemptCompletionStatus === true){
			return true;
		}
		else{
			return false;
		}
	}
	else{
		return RESULT_UNKNOWN;
	}
	
}

function Activity_IsActivityProgressKnown(canLookAtPreviousAttempt){
	
	if (canLookAtPreviousAttempt === null || canLookAtPreviousAttempt === undefined){
		Debug.AssertError("ERROR - canLookAtPreviousAttempt must be passed into IsActivityProgressKnown");
		//canLookAtPreviousAttempt = false;
	}
	
	if (this.IsTracked() === false){
		return false;
	}
	
	var activityProgressStatus = this.ActivityProgressStatus;
	var attemptProgressStatus;
	
	if (canLookAtPreviousAttempt === true && this.WasAttemptedDuringThisAttempt() === false){
		attemptProgressStatus = this.PrevAttemptProgressStatus;
	}
	else{
		attemptProgressStatus = this.AttemptProgressStatus;
	}
	
	
	if (activityProgressStatus === true && 
	    attemptProgressStatus === true){
		
		return true;    
	}
	
	return false;
}

function Activity_IsAttempted(){
	
	if (this.IsTracked() === false){
		return RESULT_UNKNOWN;
	}
	
	if (this.ActivityProgressStatus === true){
		
		if (this.GetAttemptCount() > 0){
			return true;
		}
	}
	else{
		return RESULT_UNKNOWN;
	}
	
	return false;
}


function Activity_IsAttemptLimitExceeded(){
	
	if (this.IsTracked() === false){
		return RESULT_UNKNOWN;
	}
	
	//TODO - if LimitConditionAttemptControl === false, do we return false or unknown? is it unknown b/c (true && unknown) == unknown?
	
	if (this.ActivityProgressStatus === true){
		
		if (this.GetLimitConditionAttemptControl() === true){
			
			if (this.GetAttemptCount() >= this.GetLimitConditionAttemptLimit()){
				return true;
			}
		}
	}
	else{
		return RESULT_UNKNOWN;
	}
	
	return false;
}

function Activity_GetObjectives(){
	return this.ActivityObjectives;
}

function Activity_FindObjective(objectiveIdentifier){
	
	//if the identifer is null or "", returns the primaryObjective
	
	var objectives = this.GetObjectives();
	
	for (var i=0; i < objectives.length; i++){
		
		if (objectiveIdentifier === "" || objectiveIdentifier === null){
			if (objectives[i].GetContributesToRollup() === true){
				return objectives[i];
			}
		}
		else{
			if (objectives[i].GetIdentifier() == objectiveIdentifier){
				return objectives[i];
			}
		}
	}
	
	return null;
}


function Activity_GetPrimaryObjective(){

	if (this.CachedPrimaryObjective	=== null){
		var targetObjective = null;
		
		var objectives = this.GetObjectives();
		for (var i=0; i < objectives.length; i++){
			
			if (objectives[i].GetContributesToRollup() === true){
			
				targetObjective = objectives[i];
				
				break;
			}
		}
		
		this.CachedPrimaryObjective = targetObjective;
	}
	
	if (this.CachedPrimaryObjective === null){
		Debug.AssertError("Could not find a primary objective.");
	}
	
	return this.CachedPrimaryObjective;
}

function Activity_GetRollupObjectiveMeasureWeight(){
	
	var weight = this.LearningObject.SequencingData.RollupObjectiveMeasureWeight;
	weight = parseFloat(weight);
	
	return weight;
}

function Activity_GetMeasureSatisfactionIfActive(){
	var measureSatisfiaction = this.LearningObject.SequencingData.MeasureSatisfactionIfActive;
	return measureSatisfiaction;
}

function Activity_GetRollupRules(){
	var rules = this.LearningObject.SequencingData.RollupRules;
	return rules;
}

function Activity_GetRollupObjectiveSatisfied(){
	var rollupObjectiveSatisfied = this.LearningObject.SequencingData.RollupObjectiveSatisfied;
	return rollupObjectiveSatisfied;
}

function Activity_GetRequiredForSatisfied(){
	var requiredForSatisfied = this.LearningObject.SequencingData.RequiredForSatisfied;
	return requiredForSatisfied;
}

function Activity_GetRequiredForNotSatisfied(){
	var requiredForNotSatisfied = this.LearningObject.SequencingData.RequiredForNotSatisfied;
	return requiredForNotSatisfied;
}

function Activity_RollupProgressCompletion(){
	var rollupProgressCompletion = this.LearningObject.SequencingData.RollupProgressCompletion;
	return rollupProgressCompletion;
}

function Activity_GetRequiredForCompleted(){
	var requiredForCompelted = this.LearningObject.SequencingData.RequiredForCompleted;
	return requiredForCompelted;
}

function Activity_GetRequiredForIncomplete(){
	var requiredForIncomplete = this.LearningObject.SequencingData.RequiredForIncomplete;
	return requiredForIncomplete;
}

function Activity_IncrementAttemptCount(){
	this.ActivityAttemptCount++;
}

function Activity_SetRandomizedChildren(value){
	this.RandomizedChildren = value;
	this.SetDirtyData();
}

function Activity_SetSelectedChildren(value){
	this.SelectedChildren = value;
	this.SetDirtyData();
}	

function Activity_GetRandomizedChildren(){
	var randomized = this.RandomizedChildren;
	return randomized;
}

function Activity_GetSelectedChildren(){
	var selected = this.SelectedChildren;
	return selected;
}

function Activity_GetActivityListBetweenChildren(startActivity, endActivity, includeEndActivity){
			
	var activityList = this.GetAvailableChildren();
	var aryReturn = new Array();
	
	var startActivityIndex = null;
	var endActivityIndex = null;
	
	for (var i=0; i < activityList.length; i++){
		if (startActivity == activityList[i]){
			startActivityIndex = i;
		}
		
		if (endActivity == activityList[i]){
			endActivityIndex = i;
		}			
	}
	
	if (startActivityIndex == endActivityIndex){
		if (includeEndActivity){
			aryReturn[0] = activityList[startActivityIndex];
		}
	}
	
	else if(startActivityIndex < endActivityIndex){
		if (includeEndActivity){
			endActivityIndex ++;
		}
		aryReturn = activityList.slice(startActivityIndex, endActivityIndex);
	}
	
	else if(startActivityIndex > endActivityIndex){
		if (!includeEndActivity){
			endActivityIndex ++;
		}
		
		aryReturn = activityList.slice(endActivityIndex, startActivityIndex + 1);
	}
	
	return aryReturn;
}


function Activity_IsActivityAnAvailableChild(activity){
	var availableChildren = this.GetAvailableChildren();
	
	for (var i=0; i < availableChildren.length; i++){
		if (availableChildren[i] == activity){
			return true;
		}
	}
	
	return false;
}

function Activity_IsActivityAnAvailableDescendent(activityToFind){

	return Activity_SearchAllAvailableDescendents(this, activityToFind);
	
}

function Activity_SearchAllAvailableDescendents(activityToSearch, activityToFind){
	
	var availableChildren = activityToSearch.GetAvailableChildren();
	
	for (var i=0; i < availableChildren.length; i++){
		
		if (availableChildren[i] == activityToFind){
			return true;
		}
				
		if (Activity_SearchAllAvailableDescendents(availableChildren[i], activityToFind)){
			return true;
		}
		
	}
	
	return false;
}

function Activity_IsActivityTheLastAvailableChild(activity){
	
	var availableChildren = this.GetAvailableChildren();
	
	if (availableChildren[availableChildren.length - 1] == activity){
		return true;
	}
	
	return false;
}

function Activity_IsActivityTheFirstAvailableChild(activity){
	
	var availableChildren = this.GetAvailableChildren();
	
	if (availableChildren[0] == activity){
		return true;
	}
	
	return false;
}

function Activity_GetFirstAvailableChild(){
	var availableChildren = this.GetAvailableChildren();
	return availableChildren[0];
}

function Activity_GetNextActivity(currentActivity){
	
	var currentActivityIndex = null;
	
	var parentActivity = currentActivity.ParentActivity;
	var availableChildren = parentActivity.GetAvailableChildren();
	
	for (var i=0; i < availableChildren.length; i++){
		if (availableChildren[i] == currentActivity){
			currentActivityIndex = i;
			break;
		}
	}
	
	if (currentActivityIndex !== null && currentActivityIndex < (availableChildren.length - 1)){
		return availableChildren[currentActivityIndex + 1];
	}
	
	return null;
}

function Actvity_GetPreviousActivity(currentActivity){
	
	var currentActivityIndex = null;
	
	var parentActivity = currentActivity.ParentActivity;
	var availableChildren = parentActivity.GetAvailableChildren();
	
	for (var i=0; i < availableChildren.length; i++){
		if (availableChildren[i] == currentActivity){
			currentActivityIndex = i;
			break;
		}
	}

	if (currentActivityIndex !== null && currentActivityIndex > 0){
		return availableChildren[currentActivityIndex - 1];
	}
	
	return null;
}


function Activity_InitializeAvailableChildren(){
	
	//go through and find all the children that are included
	//if none are included, then include them all

	var allChildren = this.GetChildren();
	var includedChildren = new Array();
	
	for (var i=0; i < allChildren.length; i++){
		if (allChildren[i].Included === true){
			includedChildren[includedChildren.length] = allChildren[i];
		}
	}
	
	if (includedChildren.length === 0){
		this.SetAvailableChildren(allChildren);
	}
	else{
		//sort the array based on the values of the ordinals
		includedChildren.sort(
								function (activity1, activity2){
									
									var ordinal1 = activity1.Ordinal;
									var ordinal2 = activity2.Ordinal;
									
									if (ordinal1 < ordinal2){
										return -1;	//value less than 0 means arguement 1 is first
									}
									else if (ordinal2 > ordinal1){
										return 1;	//value greater than 0 means arguement 2 is first
									}
									else{
										return 0;	//0 indicates that the arguments are equilivant
									}
								}
							);

		this.SetAvailableChildren(includedChildren);
	}
	
}

function Activity_GetAvailableChildren(){

	//we can't initialize these in the constructor because the constructor relies on the ObjectRepository being populated
	//Since the object repository is still being populated when these objects are created, we can't rely on it

	if (this.AvailableChildren === null){
		this.InitializeAvailableChildren();
	}
	
	return this.AvailableChildren;
}


/*
function Activity_GetUnAvailableChildren(){
//TODO: - is this used any more?	
	var allChildren = this.GetChildren();
	var unavailableChildren = new Array();
	
	for (var i=0; i < allChildren.length; i++){
		if (allChildren[i].Included === false){
			unavailableChildren[unavailableChildren.length] = allChildren[i];
		}
	}
	
	return unavailableChildren;
}
*/
function Activity_SetAvailableChildren(childArray){

	this.AvailableChildren = childArray;
	
	//reset all included and ordinal fields
	var allChildren = this.GetChildren();
	
	var i;
	
	for (i=0; i < allChildren.length; i++){
		allChildren[i].Ordinal = 0;
		allChildren[i].Included = false;
	}
	
	for (i=0; i < this.AvailableChildren.length; i++){
		this.AvailableChildren[i].Ordinal = (i + 1);
		this.AvailableChildren[i].Included = true;
	}

	this.SetDirtyData();

}

function Activity_IsAvailable(){
	return this.Included;
}

function Activity_InitializeForNewAttempt(resetObjectives, resetAttemptState){
	
	//Initialize Objective Progress Information and Attempt Progress Information required for the new attempt. Initialize tracking information for the new attempt.
	//We need to reset the attempt data if only the current attempt is relevent
	
	var i;
	
	this.AttemptedDuringThisAttempt = false;
	
	var objectives = this.GetObjectives();
	
	if (resetObjectives && this.LearningObject.SequencingData.UseCurrentAttemptObjectiveInformation === true){
		
		resetObjectives = true;
	
		for (i=0; i < objectives.length; i++){
			objectives[i].ResetAttemptState();
		}
	}
	else{
		resetObjectives = false;
	}
	
	if (resetAttemptState && this.LearningObject.SequencingData.UseCurrentAttemptProgressInformation === true){
		
		resetAttemptState = true;
		
		this.ResetAttemptState();
	}
	else{
		resetAttemptState = false;
	}

	
	var children = this.GetChildren();
	
	for (i=0; i < children.length; i++){
		children[i].InitializeForNewAttempt(resetObjectives, resetAttemptState);
	}
	
	this.SetDirtyData();
}



function Activity_ResetAttemptState(){
		
	this.PrevAttemptProgressStatus = this.AttemptProgressStatus;
	this.PrevAttemptCompletionStatus = this.AttemptCompletionStatus;
		
	this.AttemptProgressStatus = false;
	this.AttemptCompletionAmount = 0;
	this.AttemptCompletionStatus = false;
	
	this.AttemptAbsoluteDuration = 0;
	this.AttemptExperiencedDuration = 0;
	
	this.SetDirtyData();
}


function Activity_SetDirtyData(){
	this.DataState = DATA_STATE_DIRTY;
}

function Activity_IsAnythingDirty(){
	if (this.DataState == DATA_STATE_DIRTY){
		return true;
	}
	
	for (var i=0; i < this.ActivityObjectives.length; i++){
		if (this.ActivityObjectives[i].DataState == DATA_STATE_DIRTY){
			return true;
		}
	}
	
	return false;
}

function Activity_MarkPostedObjectiveDataDirty(){
	for (var i=0; i < this.ActivityObjectives.length; i++){
		if (this.ActivityObjectives[i].DataState == DATA_STATE_POSTED){
			this.ActivityObjectives[i].SetDirtyData();
		}
	}
}

function Activity_MarkPostedObjectiveDataClean(){
	for (var i=0; i < this.ActivityObjectives.length; i++){
		if (this.ActivityObjectives[i].DataState == DATA_STATE_POSTED){
			this.ActivityObjectives[i].DataState = DATA_STATE_CLEAN;
		}
	}
}

function Activity_MarkDirtyObjectiveDataPosted(){
	for (var i=0; i < this.ActivityObjectives.length; i++){
		if (this.ActivityObjectives[i].DataState == DATA_STATE_DIRTY){
			this.ActivityObjectives[i].DataState = DATA_STATE_POSTED;
		}
	}
}

function Activity_SetSequencer(sequencer, isLookAhead){
	
	this.Sequencer = sequencer;
	this.LookAheadActivity = isLookAhead;
	
	for (var i=0; i < this.ActivityObjectives.length; i++){
		this.ActivityObjectives[i].SetSequencer(sequencer);
	}
}


function Activity_Clone(){

	var clone = new Activity (
				this.DatabaseId,
				this.ScormObjectDatabaseId, 
				this.ActivityProgressStatus, 
				this.ActivityAbsoluteDuration, 
				this.ActivityExperiencedDuration, 
				this.ActivityAttemptCount,
				this.AttemptProgressStatus,
				this.AttemptCompletionAmount,
				this.AttemptCompletionStatus,
				this.AttemptAbsoluteDuration,
				this.AttemptExperiencedDuration,
				this.Active,
				this.Suspended,
				this.Included,
				this.Ordinal,
				this.SelectedChildren,
				this.RandomizedChildren,
				null,
				null);
	
	clone.StringIdentifier = this.toString();
	
	clone.ActivityObjectives = new Array();
	for (var objectiveId in this.ActivityObjectives){
		clone.ActivityObjectives[objectiveId] = this.ActivityObjectives[objectiveId].Clone();
	}
	
	clone.RunTime = this.RunTime;
	clone.LearningObject = this.LearningObject;
	
	clone.DataState = DATA_STATE_CLEAN;
	
	clone.LaunchedThisSession = this.LaunchedThisSession;
	
	return clone;		

}

function Activity_TearDown(){

	this.StringIdentifier = null;
	this.DatabaseId = null; 
	this.ScormObjectDatabaseId = null; 
	this.ActivityProgressStatus = null; 
	this.ActivityAbsoluteDuration = null; 
	this.ActivityExperiencedDuration = null; 
	this.ActivityAttemptCount = null;
	this.AttemptProgressStatus = null;
	this.AttemptCompletionAmount = null;
	this.AttemptCompletionStatus = null;
	this.AttemptAbsoluteDuration = null;
	this.AttemptExperiencedDuration = null;
	this.Active = null;
	this.Suspended = null;
	this.Included = null;
	this.Ordinal = null;
	this.SelectedChildren = null;
	this.RandomizedChildren = null;
	this.RunTime = null;
	this.Sequencer = null;
	this.LookAheadActivity = null;
	this.LearningObject = null;
	this.ParentActivity = null;
	this.AvailableChildren = null;
	this.DataState = null;
	this.MenuItem = null;
	this.ChildActivities = null;
	this.CachedPrimaryObjective = null;
	this.HiddenFromChoice = null;
	
	for (var objectiveId in this.ActivityObjectives){
		this.ActivityObjectives[objectiveId].TearDown();
		this.ActivityObjectives[objectiveId] = null;
	}
	
	this.ActivityObjectives = null;
}

function Activity_DisplayInChoice(){
	
	if (this.LearningObject.Visible === false){	
		return false;
	}
	else if (this.IsAvailable() === false){
		return false;
	}
	else if (this.HiddenFromChoice === true){
		return false;
	}
	
	return true;
}

function Activity_SetHiddenFromChoice(blnArg){
	this.HiddenFromChoice = blnArg;
}

function Activity_WasLaunchedThisSession(){
	return this.LaunchedThisSession;
}

function Activity_SetLaunchedThisSession(){
	this.LaunchedThisSession = true;
}

function Activity_WasAttemptedDuringThisAttempt(){
	return this.AttemptedDuringThisAttempt;
}
function Activity_SetAttemptedDuringThisAttempt(){
	this.AttemptedDuringThisAttempt = true;
}
