6 Windows, Messages, SysUtils, Classes,
7 GikoSystem, BoardGroup;
10 TGikoRoundType = (grtBoard, grtItem);
13 TRoundList = class(TObject)
15 FOldFileRead: Boolean;
18 function GetCount(RoundType: TGikoRoundType): Integer;
19 function GetRoundItem(Index: Integer; RoundType: TGikoRoundType): TRoundItem;
20 function ParseRoundBoardLine(Line: string): Boolean;
21 function ParseRoundThreadLine(Line: string): Boolean;
22 function ParseOldRoundBoardLine(Line: string): Boolean;
23 function ParseOldRoundThreadLine(Line: string): Boolean;
25 RoundNameList: TStringList;
28 destructor Destroy; override;
29 function Add(Board: TBoard): Integer; overload;
30 function Add(ThreadItem: TThreadItem): Integer; overload;
31 procedure Delete(Board: TBoard); overload;
32 procedure Delete(ThreadItem: TThreadItem); overload;
33 procedure Delete(URL: string; RoundType: TGikoRoundType); overload;
35 function Find(Board: TBoard): Integer; overload;
36 function Find(ThreadItem: TThreadItem): Integer; overload;
37 function Find(URL: string; RoundType: TGikoRoundType): Integer; overload;
38 property Count[RoundType: TGikoRoundType]: Integer read GetCount;
39 property OldFileRead: Boolean read FOldFileRead;
40 property Items[Index: integer; RoundType: TGikoRoundType]: TRoundItem read GetRoundItem;
41 procedure LoadRoundBoardFile;
42 procedure LoadRoundThreadFile;
43 procedure SaveRoundFile;
45 procedure URLReplace(oldURLs: TStringList; newURLs :TStringList);
48 TRoundItem = class(TObject)
51 FRoundType: TGikoRoundType;
53 FBoolData: Boolean; //
\82¢
\82ë
\82¢
\82ë
\8eg
\82¤
\82å
\82£
54 function GetBoardTitle : string;
55 function GetThreadTitle : string;
56 function GetURL : string;
57 function GetFileName : string;
58 //!
\8f\84\89ñ
\96¼
\8eæ
\93¾
59 function GetRoundName : string;
62 property Item : TObject read FItem;
63 property RoundName: string read GetRoundName;
64 property RoundType: TGikoRoundType read FRoundType write FRoundType;
65 property URL : string read GetURL;
66 property TmpURL : string read FTmpURL write FTmpURL;
67 property BoardTitle: string read GetBoardTitle;
68 property ThreadTitle: string read GetThreadTitle;
69 property FileName: string read GEtFileName;
70 property BoolData: Boolean read FBoolData write FBoolData;
74 RoundList: TRoundList;
78 ROUND_BOARD_FILENAME: string = 'RoundBoard.2ch'; //
\82 \82Æ
\82ÅBoardGroup
\82Ö
\88Ú
\93®
79 ROUND_ITEM_FILENAME: string = 'RoundItem.2ch'; //
\93¯
\8fã
80 ROUND_INDEX_VERSION: string = '2.00';
81 ERROR_BOARD_FILENAME: string = 'ErrorBoard.2ch'; //Error
\8ds
\82ð
\95Û
\8aÇ
\82·
\82é
82 ERROR_ITEM_FILENAME: string = 'ErrorItem.2ch'; //Error
\8ds
\82ð
\95Û
\8aÇ
\82·
\82é
83 //!
\8f\84\89ñ
\83A
\83C
\83e
\83\80\83R
\83\93\83X
\83g
\83\89\83N
\83^
84 constructor TRoundItem.Create;
89 function TRoundItem.GetBoardTitle : string;
92 if( Self.FItem <> nil) then begin
93 if( Self.FItem is TBoard) then begin
94 Result := TBoard(Self.FItem).Title;
95 end else if( Self.FItem is TThreadItem) then begin
96 Result := TThreadItem(Self.FItem).ParentBoard.Title;
100 //!
\83X
\83\8c\83b
\83h
\96¼
\8eæ
\93¾
101 function TRoundItem.GetThreadTitle : string;
104 if( Self.FItem <> nil) then begin
105 if( Self.FItem is TThreadItem) then begin
106 Result := TThreadItem(Self.FItem).Title;
111 function TRoundItem.GetURL : string;
114 if( Self.FItem <> nil) then begin
115 if( Self.FItem is TBoard) then begin
116 Result := TBoard(Self.FItem).URL;
117 end else if( Self.FItem is TThreadItem) then begin
118 Result := TThreadItem(Self.FItem).URL;
122 //!
\83X
\83\8c\83b
\83h
\82Ì
\83t
\83@
\83C
\96¼
\8eæ
\93¾
123 function TRoundItem.GetFileName : string;
126 if( Self.FItem <> nil) then begin
127 if( Self.FItem is TThreadItem) then begin
128 Result := TThreadItem(Self.FItem).FileName;
132 //!
\8f\84\89ñ
\96¼
\8eæ
\93¾
133 function TRoundItem.GetRoundName : string;
136 if( Self.FItem <> nil) then begin
137 if( Self.FItem is TBoard) then begin
138 Result := TBoard(Self.FItem).RoundName;
139 end else if( Self.FItem is TThreadItem) then begin
140 Result := TThreadItem(Self.FItem).RoundName;
144 //!
\8f\84\89ñ
\83\8a\83X
\83g
\83R
\83\93\83X
\83g
\83\89\83N
\83^
145 constructor TRoundList.Create;
148 FBoardList := TList.Create;
149 FItemList := TList.Create;
150 RoundNameList := TStringList.Create;
151 RoundNameList.Sorted := True;
152 RoundNameList.Duplicates := dupIgnore;
153 FOldFileRead := false;
155 //!
\8f\84\89ñ
\83\8a\83X
\83g
\83f
\83X
\83g
\83\89\83N
\83^
156 destructor TRoundList.Destroy;
164 //!
\8f\84\89ñ
\97\
\96ñ
\92Ç
\89Á
\81i
\94Â
\81j
165 function TRoundList.Add(Board: TBoard): Integer;
172 if idx = -1 then begin
173 Item := TRoundItem.Create;
175 // Item.BBSType := gbt2ch; //
\82Æ
\82è
\82 \82¦
\82¸
176 Item.RoundType := grtBoard;
177 Result := FBoardList.Add(Item);
180 //!
\8f\84\89ñ
\97\
\96ñ
\92Ç
\89Á
\81i
\83X
\83\8c\83b
\83h
\81j
181 function TRoundList.Add(ThreadItem: TThreadItem): Integer;
187 idx := Find(ThreadItem);
188 if idx = -1 then begin
189 Item := TRoundItem.Create;
190 Item.FItem := ThreadItem;
191 // Item.BBSType := gbt2ch; //
\82Æ
\82è
\82 \82¦
\82¸
192 Item.RoundType := grtItem;
193 Result := FItemList.Add(Item);
196 //!
\8f\84\89ñ
\97\
\96ñ
\8dí
\8f\9c\81i
\94Â
\81j
197 procedure TRoundList.Delete(Board: TBoard);
202 if idx <> -1 then begin
203 TBoard(TRoundItem(FBoardList[idx]).FItem).RoundName := '';
204 TRoundItem(FBoardList[idx]).Free;
205 FBoardList.Delete(idx);
208 //!
\8f\84\89ñ
\97\
\96ñ
\8dí
\8f\9c\81i
\83X
\83\8c\83b
\83h
\81j
209 procedure TRoundList.Delete(ThreadItem: TThreadItem);
213 idx := Find(ThreadItem);
214 if idx <> -1 then begin
215 TThreadItem(TRoundItem(FItemList[idx]).FItem).RoundName := '';
216 TRoundItem(FItemList[idx]).Free;
217 FItemList.Delete(idx);
220 //!
\8f\84\89ñ
\97\
\96ñ
\8fÁ
\8b\8e
221 procedure TRoundList.Clear;
225 for i := FBoardList.Count - 1 downto 0 do begin
226 if FBoardList[i] <> nil then
227 TRoundItem(FBoardList[i]).Free;
228 FBoardList.Delete(i);
230 FBoardList.Capacity := FBoardList.Count;
231 for i := FItemList.Count - 1 downto 0 do begin
232 if FItemList[i] <> nil then
233 TRoundItem(FItemList[i]).Free;
236 FItemList.Capacity := FItemList.Count;
238 //!
\8f\84\89ñ
\97\
\96ñ
\8c\9f\8dõ
\81i
\94Â
\81j
239 function TRoundList.Find(Board: TBoard): Integer;
245 for i := 0 to FBoardList.Count - 1 do begin
246 Item := TRoundItem(FBoardList[i]);
247 if Item.FRoundType <> grtBoard then Continue;
248 if Item.FItem = Board then begin
254 //!
\8f\84\89ñ
\97\
\96ñ
\8c\9f\8dõ
\81i
\83X
\83\8c\83b
\83h
\81j
255 function TRoundList.Find(ThreadItem: TThreadItem): Integer;
261 for i := 0 to FItemList.Count - 1 do begin
262 Item := TRoundItem(FItemList[i]);
263 if Item.FRoundType <> grtItem then Continue;
264 if Item.FItem = ThreadItem then begin
270 //!
\8f\84\89ñ
\97\
\96ñ
\8c\9f\8dõ
\81iURL
\81{
\83A
\83C
\83e
\83\80\83^
\83C
\83v
\81j
271 function TRoundList.Find(URL: string; RoundType: TGikoRoundType): Integer;
277 if RoundType = grtItem then begin
278 for i := 0 to FItemList.Count - 1 do begin
279 Item := TRoundItem(FItemList[i]);
280 if Item.FRoundType <> RoundType then Continue;
281 if Item.URL = URL then begin
287 for i := 0 to FBoardList.Count - 1 do begin
288 Item := TRoundItem(FBoardList[i]);
289 if Item.FRoundType <> RoundType then Continue;
290 if Item.URL = URL then begin
297 //!
\8f\84\89ñ
\97\
\96ñ
\8dí
\8f\9c\81iURL
\81{
\83A
\83C
\83e
\83\80\83^
\83C
\83v
\81j
298 procedure TRoundList.Delete(URL: string; RoundType: TGikoRoundType);
303 threadItem: TThreadItem;
305 idx := Find(URL, RoundType);
306 if idx <> -1 then begin
308 if RoundType = grtBoard then begin
309 Item := TRoundItem(FBoardList[idx]);
310 board := TBoard(Item);
312 FBoardList.Delete(idx);
313 if board <> nil then begin
314 board.Round := False;
315 board.RoundName := '';
318 Item := TRoundItem(FItemList[idx]);
319 threadItem := TThreadItem(Item.FItem);
321 FItemList.Delete(idx);
323 if threadItem <> nil then begin
324 threadItem.Round := false;
325 threadItem.RoundName := '';
330 //!
\8f\84\89ñ
\97\
\96ñ
\90\94\8eæ
\93¾
331 function TRoundList.GetCount(RoundType: TGikoRoundType): Integer;
334 if RoundType = grtBoard then
335 Result := FBoardList.Count
336 else if RoundType = grtItem then
337 Result := FItemList.Count;
339 //!
\8f\84\89ñ
\97\
\96ñ
\8eæ
\93¾
340 function TRoundList.GetRoundItem(Index: Integer; RoundType: TGikoRoundType): TRoundItem;
343 if RoundType = grtBoard then begin
344 if (Index >= 0) and (Index < FBoardList.Count) then
345 Result := TRoundItem(FBoardList[Index]);
346 end else if RoundType = grtItem then begin
347 if (Index >= 0) and (Index < FItemList.Count) then
348 Result := TRoundItem(FItemList[Index]);
351 //!
\83{
\81[
\83h
\8f\84\89ñ
\97\
\96ñ
\83t
\83@
\83C
\83\8b\93Ç
\82Ý
\8d\9e\82Ý
352 procedure TRoundList.LoadRoundBoardFile;
356 FileName, bFileName: string;
357 errorSl: TStringList;
358 errorFileName: string;
361 sl := TStringList.Create;
362 errorSl := TStringList.Create;
363 errorSl.Duplicates := dupIgnore;
365 //
\83{
\81[
\83h
\8f\84\89ñ
\83t
\83@
\83C
\83\8b\93Ç
\82Ý
\8d\9e\82Ý
366 FileName := GikoSys.GetConfigDir + ROUND_BOARD_FILENAME;
367 bFileName := GikoSys.GetConfigDir + '~' + ROUND_BOARD_FILENAME;
368 //
\83G
\83\89\81[
\8ds
\95Û
\91¶
\83t
\83@
\83C
\83\8b\93Ç
\82Ý
\8d\9e\82Ý
369 errorFileName := GikoSys.GetConfigDir + ERROR_BOARD_FILENAME;
371 if FileExists(FileName) then begin
372 sl.LoadFromFile(FileName);
373 if FileExists(bFileName) then
374 DeleteFile(bFileName);
375 //
\83o
\83b
\83N
\83A
\83b
\83v
\97p
\82Ì
\83t
\83@
\83C
\83\8b\82ð
\8dì
\90¬
\82·
\82é
376 sl.SaveToFile(bFileName);
377 if FileExists(errorFileName) then begin
379 errorSl.LoadFromFile(errorFileName);
383 //Item := TRoundItem.Create;
385 //
\82P
\8ds
\96Ú
\82Í
\83o
\81[
\83W
\83\87\83\93
386 if sl[0] = ROUND_INDEX_VERSION then begin
387 for i := 1 to sl.Count - 1 do begin
388 if not ParseRoundBoardLine(sl[i - delCount]) then begin
389 errorSl.Add( sl[i - delCount] );
390 sl.Delete(i- delCount);
395 if FOldFileRead then begin //
\83M
\83R
\83i
\83r
\96{
\91Ì
\82ª
\83{
\81[
\83h
\83t
\83@
\83C
\83\8b\82ð
\82æ
\82Ý
\82Æ
\82Á
\82½
\8cã
\82¶
\82á
\82È
\82¢
\82Æ
\83N
\83\89\83b
\83V
\83\85\82·
\82é
\82Ì
\82Å
396 for i := 1 to sl.Count - 1 do begin
397 if not ParseOldRoundBoardLine(sl[i - delCount]) then begin
398 errorSl.Add( sl[i- delCount] );
399 sl.Delete(i- delCount);
404 FOldFileRead := true;
407 if errorSl.Count > 0 then
408 errorSl.SaveToFile(errorFileName);
414 //!
\83X
\83\8c\83b
\83h
\8f\84\89ñ
\97\
\96ñ
\83t
\83@
\83C
\83\8b\93Ç
\82Ý
\8d\9e\82Ý
415 procedure TRoundList.LoadRoundThreadFile;
419 FileName, bFileName: string;
420 errorSl: TStringList;
421 errorFileName: string;
424 errorSl := TStringList.Create;
425 errorSl.Duplicates := dupIgnore;
426 sl := TStringList.Create;
428 //
\83X
\83\8c\8f\84\89ñ
\83t
\83@
\83C
\83\8b\93Ç
\82Ý
\8d\9e\82Ý
429 FileName := GikoSys.GetConfigDir + ROUND_ITEM_FILENAME;
430 bFileName := GikoSys.GetConfigDir + '~' + ROUND_ITEM_FILENAME;
431 //
\83G
\83\89\81[
\8ds
\95Û
\91¶
\83t
\83@
\83C
\83\8b\93Ç
\82Ý
\8d\9e\82Ý
432 errorFileName := GikoSys.GetConfigDir + ERROR_ITEM_FILENAME;
433 if FileExists(FileName) then begin
434 sl.LoadFromFile(FileName);
435 if FileExists(bFileName) then
436 DeleteFile(bFileName);
437 sl.SaveToFile(bFileName);
438 if FileExists(errorFileName) then begin
440 errorSl.LoadFromFile(errorFileName);
444 //Item := TRoundItem.Create;
446 //
\82P
\8ds
\96Ú
\82Í
\83o
\81[
\83W
\83\87\83\93
447 if sl[0] = ROUND_INDEX_VERSION then begin
448 for i := 1 to sl.Count - 1 do begin
449 if not ParseRoundThreadLine(sl[i - delCount]) then begin
450 errorSl.Add(sl[i - delCount]);
451 sl.Delete(i - delCount);
457 for i := 1 to sl.Count - 1 do begin
458 if not ParseOldRoundThreadLine(sl[i - delCount]) then begin
459 errorSl.Add(sl[i - delCount]);
460 sl.Delete(i - delCount);
465 if errorSl.Count > 0 then
466 errorSl.SaveToFile(errorFileName);
473 //!
\8f\84\89ñ
\97\
\96ñ
\83t
\83@
\83C
\83\8b\95Û
\91¶
474 procedure TRoundList.SaveRoundFile;
482 GikoSys.ForceDirectoriesEx(GikoSys.GetConfigDir);
484 sl := TStringList.Create;
486 FileName := GikoSys.GetConfigDir + ROUND_BOARD_FILENAME;
487 sl.Add(ROUND_INDEX_VERSION);
488 for i := 0 to FBoardList.Count - 1 do begin
489 Item := TRoundItem(FBoardList[i]);
491 if Item.TmpURL <> '' then begin
492 s := Item.TmpURL + #1
493 + Item.BoardTitle + #1
497 + Item.BoardTitle + #1
504 sl.SaveToFile(FileName);
506 FileName := GikoSys.GetConfigDir + ROUND_ITEM_FILENAME;
507 sl.Add(ROUND_INDEX_VERSION);
508 for i := 0 to FItemList.Count - 1 do begin
509 Item := TRoundItem(FItemList[i]);
511 if Item.TmpURL <> '' then begin
512 s := Item.TmpURL + #1
513 + Item.BoardTitle + #1
515 + Item.ThreadTitle + #1
519 + Item.BoardTitle + #1
521 + Item.ThreadTitle + #1
528 sl.SaveToFile(FileName);
533 function TRoundList.ParseRoundBoardLine(Line: string): Boolean;
540 //Result := TRoundItem.Create;
541 //Result.ThreadTitle := '';
542 //Result.FileName := '';
543 //Result.RoundType := grtBoard;
545 for i := 0 to 2 do begin
546 s := GikoSys.GetTokenIndex(Line, #1, i);
551 board := BBSsFindBoardFromURL(s);
554 //1: Result.BoardTitle := s;
562 if( board <> nil ) then begin
563 if not board.Round then begin
564 board.RoundName := roundname;
565 RoundNameList.Add(roundname);
566 //RoundNameList.Find(roundname, i);
567 //board.RoundName := PChar(RoundNameList[i]);
576 function TRoundList.ParseRoundThreadLine(Line: string): Boolean;
580 threadItem: TThreadItem;
582 // threadItem: TThreadItem;
584 //Result := TRoundItem.Create;
585 //Result.RoundType := grtItem;
587 for i := 0 to 4 do begin
588 s := GikoSys.GetTokenIndex(Line, #1, i);
594 threadItem := BBSsFindThreadFromURL( s );
595 //if threadItem <> nil then begin
596 // BoardList.Add( threadItem.ParentBoard.URL );
599 //1: Result.BoardTitle := s;
600 //2: Result.FileName := s;
601 //3: Result.ThreadTitle := s;
609 if( threadItem <> nil ) then begin
610 if not threadItem.Round then begin
611 threadItem.RoundName := roundname;
612 RoundNameList.Add(roundname);
613 //RoundNameList.Find(roundname, i);
614 //threadItem.RoundName := PChar(RoundNameList[i]);
615 threadItem.Round := True;
623 function TRoundList.ParseOldRoundBoardLine(Line: string): Boolean;
630 //Result := TRoundItem.Create;
631 //Result.ThreadTitle := '';
632 //Result.FileName := '';
633 //Result.RoundType := grtBoard;
635 for i := 0 to 2 do begin
636 s := GikoSys.GetTokenIndex(Line, #1, i);
641 board := BBSs[ 0 ].FindBBSID( s );
642 if board = nil then begin
643 raise Exception.Create('
\82±
\82Ì
\8f\84\89ñ
\82Í
\93Ç
\82Ý
\8d\9e\82ß
\82È
\82¢
\82æ
\81i
\91½
\95ª
\8aO
\95\94\94Â
\81j');
646 //1: Result.FBoardTitle := s;
654 if( board <> nil ) then begin
655 if not board.Round then begin
656 board.RoundName := roundname;
657 RoundNameList.Add(roundname);
658 //RoundNameList.Find(roundname, i);
659 //board.RoundName := PChar(RoundNameList[i]);
668 function TRoundList.ParseOldRoundThreadLine(Line: string): Boolean;
675 threadItem: TThreadItem;
678 // Result := TRoundItem.Create;
679 // Result.RoundType := grtItem;
681 for i := 0 to 4 do begin
682 s := GikoSys.GetTokenIndex(Line, #1, i);
686 //1: Result.BoardTitle := s;
689 //Result.FileName := s;
690 board := BBSs[ 0 ].FindBBSID(bbsID);
691 if board <> nil then begin
692 buf := Copy(board.GetSendURL,1,LastDelimiter('/', board.GetSendURL)-1);
693 buf := buf + '/read.cgi/'+ board.BBSID+ '/' +ChangeFileExt(s,'') + '/l50';
694 threadItem := BBSsFindThreadFromURL(buf);
696 raise Exception.Create('
\82±
\82Ì
\8f\84\89ñ
\82Í
\93Ç
\82Ý
\8d\9e\82ß
\82È
\82¢
\82æ');
699 //3: Result.ThreadTitle := s;
707 if( threadItem <> nil ) then begin
708 if not threadItem.Round then begin
709 threadItem.RoundName := roundname;
710 RoundNameList.Add(roundname);
711 //RoundNameList.Find(roundname, i);
712 //threadItem.RoundName := PChar(RoundNameList[i]);
713 threadItem.Round := true;
721 procedure TRoundList.URLReplace(oldURLs: TStringList; newURLs :TStringList);
728 oldBoardName: string;
730 newBoardName: string;
732 if oldURLs.Count <> newURLs.Count then
734 //
\82±
\82±
\82©
\82ç
\81ABoard
\82ÌURL
\82Ì
\95Ï
\8dX
735 for j :=0 to oldURLs.Count - 1 do begin
736 for i :=0 to FBoardList.Count - 1 do begin
737 if TRoundItem(FBoardList[i]).URL = oldURLs[j] then
738 TRoundItem(FBoardList[i]).TmpURL := newURLs[j];
741 //
\82±
\82±
\82Ü
\82Å
\81ABoard
\82ÌURL
\82Ì
\95Ï
\8dX
743 //
\82±
\82±
\82©
\82ç
\81AThread
\82ÌURL
\82Ì
\95Ï
\8dX
744 //
\96Ê
\93|
\82¾
\82¯
\82Çthread
\82Í
\82»
\82ê
\82¼
\82êURL
\82ð
\83`
\83\83\83b
\83N
\82µ
\82È
\82ª
\82ç
\82â
\82Á
\82Ä
\82©
\82È
\82«
\82á
\82¢
\82¯
\82È
\82¢
\81B
745 for i := 0 to oldURLs.Count - 1 do begin
746 tmpURL := Copy(oldURLs[i], 1, Length(oldURLs[i]) -1);
747 oldHost := Copy(tmpURL, 1, LastDelimiter('/', tmpURL) );
748 oldBoardName := Copy(tmpURL, LastDelimiter('/', tmpURL), Length(tmpURL) ) + '/';
749 tmpURL := Copy(newURLs[i], 1, Length(newURLs[i]) -1);
750 newHost := Copy(tmpURL, 1, LastDelimiter('/', tmpURL) );
751 newBoardName := Copy(tmpURL, LastDelimiter('/', tmpURL), Length(tmpURL) ) + '/';
753 for j := 0 to FItemList.Count - 1 do begin
754 tempString := TRoundItem(FItemList[j]).URL;
755 if ( AnsiPos(oldBoardName, tempString) <> 0 ) and ( AnsiPos(oldHost, tempString ) <> 0 ) then begin
756 tempString := StringReplace(tempString, oldHost, newHost,[]);
757 TRoundItem(FItemList[j]).TmpURL := tempString;
761 //
\82±
\82±
\82Ü
\82Å
\81AThread
\82ÌURL
\82Ì
\95Ï
\8dX