Как реализовать матрицу решений в Delphi - PullRequest
0 голосов
/ 06 марта 2012

Я должен реализовать матрицу решений в Delphi 7. Функция

CalcNewStatus (actionCode: строка; reportType: строка; currentStatus: строка): строка;

  • ActionCode может иметь значения «A» и «N»
  • ReportType может иметь значения «I» и «F»
  • CurrentStatus может иметь значения «P», «I», «F».

В C # я бы, например, использовал словарь. Как я могу сделать это в Delphi 7?

Ответы [ 3 ]

10 голосов
/ 06 марта 2012

Нормализуйте свои входные символы в порядковые значения, начинающиеся с нуля, и все станет намного проще.Начните с нескольких объявлений типов:

type
  TActionCode = (acA, acN);
  TReportType = (rtI, rtF);
  TStatus = (sP, sI, sF);

Затем вы можете определить массив, используя эти типы со всеми возможными значениями состояния.Замените sX на то, какое значение состояния находится в каждом месте.

const
  NextStatus: array[TActionCode, TReportType, TStatus] of TStatus = (
    {acA} (// sP, sI, sF
      {rtI} ( sX, sX, sX),
      {rtF} ( sX, sX, sX)
          ),
    {acN} (
      {rtI} ( sX, sX, sX),
      {rtF} ( sX, sX, sX)
          )
  );

Тогда ваша функция выглядит просто так:

function CalcNewStatus(const actionCode, reportType, currentStatus: string): string;
var
  ac: TActionCode;
  rt: TReportType;
  s: TStatus;
const
  StateChars: array[TState] of Char = ('P', 'I', 'F');
begin
  Assert(actionCode <> ''); Assert(reportType <> ''); Assert(currentStatus <> '');
  Assert(actionCode[1] in ['A', 'N']);
  Assert(reportType[1] in ['I', 'F']);
  Assert(currentStatus[1] in ['P', 'I', 'F']);
  if actionCode[1] = 'A' then ac := acA else ac := acN;
  if reportType[1] = 'I' then rt := rtI else rt := rtF;
  if currentStatus[1] = 'P' then s := sP
  else if currentStatus[1] = 'I' then s := sI
  else s := sF;

  Result := StateChars[NextStatus[ac, rt, s]];
end;

Как видите, большая часть этого кода расходуется на преобразованиемежду строками и типами перечислений.Если можете, избегайте строк в этом случае.Переключайтесь на типы enum как можно раньше в своей программе и конвертируйте обратно в строки или символы только тогда, когда это абсолютно необходимо.Строки могут иметь произвольную длину, с которой вам действительно не нужно иметь дело, и строки могут также иметь значения вне заданного вами диапазона.Enums не может, если вы не делаете что-то странное.Кроме того, компилятор не позволит вам случайно использовать значение TState там, где ожидается TReportType, что поможет вам перепутать ваши I и F.

4 голосов
/ 06 марта 2012

Прежде всего в таком ограниченном случае (2 ActionCodes, 2 ReportTypes, 3 Status), я определенно должен использовать перечисляемые типы вместо строк.

А для матрицы решений ... Матрица:

Type 
  TActionCode = (taA, taN);
  TReprotType = (rtI, rtF);
  TStatus = (stP, stI, stF);

const
  NewStatus: array [TActionCode, TReportType, TStatus] of TStatus = 
        ((((,,)),((,,))),(((,,)),((,,))))    // values of the new statuses here
0 голосов
/ 06 марта 2012

Существует одно решение, использующее одномерный массив.

unit XnResultStatusOverride;

interface

function XnCalcOverridenResultStatus(
    actionCodeStr: string;
    reportTypeStr: string;
    currentStatusStr: string ): string;


implementation

uses SysUtils;

type
TActionCodes = ( ActionCodeA = 0, ActionCodeN = 1);
TReportTypes = (ReportTypeI = 0, ReportTypeF = 1);
TResultStatus = (ResultStatusP = 0, ResultStatusF = 1, ResultStatusI = 2);

const
    DecisionMatrix: array[ 0 .. 15 ] of TResultStatus
    =
    (
      ResultStatusF, // 0 A-I-P
      ResultStatusF, // 1 A-I-F
      ResultStatusF, // 2 A-I-I
      ResultStatusF, // 3 N/A
      ResultStatusP, // 4 A-F-P
      ResultStatusP, // 5 A-F-F
      ResultStatusF, // 6 A-F-I
      ResultStatusF, // 7 N/A
      ResultStatusF, // 8 N-I-P
      ResultStatusF, // 9 N-I-F
      ResultStatusP, // 10 N-I-I
      ResultStatusF, // 11 N/A
      ResultStatusF, // 12 N-F-P
      ResultStatusI, // 13 N-F-F
      ResultStatusF, // 14 N-F-I
      ResultStatusF  // 15 N/A
    );


function ParseActionCodeString( value: string ): TActionCodes;
begin
    if value = 'A' then
    begin
        result := ActionCodeA;
        exit;
    end;

    if value = 'N' then
    begin
        result := ActionCodeN;
        exit;
    end;

    raise Exception.Create('Invalid action code string' );
end;

function ParseReportTypeString( value: string ): TReportTypes;
begin
    if value = 'I' then
    begin
        result := ReportTypeI;
        exit;
    end;

    if value = 'F' then
    begin
        result := ReportTypeF;
        exit;
    end;

    raise Exception.Create('Invalid report type string' );
end;


function ParseResultStatusString( value: string ): TResultStatus;
begin
    if value = 'P' then
    begin
        result := ResultStatusP;
        exit;
    end;

    if value = 'F' then
    begin
        result := ResultStatusF;
        exit;
    end;

    if value = 'I' then
    begin
        result := ResultStatusI;
        exit;
    end;

    raise Exception.Create('Invalid result status string' );
end;

function ResultStatusToString( value: TResultStatus ): string;
begin

    if value = ResultStatusP then
    begin
        result := 'P';
        exit;
    end;

    if value = ResultStatusF then
    begin
        result := 'F';
        exit;
    end;

    if value = ResultStatusI then
    begin
        result := 'I';
        exit;
    end;

    raise Exception.Create('Unknown TResultStatus enum member' );

end;

function XnCalcOverridenResultStatus(
    actionCodeStr: string;
    reportTypeStr: string;
    currentStatusStr: string ): string;
var
    actionCode: TActionCodes;
    reportType: TReportTypes;
    currentStatus:TResultStatus;
    discriminant: integer;
    newStatusInt: integer;
    newStatus: TResultStatus;
begin

    actionCode    := ParseActionCodeString( actionCodeStr );
    reportType    := ParseReportTypeString( reportTypeStr );
    currentStatus := ParseResultStatusString( currentStatusStr );

    discriminant  := integer(actionCode) * 8 + integer(reportType) * 4 + integer(currentStatus);

    newStatusInt  := DecisionMatrix[ discriminant ];
    newStatus     := TResultStatus( newStatusInt);

    Result        := ResultStatusToString( newStatus );

end;


end.
...