/*
* ASCLITE
* Author: Jerome Ajot, Jon Fiscus, Nicolas Radde, Chris Laprun
*
* This software was developed at the National Institute of Standards and Technology by
* employees of the Federal Government in the course of their official duties. Pursuant
* to title 17 Section 105 of the United States Code this software is not subject to
* copyright protection and is in the public domain. ASCLITE is an experimental system.
* NIST assumes no responsibility whatsoever for its use by other parties, and makes no
* guarantees, expressed or implied, about its quality, reliability, or any other
* characteristic. We would appreciate acknowledgement if the software is used.
*
* THIS SOFTWARE IS PROVIDED "AS IS." With regard to this software, NIST MAKES NO EXPRESS
* OR IMPLIED WARRANTY AS TO ANY MATTER WHATSOEVER, INCLUDING MERCHANTABILITY,
* OR FITNESS FOR A PARTICULAR PURPOSE.
*/
/**
* Internal representation of a segment.
* A segment is a list of Token.
*/
#include "segment.h" // class's header file
#include "speech.h"
#include "speechset.h"
Logger* Segment::logger = Logger::getLogger();
Segment* Segment::CreateWithDuration(const int& _startTime, const int& _duration, Speech* parent)
{
Segment* segment = new Segment();
segment->speech = parent;
return (Segment*) segment->InitWithDuration(_startTime, _duration);
}
Segment* Segment::CreateWithEndTime(const int& _startTime, const int& _endTime, Speech* parent)
{
Segment* segment = new Segment();
segment->speech = parent;
return (Segment*) segment->InitWithEndTime(_startTime, _endTime);
}
bool Segment::AreStartTimeAndEndTimeValid(const int& _startTime, const int& _endTime)
{
if(!TimedObject::AreStartTimeAndEndTimeValid(_startTime, _endTime))
return false;
return _startTime <= GetLowestTokenStartTime() && _endTime >= GetHighestTokenEndTime();
}
/**
* Merge all Segments in one segments
*/
Segment* Segment::Merge(const vector & segments)
{
int start=INT_MAX, end=0;
Token* t_start = NULL;
Token* t_end = NULL;
Segment* currentSegment = NULL;
for (size_t i=0 ; i < segments.size() ; ++i)
{
currentSegment = segments[i];
if (currentSegment->GetStartTime() < start)
{
t_start = currentSegment->f_token;
start = currentSegment->GetStartTime();
}
if (currentSegment->GetEndTime() > end)
{
t_end = currentSegment->l_token;
end = currentSegment->GetEndTime();
}
}
Segment* seg = Segment::CreateWithEndTime(start, end, currentSegment->GetParentSpeech());
seg->f_token = t_start;
seg->l_token = t_end;
return seg;
}
int Segment::GetLowestTokenStartTime()
{
int lowestStartTime = 0;
for(size_t i = 0; i < f_token->GetNbOfNextTokens() ; ++i)
{
int sTime = f_token->GetNextToken(i)->GetStartTime();
if(sTime < lowestStartTime)
lowestStartTime = sTime;
}
return lowestStartTime;
}
int Segment::GetHighestTokenEndTime()
{
int highestEndTime = 0;
for(size_t i = 0; i < l_token->GetNbOfNextTokens() ; ++i)
{
int eTime = l_token->GetNextToken(i)->GetEndTime();
if(eTime < highestEndTime)
highestEndTime = eTime;
}
return highestEndTime;
}
// class constructor
Segment::Segment()
{
//f_token = new Token();
f_token = Token::CreateWithEndTime(0, 0, this);
l_token = Token::CreateWithEndTime(0, 0, this);
ignoreSegmentInScoring = false;
}
// class destructor
Segment::~Segment()
{
vector listAllTokens = ToTopologicalOrderedStruct();
for(size_t i=0; i\n\tspkrId='" << GetSpeakerId()
<< "' src='" << GetSource() << "' chnl='" << GetChannel() << "'" << endl;
vector tokens = ToTopologicalOrderedStruct();
Token* token;
for(size_t i = 0; i < tokens.size(); ++i)
{
token = tokens[i];
if(token != NULL)
oss << "\t" << token->ToString() << endl;
}
oss << "";
return oss.str();
}
string Segment::ToStringAsLine()
{
std::ostringstream oss;
oss << " tokens = ToTopologicalOrderedStruct();
Token* token;
for(size_t i = 0; i < tokens.size(); ++i)
{
token = tokens[i];
if(token != NULL)
oss << " " << token->ToString();
}
return oss.str();
}
// sets the value of token
void Segment::AddFirstToken(Token* token)
{
if (token->GetStartTime() != -1 && (token->GetStartTime() < this->GetStartTime()))
{
char buffer[BUFFER_SIZE];
sprintf(buffer, "Segment: Tried to add a token with start time before begin of segment file ='%s' tkn='%s' src=%s chnl=%s st=%d et=%d seg: st=%d et=%d",
GetParentSpeech()->GetParentSpeechSet()->GetSourceFileName().c_str(),
token->GetText().c_str(), GetSource().c_str(), GetChannel().c_str(), token->GetStartTime(), token->GetEndTime(), GetStartTime(), GetEndTime());
LOG_FATAL(logger, buffer);
exit(E_INVALID);
}
else
{
f_token->AddNextToken(token);
}
}
// sets the value of token
void Segment::AddLastToken(Token* token)
{
if (token->GetEndTime() != -1 && (token->GetEndTime() > this->GetEndTime()))
{
char buffer[BUFFER_SIZE];
sprintf(buffer, "Segment: Tried to add a token with start time before begin of segment file ='%s' tkn='%s' src=%s chnl=%s st=%d et=%d seg: st=%d et=%d",
GetParentSpeech()->GetParentSpeechSet()->GetSourceFileName().c_str(),
token->GetText().c_str(), GetSource().c_str(), GetChannel().c_str(), token->GetStartTime(), token->GetEndTime(), GetStartTime(), GetEndTime());
LOG_FATAL(logger, buffer);
exit(E_INVALID);
}
else
{
l_token->AddNextToken(token);
}
}
/**
* Output a plan version of the segment.
* Put them on a topological order.
*/
vector Segment::ToTopologicalOrderedStruct()
{
vector res;
for(size_t i = 0 ; i < f_token->GetNbOfNextTokens() ; ++i)
{
Token* token = f_token->GetNextToken(i);
res.push_back(token);
ToTopologicalOrderedStruct(token, &res);
}
return res;
}
/**
* Recurs methods to compute a topological order of a graph
*/
void Segment::ToTopologicalOrderedStruct(Token* start, vector* doneNode)
{
if (!isLastToken(start))
{
for(size_t i = 0 ; i < start->GetNbOfNextTokens() ; ++i)
{
Token* token = start->GetNextToken(i);
if (find(doneNode->begin(), doneNode->end(), token) == doneNode->end())
{
doneNode->push_back(token);
ToTopologicalOrderedStruct(token, doneNode);
}
}
}
}
/**
* Return if the token is on the list of the First tokens.
*/
bool Segment::isFirstToken(Token* token)
{
for(size_t i = 0 ; i < f_token->GetNbOfNextTokens() ; ++i)
if (f_token->GetNextToken(i) == token)
return true;
return false;
}
/**
* Return if the token is on the list of the last tokens.
*/
bool Segment::isLastToken(Token* token)
{
for(size_t i = 0 ; i < l_token->GetNbOfNextTokens() ; ++i)
if (l_token->GetNextToken(i) == token)
return true;
return false;
}
/**
* Return the parent Speech
*/
Speech* Segment::GetParentSpeech()
{
return speech;
}
/** Determines if case is taken into account to align Tokens part of this Speech. */
bool Segment::PerformCaseSensitiveAlignment()
{
return speech->PerformCaseSensitiveAlignment();
}
/** Determines if fragments are considered as correct when aligning Tokens part of this Speech. */
bool Segment::AreFragmentsCorrect()
{
return speech->AreFragmentsCorrect();
}
/** Determines if optionally deletable Tokens need to be accounted for. */
bool Segment::UseOptionallyDeletable()
{
return speech->UseOptionallyDeletable();
}
/** Replaces the token with a linked list of tokens. The initial token is NOT deleted **/
void Segment:: ReplaceTokenWith(Token *token, const vector & startTokens, const vector & endTokens)
{
// Store a list of prev tokens to avoid continual adding of tokens!!!
vectorprevTokens;
for (size_t p=0; pGetNbOfPrecTokens(); ++p)
prevTokens.push_back(token->GetPrecToken(p));
// Do the link
for (size_t s = 0; sLinkTokens(startTokens[s]);
// Link in the Starts
if (isFirstToken(token))
for (size_t s = 0; snextTokens;
for (size_t n=0; nGetNbOfNextTokens(); ++n)
nextTokens.push_back(token->GetNextToken(n));
// Do the link
for (size_t e = 0; eLinkTokens(nextTokens[n]);
// Link in the End
if (isLastToken(token))
for (size_t e = 0; eUnlinkNextToken(token);
if(isLastToken(token))
l_token->UnlinkNextToken(token);
while(token->GetNbOfPrecTokens() > 0)
token->GetPrecToken(0)->UnlinkTokens(token);
while(token->GetNbOfNextTokens() > 0)
token->UnlinkTokens(token->GetNextToken(0));
// cleanup
prevTokens.clear();
nextTokens.clear();
}
int Segment::GetMinTokensTime()
{
int minTime = -1;
vector vectok = ToTopologicalOrderedStruct();
for(size_t veci=0; veciGetStartTime() < minTime) )
minTime = vectok[veci]->GetStartTime();
vectok.clear();
return minTime;
}
int Segment::GetMaxTokensTime()
{
int maxTime = -1;
vector vectok = ToTopologicalOrderedStruct();
for(size_t veci=0; veciGetEndTime() > maxTime) )
maxTime = vectok[veci]->GetStartTime();
vectok.clear();
return maxTime;
}
void Segment::SetTokensOptionallyDeletable()
{
vector vectok = ToTopologicalOrderedStruct();
for(size_t veci=0; veciBecomeOptionallyDeletable();
}
vectok.clear();
}