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 SetRoundName(Board: TBoard; RoundName: string); overload;
42 //procedure SetRoundName(ThreadItem: TThreadItem; RoundName: string); overload;
44 procedure LoadRoundBoardFile;
45 procedure LoadRoundThreadFile;
46 procedure SaveRoundFile;
48 procedure URLReplace(oldURLs: TStringList; newURLs :TStringList);
51 TRoundItem = class(TObject)
55 FRoundType: TGikoRoundType;
57 FBoolData: Boolean; //
\82¢
\82ë
\82¢
\82ë
\8eg
\82¤
\82å
\82£
58 function GetBoardTitle : string;
59 function GetThreadTitle : string;
60 function GetURL : string;
61 function GetFileName : string;
62 //!
\8f\84\89ñ
\96¼
\8eæ
\93¾
63 function GetRoundName : string;
66 property Item : TObject read FItem;
67 property RoundName: string read GetRoundName;
68 property RoundType: TGikoRoundType read FRoundType write FRoundType;
69 property URL : string read GetURL;
70 property TmpURL : string read FTmpURL write FTmpURL;
71 property BoardTitle: string read GetBoardTitle;
72 property ThreadTitle: string read GetThreadTitle;
73 property FileName: string read GEtFileName;
74 property BoolData: Boolean read FBoolData write FBoolData;
78 RoundList: TRoundList;
82 ROUND_BOARD_FILENAME: string = 'RoundBoard.2ch'; //
\82 \82Æ
\82ÅBoardGroup
\82Ö
\88Ú
\93®
83 ROUND_ITEM_FILENAME: string = 'RoundItem.2ch'; //
\93¯
\8fã
84 ROUND_INDEX_VERSION: string = '2.00';
85 ERROR_BOARD_FILENAME: string = 'ErrorBoard.2ch'; //Error
\8ds
\82ð
\95Û
\8aÇ
\82·
\82é
86 ERROR_ITEM_FILENAME: string = 'ErrorItem.2ch'; //Error
\8ds
\82ð
\95Û
\8aÇ
\82·
\82é
87 constructor TRoundItem.Create;
91 function TRoundItem.GetBoardTitle : string;
94 if( Self.FItem <> nil) then begin
95 if( Self.FItem is TBoard) then begin
96 Result := TBoard(Self.FItem).Title;
97 end else if( Self.FItem is TThreadItem) then begin
98 Result := TThreadItem(Self.FItem).ParentBoard.Title;
102 function TRoundItem.GetThreadTitle : string;
105 if( Self.FItem <> nil) then begin
106 if( Self.FItem is TThreadItem) then begin
107 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 function TRoundItem.GetFileName : string;
125 if( Self.FItem <> nil) then begin
126 if( Self.FItem is TThreadItem) then begin
127 Result := TThreadItem(Self.FItem).FileName;
131 //!
\8f\84\89ñ
\96¼
\8eæ
\93¾
132 function TRoundItem.GetRoundName : string;
135 if( Self.FItem <> nil) then begin
136 if( Self.FItem is TBoard) then begin
137 Result := TBoard(Self.FItem).RoundName;
138 end else if( Self.FItem is TThreadItem) then begin
139 Result := TThreadItem(Self.FItem).RoundName;
144 constructor TRoundList.Create;
147 FBoardList := TList.Create;
148 FItemList := TList.Create;
149 RoundNameList := TStringList.Create;
150 RoundNameList.Sorted := True;
151 RoundNameList.Duplicates := dupIgnore;
152 FOldFileRead := false;
155 destructor TRoundList.Destroy;
164 function TRoundList.Add(Board: TBoard): Integer;
171 //RoundNameList.Add(Board.RoundName);
172 if idx = -1 then begin
173 Item := TRoundItem.Create;
175 // Item.BBSType := gbt2ch; //
\82Æ
\82è
\82 \82¦
\82¸
176 Item.RoundType := grtBoard;
177 // Item.Item := Board;
178 //Item.URL := Board.URL;
179 //Item.BoardTitle := Board.Title;
180 //Item.ThreadTitle := '';
181 //Item.FileName := '';
182 //Item.RoundName := Board.RoundName;
183 Result := FBoardList.Add(Item);
187 function TRoundList.Add(ThreadItem: TThreadItem): Integer;
193 idx := Find(ThreadItem);
194 //RoundNameList.Add(ThreadItem.RoundName);
195 if idx = -1 then begin
196 Item := TRoundItem.Create;
197 Item.FItem := ThreadItem;
198 // Item.BBSType := gbt2ch; //
\82Æ
\82è
\82 \82¦
\82¸
199 Item.RoundType := grtItem;
200 // Item.Item := ThreadItem;
201 //Item.URL := Threaditem.URL;
202 //Item.BoardTitle := ThreadItem.ParentBoard.Title;
203 //Item.ThreadTitle := ThreadItem.Title;
204 //Item.FileName := ThreadItem.FileName;
205 //Item.RoundName := ThreadItem.RoundName;
206 Result := FItemList.Add(Item);
210 procedure TRoundList.Delete(Board: TBoard);
216 if idx <> -1 then begin
217 TBoard(TRoundItem(FBoardList[idx]).FItem).RoundName := '';
218 TRoundItem(FBoardList[idx]).Free;
219 FBoardList.Delete(idx);
223 procedure TRoundList.Delete(ThreadItem: TThreadItem);
228 idx := Find(ThreadItem);
229 if idx <> -1 then begin
230 TThreadItem(TRoundItem(FItemList[idx]).FItem).RoundName := '';
231 TRoundItem(FItemList[idx]).Free;
232 FItemList.Delete(idx);
236 procedure TRoundList.Clear;
240 for i := FBoardList.Count - 1 downto 0 do begin
241 if FBoardList[i] <> nil then
242 TRoundItem(FBoardList[i]).Free;
243 FBoardList.Delete(i);
245 FBoardList.Capacity := FBoardList.Count;
246 for i := FItemList.Count - 1 downto 0 do begin
247 if FItemList[i] <> nil then
248 TRoundItem(FItemList[i]).Free;
251 FItemList.Capacity := FItemList.Count;
254 function TRoundList.Find(Board: TBoard): Integer;
260 for i := 0 to FBoardList.Count - 1 do begin
261 Item := TRoundItem(FBoardList[i]);
262 if Item.FRoundType <> grtBoard then Continue;
263 if Item.FItem = Board then begin
270 function TRoundList.Find(ThreadItem: TThreadItem): Integer;
276 for i := 0 to FItemList.Count - 1 do begin
277 Item := TRoundItem(FItemList[i]);
278 if Item.FRoundType <> grtItem then Continue;
279 if Item.FItem = ThreadItem then begin
285 function TRoundList.Find(URL: string; RoundType: TGikoRoundType): Integer;
291 if RoundType = grtItem then begin
292 for i := 0 to FItemList.Count - 1 do begin
293 Item := TRoundItem(FItemList[i]);
294 if Item.FRoundType <> RoundType then Continue;
295 if Item.URL = URL then begin
301 for i := 0 to FBoardList.Count - 1 do begin
302 Item := TRoundItem(FBoardList[i]);
303 if Item.FRoundType <> RoundType then Continue;
304 if Item.URL = URL then begin
311 procedure TRoundList.Delete(URL: string; RoundType: TGikoRoundType);
316 threadItem: TThreadItem;
318 idx := Find(URL, RoundType);
319 if idx <> -1 then begin
321 if RoundType = grtBoard then begin
322 Item := TRoundItem(FBoardList[idx]);
323 board := TBoard(Item);
325 FBoardList.Delete(idx);
326 //board := BBSsFindBoardFromURL(URL);
327 if board <> nil then begin
328 board.Round := False;
329 board.RoundName := '';
332 Item := TRoundItem(FItemList[idx]);
333 threadItem := TThreadItem(Item.FItem);
335 FItemList.Delete(idx);
337 //threadItem := BBSsFindThreadFromURL(URL);
338 if threadItem <> nil then begin
339 threadItem.Round := false;
340 threadItem.RoundName := '';
346 procedure TRoundList.SetRoundName(Board: TBoard; RoundName: string);
352 if idx <> -1 then begin
353 Item := TRoundItem(FBoardList[idx]);
354 Item.RoundName := RoundName;
359 procedure TRoundList.SetRoundName(ThreadItem: TThreadItem; RoundName: string);
364 idx := Find(ThreadItem);
365 if idx <> -1 then begin
366 Item := TRoundItem(FItemList[idx]);
367 Item.RoundName := RoundName;
371 function TRoundList.GetCount(RoundType: TGikoRoundType): Integer;
374 if RoundType = grtBoard then
375 Result := FBoardList.Count
376 else if RoundType = grtItem then
377 Result := FItemList.Count;
380 function TRoundList.GetRoundItem(Index: Integer; RoundType: TGikoRoundType): TRoundItem;
383 if RoundType = grtBoard then begin
384 if (Index >= 0) and (Index < FBoardList.Count) then
385 Result := TRoundItem(FBoardList[Index]);
386 end else if RoundType = grtItem then begin
387 if (Index >= 0) and (Index < FItemList.Count) then
388 Result := TRoundItem(FItemList[Index]);
391 procedure TRoundList.LoadRoundBoardFile;
395 FileName, bFileName: string;
396 errorSl: TStringList;
397 errorFileName: string;
401 sl := TStringList.Create;
402 errorSl := TStringList.Create;
403 errorSl.Duplicates := dupIgnore;
405 //
\83{
\81[
\83h
\8f\84\89ñ
\83t
\83@
\83C
\83\8b\93Ç
\82Ý
\8d\9e\82Ý
406 FileName := GikoSys.GetConfigDir + ROUND_BOARD_FILENAME;
407 bFileName := GikoSys.GetConfigDir + '~' + ROUND_BOARD_FILENAME;
408 //
\83G
\83\89\81[
\8ds
\95Û
\91¶
\83t
\83@
\83C
\83\8b\93Ç
\82Ý
\8d\9e\82Ý
409 errorFileName := GikoSys.GetConfigDir + ERROR_BOARD_FILENAME;
411 if FileExists(FileName) then begin
412 sl.LoadFromFile(FileName);
413 if FileExists(bFileName) then
414 DeleteFile(bFileName);
415 //
\83o
\83b
\83N
\83A
\83b
\83v
\97p
\82Ì
\83t
\83@
\83C
\83\8b\82ð
\8dì
\90¬
\82·
\82é
416 sl.SaveToFile(bFileName);
417 if FileExists(errorFileName) then begin
419 errorSl.LoadFromFile(errorFileName);
423 //Item := TRoundItem.Create;
425 //
\82P
\8ds
\96Ú
\82Í
\83o
\81[
\83W
\83\87\83\93
426 if sl[0] = ROUND_INDEX_VERSION then begin
427 for i := 1 to sl.Count - 1 do begin
428 if not ParseRoundBoardLine(sl[i - delCount]) then begin
429 errorSl.Add( sl[i - delCount] );
430 sl.Delete(i- delCount);
435 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Å
436 for i := 1 to sl.Count - 1 do begin
437 if not ParseOldRoundBoardLine(sl[i - delCount]) then begin
438 errorSl.Add( sl[i- delCount] );
439 sl.Delete(i- delCount);
444 FOldFileRead := true;
447 if errorSl.Count > 0 then
448 errorSl.SaveToFile(errorFileName);
454 procedure TRoundList.LoadRoundThreadFile;
459 FileName, bFileName: string;
460 errorSl: TStringList;
461 errorFileName: string;
464 // boardList : TStringList;
466 // boardList := TStringList.Create;
467 // boardList.Duplicates := dupIgnore;
468 errorSl := TStringList.Create;
469 errorSl.Duplicates := dupIgnore;
470 sl := TStringList.Create;
472 //
\83X
\83\8c\8f\84\89ñ
\83t
\83@
\83C
\83\8b\93Ç
\82Ý
\8d\9e\82Ý
473 FileName := GikoSys.GetConfigDir + ROUND_ITEM_FILENAME;
474 bFileName := GikoSys.GetConfigDir + '~' + ROUND_ITEM_FILENAME;
475 //
\83G
\83\89\81[
\8ds
\95Û
\91¶
\83t
\83@
\83C
\83\8b\93Ç
\82Ý
\8d\9e\82Ý
476 errorFileName := GikoSys.GetConfigDir + ERROR_ITEM_FILENAME;
477 if FileExists(FileName) then begin
478 sl.LoadFromFile(FileName);
479 if FileExists(bFileName) then
480 DeleteFile(bFileName);
481 sl.SaveToFile(bFileName);
482 if FileExists(errorFileName) then begin
484 errorSl.LoadFromFile(errorFileName);
488 //Item := TRoundItem.Create;
490 //
\82P
\8ds
\96Ú
\82Í
\83o
\81[
\83W
\83\87\83\93
491 if sl[0] = ROUND_INDEX_VERSION then begin
492 for i := 1 to sl.Count - 1 do begin
493 if not ParseRoundThreadLine(sl[i - delCount]) then begin
494 errorSl.Add(sl[i - delCount]);
495 sl.Delete(i - delCount);
501 for i := 1 to sl.Count - 1 do begin
502 if not ParseOldRoundThreadLine(sl[i - delCount]) then begin
503 errorSl.Add(sl[i - delCount]);
504 sl.Delete(i - delCount);
509 // j := boardList.Count - 1;
510 // while j >= 0 do begin
511 // GikoSys.ReadSubjectFile( BBSsFindBoardFromURL( boardList[j] ) );
512 // boardList.Delete(j);
515 if errorSl.Count > 0 then
516 errorSl.SaveToFile(errorFileName);
524 procedure TRoundList.SaveRoundFile;
532 GikoSys.ForceDirectoriesEx(GikoSys.GetConfigDir);
534 sl := TStringList.Create;
536 FileName := GikoSys.GetConfigDir + ROUND_BOARD_FILENAME;
537 sl.Add(ROUND_INDEX_VERSION);
538 for i := 0 to FBoardList.Count - 1 do begin
539 Item := TRoundItem(FBoardList[i]);
541 if Item.TmpURL <> '' then begin
542 s := Item.TmpURL + #1
543 + Item.BoardTitle + #1
547 + Item.BoardTitle + #1
554 sl.SaveToFile(FileName);
556 FileName := GikoSys.GetConfigDir + ROUND_ITEM_FILENAME;
557 sl.Add(ROUND_INDEX_VERSION);
558 for i := 0 to FItemList.Count - 1 do begin
559 Item := TRoundItem(FItemList[i]);
561 if Item.TmpURL <> '' then begin
562 s := Item.TmpURL + #1
563 + Item.BoardTitle + #1
565 + Item.ThreadTitle + #1
569 + Item.BoardTitle + #1
571 + Item.ThreadTitle + #1
578 sl.SaveToFile(FileName);
583 function TRoundList.ParseRoundBoardLine(Line: string): Boolean;
590 //Result := TRoundItem.Create;
591 //Result.ThreadTitle := '';
592 //Result.FileName := '';
593 //Result.RoundType := grtBoard;
595 for i := 0 to 2 do begin
596 s := GikoSys.GetTokenIndex(Line, #1, i);
601 board := BBSsFindBoardFromURL(s);
604 //1: Result.BoardTitle := s;
612 if( board <> nil ) then begin
613 if not board.Round then begin
614 board.RoundName := roundname;
615 RoundNameList.Add(roundname);
616 //RoundNameList.Find(roundname, i);
617 //board.RoundName := PChar(RoundNameList[i]);
626 function TRoundList.ParseRoundThreadLine(Line: string): Boolean;
630 threadItem: TThreadItem;
632 // threadItem: TThreadItem;
634 //Result := TRoundItem.Create;
635 //Result.RoundType := grtItem;
637 for i := 0 to 4 do begin
638 s := GikoSys.GetTokenIndex(Line, #1, i);
644 threadItem := BBSsFindThreadFromURL( s );
645 //if threadItem <> nil then begin
646 // BoardList.Add( threadItem.ParentBoard.URL );
649 //1: Result.BoardTitle := s;
650 //2: Result.FileName := s;
651 //3: Result.ThreadTitle := s;
659 if( threadItem <> nil ) then begin
660 if not threadItem.Round then begin
661 threadItem.RoundName := roundname;
662 RoundNameList.Add(roundname);
663 //RoundNameList.Find(roundname, i);
664 //threadItem.RoundName := PChar(RoundNameList[i]);
665 threadItem.Round := True;
673 function TRoundList.ParseOldRoundBoardLine(Line: string): Boolean;
680 //Result := TRoundItem.Create;
681 //Result.ThreadTitle := '';
682 //Result.FileName := '';
683 //Result.RoundType := grtBoard;
685 for i := 0 to 2 do begin
686 s := GikoSys.GetTokenIndex(Line, #1, i);
691 board := BBSs[ 0 ].FindBBSID( s );
692 if board = nil then begin
693 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');
696 //1: Result.FBoardTitle := s;
704 if( board <> nil ) then begin
705 if not board.Round then begin
706 board.RoundName := roundname;
707 RoundNameList.Add(roundname);
708 //RoundNameList.Find(roundname, i);
709 //board.RoundName := PChar(RoundNameList[i]);
718 function TRoundList.ParseOldRoundThreadLine(Line: string): Boolean;
725 threadItem: TThreadItem;
728 // Result := TRoundItem.Create;
729 // Result.RoundType := grtItem;
731 for i := 0 to 4 do begin
732 s := GikoSys.GetTokenIndex(Line, #1, i);
736 //1: Result.BoardTitle := s;
739 //Result.FileName := s;
740 board := BBSs[ 0 ].FindBBSID(bbsID);
741 if board <> nil then begin
742 buf := Copy(board.GetSendURL,1,LastDelimiter('/', board.GetSendURL)-1);
743 buf := buf + '/read.cgi/'+ board.BBSID+ '/' +ChangeFileExt(s,'') + '/l50';
744 threadItem := BBSsFindThreadFromURL(buf);
746 raise Exception.Create('
\82±
\82Ì
\8f\84\89ñ
\82Í
\93Ç
\82Ý
\8d\9e\82ß
\82È
\82¢
\82æ');
749 //3: Result.ThreadTitle := s;
757 if( threadItem <> nil ) then begin
758 if not threadItem.Round then begin
759 threadItem.RoundName := roundname;
760 RoundNameList.Add(roundname);
761 //RoundNameList.Find(roundname, i);
762 //threadItem.RoundName := PChar(RoundNameList[i]);
763 threadItem.Round := true;
771 procedure TRoundList.URLReplace(oldURLs: TStringList; newURLs :TStringList);
778 oldBoardName: string;
780 newBoardName: string;
782 if oldURLs.Count <> newURLs.Count then
784 //
\82±
\82±
\82©
\82ç
\81ABoard
\82ÌURL
\82Ì
\95Ï
\8dX
785 for j :=0 to oldURLs.Count - 1 do begin
786 for i :=0 to FBoardList.Count - 1 do begin
787 if TRoundItem(FBoardList[i]).URL = oldURLs[j] then
788 TRoundItem(FBoardList[i]).TmpURL := newURLs[j];
791 //
\82±
\82±
\82Ü
\82Å
\81ABoard
\82ÌURL
\82Ì
\95Ï
\8dX
793 //
\82±
\82±
\82©
\82ç
\81AThread
\82ÌURL
\82Ì
\95Ï
\8dX
794 //
\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
795 for i := 0 to oldURLs.Count - 1 do begin
796 tmpURL := Copy(oldURLs[i], 1, Length(oldURLs[i]) -1);
797 oldHost := Copy(tmpURL, 1, LastDelimiter('/', tmpURL) );
798 oldBoardName := Copy(tmpURL, LastDelimiter('/', tmpURL), Length(tmpURL) ) + '/';
799 tmpURL := Copy(newURLs[i], 1, Length(newURLs[i]) -1);
800 newHost := Copy(tmpURL, 1, LastDelimiter('/', tmpURL) );
801 newBoardName := Copy(tmpURL, LastDelimiter('/', tmpURL), Length(tmpURL) ) + '/';
803 for j := 0 to FItemList.Count - 1 do begin
804 tempString := TRoundItem(FItemList[j]).URL;
805 if ( AnsiPos(oldBoardName, tempString) <> 0 ) and ( AnsiPos(oldHost, tempString ) <> 0 ) then begin
806 tempString := StringReplace(tempString, oldHost, newHost,[]);
807 TRoundItem(FItemList[j]).TmpURL := tempString;
811 //
\82±
\82±
\82Ü
\82Å
\81AThread
\82ÌURL
\82Ì
\95Ï
\8dX