1 {*************************************************************}
2 { TSsPlayTime Component - Estimates SakuraScript playing time }
4 { Copyright (c) 2001-2003 naruto/CANO-Lab }
5 { (c) 2001-2005 WinBottle Project }
6 {*************************************************************}
13 Windows, SysUtils, Classes, SsParser;
16 TSsPlayTimeException = class(Exception);
17 TSsPlayTimeInitException = class(TSsPlayTimeException);
19 TSsPlayTimeSpecialChar = class(TCollectionItem)
23 procedure SetChar(const Value: String);
24 procedure SetWait(const Value: integer);
26 function GetDisplayName: String; override;
28 procedure Assign(Source: TPersistent); override;
29 function DisplayChar: String;
31 property Char: String read FChar write SetChar;
32 property Wait: integer read FWait write SetWait;
35 TSsPlayTimeSpecialChars = class(TCollection)
38 TSsPlayTimeParams = class(TComponent)
44 FCostHiResWait: integer;
45 FCostSurface: integer;
46 FCostQuickChar: integer;
48 FSpecialChars: TSsPlayTimeSpecialChars;
49 procedure SetCostChar(const Value: integer);
50 procedure SetCostConst(const Value: integer);
51 procedure SetCostDBChar(const Value: integer);
52 procedure SetCostWait(const Value: integer);
53 procedure SetCostHiResWait(const Value: integer);
54 procedure SetCostSurface(const Value: integer);
55 procedure SetCostQuickChar(const Value: integer);
56 procedure SetProfileName(const Value: String);
57 procedure SetSpecialChars(const Value: TSsPlayTimeSpecialChars);
59 constructor Create(AOwner: TComponent); override;
60 destructor Destroy; override;
61 procedure Assign(Source: TPersistent); override;
63 property ProfileName: String read FProfileName write SetProfileName;
64 property CostConst: integer read FCostConst write SetCostConst default 0;
65 property CostWait: integer read FCostWait write SetCostWait default 50;
66 property CostHiResWait: integer read FCostHiResWait write SetCostHiResWait default 1;
67 property CostSurface: integer read FCostSurface write SetCostSurface default 5;
68 property CostChar: integer read FCostChar write SetCostChar default 50;
69 property CostDBChar: integer read FCostDBChar write SetCostDBChar default 50;
70 property CostQuickChar: integer read FCostQuickChar write SetCostQuickChar default 0;
71 property SpecialChars: TSsPlayTimeSpecialChars read FSpecialChars write SetSpecialChars;
74 TSsPlayTimeCount = record
84 TSsPlayTime = class(TComponent)
86 FPlayTimeParams: TSsPlayTimeParams;
88 FCounts: TSsPlayTimeCount;
89 procedure SetPlayTimeParams(const Value: TSsPlayTimeParams);
90 procedure SetSsParser(const Value: TSsParser);
92 procedure CountElements;
93 procedure CountCharacterType(const Str: String; out SB, DB,
94 SPNum, SPWait: integer);
95 procedure Notification(AComponent: TComponent;
96 Operation: TOperation); override;
98 function PlayTime(const Script: String): integer;
99 property Counts: TSsPlayTimeCount read FCounts;
101 property PlayTimeParams: TSsPlayTimeParams read FPlayTimeParams write SetPlayTimeParams;
102 property SsParser: TSsParser read FSsParser write SetSsParser;
110 CDBWhiteSpace = #129 + #64; // Shift_JIS DB White Space;
114 RegisterComponents('Samples', [TSsPlayTime, TSsPlayTimeParams]);
117 { TSsPlayTimeParams }
119 procedure TSsPlayTimeParams.Assign(Source: TPersistent);
121 Src: TSsPlayTimeParams;
123 if not (Source is TSsPlayTimeParams) then
127 Src := Source as TSsPlayTimeParams;
128 FCostConst := Src.FCostConst;
129 FCostWait := Src.FCostWait;
130 FCostHiResWait := Src.FCostHiResWait;
131 FCostSurface := Src.FCostSurface;
132 FCostChar := Src.FCostChar;
133 FCostDBChar := Src.FCostDBChar;
134 FCostQuickChar := Src.FCostQuickChar;
135 FProfileName := Src.FProfileName;
136 FSpecialChars.Assign(Src.SpecialChars);
140 constructor TSsPlayTimeParams.Create(AOwner: TComponent);
150 FSpecialChars := TSsPlayTimeSpecialChars.Create(TSsPlayTimeSpecialChar);
153 destructor TSsPlayTimeParams.Destroy;
159 procedure TSsPlayTimeParams.SetCostChar(const Value: integer);
164 procedure TSsPlayTimeParams.SetCostConst(const Value: integer);
169 procedure TSsPlayTimeParams.SetCostDBChar(const Value: integer);
171 FCostDBChar := Value;
174 procedure TSsPlayTimeParams.SetCostHiResWait(const Value: integer);
176 FCostHiResWait := Value;
179 procedure TSsPlayTimeParams.SetCostQuickChar(const Value: integer);
181 FCostQuickChar := Value;
184 procedure TSsPlayTimeParams.SetCostSurface(const Value: integer);
186 FCostSurface := Value;
189 procedure TSsPlayTimeParams.SetCostWait(const Value: integer);
194 procedure TSsPlayTimeParams.SetProfileName(const Value: String);
196 FProfileName := Value;
199 procedure TSsPlayTimeParams.SetSpecialChars(
200 const Value: TSsPlayTimeSpecialChars);
202 FSpecialChars.Assign(Value);
207 procedure TSsPlayTime.CountCharacterType(const Str: String; out SB,
208 DB, SPNum, SPWait: integer);
210 i, j, lnStr: integer;
211 InLeadByte, Flag: boolean;
212 AChar: TSsPlayTimeSpecialChar;
219 lnStr := Length(Str);
220 for i := 1 to lnStr do
230 for j := 0 to PlayTimeParams.SpecialChars.Count-1 do
232 AChar := PlayTimeParams.SpecialChars.Items[j] as TSsPlayTimeSpecialChar;
233 if (Length(AChar.Char) = 2) and (lnStr-i > 0) then
235 if Str[i] + Str[i+1] = AChar.Char then
237 Inc(SPWait, AChar.Wait);
246 if Str[i] = AChar.Char then
248 Inc(SPWait, AChar.Wait);
257 if Str[i] in LeadBytes then
266 procedure TSsPlayTime.CountElements;
268 i, SB, DB, SPNum, SPWait: integer;
272 ZeroMemory(@FCounts, sizeof(FCounts));
276 for i := 0 to SsParser.Count-1 do
279 case MarkUpType[i] of
283 InQuick := not InQuick
284 else if Match(Mark, '\w%d') = 3 then
285 FCounts.Wait := FCounts.Wait + Ord(Mark[3]) - Ord('0')
286 else if Match(Mark, '\_w[%D]') > 0 then
287 Inc(FCounts.HiResWait, StrToInt(GetParam(Mark, 0)))
288 else if Match(Mark, '\s%d') = 3 then
290 else if Match(Mark, '\s%b') > 0 then
297 CountCharacterType(Mark, SB, DB, SPNum, SPWait);
298 Inc(FCounts.QuickChar, SB + DB + SPNum);
301 CountCharacterType(Mark, SB, DB, SPNum, SPWait);
302 Inc(FCounts.Char, SB);
303 Inc(FCounts.DBChar, DB);
304 Inc(FCounts.Specials, SPWait);
307 // Ignore all tag errors
313 procedure TSsPlayTime.Notification(AComponent: TComponent;
314 Operation: TOperation);
317 if Operation = opRemove then
319 if AComponent = FPlayTimeParams then
320 FPlayTimeParams := nil;
321 if AComponent = FSsParser then
326 function TSsPlayTime.PlayTime(const Script: String): integer;
329 if FSsParser = nil then
330 raise TSsPlayTimeInitException.Create('SsParser is not set');
331 if FPlayTimeParams = nil then
332 raise TSsPlayTimeInitException.Create('PlayTimeParams is not set');
333 SsParser.InputString := Script;
335 with PlayTimeParams do
336 Result := CostConst + CostWait * FCounts.Wait + CostSurface * FCounts.Surface +
337 CostHiResWait * FCounts.HiResWait + CostChar * FCounts.Char +
338 CostDBChar * FCounts.DBChar + FCounts.Specials +
339 CostQuickChar * FCounts.QuickChar;
342 procedure TSsPlayTime.SetPlayTimeParams(const Value: TSsPlayTimeParams);
344 FPlayTimeParams := Value;
346 Value.FreeNotification(self);
349 procedure TSsPlayTime.SetSsParser(const Value: TSsParser);
353 Value.FreeNotification(self);
356 { TSsPlayTimeSpecialChar }
358 procedure TSsPlayTimeSpecialChar.Assign(Source: TPersistent);
360 if not(Source is TSsPlayTimeSpecialChar) then
364 Self.FChar := (Source as TSsPlayTimeSpecialChar).FChar;
365 Self.FWait := (Source as TSsPlayTimeSpecialChar).FWait;
369 function TSsPlayTimeSpecialChar.DisplayChar: String;
373 else if FChar = CDBWhiteSpace then
379 function TSsPlayTimeSpecialChar.GetDisplayName: String;
381 Result := Format('"%s" = %d', [DisplayChar, FWait]);
384 procedure TSsPlayTimeSpecialChar.SetChar(const Value: String);
390 if (Value[1] in LeadBytes) then
392 if Length(Value) = 2 then
394 end else if Length(Value) = 1 then
399 procedure TSsPlayTimeSpecialChar.SetWait(const Value: integer);