OSDN Git Service

[YCへマージ]
[winbottle/winbottle.git] / sakurasuite / SsPlayTime.pas
index b680b9a..5382d2d 100644 (file)
@@ -2,6 +2,7 @@
 { TSsPlayTime Component - Estimates SakuraScript playing time }
 {                                                             }
 {       Copyright (c) 2001-2003 naruto/CANO-Lab               }
+{                 (c) 2001-2005 WinBottle Project             }
 {*************************************************************}
 
 unit SsPlayTime;
@@ -15,6 +16,25 @@ type
   TSsPlayTimeException = class(Exception);
   TSsPlayTimeInitException = class(TSsPlayTimeException);
 
+  TSsPlayTimeSpecialChar = class(TCollectionItem)
+  private
+    FWait: integer;
+    FChar: String;
+    procedure SetChar(const Value: String);
+    procedure SetWait(const Value: integer);
+  protected
+    function GetDisplayName: String; override;
+  public
+    procedure Assign(Source: TPersistent); override;
+    function DisplayChar: String;
+  published
+    property Char: String read FChar write SetChar;
+    property Wait: integer read FWait write SetWait;
+  end;
+
+  TSsPlayTimeSpecialChars = class(TCollection)
+  end;
+
   TSsPlayTimeParams = class(TComponent)
   private
     FCostWait: integer;
@@ -24,9 +44,8 @@ type
     FCostHiResWait: integer;
     FCostSurface: integer;
     FCostQuickChar: integer;
-    FCostWhiteSpace: integer;
-    FCostDBWhiteSpace: integer;
     FProfileName: String;
+    FSpecialChars: TSsPlayTimeSpecialChars;
     procedure SetCostChar(const Value: integer);
     procedure SetCostConst(const Value: integer);
     procedure SetCostDBChar(const Value: integer);
@@ -35,8 +54,10 @@ type
     procedure SetCostSurface(const Value: integer);
     procedure SetCostQuickChar(const Value: integer);
     procedure SetProfileName(const Value: String);
+    procedure SetSpecialChars(const Value: TSsPlayTimeSpecialChars);
   public
     constructor Create(AOwner: TComponent); override;
+    destructor Destroy; override;
     procedure Assign(Source: TPersistent); override;
   published
     property ProfileName: String read FProfileName write SetProfileName;
@@ -46,9 +67,8 @@ type
     property CostSurface: integer read FCostSurface write SetCostSurface default 5;
     property CostChar: integer read FCostChar write SetCostChar default 50;
     property CostDBChar: integer read FCostDBChar write SetCostDBChar default 50;
-    property CostWhiteSpace: integer read FCostWhiteSpace write FCostWhiteSpace default 10;
-    property CostDBWhiteSpace: integer read FCostDBWhiteSpace write FCostDBWhiteSpace default 10;
     property CostQuickChar: integer read FCostQuickChar write SetCostQuickChar default 0;
+    property SpecialChars: TSsPlayTimeSpecialChars read FSpecialChars write SetSpecialChars;
   end;
 
   TSsPlayTimeCount = record
@@ -57,9 +77,8 @@ type
     Surface: integer;
     Char: integer;
     DBChar: integer;
-    WhiteSpace: integer;
-    DBWhiteSpace : integer;
     QuickChar: integer;
+    Specials: integer;
   end;
 
   TSsPlayTime = class(TComponent)
@@ -72,7 +91,7 @@ type
   protected
     procedure CountElements;
     procedure CountCharacterType(const Str: String; out SB, DB,
-      SBS, DBS: integer);
+      SPNum, SPWait: integer);
   public
     function PlayTime(const Script: String): integer;
     property Counts: TSsPlayTimeCount read FCounts;
@@ -110,10 +129,9 @@ begin
     FCostSurface      := Src.FCostSurface;
     FCostChar         := Src.FCostChar;
     FCostDBChar       := Src.FCostDBChar;
-    FCostWhiteSpace   := Src.FCostWhiteSpace;
-    FCostDBWhiteSpace := Src.FCostDBWhiteSpace;
     FCostQuickChar    := Src.FCostQuickChar;
     FProfileName      := Src.FProfileName;
+    FSpecialChars.Assign(Src.SpecialChars);
   end;
 end;
 
@@ -126,9 +144,14 @@ begin
   FCostSurface      := 5;
   FCostChar         := 50;
   FCostDBChar       := 50;
-  FCostWhiteSpace   := 10;
-  FCostDBWhiteSpace := 10;
   FCostQuickChar    := 0;
+  FSpecialChars := TSsPlayTimeSpecialChars.Create(TSsPlayTimeSpecialChar);
+end;
+
+destructor TSsPlayTimeParams.Destroy;
+begin
+  FSpecialChars.Free;
+  inherited;
 end;
 
 procedure TSsPlayTimeParams.SetCostChar(const Value: integer);
@@ -171,45 +194,76 @@ begin
   FProfileName := Value;
 end;
 
+procedure TSsPlayTimeParams.SetSpecialChars(
+  const Value: TSsPlayTimeSpecialChars);
+begin
+  FSpecialChars.Assign(Value);
+end;
+
 { TSsPlayTime }
 
 procedure TSsPlayTime.CountCharacterType(const Str: String; out SB,
-  DB, SBS, DBS: integer);
+  DB, SPNum, SPWait: integer);
 var
-  i: integer;
-  InLeadByte: boolean;
+  i, j, lnStr: integer;
+  InLeadByte, Flag: boolean;
+  AChar: TSsPlayTimeSpecialChar;
 begin
   SB := 0;
   DB := 0;
-  SBS := 0;
-  DBS := 0;
+  SPNum := 0;
+  SPWait := 0;
   InLeadByte := false;
-  for i := 1 to Length(Str) do
+  lnStr := Length(Str);
+  for i := 1 to lnStr do
   begin
     if InLeadByte then
     begin
       Inc(DB);
       InLeadByte := false;
     end
-    else if Str[i] in LeadBytes then
+    else
     begin
-      InLeadByte := true;
-      if Str[i] + Str[i+1] = CDBWhiteSpace then
+      Flag := false;
+      for j := 0 to PlayTimeParams.SpecialChars.Count-1 do
       begin
-        Inc(DBS);
-        Dec(DB);
+        AChar := PlayTimeParams.SpecialChars.Items[j] as TSsPlayTimeSpecialChar;
+        if (Length(AChar.Char) = 2) and (lnStr-i > 0) then
+        begin
+          if Str[i] + Str[i+1] = AChar.Char then
+          begin
+            Inc(SPWait, AChar.Wait);
+            Inc(SPNum);
+            Dec(DB);
+            Flag := true;
+            InLeadByte := true;
+            Break;
+          end;
+        end else
+        begin
+          if Str[i] = AChar.Char then
+          begin
+            Inc(SPWait, AChar.Wait);
+            Inc(SPNum);
+            Flag := true;
+            Break;
+          end;
+        end;
       end;
-    end
-    else if Str[i] = ' ' then
-      Inc(SBS)
-    else
-      Inc(SB);
+      if not Flag then
+      begin
+        if Str[i] in LeadBytes then
+          InLeadByte := true
+        else
+          Inc(SB);
+      end;
+    end;
   end;
 end;
 
 procedure TSsPlayTime.CountElements;
 var
-  i, SB, DB, SBS, DBS: integer;
+  i, SB, DB, SPNum, SPWait: integer;
   Mark: String;
   InQuick: boolean;
 begin
@@ -238,15 +292,14 @@ begin
           begin
             if InQuick then
             begin
-              CountCharacterType(Mark, SB, DB, SBS, DBS);
-              Inc(FCounts.QuickChar, SB + DB + SBS + DBS);
+              CountCharacterType(Mark, SB, DB, SPNum, SPWait);
+              Inc(FCounts.QuickChar, SB + DB + SPNum);
             end else
             begin
-              CountCharacterType(Mark, SB, DB, SBS, DBS);
+              CountCharacterType(Mark, SB, DB, SPNum, SPWait);
               Inc(FCounts.Char, SB);
               Inc(FCounts.DBChar, DB);
-              Inc(FCounts.WhiteSpace, SBS);
-              Inc(FCounts.DBWhiteSpace, DBS);
+              Inc(FCounts.Specials, SPWait);
             end;
           end;
         // Ignore all tag errors
@@ -262,19 +315,13 @@ begin
     raise TSsPlayTimeInitException.Create('SsParser is not set');
   if FPlayTimeParams = nil then
     raise TSsPlayTimeInitException.Create('PlayTimeParams is not set');
-  try
-    SsParser.InputString := Script;
-    CountElements;
-    with PlayTimeParams do
-      Result := CostConst + CostWait * FCounts.Wait + CostSurface * FCounts.Surface +
-        CostHiResWait * FCounts.HiResWait + CostChar * FCounts.Char +
-        CostDBChar * FCounts.DBChar +
-        CostWhiteSpace * FCounts.WhiteSpace + CostDBWhiteSpace * FCounts.DBWhiteSpace + 
-        CostQuickChar * FCounts.QuickChar;
-  except
-    Result := 0;
-    raise;
-  end;
+  SsParser.InputString := Script;
+  CountElements;
+  with PlayTimeParams do
+    Result := CostConst + CostWait * FCounts.Wait + CostSurface * FCounts.Surface +
+      CostHiResWait * FCounts.HiResWait + CostChar * FCounts.Char +
+      CostDBChar * FCounts.DBChar + FCounts.Specials +
+      CostQuickChar * FCounts.QuickChar;
 end;
 
 procedure TSsPlayTime.SetPlayTimeParams(const Value: TSsPlayTimeParams);
@@ -287,5 +334,53 @@ begin
   FSsParser := Value;
 end;
 
+{ TSsPlayTimeSpecialChar }
+
+procedure TSsPlayTimeSpecialChar.Assign(Source: TPersistent);
+begin
+  if not(Source is TSsPlayTimeSpecialChar) then
+    inherited
+  else
+  begin
+    Self.FChar := (Source as TSsPlayTimeSpecialChar).FChar;
+    Self.FWait := (Source as TSsPlayTimeSpecialChar).FWait;
+  end;
+end;
+
+function TSsPlayTimeSpecialChar.DisplayChar: String;
+begin
+  if FChar = ' ' then
+    Result := '(SP)'
+  else if FChar = CDBWhiteSpace then
+    Result := '(DB SP)'
+  else
+    Result := FChar;
+end;
+
+function TSsPlayTimeSpecialChar.GetDisplayName: String;
+begin
+  Result := Format('"%s" = %d', [DisplayChar, FWait]);
+end;
+
+procedure TSsPlayTimeSpecialChar.SetChar(const Value: String);
+begin
+  if Value = '' then
+    FChar := Value
+  else
+  begin
+    if (Value[1] in LeadBytes) then
+    begin
+      if Length(Value) = 2 then
+        FChar := Value;
+    end else if Length(Value) = 1 then
+      FChar := Value;
+  end;
+end;
+
+procedure TSsPlayTimeSpecialChar.SetWait(const Value: integer);
+begin
+  FWait := Value;
+end;
+
 end.
  
\ No newline at end of file