4
Validasi Opsi dan Loop Menu
Menu GhostTrack tidak menyimpan nomor opsinya di dalam kode pencetak menu. Nomor itu hidup di list options, dan satu fungsi kecil is_in_options menjadi satu-satunya gerbang yang memutuskan apakah sebuah nomor boleh dijalankan. Bagian ini membahas kedua struktur tersebut, nilai ValueError yang dilempar ketika validasi gagal, dan cara loop menu menyusun ulang dirinya setelah satu opsi selesai.
options sebagai sumber kebenaran nomor menu
options adalah list berisi lima dict, masing-masing dengan tiga kunci: num, text, dan func. GhostTR.py:180-2071
num | text | func |
|---|---|---|
| 1 | IP Tracker | IP_Track |
| 2 | Show Your IP | showIP |
| 3 | Phone Number Tracker | phoneGW |
| 4 | Username Tracker | TrackLu |
| 0 | Exit | exit |
Karena kelima entri memiliki kunci func, cabang print('No function detected') di dalam call_option tidak pernah tercapai dengan data saat ini. GhostTR.py:222-2272
Dua konsumen membaca list yang sama. option_text merangkai seluruh entri menjadi baris teks berbentuk [ num ] text lewat satu loop, GhostTR.py:245-2493, dan option menuliskan hasilnya ke stderr setelah banner besar, GhostTR.py:259-2724. Banner itu sendiri dan dekorator is_option yang menempel padanya dibahas di Banner dan Dekorator is_option.
Gerbang is_in_options
is_in_options(num) melakukan pencarian linear atas options. Ia mengembalikan True pada entri pertama yang opt['num'] == num, dan False bila loop selesai tanpa kecocokan. GhostTR.py:252-2565
Fungsi itu dipanggil sekali saja, di baris pertama call_option, sebagai penjaga sebelum dispatch. call_option(opt) memeriksa if not is_in_options(opt) lalu melempar ValueError('Option not found'); bila lolos, ia menelusuri options sekali lagi untuk mencari entri dengan option['num'] == opt dan memanggil option['func'](). GhostTR.py:219-2276 Akibatnya satu pilihan yang valid melewati list options dua kali: sekali untuk validasi, sekali untuk dispatch.
Dua jalur ValueError
| Titik validasi | Fungsi penjaga | Kondisi gagal | Reaksi |
|---|---|---|---|
opt = int(input(...)) | main | input bukan angka | cetak Please input number, lalu main() lagi |
is_in_options(opt) | call_option | nomor tidak ada di options | cetak isi ValueError, tunggu 2 detik, lalu execute_option(opt) lagi |
Jalur pertama terjadi sebelum execute_option dipanggil: konversi int pada baris input berada di dalam try milik main, dan handler-nya mencetak Please input number, menunggu time.sleep(2), lalu memanggil main() kembali. GhostTR.py:296-3067 Jalur kedua terjadi lebih dalam: call_option melempar ValueError('Option not found') GhostTR.py:219-2276, dan execute_option menangkapnya, mencetak pesan error itu apa adanya, lalu mengulang pemanggilan. GhostTR.py:230-2428 Penanganan KeyboardInterrupt pada kedua lapisan itu dibahas terpisah di Penanganan Error dan Interupsi.
Siklus keadaan loop menu
Kedua jalur ValueError di atas sama-sama berujung pada pemanggilan ulang fungsi, bukan pada while loop. Diagram berikut merangkum perpindahan keadaan dari menu tampil sampai opsi selesai dijalankan.
stateDiagram-v2
[*] --> main
main --> ReadInput: "option() lalu input()"
ReadInput --> main: "ValueError: Please input number"
ReadInput --> call_option: "opt = int(input(...))"
call_option --> is_in_options: "cek nomor"
is_in_options --> not_found: "False"
not_found --> not_found: "ValueError: Option not found"
is_in_options --> dispatch: "True"
dispatch --> main: "Press enter to continue"
dispatch --> [*]: "num 0: exit"
style ReadInput fill:#8b5cf6,color:#fff
style is_in_options fill:#f59e0b,color:#000
style dispatch fill:#2d7d46,color:#fff
style not_found fill:#dc2626,color:#fff
%% fig: Siklus keadaan loop menu GhostTrack
%% desc: Input diubah menjadi int, divalidasi is_in_options, lalu dispatch; kegagalan memutar kembali ke keadaan sebelumnya, bukan keluar dari loop.Setelah satu opsi selesai dijalankan, execute_option menunggu satu input(f'\n{Wh}[ {Gr}+ {Wh}] {Gr}Press enter to continue') lalu memanggil main() sehingga seluruh menu digambar ulang. GhostTR.py:230-2349 Karena main sendiri memanggil option(), setiap putaran menu menambah satu frame pemanggilan baru, bukan mengembalikan kendali ke pemanggil sebelumnya. Loop berakhir hanya lewat opsi num 0 yang memanggil exit, atau lewat KeyboardInterrupt yang ditangkap di blok penjaga modul. GhostTR.py:309-31510
⚠️
execute_option(opt)memanggil dirinya sendiri denganoptyang sama persis setelah menangkapValueError. Karenaopttidak pernah dibaca ulang dariinput, kondisi gagal yang sama berulang:call_optionmelemparValueError('Option not found')lagi, pesannya dicetak,time.sleep(2)dijalankan, dan rekursi berlanjut tanpa batas. Satu-satunya jalan keluar dari keadaan itu adalahKeyboardInterrupt. GhostTR.py:230-2428