ISUII AmigaVirtual-皆のためのナニバヌサルAI

ロゎ 人工知胜の愛奜家や研究者の皆さん、こんにちは この蚘事では、興味深いプロゞェクトに぀いおお話ししたいず思いたす。AmigaVirtualAV、Virtual Girlfriendナニバヌサル人工知胜ISUIIのモゞュラヌシステムです。 その䜜業の基本原則に぀いお説明し、実装の詳现を説明したす。最も奜奇心が匷いものは、すべおの゜ヌスコヌドを調べるこずができたす。 Delphiでは開発が進行䞭ですが、理論的にはモゞュヌルはどの蚀語でも䜜成できたす。 このシステムは、チャットボットの゚ンドナヌザヌず関連システムの䞡方、およびAI開発者の関心を匕くでしょう。結局のずころ、ほがすべおの皮類のAIをそのベヌスで開発できたす。



たず、少し歎史。 プロゞェクトは、チャットボットの開発を開始するこずにした2012幎に開始されたした。 そしお、仮想女の子ず話すこずに぀いおの簡単なフラッシュゲヌムであるSayme 2に出䌚った埌、残念ながら、このゲヌムの野心的な継続バヌゞョン3は芜で死んだようです。RIP、Sayme 3。 その埌、AVはモノリスであり、アバタヌの䞀郚を含む1぀のDLLで写真が撮圱されたした-アバタヌが䞍芁な堎合に䜙分なメガバむトをダりンロヌドしないようにするためです。



スクリオンショットト1






スクリヌンショットト2






これが、Amiga Virtualの最初のバヌゞョンの倖芳です。



それ以来、コンセプトが倉わりたした-珟圚、AV自䜓はモゞュヌルの操䜜を敎理するためのプラットフォヌムにすぎたせん。 すべおのAI「噚官」はモゞュヌルに配眮されたす。



プログラミング蚀語に぀いおのいく぀かの蚀葉。 2012幎に、Delphiを遞択したした。圌以倖はほずんど䜕も知らなかったからですTurbo Pascalを陀く。 埌で倚くの蚀語を詊しおみたした...ずりわけAdaが奜きでしたが、トレヌニング資料が十分ではなく、プログラムが遅いこずがわかりたした。 OxygenDelphi Prismも詊しおみたしたが、材料はさらに少なくなっおいたす。 私はC ++や他のCラむクな蚀語がたったく奜きではありたせん。 そのため、最終的に私はDelphiに戻りたした。Delphiはよく知っおいお、単にむンタヌネット䞊にたくさんのトレヌニング資料があり、既成の゜リュヌションも数倚くありたす。



次にプロゞェクト自䜓に぀いお。 Amiga Virtualは、倚目的マルチ゚ヌゞェントシステムです。 䞀般的には、次のように線成されおいたす。特定のリストから特定のむンタヌフェむスを実装したメむンプログラムOPず䞀連のモゞュヌルDLLの圢匏で提瀺され、゜フトりェア゚ヌゞェントがありたす。 起動䞭に、OPはすべおのモゞュヌルをロヌドしお識別しモゞュヌルの機胜を決定し、プログラムぞのモゞュヌルの割り圓おは報告されたせん-意味がありたせん、ナヌザヌは䜜業したいモゞュヌルを遞択し、遞択したモゞュヌルの入力/出力むンタヌフェむスのマルチスレッド凊理を開始したす。 これはモゞュヌルがどのようにロヌドされ、識別されるかです



procedure LoadModules; var i: Integer; begin for i := 0 to Length(Module) - 1 do begin if Module[i].Handle > 0 then FreeModule(Module[i]); if LoadModule(Module[i]) then DetermineModuleType(Module[i]); end; end; function LoadModule(var M: TModule): boolean; var B: String; C: Integer; begin with M do begin Handle := LoadLibrary(PWideChar(FileName)); if Handle > 0 then begin @SetLanguage := GetProcAddress(Handle, 'SetLanguage'); IncAndUpdateProgress; //  - @SendLanguageData := GetProcAddress(Handle, 'SendLanguageData'); IncAndUpdateProgress; @GetName := GetProcAddress(Handle, 'GetName'); IncAndUpdateProgress; //   ,   //      if @GetName <> nil then begin B := GetName; C := Pos(ControlCodeMarker, B); if C > 0 then begin Name := Copy(B, C + 1, Length(B)); ControlCode := Copy(B, 1, C - 1); ControlCodeFormated := FormatControlCode(ControlCode); end else begin Name := B; ControlCode := MainForm.LanguageData[133]; end; end else begin Name := MainForm.LanguageData[114]; ControlCode := MainForm.LanguageData[133]; end; if (@OpenWindow <> nil) and (@CloseWindow <> nil) then WindowState := closed else WindowState := window_does_not_exist; if (@Sleep <> nil) and (@WakeUp <> nil) then ModuleState := working else ModuleState := module_cant_sleep; LoadStatistics; //     Result := true; end else Result := false; end; end; function DetermineModuleType(var M: TModule): TModuleType; begin with M do begin MType := undetermined; if (@SetLanguage = nil) and ... (*     nil *) then MType := erroneous_or_empty else begin if (@SetSource <> nil) or (@NextData <> nil) or (@Progress <> nil) or (@RestartParsing <> nil) then MType := parser else begin if (@GetData <> nil) and (@SendData <> nil) then MType := input_and_output else if (@GetData <> nil) and (@SendData = nil) then MType := only_input else if (@GetData = nil) and (@SendData <> nil) then MType := only_output else if (@GetData = nil) and (@SendData = nil) then MType := no_input_and_no_output; end; end; Result := MType; end; end;
      
      





OPは、ナヌザヌがモゞュヌルず察話するためのテキストベヌスのむンタヌフェむス、たたはより簡単にチャットりィンドりのみを実装したす。 すべおのモゞュヌルはこのチャットを通じお通信したすが、通垞、モゞュヌルの技術的なメッセヌゞはナヌザヌに衚瀺されたせん。 圌には関係ありたせんデバッグの目的で、これらのメッセヌゞを衚瀺できたす。 技術メッセヌゞは、行の先頭にいく぀かの印刷できない文字ずしおマヌクされたす。 このコヌド「制埡コヌド」は、モゞュヌルの開発者によっお蚭定されたす。 1぀の制埡コヌドで2぀のモゞュヌルをダりンロヌドするず、システムルヌプが発生する可胜性がありたす。これら2぀のモゞュヌルは、2぀のミラヌが盞互に蚭定されおいるように、メッセヌゞを無限に亀換したす。 芁するに、モゞュヌルがそれらに宛おられおいないメッセヌゞを無芖するために、制埡コヌドが必芁です。 ただし、むンテリゞェンスカヌネルモゞュヌルなど、䞀郚のモゞュヌルはすべおのメッセヌゞを凊理できたす。



入力、出力、たたは入出力むンタヌフェヌスを持぀各モゞュヌルは、個別のOPストリヌムで凊理されたす。 これにより、䞀郚のモゞュヌルがフリヌズするか、単に「考え盎す」堎合に、OPの操䜜性を維持できたす。 残りのモゞュヌルは、ナヌザヌが独自のりィンドりを䜿甚しお手動モヌドで䜿甚したす。 次のクラスは、入力/出力ストリヌムを実装したす。



  TIOThread = class(TThread) public const SleepTime = 1000; var Module: TModule; SelfID: Integer; constructor Create(M: TModule; ID: Integer); protected procedure Execute; override; end;
      
      





そしお、I / O凊理がどのように行われるかを次に瀺したす。



 procedure TIOThread.Execute; procedure GetData; var M: String; begin M := String(Module.GetData); if M <> SCM_No_Message then Synchronize( procedure begin Pool.AddRecord(M, SelfID); end); end; procedure SendData; var i: Integer; begin with Pool do if not Empty then begin for i := 0 to Length(Records) - 1 do with Records[i] do if not ModuleGot[SelfID] and (AuthorID <> SelfID) then begin Module.SendData(PChar(Text)); ModuleGot[SelfID] := true; end; Synchronize( procedure begin CheckAndDeleteOddRecords; end); end; end; begin inherited; while not Terminated do begin case Module.MType of only_input: GetData; only_output: SendData; input_and_output: begin SendData; GetData; end; end; Sleep(SleepTime); end; end;
      
      





メッセヌゞングの堎合、OPはメッセヌゞプヌルを実装したす。 チャットりィンドりずモゞュヌルから送信されたすべおのメッセヌゞはそのりィンドりに保存され、すべおのモゞュヌルがこれらのメッセヌゞを受信するたで保存され、その埌削陀されたす。 次のクラスは、メッセヌゞプヌルを実装したす。



  TPoolRecord = record Text: String; AuthorID: Integer; ModuleGot: array of Boolean; end; TPool = class Records: array of TPoolRecord; Empty: Boolean; procedure AddRecord(RecordText: String; RecordAuthor: Integer); procedure CheckAndDeleteOddRecords; constructor Create; procedure Show; end; procedure TPool.AddRecord(RecordText: String; RecordAuthor: Integer); var i, RL: Integer; begin RL := Length(Records); SetLength(Records, RL + 1); with Records[RL] do begin Text := RecordText; AuthorID := RecordAuthor; SetLength(ModuleGot, OutputModulesCount); for i := 0 to OutputModulesCount - 1 do if i = AuthorID then ModuleGot[i] := true else ModuleGot[i] := false; end; with MainForm, MainForm.ChatBox.Lines do case RecordAuthor of - 1: Add(User.Name + ': ' + RecordText); else if RecordText = SCM_Dont_Know_Answer then begin if DontKnowCheckBtn.Checked then Add(LanguageData[156]); end else Add(AVirtual.Name + ': ' + RecordText); end; Empty := false; end; procedure TPool.CheckAndDeleteOddRecords; function ItsOdd(ID: Integer): Boolean; var i: Integer; begin ItsOdd := true; with Records[ID] do for i := 0 to Length(ModuleGot) - 1 do if not ModuleGot[i] then begin ItsOdd := false; exit; end; end; procedure DeleteRecord(ID: Integer); var i: Integer; begin for i := ID to Length(Records) - 2 do Records[i] := Records[i + 1]; SetLength(Records, Length(Records) - 1); end; var i: Integer; begin if not Empty then begin for i := Length(Records) - 1 downto 0 do if ItsOdd(i) then DeleteRecord(i); if Length(Records) = 0 then Empty := true; end; if MainForm.PoolShowBtn.Checked then Show; end;
      
      





次に、可胜なモゞュヌルのクラスずその機胜に぀いお説明したしょう。



ガヌルフレンドが考案され実装された最も重芁な䞻芁クラスのモゞュヌルは、「知的カヌネル」IJ、たたは単にカヌネルです。 カヌネルは、チャットに蚭定されたアルゎリズムに埓っおチャットに入るすべおのメッセヌゞを凊理したす。 ぀たり、圌は䞻な知的䜜業を実行したす。 特定のアルゎリズムずその実装は、カヌネル開発者に䟝存したす。 優れたカヌネルを䜜成する方法は興味深い質問であり、䞀連のコアを䟋ずしお䜿甚しお別の蚘事で説明したす。 別の興味深い質問は、カヌネルを個別のモゞュヌルに分割する方法です。 珟圚䜜業䞭のカヌネルを现分化するこずはできたせん。 ただし、原則ずしお、耇合コアの䜜成を劚げるものはありたせん。



他のすべおのモゞュヌルはいく぀かのカテゎリに分類されたす受容䜓チャットでメッセヌゞを生成-ビゞョンモゞュヌル、聎芚モゞュヌルなど、゚フェクタヌチャットからのメッセヌゞに応じおアクションを実行、ツヌルAIに盎接適甚せず、ナヌザヌが手動で䜿甚したす 、パヌサヌトレヌニングモゞュヌル「Dream Fusion」で䜿甚、およびいく぀かの特別なモゞュヌルで䜿甚できるその他のモゞュヌル。



䞀郚の受容䜓ず゚フェクタヌは、それぞれ「制埡コヌド+コマンド」のスタむルで蚘録されたメッセヌゞを゚ンコヌドおよびデコヌドしたす。 通垞、このようなメッセヌゞはナヌザヌには衚瀺されたせん。 これらのメッセヌゞの本質は次のずおりです。受容䜓は、ナヌザヌによっお実行された特定のアクションを認識し、メッセヌゞに゚ンコヌドし、保存のためにカヌネルに送信したす。 カヌネルがこのメッセヌゞを発行するず、察応する゚フェクタがメッセヌゞをデコヌドし、ナヌザヌのアクションに察応するコマンドを受信し、このアクションを実行したす。 メッセヌゞを蚘憶しお発行するカヌネルに違いはなく、任意の受容䜓ず゚フェクタヌをシステムに接続できるため、知性は普遍的であるこずがわかりたす。぀たり、䜕でも教えられたす。 いいですね



䟿宜䞊、関連する受容䜓ず゚フェクタヌを1぀のモゞュヌルに実装できるこずに眮き換えおください。 䟋は、䞀般的な名前「゚モヌショナルアバタヌ」私はそれを「゚モタヌ」ず呌びたすの䞋のモゞュヌルのクラスです。ナヌザヌは特定の感情を衚珟する顔をパヌツか​​ら収集し、モゞュヌルは遞択された感情を゚ンコヌドするメッセヌゞを䜜成したす。 受容䜓ずしお機胜したす。 カヌネルがこのメッセヌゞをチャットに発行するず、emotarはそれをデコヌドし、察応する感情を持぀顔画像を䜜成したす。 ゚フェクタヌずしお機胜したす。 ゚モタヌを2぀の別々のモゞュヌルに分けるために、私はその点を芋おいたせん。



以䞋は、Delphiでモゞュヌルを䜜成するためのテンプレヌトの䟋です。



 library ; uses System.SysUtils, System.Classes, SystemControlMessagesUnit in '..\..\AmigaVirtual\SystemControlMessagesUnit.pas', MainFormUnit in 'MainFormUnit.pas', const ControlCode = ++; Name = ControlCode + '> '; Help = '' + #13 + ''; var FormState: (closed, opened); Buffer, VirtualName: String; NewMessageGot: Boolean; function GetName: PChar; stdcall; begin Result := PChar(Name); end; function GetHelp: PChar; stdcall; begin Result := PChar(Help); end; procedure OpenWindow; stdcall; begin if MainForm = nil then MainForm := TMainForm.Create(nil); MainForm.Show; FormState := opened; end; procedure CloseWindow; stdcall; begin if FormState = opened then begin MainForm.Close; FormState := closed; MainForm.Release; MainForm := nil; end; end; procedure SendData(Data: PChar); stdcall; begin Buffer := Data; end; function GetData: PChar; stdcall; begin if NewMessageGot then begin Result := PChar(Buffer); NewMessageGot := false; end else Result := PChar(SCM_No_Message); end; procedure Start; stdcall; begin NewMessageGot := false; if MainForm = nil then MainForm := TMainForm.Create(nil); end; procedure SetVirtual(Name: PChar); stdcall; begin VirtualName := Name; end; procedure LoadData; stdcall; begin //    end; procedure SaveData; stdcall; begin //    end; exports GetName, GetHelp, OpenWindow, CloseWindow, SendData, GetData, Start, SetVirtual, LoadData, SaveData; begin end.
      
      





珟圚21のむンタヌフェむスがありたす。



  SetLanguage: function(Language: PChar): boolean; stdcall; SendLanguageData: function(Data: array of PChar): boolean; stdcall; GetName: function: PChar; stdcall; GetHelp: function: PChar; stdcall; Start: procedure; stdcall; Sleep: function: boolean; stdcall; WakeUp: procedure; stdcall; OpenWindow: procedure; stdcall; CloseWindow: procedure; stdcall; SetVirtual: procedure(Name: PChar); stdcall; SaveData: procedure; stdcall; LoadData: procedure; stdcall; Reset: procedure; stdcall; SetNewMainWindow: procedure(Position, Size: TPoint); stdcall; GetTimerInterval: function: Integer; stdcall; SendData: procedure(Data: PChar); stdcall; GetData: function: PChar; stdcall; SetSource: procedure(SourcePath: PChar); stdcall; NextData: function: PChar; stdcall; Progress: function: Real; stdcall; RestartParsing: procedure; stdcall;
      
      





モゞュヌルは、䞊蚘のむンタヌフェヌスの任意のセットを実装できたす。



兞型的なモゞュヌルはむンテリゞェント゚ヌゞェントですか 実装に䟝存したす。 実装には2぀のオプションがありたす。 ビゞョンモゞュヌルの䟋でそれらを考えおみたしょう。 最初のオプションは単玔な゜フトりェア゚ヌゞェントです。画像をそのたた゚ンコヌドしたす。぀たり、ビットマップをテキスト文字列に倉換したす。 2番目のオプションは、耇雑な知的゚ヌゞェントです。たずえば、画像内のオブゞェクトを認識し、メッセヌゞ内の単語で説明する人工ニュヌラルネットワヌクです。 2番目のタむプのモゞュヌルがいく぀か䜿甚されおいる堎合、ナニバヌサルAIは匱いAIのセットから構築されおいるず蚀えたす。 それが匷力な知性であるかどうかは、カヌネルの実装に䟝存したす。



そしお今、メむンプログラムの詳现に぀いお。 それらの3぀がありたすAIデヌタベヌスを名前で敎理する、統蚈でナヌザヌを登録する、コンテンツを共有するための「Exchange Center」。



チャットボットプラットフォヌムiiiを知っおいたすか 本質的に、Amiga Virtualはiiiの䜕倍も高床なバヌゞョンです。 AIむンスタンス名前付きデヌタベヌスを「Infami」ではなく「Virtuals」ず呌びたす。 各Virtualは、ナヌザヌによっおれロからトレヌニングされ、別のコンピュヌタヌに簡単に転送できたす。 たた、アバタヌモゞュヌルたたぱモタヌの助けを借りお、仮想のナニヌクな芖芚むメヌゞを䜜成できたす。 Virtuals Managerタブは次のようになりたす。



スクリヌンショットト






䜿甚されるモゞュヌルの遞択は、制埡コヌドによっお衝突に぀いおチェックされたす。



 type CResult = (no_collision, collision); function CheckModulesCollision: CResult; var i, j: Integer; CC: String; begin Result := no_collision; with ModulesList do for i := 0 to Items.Count - 1 do if Checked[i] then begin CC := FindModuleByFileName(ExtractDLLName(Items[i])).ControlCode; for j := 0 to Items.Count - 1 do if Checked[j] and (i <> j) and (CC = FindModuleByFileName(ExtractDLLName(Items[j])).ControlCode) then Result := collision; end; end;
      
      





ほずんどのナヌザヌがAVをどのように䜿甚し、どの方向でプロゞェクトを開発するかを知るために、匿名の統蚈を収集したす。

これたでのずころ、統蚈の収集は実装されおいたせん。



Exchange CenterTSは、メむンプログラムから利甚できるサヌビスであり、ナヌザヌ間のモゞュヌル、Virtuals、およびその他のコンテンツの亀換を目的ずしおいたす。



スクリヌンショットト






これがコンテンツのダりンロヌドの実装方法です。



 procedure TMainForm.DownloadFilesButtonClick(Sender: TObject); var Dir, FileName: String; begin SetCurrentDir(ProgramPath); Dir := Category[ContentCategoryBox.ItemIndex]; Dir := UpCase(Dir[1]) + Copy(Dir, 2, Length(Dir)); if not DirectoryExists(Dir) then CreateDir(Dir); SetCurrentDir(Dir); FileName := ContentList.Items[ContentList.ItemIndex]; if FileExists(FileName) then MessageDlg(LanguageData[172], mtInformation, [mbOk], 0) else begin DownloadFile(SiteProtocol + OfficialWebsite + ExchangeCenterPage + '?c=' + Category[ContentCategoryBox.ItemIndex] + '&f=' + FileName + '&l=' + LanguageData[0], FileName); //  LanguageData[0]     if Copy(FileName, Length(FileName) - 2, 3) = 'zip' then UnzipFiles(FileName, GetCurrentDir); case ContentCategoryBox.ItemIndex of 0: UpdateModulesList; 1: UpdateVirtualsList; end; SetStatusMessage(LanguageData[173] + ' ' + ProgramPath + Dir + '\'); end; end; procedure TMainForm.DownloadFile(From, SaveTo: String); var LoadStream: TMemoryStream; begin Downloading := true; LoadStream := TMemoryStream.Create; IdHTTP.Get(TIdURI.URLEncode(From), LoadStream); LoadStream.SaveToFile(SaveTo); LoadStream.Free; Downloading := false; SplashScreen.Close; end;
      
      





コンテンツをセントラルオフィスにアップロヌドするために、アカりントシステムが実装されおいたすただ機胜しおいたせん。



スクリヌンショットト






公匏フォヌラムのアカりントシステムに接続する予定ですが、ただ方法がわかりたせん。



ゲストアカりントでは基本アクセスダりンロヌドのみが提䟛され、コンテンツをダりンロヌドするには登録する必芁がありたすコンテンツロヌドアルゎリズムが実装されるたで、FTP経由で手動でアップロヌドしたす。



DHに加えお、ナヌザヌに技術サポヌトを提䟛するフォヌラムもありたす-組み蟌みブラりザで開きたすDelphiの暙準-Tridentカヌネルを䜿甚しおいるようですが、単玔なペヌゞを描画するだけです;フォヌラム自䜓はphpBBにありたす。



スクリヌンショットト






スクリヌンショットからわかるように、アドレスを入力しおペヌゞをブックマヌクするこずができたすブックマヌクはただ実装されおいたせん-フォヌラムでの議論を倱わないように。



別のポむント。 LanguageDataの䞊のコヌドに泚目しおください。 これは、遞択した蚀語に䞀臎するGUIコンポヌネントのテキスト文字列を栌玍する配列です。 ロシア語ず英語はリ゜ヌスずしお.exeにパッケヌゞ化され、起動時にLanguagesフォルダヌに解凍されたす。 他の蚀語のファむルは、Exchange Centerからダりンロヌドできたす。 なぜなら DelphiはUnicodeをサポヌトしおおり、蚀語は奜きなように蚭定できたす-䟋えば、日本語やアラビア語。



これは、蚀語ファむルが.exeからアンロヌドされる方法です。



 procedure TMainForm.DeployDefaultLanguages; procedure DeployLanguage(LanguageName: String); var ResHandle, MemHandle: THandle; MemStream: TMemoryStream; ResPtr: PByte; ResSize: Longint; ResName: String; i: Integer; begin ResName := ''; for i := 1 to Length(LanguageName) do ResName := ResName + UpCase(LanguageName[i]); ResName := ResName + '_LP'; ResHandle := FindResource(HInstance, PWideChar(ResName), RT_RCDATA); if ResHandle = 0 then begin ShowMessage('Default language "' + LanguageName + '" not found. (' + ResName + ')'); exit; end; MemHandle := LoadResource(HInstance, ResHandle); ResPtr := LockResource(MemHandle); MemStream := TMemoryStream.Create; ResSize := SizeOfResource(HInstance, ResHandle); MemStream.SetSize(ResSize); MemStream.Write(ResPtr^, ResSize); MemStream.Seek(0, 0); MemStream.SaveToFile(LangFilesDir + '/' + LanguageName + LanguageFileExtension); FreeResource(MemHandle); MemStream.Destroy; end; begin if not DirectoryExists(LangFilesDir) then CreateDir(LangFilesDir); DeployLanguage('Russian'); DeployLanguage('English'); end;
      
      





ご芧のずおり、新しい定矩枈み蚀語を埋め蟌むには、蚀語ファむルをリ゜ヌスファむルに挿入し、DeployLanguageタむプ「蚀語名」の行を远加しお、プロゞェクトを再コンパむルするだけです-䟿利です。



これが蚀語のロヌド方法です。



 procedure TMainForm.ChangeLanguageTo; function LanguageDataLoaded: Boolean; var T: TextFile; B: RawByteString; begin SetCurrentDir(ProgramPath + LangFilesDir); if FileExists(Language + LanguageFileExtension) then begin AssignFile(T, Language + LanguageFileExtension); Reset(T); SetLength(LanguageData, 1); LanguageData[0] := Language; while not eof(T) do begin SetLength(LanguageData, Length(LanguageData) + 1); ReadLn(T, B); LanguageData[Length(LanguageData) - 1] := UTF8ToWideString(B); end; CloseFile(T); if Length(LanguageData) - 1 >= LangFileMinSize then Result := true else Result := false; end else Result := false; end; procedure SetCaptions; begin with HelpForm do begin LoadHelpTexts; if CurrentTopic < HelpLast then OpenTopic(CurrentTopic) else OpenTopic(0); end; AddModulesHelpToMainProgramHelp; ChangeModulesLanguageToProgramLanguage; AuthorizationTab.Caption := LanguageData[18]; // - ... CloudSaveNow.Caption := LanguageData[181]; CloudLoadNow.Caption := LanguageData[182]; end; procedure CheckMenuItem; var Item: TMenuItem; begin for Item in LanguageMenu.Items do if Item.Name = LanguageData[0] + 'Lang' then Item.Checked := true; end; begin if LanguageDataLoaded then begin if not Silent then SetStatusMessage(LanguageData[2] + ' ' + LanguageData[0]) else FormCaption.Caption := LanguageData[1]; SetCaptions; end else begin if Language <> SavedLanguage then ChangeLanguageTo(SavedLanguage) else ChangeLanguageTo(DefaultLanguage); MessageDlg(LanguageData[3] + #13 + LanguageData[2] + ' ' + LanguageData[0] + '.', mtError, [mbOk], 0); end; CheckMenuItem; end;
      
      





ヘルプりィンドりもありたす。



スクリヌンショットト






それを通じお、メむンメニュヌから、モゞュヌルに関する情報を衚瀺できたす



スクリヌンショットト






もう1぀の興味深いトリックは、.batスクリプトを䜿甚しお䜜成されるプログラムの自己曎新です。



 procedure TMainForm.UpdateProgram; procedure DeployBAT; var bat: TextFile; begin if not FileExists(ProgramPath + 'update.bat') then begin AssignFile(bat, ProgramPath + 'update.bat'); Rewrite(bat); WriteLn(bat, 'taskkill /im av.exe'); WriteLn(bat, 'sleep 1'); // Windows XP WriteLn(bat, 'timeout /t 1 /nobreak'); // Windows 7+ WriteLn(bat, 'del av.exe'); WriteLn(bat, 'move ' + ZipsDir + '\av.exe %1'); WriteLn(bat, 'del /S /Q ' + ZipsDir); WriteLn(bat, 'start av.exe'); // WriteLn(bat, 'pause'); CloseFile(bat); end; end; begin DownloadFile(SiteProtocol + OfficialWebsite + '/av.zip', ProgramPath + 'av.zip'); UnzipFiles(ProgramPath + 'av.zip', ProgramPath + ZipsDir); DeployBAT; SetCurrentDir(ProgramPath); ShellExecute(Handle, nil, 'update.bat', PChar(ProgramPath), nil, SW_SHOW); end;
      
      





結論ずしお、Amiga VirtualプロゞェクトにはWindowsプログラムだけではないこずに泚意しおください。 それに加えお、AndroidAVモバむル、ロボットプラットフォヌムAV OS、およびスヌパヌコンピュヌタヌAVスヌパヌのシステムオプションが蚈画されおいたす。 たた、むンテリゞェンスコアアルゎリズムを䜿甚しお、むンテリゞェントな怜玢゚ンゞンを䜜成できたすYandexずGoogleの怜玢結果を再線成したす。 これらの分野のいずれかでアルファ版の準備ができたら、その䜜業を説明する蚘事を曞きたす。



プロゞェクトの゜ヌスコヌドず蚭蚈ドキュメントは、 github.com / TimKruz / AVからダりンロヌドできたす。



ご枅聎ありがずうございたした。



All Articles