Advertisement
Najeebsk

SYSINFO.ahk

Feb 19th, 2022
210
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ; <COMPILER: v1.1.33.10>
  2. #NoEnv
  3. #SingleInstance Force
  4. SetBatchLines -1
  5. global WinTitel     := "htopmini " A_Now
  6. global Today        := A_DD "." A_MM "." A_YYYY
  7. global OldFormat    := A_FormatInteger
  8. global varPerc      := 0
  9. global Weather_ID   := "693838"
  10. global Weather_DG   := "c"
  11. global ownPID       := DllCall("Kernel32.dll\GetCurrentProcessId")
  12. global BuildVersion := DllCall("Kernel32.dll\GetVersion") >> 16 & 0xffff
  13. Menu, Tray, DeleteAll
  14. Menu, Tray, NoStandard
  15. Menu, Tray, Add, Toggle Percentage, Menu_Percentage
  16. Menu, Tray, Add,
  17. Menu, Tray, Add, Reset Transparency, Menu_Transparency
  18. Menu, Tray, Add, Toggle AlwaysOnTop, Menu_AlwaysOnTop
  19. Menu, Tray, Add, Show/Hide, Menu_ShowHide
  20. Menu, Tray, Add,
  21. Menu, Tray, Add, Exit, Close
  22. Menu, Tray, Default, Show/Hide
  23. MakeGui:
  24. Gui +LastFound -Caption +ToolWindow +hwndhMain
  25. Gui, Margin, 10, 10
  26. Gui, Color, 000000
  27. Gui, Font, cFFFFFF, Consolas
  28. Gui, Add, Text,     xm     ym w250 vTime01
  29. Gui, Add, Text,     xm+260 ym w170 0x202 vTemp01,
  30. Gui, Add, Text,     xm     y+2  w430 h1 0x7
  31. Gui, Font, cFFFFFF,
  32. Gui, Add, Text,     xm     y+4 w30 0x200, CPU:
  33. Gui, Font, c00FF00,
  34. Gui, Add, Text,     xm+40  yp w80 0x202 vCPU1,
  35. Gui, Add, Text,     xm+140 yp   w80 0x202 vCPU2,
  36. Gui, Add, Progress, xm+250 yp+1 w180 h10 BackgroundF0F0F0 vCPU3,
  37. Gui, Add, Text,     xm     y+3  w430 h1 0x7
  38. Gui, Font, cFFFFFF,
  39. Gui, Add, Text,     xm     y+3 w30 0x200, Mem:
  40. Gui, Font, c00FF00,
  41. Gui, Add, Text,     xm+40  yp   w80 0x202 vMEM01,
  42. Gui, Font, cFFFFFF,
  43. Gui, Add, Text,     xm+140 yp   w80 0x202 vMEM02,
  44. Gui, Add, Progress, xm+250 yp+1 w180 h10 BackgroundF0F0F0 vMEM03,
  45. Gui, Font, c000000 s7,
  46. Gui, Add, Text,     xm+250 yp w180 h11 0x202 +BackgroundTrans vMEM04,
  47. Gui, Font, cFFFFFF s8,
  48. Gui, Add, Text,     xm     y+3 w30 0x200, Swp:
  49. Gui, Font, c00FF00,
  50. Gui, Add, Text,     xm+40  yp   w80 0x202 vSWP01,
  51. Gui, Font, cFFFFFF,
  52. Gui, Add, Text,     xm+140 yp   w80 0x202 vSWP02,
  53. Gui, Add, Progress, xm+250 yp+1 w180 h10 BackgroundF0F0F0 vSWP03,
  54. Gui, Font, c000000 s7,
  55. Gui, Add, Text,     xm+250 yp w180 h11 0x202 +BackgroundTrans vSWP04,
  56. Gui, Font, cFFFFFF s8,
  57. Gui, Add, Text,     xm     y+3  w430 h1 0x7
  58. DriveGet, DrvLstFxd, List, FIXED
  59. loop, Parse, DrvLstFxd
  60. {
  61. Gui, Font, cFFFFFF,
  62. Gui, Add, Text,     xm     y+1 w30 0x200 gDriveClick, F_%A_Loopfield%:\
  63. Gui, Font, c00FF00,
  64. Gui, Add, Text,     xm+40  yp w80 0x202 vD%A_Loopfield%1,
  65. Gui, Font, cFFFFFF,
  66. Gui, Add, Text,     xm+140 yp w80 0x202 vD%A_Loopfield%2,
  67. Gui, Add, Progress, xm+250 yp+1 w180 h10 vD%A_Loopfield%3,
  68. Gui, Font, c000000 s7,
  69. Gui, Add, Text,     xm+250 yp w180 h11 0x202 +BackgroundTrans vD%A_Loopfield%4,
  70. Gui, Font, cFFFFFF s8,
  71. }
  72. DriveGet, DrvLstRmvbl, List, REMOVABLE
  73. loop, Parse, DrvLstRmvbl
  74. {
  75. Gui, Font, cFFFFFF,
  76. Gui, Add, Text,     xm     y+1 w30 0x200 gDriveClick, R_%A_Loopfield%:\
  77. Gui, Font, c00FF00,
  78. Gui, Add, Text,     xm+40  yp w80 0x202 vD%A_Loopfield%1,
  79. Gui, Font, cFFFFFF,
  80. Gui, Add, Text,     xm+140 yp w80 0x202 vD%A_Loopfield%2,
  81. Gui, Add, Progress, xm+250 yp+1 w180 h10 vD%A_Loopfield%3,
  82. Gui, Font, c000000 s7,
  83. Gui, Add, Text,     xm+250 yp w180 h11 0x202 +BackgroundTrans vD%A_Loopfield%4,
  84. Gui, Font, cFFFFFF s8,
  85. }
  86. DriveGet, DrvLstNtwrk, List, NETWORK
  87. loop, Parse, DrvLstNtwrk
  88. {
  89. Gui, Font, cFFFFFF,
  90. Gui, Add, Text,     xm     y+1 w30 0x200 gDriveClick, N_%A_Loopfield%:\
  91. Gui, Font, c00FF00,
  92. Gui, Add, Text,     xm+40  yp w80 0x202 vD%A_Loopfield%1,
  93. Gui, Font, cFFFFFF,
  94. Gui, Add, Text,     xm+140 yp w80 0x202 vD%A_Loopfield%2,
  95. Gui, Add, Progress, xm+250 yp+1 w180 h10 vD%A_Loopfield%3,
  96. Gui, Font, c000000 s7,
  97. Gui, Add, Text,     xm+250 yp w180 h11 0x202 +BackgroundTrans vD%A_Loopfield%4,
  98. Gui, Font, cFFFFFF s8,
  99. }
  100. Gui, Add, Text,     xm     y+3  w430 h1 0x7
  101. Gui, Font, cFFFFFF,
  102. Gui, Add, Text,     xm     y+1  w30 0x200, IN/OUT:
  103. Gui, Font, c00FF00,
  104. Gui, Add, Text,     xm+40  yp   w80 0x202 vIN1,
  105. Gui, Font, cFF0000,
  106. Gui, Add, Text,     xm+140 yp   w80 0x202 vOU1,
  107. Gui, Add, Text,     xm     y+3  w430 h1 0x7
  108. Gui, Font, cFFFFFF,
  109. Gui, Add, Text,     xm     y+10 w150 0x200 vOwnMem,
  110. Gui, Add, Button,   xm+240 yp-6 w60 h20 -Theme 0x8000 gClear, Clear
  111. Gui, Add, Button,   xm+305 yp   w60 h20 -Theme 0x8000 gMinimi, Minimize
  112. Gui, Add, Button,   xm+370 yp   w60 h20 -Theme 0x8000 gClose, Close
  113. Gui, Show, % "AutoSize" (htopx ? " x" htopx " y" htopy : ""), % WinTitel
  114. WinSet, Transparent, 170, % WinTitel
  115. SetTimer, UpdateTime, 1000
  116. SetTimer, UpdateWeather, -1000
  117. SetTimer, UpdateCPULoad, -1000
  118. SetTimer, UpdateMemory, -1000
  119. SetTimer, UpdateTraffic, 1000
  120. SetTimer, UpdateDrive, -1000
  121. SetTimer, UpdateMemHtop, -1000
  122. OnMessage(0x201, "WM_LBUTTONDOWN")
  123. OnMessage(0x219, "WM_DEVICECHANGE")
  124. return
  125. UpdateTime:
  126. GuiControl,, Time01, % Today "  " A_Hour ":" A_Min ":" A_Sec " | Up: " GetDurationFormat(A_TickCount / 1000)
  127. return
  128. UpdateWeather:
  129. url := DownloadToString("http://weather.yahooapis.com/forecastrss?w=" Weather_ID "&u=" Weather_DG)
  130. RegExMatch(url, "(?<=Weather for )(.*)(?=\<\/description\>\s\<language\>)", varCity)
  131. RegExMatch(url, "(?<=temp="")(.*)(?=""  date)", varTemp)
  132. RegExMatch(url, "(?<=temperature="")(.*)(?=""\s*distance)", varUnits)
  133. GuiControl,, Temp01, % varCity " | " varTemp " °" varUnits
  134. SetTimer, UpdateWeather, 60000
  135. return
  136. UpdateCPULoad:
  137. GuiControl,, CPU1, % GetProcessCount() " proc"
  138. CPU := CPULoad()
  139. GuiControl,, CPU2, % CPU " % "
  140. GuiControl, % ((CPU <= "50") ? "+c00FF00" : ((CPU <= "80") ? "+cFFA500" : "+cFF0000")), CPU3
  141. GuiControl,, CPU3, % CPU
  142. SetTimer, UpdateCPULoad, 1000
  143. return
  144. UpdateMemory:
  145. GMSEx := GlobalMemoryStatusEx()
  146. GMSExM01 := Round(GMSEx[2] / 1024**2, 2)
  147. GMSExM02 := Round(GMSEx[3] / 1024**2, 2)
  148. GMSExM03 := Round(GMSExM01 - GMSExM02, 2)
  149. GMSExM04 := Round(GMSExM03 / GMSExM01 * 100, 2)
  150. GMSExS01 := Round(GMSEx[4] / 1024**2, 2)
  151. GMSExS02 := Round(GMSEx[5] / 1024**2, 2)
  152. GMSExS03 := Round(GMSExS01 - GMSExS02, 2)
  153. GMSExS04 := Round(GMSExS03 / GMSExS01 * 100, 2)
  154. GuiControl,, MEM01, % GMSExM03 " MB"
  155. GuiControl,, MEM02, % GMSExM01 " MB"
  156. GuiControl, % (GMSExM04 <= "75") ? "+c00FF00" : (GMSExM04 <= "90") ? "+cFFA500" : "+cFF0000", MEM03
  157. GuiControl,, MEM03, % GMSExM04
  158. GuiControl,, MEM04, % (varPerc = "1") ? GMSExM04 " % " : ""
  159. GuiControl,, SWP01, % GMSExS03 " MB"
  160. GuiControl,, SWP02, % GMSExS01 " MB"
  161. GuiControl, % (GMSExS04 <= "75") ? "+c00FF00" : (GMSExS04 <= "90") ? "+cFFA500" : "+cFF0000", SWP03
  162. GuiControl,, SWP03, % GMSExS04
  163. GuiControl,, SWP04, % (varPerc = "1") ? GMSExS04 " % " : ""
  164. SetTimer, UpdateMemory, 2000
  165. return
  166. UpdateDrive:
  167. loop, Parse, DrvLstFxd
  168. {
  169. i := A_LoopField
  170. DriveGet, cap%i%, Capacity, %i%:\
  171. DriveSpaceFree, free%i%, %i%:\
  172. used%i% := cap%i% - free%i%
  173. perc%i% := used%i% / cap%i% * 100
  174. GuiControl,, D%i%1, % Round(used%i% / 1024, 2) " GB"
  175. GuiControl,, D%i%2, % Round(cap%i% / 1024, 2) " GB"
  176. GuiControl, % "+Range0-" cap%i%, D%i%3
  177. GuiControl, % (perc%i% <= "80") ? "+c00FF00" : (perc%i% <= "90") ? "+cFFA500" : "+cFF0000", D%i%3
  178. GuiControl,, D%i%3, % used%i%
  179. GuiControl,, D%i%4, % (varPerc = "1") ? Round(perc%i%, 2) " % " : ""
  180. }
  181. loop, Parse, DrvLstRmvbl
  182. {
  183. j := A_LoopField
  184. DriveGet, cap%j%, Capacity, %j%:\
  185. DriveSpaceFree, free%j%, %j%:\
  186. used%j% := cap%j% - free%j%
  187. perc%j% := used%j% / cap%j% * 100
  188. GuiControl,, D%j%1, % Round(used%j% / 1024, 2) " GB"
  189. GuiControl,, D%j%2, % Round(cap%j% / 1024, 2) " GB"
  190. GuiControl, % "+Range0-" cap%j%, D%j%3
  191. GuiControl, % (perc%j% <= "80") ? "+c00FF00" : (perc%j% <= "90") ? "+cFFA500" : "+cFF0000", D%j%3
  192. GuiControl,, D%j%3, % used%j%
  193. GuiControl,, D%j%4, % (varPerc = "1") ? Round(perc%j%, 2) " % " : ""
  194. }
  195. loop, Parse, DrvLstNtwrk
  196. {
  197. k := A_LoopField
  198. DriveGet, cap%k%, Capacity, %k%:\
  199. DriveSpaceFree, free%k%, %k%:\
  200. used%k% := cap%k% - free%k%
  201. perc%k% := used%k% / cap%k% * 100
  202. GuiControl,, D%k%1, % Round(used%k% / 1024, 2) " GB"
  203. GuiControl,, D%k%2, % Round(cap%k% / 1024, 2) " GB"
  204. GuiControl, % "+Range0-" cap%k%, D%k%3
  205. GuiControl, % (perc%k% <= "80") ? "+c00FF00" : (perc%k% <= "90") ? "+cFFA500" : "+cFF0000", D%k%3
  206. GuiControl,, D%k%3, % used%k%
  207. GuiControl,, D%k%4, % (varPerc = "1") ? Round(perc%k%, 2) " % " : ""
  208. }
  209. SetTimer, UpdateDrive, 5000
  210. return
  211. UpdateTraffic:
  212. dnNew := 0
  213. upNew := 0
  214. GetIfTable(tb)
  215. loop, % DecodeInteger(&tb)
  216. {
  217. dnNew += DecodeInteger(&tb + 4 + 860 * (A_Index - 1) + 552)
  218. upNew += DecodeInteger(&tb + 4 + 860 * (A_Index - 1) + 576)
  219. }
  220. dnRate := Round((dnNew - dnOld) / 1024)
  221. upRate := Round((upNew - upOld) / 1024)
  222. GuiControl,, In1, % dnRate " kb/s"
  223. GuiControl,, Ou1, % upRate " kb/s"
  224. dnOld := dnNew
  225. upOld := upNew
  226. return
  227. UpdateMemHtop:
  228. if (BuildVersion >= "7600")
  229. {
  230. GPMI := GetProcessMemoryInfo_PMCEX(ownPID)
  231. PUsage := Round(GPMI[10] / 1024, 0)
  232. }
  233. else
  234. {
  235. GPMI := GetProcessMemoryInfo_PMC(ownPID)
  236. PUsage := Round(GPMI[8] / 1024, 0)
  237. }
  238. GuiControl,, OwnMem, % "PID: " ownPID " | " PUsage " K"
  239. SetTimer, UpdateMemHtop, 2000
  240. return
  241. DriveClick:
  242. Run, % SubStr(A_GuiControl, 3)
  243. Return
  244. Clear:
  245. ClearMemory()
  246. FreeMemory()
  247. return
  248. Minimi:
  249. Gui, Hide
  250. return
  251. Menu_Percentage:
  252. varPerc := (varPerc = "0") ? "1" : "0"
  253. Menu, Tray, ToggleCheck, Toggle Percentage
  254. return
  255. Menu_Transparency:
  256. WinSet, Transparent, 170, % name
  257. return
  258. Menu_AlwaysOnTop:
  259. WinSet, AlwaysOnTop, Toggle, %WinTitel%
  260. Menu, Tray, ToggleCheck, Toggle AlwaysOnTop
  261. return
  262. Menu_ShowHide:
  263. WinGet, winStyle, Style, %WinTitel%
  264. if (winStyle & 0x10000000)
  265. {
  266. WinHide, %WinTitel%
  267. }
  268. else
  269. {
  270. WinShow, %WinTitel%
  271. WinSet, AlwaysOnTop, Toggle, %WinTitel%
  272. WinSet, AlwaysOnTop, Toggle, %WinTitel%
  273. }
  274. return
  275. ^WheelUp::GUITrans(1)
  276. ^WheelDown::GUITrans(0)
  277. WM_LBUTTONDOWN(wParam, lParam, msg, hwnd)
  278. {
  279. global hMain
  280. if (hwnd = hMain)
  281. {
  282. PostMessage, 0xA1, 2,,, % WinTitel
  283. }
  284. }
  285. WM_DEVICECHANGE(wParam, lParam, msg, hwnd)
  286. {
  287. global hmain, htopx, htopy
  288. if (wParam = 0x8000 || wParam = 0x8004)
  289. {
  290. Thread, NoTimers
  291. WinGetPos, htopx, htopy,,, ahk_id %hmain%
  292. Gui, Destroy
  293. Gosub, MakeGui
  294. }
  295. }
  296. GUITrans(b := 1)
  297. {
  298. WinGet, ct, Transparent, % WinTitel
  299. WinSet, Transparent, % ((b = 1) ? ct + 1 : ct - 1), % WinTitel
  300. }
  301. DownloadToString(url, encoding := "utf-8")
  302. {
  303. static a := "AutoHotkey/" A_AhkVersion
  304. if (!DllCall("LoadLibrary", "Str", "wininet") || !(h := DllCall("wininet\InternetOpen", "Str", a, "UInt", 1, "Ptr", 0, "Ptr", 0, "UInt", 0, "Ptr")))
  305. {
  306. return 0
  307. }
  308. c := s := 0, o := ""
  309. if (f := DllCall("wininet\InternetOpenUrl", "Ptr", h, "Str", url, "Ptr", 0, "UInt", 0, "UInt", 0x80003000, "Ptr", 0, "Ptr"))
  310. {
  311. while (DllCall("wininet\InternetQueryDataAvailable", "Ptr", f, "UInt*", s, "UInt", 0, "Ptr", 0) && s > 0)
  312. {
  313. VarSetCapacity(b, s, 0)
  314. DllCall("wininet\InternetReadFile", "Ptr", f, "Ptr", &b, "UInt", s, "UInt*", r)
  315. o .= StrGet(&b, r >> (encoding = "utf-16" || encoding = "cp1200"), encoding)
  316. }
  317. DllCall("wininet\InternetCloseHandle", "Ptr", f)
  318. }
  319. DllCall("wininet\InternetCloseHandle", "Ptr", h)
  320. return o
  321. }
  322. GetProcessCount()
  323. {
  324. proc := ""
  325. for process in ComObjGet("winmgmts:\\.\root\CIMV2").ExecQuery("SELECT * FROM Win32_Process")
  326. {
  327. proc++
  328. }
  329. return proc
  330. }
  331. CPULoad()
  332. {
  333. static PIT, PKT, PUT
  334. if (Pit = "")
  335. {
  336. return 0, DllCall("GetSystemTimes", "Int64P", PIT, "Int64P", PKT, "Int64P", PUT)
  337. }
  338. DllCall("GetSystemTimes", "Int64P", CIT, "Int64P", CKT, "Int64P", CUT)
  339. IdleTime := PIT - CIT, KernelTime := PKT - CKT, UserTime := PUT - CUT
  340. SystemTime := KernelTime + UserTime
  341. return ((SystemTime - IdleTime) * 100) // SystemTime, PIT := CIT, PKT := CKT, PUT := CUT
  342. }
  343. GlobalMemoryStatusEx()
  344. {
  345. static MEMORYSTATUSEX, init := VarSetCapacity(MEMORYSTATUSEX, 64, 0) && NumPut(64, MEMORYSTATUSEX, "UInt")
  346. if (DllCall("Kernel32.dll\GlobalMemoryStatusEx", "Ptr", &MEMORYSTATUSEX))
  347. {
  348. return { 2 : NumGet(MEMORYSTATUSEX,  8, "UInt64")
  349. , 3 : NumGet(MEMORYSTATUSEX, 16, "UInt64")
  350. , 4 : NumGet(MEMORYSTATUSEX, 24, "UInt64")
  351. , 5 : NumGet(MEMORYSTATUSEX, 32, "UInt64") }
  352. }
  353. }
  354. GetProcessMemoryInfo_PMCEX(PID)
  355. {
  356. pu := ""
  357. hProcess := DllCall("Kernel32.dll\OpenProcess", "UInt", 0x001F0FFF, "UInt", 0, "UInt", PID)
  358. if (hProcess)
  359. {
  360. static PMCEX, size := (A_PtrSize = 8 ? 80 : 44), init := VarSetCapacity(PMCEX, size, 0) && NumPut(size, PMCEX)
  361. if (DllCall("Kernel32.dll\K32GetProcessMemoryInfo", "Ptr", hProcess, "UInt", &PMCEX, "UInt", size))
  362. {
  363. pu := { 10 : NumGet(PMCEX, (A_PtrSize = 8 ? 72 : 40), "Ptr") }
  364. }
  365. DllCall("Kernel32.dll\CloseHandle", "Ptr", hProcess)
  366. }
  367. return pu
  368. }
  369. GetProcessMemoryInfo_PMC(PID)
  370. {
  371. pu := ""
  372. hProcess := DllCall("Kernel32.dll\OpenProcess", "UInt", 0x001F0FFF, "UInt", 0, "UInt", PID)
  373. if (hProcess)
  374. {
  375. static PMC, size := (A_PtrSize = 8 ? 72 : 40), init := VarSetCapacity(PMC, size, 0) && NumPut(size, PMC)
  376. if (DllCall("psapi.dll\GetProcessMemoryInfo", "Ptr", hProcess, "UInt", &PMC, "UInt", size))
  377. {
  378. pu := { 8 : NumGet(PMC, (A_PtrSize = 8 ? 56 : 32), "Ptr") }
  379. }
  380. DllCall("Kernel32.dll\CloseHandle", "Ptr", hProcess)
  381. }
  382. return pu
  383. }
  384. GetDurationFormat(ullDuration, lpFormat := "d'd 'hh:mm:ss")
  385. {
  386. VarSetCapacity(lpDurationStr, 128, 0)
  387. DllCall("Kernel32.dll\GetDurationFormat", "UInt",  0x400
  388. , "UInt",  0
  389. , "Ptr",   0
  390. , "Int64", ullDuration * 10000000
  391. , "WStr",  lpFormat
  392. , "WStr",  lpDurationStr
  393. , "Int",   64)
  394. return lpDurationStr
  395. }
  396. GetIfTable(ByRef tb, bOrder = True)
  397. {
  398. nSize := 4 + 860 * GetNumberOfInterfaces() + 8
  399. VarSetCapacity(tb, nSize)
  400. return DllCall("Iphlpapi.dll\GetIfTable", "UInt", &tb, "UInt*", nSize, "UInt", bOrder)
  401. }
  402. GetIfEntry(ByRef tb, idx)
  403. {
  404. VarSetCapacity(tb, 860)
  405. DllCall("ntdll\RtlFillMemoryUlong", "Ptr", &tb + 512, "Ptr", 4, "UInt", idx)
  406. return DllCall("Iphlpapi.dll\GetIfEntry", "UInt", &tb)
  407. }
  408. GetNumberOfInterfaces()
  409. {
  410. DllCall("Iphlpapi.dll\GetNumberOfInterfaces", "UInt*", nIf)
  411. return nIf
  412. }
  413. DecodeInteger(ptr)
  414. {
  415. return *ptr | *++ptr << 8 | *++ptr << 16 | *++ptr << 24
  416. }
  417. ClearMemory()
  418. {
  419. for process in ComObjGet("winmgmts:\\.\root\CIMV2").ExecQuery("SELECT * FROM Win32_Process")
  420. {
  421. handle := DllCall("Kernel32.dll\OpenProcess", "UInt", 0x001F0FFF, "Int", 0, "Int", process.ProcessID)
  422. DllCall("Kernel32.dll\SetProcessWorkingSetSize", "UInt", handle, "Int", -1, "Int", -1)
  423. DllCall("Psapi.dll\EmptyWorkingSet", "UInt", handle)
  424. DllCall("Kernel32.dll\CloseHandle", "Int", handle)
  425. }
  426. return
  427. }
  428. FreeMemory()
  429. {
  430. return DllCall("Psapi.dll\EmptyWorkingSet", "UInt", -1)
  431. }
  432. Close:
  433. GuiClose:
  434. GuiEscape:
  435. ExitApp
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement