Скачиваний:
16
Добавлен:
01.05.2014
Размер:
19.45 Кб
Скачать
unit Attribute;

interface

uses
Classes,
DmmConstants,
DmmTypes,
FastVector,
StandardSerializableObject,
SysUtils,
Utils;

type
{Класс,который хранит сведения о номинальном атрибуте}
TDMNominalAttributeValue = class;

{Класс итератор для перебора значений типа TDMNominalAttributeValue}
TDMNominalAttributeValueEnumeration = class;

{Класс, который хранит сведения об аттрибуте}
TDMAttribute = class( TDMStandardSerializableObject )
protected
m_Name : AnsiString;
m_Type : Integer;
m_Values : TDMFastVector;
m_Index : Integer;
m_Ordering : Integer;
m_Weight : Double;
m_LowerBound : Double;
m_UpperBound : Double;
m_IsRegular : Boolean;
m_IsAveragable : Boolean;
m_HasZeroPoint : Boolean;
m_LowerBoundIsOpen : Boolean;
m_UpperBoundIsOpen : Boolean;

public
constructor Create( attributeName : AnsiString ); overload;
constructor Create( attributeName : AnsiString; attributeValues : TDMFastVector ); overload;

function addStringValue( value : AnsiString ) : Integer; overload;
function addStringValue( attribute : TDMAttribute; const index : Integer ) : Integer; overload;

function numValues : Integer;
function indexOfValue( value : AnsiString ) : Integer;
function enumerateValues : TDMNominalAttributeValueEnumeration;
function value( const valIndex : Integer ) : AnsiString;
procedure delete( const valIndex : Integer );
procedure setValue( const valIndex : Integer; value : AnsiString );

function name : AnsiString;
function index : Integer;
function attributeType : Integer;
function weight : Double;
function ordering : Integer;
procedure setName( name : AnsiString );

procedure setIndex( const index : Integer );
procedure setAttributeType( const attributeType : Integer );
procedure setWeight( const weight : Double );
procedure setOrdering( const ordering : Integer );

function hasZeropoint : Boolean;
function isAveragable : Boolean;
function isRegular : Boolean;

function isNominal : Boolean;
function isNumeric : Boolean;
function isString : Boolean;

function isInRange( const value : Double ) : Boolean;

function getLowerNumericBound : Double;
function getUpperBumericBound : Double;
procedure setUpperNumericBound( const upperBound : Double );
procedure setLowerNumericBound( const lowerBound : Double );

function lowerNumericBoundIsOpen : Boolean;
function upperNumericBoundIsOpen : Boolean;

function copyObject : TObject; override;
function cloneObject : TObject; override;

function equals( otherObject : TObject ) : Boolean; override;

procedure serializeObject( ostream : TStream ); override;
procedure deserializeObject( istream : TStream ); override;

function toString : AnsiString; override;

function attrType():integer;
function getAttrType():AnsiString;

constructor Create (attributeName : AnsiString; index : integer); overload;

constructor Create (attributeName : AnsiString; attributeValues : TDMFastVector;
index : integer); overload;
destructor Destroy(); override;
end;

TDMNominalAttributeValueEnumeration = class( TDMFastVectorEnumeration )
public
constructor Create( attribute : TDMAttribute );

function hasMoreElements : Boolean; override;
function nextElement : TDMNominalAttributeValue; reintroduce;
end;


TDMNominalAttributeValue = class( TDMStandardSerializableObject )
public
m_Name : AnsiString;

constructor Create( name : AnsiString );

function cloneObject : TObject; override;
function copyObject : TObject; override;
function equals( otherObject : TObject ) : Boolean; override;
function toString : AnsiString; override;

procedure serializeObject( ostream : TStream ); override;
procedure deserializeObject( istream : TStream ); override;
end;

implementation

constructor TDMAttribute.Create( attributeName : AnsiString );
begin
m_Type := ATTRIBUTE_TYPE_NUMERIC;
m_Name := attributeName;
m_Ordering := ATTRIBUTE_ORDERING_ORDERED;
m_Index := -1;
m_upperBoundIsOpen := true;
m_lowerBoundIsOpen := true;
m_IsRegular := true;
m_HasZeroPoint := true;
m_IsAveragable := true;
m_Values := nil;
m_Weight := 1.0;
end;

constructor TDMAttribute.Create( attributeName : AnsiString; attributeValues : TDMFastVector );
begin
if attributeValues = nil then
m_Type := ATTRIBUTE_TYPE_STRING
else
m_Type := ATTRIBUTE_TYPE_NOMINAL;

m_Ordering := ATTRIBUTE_ORDERING_ORDERED;

m_Name := attributeName;
m_Values := attributeValues.copyObject as TDMFastVector;
m_Index := -1;
m_IsRegular := false;
m_HasZeroPoint := false;
m_IsAveragable := false;
m_Weight := 1.0;
end;

constructor TDMAttribute.Create (attributeName : AnsiString; index : integer);
begin
self.Create(attributeName);
m_Index := index;
end;

constructor TDMAttribute.Create (attributeName : AnsiString; attributeValues : TDMFastVector;
index : integer);
begin
self.Create(attributeName, attributeValues);
m_Index := index;
end;

function TDMAttribute.attrType():integer;
begin
Result := m_Type;
end;

function TDMAttribute.getAttrType():AnsiString;
begin
Result := 'тип не определен';
if m_Type = 1 then
Result := 'числовой';
if m_Type = 2 then
Result := 'номинальный';
if m_Type = 3 then
Result := 'строковый';
if m_Type = 4 then
Result := 'дата';
end;

function TDMAttribute.name : AnsiString;
begin
Result := m_Name;
end;

function TDMAttribute.index : Integer;
begin
Result := m_Index;
end;

function TDMAttribute.attributeType : Integer;
begin
Result := m_Type;
end;

function TDMAttribute.weight : Double;
begin
Result := m_Weight;
end;

function TDMAttribute.hasZeropoint : Boolean;
begin
Result := m_HasZeroPoint;
end;

function TDMAttribute.isAveragable : Boolean;
begin
Result := m_IsAveragable;
end;

function TDMAttribute.isRegular : Boolean;
begin
Result := m_IsRegular;
end;

function TDMAttribute.isNominal : Boolean;
begin
Result := m_Type = ATTRIBUTE_TYPE_NOMINAL;
end;

function TDMAttribute.isNumeric : Boolean;
begin
Result := m_Type = ATTRIBUTE_TYPE_NUMERIC;
end;

function TDMAttribute.isString : Boolean;
begin
Result := m_Type = ATTRIBUTE_TYPE_STRING;
end;

function TDMAttribute.getLowerNumericBound : Double;
begin
Result := m_LowerBound;
end;

function TDMAttribute.getUpperBumericBound : Double;
begin
Result := m_UpperBound;
end;

function TDMAttribute.lowerNumericBoundIsOpen : Boolean;
begin
Result := m_LowerBoundIsOpen;
end;

function TDMAttribute.upperNumericBoundIsOpen : Boolean;
begin
Result := m_UpperBoundIsOpen;
end;

function TDMAttribute.numValues : Integer;
begin
if ( m_Type <> ATTRIBUTE_TYPE_NOMINAL ) and ( m_Type <> ATTRIBUTE_TYPE_STRING ) then Result := 0
else
if ( m_Values = nil ) then Result := 0
else Result := m_Values.size;
end;

function TDMAttribute.addStringValue( value : AnsiString ) : Integer;
var
store : TDMNominalAttributeValue;
index : Integer;
begin
if ( m_Type <> ATTRIBUTE_TYPE_STRING ) then Result := -1
else
begin
store := TDMNominalAttributeValue.Create( value );
index := m_Values.indexOf( store );
if ( index >= 0 ) then
begin
store.Destroy;
Result := index;
end
else
begin
m_Values.addElement( store );
Result := m_Values.size - 1;
end;
end;
end;

function TDMAttribute.addStringValue( attribute : TDMAttribute; const index : Integer ) : Integer;
var
navobject : TDMNominalAttributeValue;
begin
Result := -1;
if ( m_Type = ATTRIBUTE_TYPE_STRING ) and ( attribute <> nil ) then
begin
navobject := attribute.m_Values.elementAt( index ) as TDMNominalAttributeValue;
Result := addStringValue( navobject.m_Name );
end;
end;

function TDMAttribute.enumerateValues : TDMNominalAttributeValueEnumeration;
begin
Result := TDMNominalAttributeValueEnumeration.Create( Self );
end;

function TDMAttribute.indexOfValue( value : AnsiString ) : Integer;
var
store : TDMNominalAttributeValue;
begin
if ( m_Type <> ATTRIBUTE_TYPE_NOMINAL ) and ( m_Type <> ATTRIBUTE_TYPE_STRING ) then
Result := -1
else
begin
if ( m_Values = nil ) then Result := -1
else
begin
store := TDMNominalAttributeValue.Create( value );
Result := m_Values.indexOf( store );
store.Destroy;
end;
end;
end;

procedure TDMAttribute.delete( const valIndex : Integer );
begin
if ( m_Type <> ATTRIBUTE_TYPE_NOMINAL ) and ( m_Type <> ATTRIBUTE_TYPE_STRING ) then
begin
if ( m_Values <> nil ) then m_Values.removeElementAt( valIndex );
end;
end;

procedure TDMAttribute.setIndex( const index : Integer );
begin
m_Index := index;
end;

procedure TDMAttribute.setName( name : AnsiString );
begin
m_Name := name;
end;

procedure TDMAttribute.setAttributeType( const attributeType : Integer );
begin
m_Type := attributeType;
end;

procedure TDMAttribute.setWeight( const weight : Double );
begin
m_Weight := weight;
end;

procedure TDMAttribute.setOrdering( const ordering : Integer );
begin
m_Ordering := ordering;
end;

procedure TDMAttribute.setUpperNumericBound( const upperBound : Double );
begin
m_UpperBound := upperBound;
end;

procedure TDMAttribute.setLowerNumericBound( const lowerBound : Double );
begin
m_LowerBound := lowerBound;
end;

procedure TDMAttribute.setValue( const valIndex : Integer; value : AnsiString );
var
valueAtIndex : TDMNominalAttributeValue;
begin
if ( m_Type <> ATTRIBUTE_TYPE_NOMINAL ) and ( m_Type <> ATTRIBUTE_TYPE_STRING ) then
begin
if ( m_Values <> nil ) then
begin
valueAtIndex := m_Values.elementAt( valIndex ) as TDMNominalAttributeValue;
valueAtIndex.m_Name := value;
end;
end;
end;

function TDMAttribute.equals( otherObject : TObject ) : Boolean;
var
otherAttribute : TDMAttribute;
basicFieldsOk, valuesCantCompare, valuesOk : Boolean;
begin
Result := false;
if ( otherObject <> nil ) then
if ( otherObject is TDMAttribute ) then
begin
otherAttribute := otherObject as TDMAttribute;
basicFieldsOk :=
( otherAttribute.m_Name = m_Name) and
( otherAttribute.m_Type = m_Type ) and
( otherAttribute.m_Index = m_Index ) and
( otherAttribute.m_Ordering = m_Ordering ) and
( otherAttribute.m_Weight = m_Weight ) and
( otherAttribute.m_LowerBound = m_LowerBound ) and
( otherAttribute.m_UpperBound = m_UpperBound ) and
( otherAttribute.m_LowerBoundIsOpen = m_LowerBoundIsOpen ) and
( otherAttribute.m_UpperBoundIsOpen = m_UpperBoundIsOpen ) and
( otherAttribute.m_IsRegular = m_IsRegular ) and
( otherAttribute.m_IsAveragable = m_IsAveragable ) and
( otherAttribute.m_HasZeroPoint = m_HasZeroPoint );

if ( otherAttribute.m_Type = ATTRIBUTE_TYPE_NOMINAL ) and
( otherAttribute.m_Type = ATTRIBUTE_TYPE_STRING ) then
begin
valuesCantCompare := ( otherAttribute.m_Values = nil ) xor
( m_Values = nil );

if ( valuesCantCompare ) then valuesOk := false
else
begin
if ( otherAttribute.m_Values = nil ) then valuesOk := true
else valuesOk := m_Values.equals( otherAttribute.m_Values );
end;
end
else valuesOk := true;

Result := valuesOk and basicFieldsOk;
end;
end;

function TDMAttribute.ordering : Integer;
begin
Result := m_Ordering;
end;

function TDMAttribute.isInRange( const value : Double ) : Boolean;
var
nominalValue : Integer;
lowerBoundOk, upperBoundOk : Boolean;
begin
Result := true;
if ( m_Type = ATTRIBUTE_TYPE_DATE ) or ( value = MISSING_VALUE ) then Result := true;
if ( m_Type <> ATTRIBUTE_TYPE_NUMERIC ) then
begin
nominalValue := Round( value );
if ( nominalValue < 0 ) or ( nominalValue >= m_Values.size )
then Result := false;
end
else
begin
if ( m_LowerBoundIsOpen ) then lowerBoundOk := value >= m_LowerBound
else lowerBoundOk := value > m_LowerBound;
if ( m_UpperBoundIsOpen ) then upperBoundOk := value <= m_UpperBound
else upperBoundOk := value < m_LowerBound;
Result := lowerBoundOk and upperBoundOk;
end;
end;

function TDMAttribute.cloneObject : TObject;
var
rattribute : TDMAttribute;
begin
if ( m_Type = ATTRIBUTE_TYPE_NOMINAL ) or ( m_Type = ATTRIBUTE_TYPE_STRING ) then
rattribute := TDMAttribute.Create( m_Name, m_Values )
else
begin
rattribute := TDMAttribute.Create( m_Name );
rattribute.m_Values := nil;
end;

rattribute.m_Type := m_Type;
rattribute.m_Index := m_Index;
rattribute.m_Ordering := m_Ordering;
rattribute.m_Weight := m_Weight;
rattribute.m_LowerBound := m_LowerBound;
rattribute.m_UpperBound := m_UpperBound;
rattribute.m_IsRegular := m_IsRegular;
rattribute.m_IsAveragable := m_IsAveragable;
rattribute.m_HasZeroPoint := m_HasZeroPoint;
rattribute.m_LowerBoundIsOpen := m_lowerBoundIsOpen;
rattribute.m_UpperBoundIsOpen := m_upperBoundIsOpen;

Result := rattribute as TObject;
end;

function TDMAttribute.copyObject : TObject;
var
rattribute : TDMAttribute;
rvalues : TDMFastVector;
begin
if ( m_Type = ATTRIBUTE_TYPE_NOMINAL ) or ( m_Type = ATTRIBUTE_TYPE_STRING ) then
begin
rvalues := m_Values.copyObject as TDMFastVector;
rattribute := TDMAttribute.Create( m_Name, rvalues );
end
else
begin
rattribute := TDMAttribute.Create( m_Name );
rattribute.m_Values := nil;
end;

rattribute.m_Type := m_Type;
rattribute.m_Index := m_Index;
rattribute.m_Ordering := m_Ordering;
rattribute.m_Weight := m_Weight;
rattribute.m_LowerBound := m_LowerBound;
rattribute.m_UpperBound := m_UpperBound;
rattribute.m_IsRegular := m_IsRegular;
rattribute.m_IsAveragable := m_IsAveragable;
rattribute.m_HasZeroPoint := m_HasZeroPoint;
rattribute.m_LowerBoundIsOpen := m_lowerBoundIsOpen;
rattribute.m_UpperBoundIsOpen := m_upperBoundIsOpen;

Result := rattribute as TObject;
end;

procedure TDMAttribute.serializeObject( ostream : TStream );
begin
end;

procedure TDMAttribute.deserializeObject( istream : TStream );
begin
end;

function TDMAttribute.toString : AnsiString;
var
enu : TDMNominalAttributeValueEnumeration;
currentValue : TDMNominalAttributeValue;
begin
Result := ARFF_ATTRIBUTE + ' ' + Utils.simpleQuote( m_Name ) + ' ';

case m_Type of
ATTRIBUTE_TYPE_NOMINAL :
begin
Result := Result + '{ ';
enu := enumerateValues;
while ( enu.hasMoreElements ) do
begin
currentValue := enu.nextElement;
Result := Result + currentValue.toString;
if ( enu.hasMoreElements ) then Result := Result + ', ';
end;
Result := Result + ' }';
end;
ATTRIBUTE_TYPE_NUMERIC :
Result := Result + ARFF_ATTRIBUTE_NUMERIC;
ATTRIBUTE_TYPE_STRING :
Result := Result + ARFF_ATTRIBUTE_STRING;
else
Result := Result + 'unknown';
end;
end;

function TDMAttribute.value( const valIndex : Integer ) : AnsiString;
var
valueAtIndex : TDMNominalAttributeValue;
begin
if ( m_Type <> ATTRIBUTE_TYPE_NOMINAL ) and ( m_Type <> ATTRIBUTE_TYPE_STRING ) then
Result := ''
else
begin
if ( m_Values <> nil ) then
begin
valueAtIndex := m_Values.elementAt( valIndex ) as TDMNominalAttributeValue;
Result := valueAtIndex.m_Name;
end
else Result := '';
end;
end;

destructor TDMAttribute.Destroy();
begin
FreeAndNil(m_Values);
end;

constructor TDMNominalAttributeValue.Create( name : AnsiString );
begin
m_Name := name;
end;

function TDMNominalAttributeValue.cloneObject : TObject;
begin
Result := TDMNominalAttributeValue.Create( m_Name );
end;

function TDMNominalAttributeValue.copyObject : TObject;
begin
Result := TDMNominalAttributeValue.Create( m_Name );
end;

function TDMNominalAttributeValue.equals( otherObject : TObject ) : Boolean;
var
navobject : TDMNominalAttributeValue;
begin
if ( otherObject = nil ) then Result := false
else
if ( otherObject is TDMNominalAttributeValue ) then
begin
navobject := otherObject as TDMNominalAttributeValue;
Result := navobject.m_Name = m_Name;
end
else Result := false;
end;

function TDMNominalAttributeValue.toString : AnsiString;
begin
Result := Utils.simpleQuote( m_Name );
end;

procedure TDMNominalAttributeValue.serializeObject( ostream : TStream );
var
slength : Integer;
begin
if ( ostream <> nil ) then
begin
slength := Length( m_Name );
ostream.Write( slength, 4 );
ostream.WriteBuffer( PChar( m_Name )^, slength );
end;
end;

procedure TDMNominalAttributeValue.deserializeObject( istream : TStream );
var
slength : Integer;
begin
if ( istream <> nil ) then
begin
istream.Read( slength, 4 );
if ( slength > 0 ) then
begin
SetLength( m_Name, slength );
istream.Read( PChar( m_Name )^, slength )
end;
end;
end;

constructor TDMNominalAttributeValueEnumeration.Create( attribute : TDMAttribute );
begin
if ( attribute.isNominal ) then
begin
m_Counter := 0;
m_FastVector := attribute.m_Values;
m_SpecialElement := -1;
end;
end;

function TDMNominalAttributeValueEnumeration.hasMoreElements : Boolean;
begin
Result := false;
if ( m_Counter < m_FastVector.size ) then Result := true;
end;

function TDMNominalAttributeValueEnumeration.nextElement : TDMNominalAttributeValue;
begin
Result := m_FastVector.elementAt( m_Counter ) as TDMNominalAttributeValue;
m_Counter := m_Counter + 1;
if ( m_Counter = m_SpecialElement ) then m_Counter := m_Counter + 1;
end;

end.
Соседние файлы в папке DMCore