Reading web Pages

Blitz3D Forums/Blitz3D Programming/Reading web Pages

-Rick-(Posted 2010) [#1]
I'd like to write up a program that reads a web page to parse the information from it. I'm assuming that it would require the user32 decls commands, but I really don't understand any of them and there are so many that trying to research which ones I would need seems daunting.

My intent is that the program would run in the background and would recognize a specific page (tab) and if the contents of that page changes then it would record it, probably into the clipboard? Or even a direct read into a string file which I could then parse and process. A lesser and acceptable solution would be that I could cause the read with some kind of command keypress (like shft-F1 or something that wouldn't conflict with windows or other applications)

Can anyone help me by explaining what user32 commands I would use? And how to use them properly? When I look through the code archives and read the comments in the user32.decl archive there is a reference to http://msdn.microsoft.com/ to find information on the commands, but the site itself is so vast that I quickly get lost and overwhelmed.


Leon Drake(Posted 2010) [#2]
if i remember there was a few html parsers in the code archive, couple that with one o fthe other code snippets for retrieving a file from the internet and you got what you need.

i'm not sure why you would need a user32 lib for that, it could be done without using the windows api.


Leon Drake(Posted 2010) [#3]
here is a snippet by mark to get an html page

http://www.blitzbasic.com/codearcs/codearcs.php?code=21

i didnt see any html parsers for anything before blitzmax :( thats ok, if your dynamically creating websites using asp.net, php for example then you can output the page as xml, then you can use the xml parser offered here

http://www.blitzbasic.com/codearcs/codearcs.php?code=1393

to parse the data into your game from your site. then when you need to send updates back to the site you could use the post http functions here

http://www.blitzbasic.com/codearcs/codearcs.php?code=1278

then on your website just parse the post variables and update your database or whatever your using. there are other code snippets in the archive for doing that this is just a couple examples.


-Rick-(Posted 2010) [#4]
I'm not too worried about parsers.

What I've got is an online game that plays through facebook. The game itself allows you to run it without facebook. Basically its a text style wargame. One of the pages lists the planets in a system with information on each planet (who owns it, their ranking, player status, etc). There are 15 planets in each system. The player can then page through the "galaxy" which contains 499 pages, each page holding a system of 15 planets. there are about 100 galaxies and those grow as more players join.

In game you can scan the planets and get information with a probe, but what I'm looking to try to do is just to collect the information presented on that system page so that I can use it. Each player is allowed to control 9 planets, but players generally place their planets apart so that they are in different systems. It is a huge hassle to write down where you find a players planet so that if you attack that player you know where all his other planets are to monitor them to see if they are online, or if the ships on those planets suddenly disapear suggesting they are going to reinforce a planet you are attacking.

What I was looking to do was to have a program that would run in the background and as you changed pages (systems) by clicking the next and previous button it would record all the viewable planet data and who owns them and their status, etc. Then I would just flip through the pages and record that info so I could then call up information on a specific player.

I thought that i would have to use the windows api commands to first identify the firefox tab I am using. It would monitor it for page changes and then record (parse) the info into a database. I've figured out how to read from the clipboard and one option was to just do a copy/paste type style, but I'd like to eliminate that manual interaction if possible.

Is that making sense?

I thought that I'd need the windows api to identify the window or tab i was working from and to be able to read from that window/tab. I'd rather not make calls to the game server itself because they are very strict on bot cheating. Simply READING information on a screen for data use is not illegal, but automatic actions to the server could be construed as botting, or cheating.


Leon Drake(Posted 2010) [#5]
ah i got ya. but im not sure on a couple things. the program you are making is it just a background service or is there and actual game that goes with it. otherwise why not just make it in php.

but i know where you're coming from i decided pretty recently to start making games for facebook myself but realized blitzmax and even blitz i was having just too many obstacles to keep the facebook app and the game synced up. One thing i did do similar to what your doing is i had set up a small server app on my webserver and ran my facebook app as an iframe. anytime someone made a change on the webpage it was posted to my server app and then my Blitz app would be sent the info from the server. I suppose its a decent way around using windows api. I figure if your going to go that far perhaps you should just create a sandbox and run your blitz3d app as a browser object.

I gave up on the hassle recently and decided it was easier to write a game in java. lol


-Rick-(Posted 2010) [#6]
The game already exists, Starfleet Commander, and I'm just trying to figure a way to manage the data so that i can use it in game by reading the information out of firefox.

If you are interested to try it, then use this link and I'll get credit for a new crew member (you can only get crew member credits from new players, its not one of those spam whore games where you have to get all your friends to join with you like Mafia Wars and such)


http://apps.facebook.com/starfleet_commander/?ref_id=620769623&ref_type=link

If you do go into it then look at the "Fleets" page and you can see what I'm trying to capture to sift through. The only reason I post the link is so you can see what I'm talking about. Not trying to promote the game in some way that would be contrary to spamming rules. I will get the benefit of a new crew member, but that is not the intent, just a useful side effect for me.

Being a new player you won't have much fuel to explore the galaxy with (it costs 10 hydro to change pages) but you should get the idea. I'm interested in collecting that planet data to track other players.


Leon Drake(Posted 2010) [#7]
very cool app


_PJ_(Posted 2010) [#8]
I used to play an MMO in which certain stats were available through a webpage. I wrote a simple program that would etract tehe info I needed by downloading the page (with Blitzget I think it was) and then reading through the download (which was pure ascii saved as a .dat file and read with the basic OpenFile() and ReadLine() etc.

I would search for the required html tags and so on, then extract the correct parts from strings.

Most certainly not the best or most efficient means of accomplishing this but it was simple enough and did the trick.
I could dig out my old code if you needed to see it, though it was only gfor my own personal use and was very rough and did not look at all prettified :)


-Rick-(Posted 2010) [#9]
Thanks malice!

the only thing I'm concerned about is it calling their site for the information. These guys are fanatical against any kind of external programs that run things in the game with automatic commands. It's ok compile the data, run sims, etc, but anything that would automatically push buttons, send fleets, probe, load pages, etc would probably be construed as cheating and their methods to handle what they consider as cheaters is pretty draconian. The reset your stuff back to 0 and make you start over. Because of the nature of the game they can't give you your stuff back if they screw up (many have claimed they have but they claim they haven't) because other players could move into the areas you once "lived".

I'm just afriad that if they detected a call to their website that wasn't from something recognizeable like firefox, explorer, etc they'd just assume it was some form of cheat.

That's why I'm looking for a way to read the data unobtrusively. At this point I'm just working with copy/paste and plan to have the clipboard monitored for changes to automatically parse new info and store it. If I can get the time to sit down and do it, lol.


BlitzSupport(Posted 2010) [#10]
Look up where each browser's cache is stored -- you should be able to read pages from there. You may have to parse an index file to determine which cached page relates to which site. This whole idea probably won't be easy.

This program does it, for example, and you'll see links to readers for other browser caches too:

http://www.nirsoft.net/utils/chrome_cache_view.html

Another way to do it might be to just read through the whole cache (bear in mind that it won't be in the same hard-coded path for everybody), discarding files over a certain size, and check for the <TITLE> tag, and/or some other more reliable information from the page.


_PJ_(Posted 2010) [#11]
the only thing I'm concerned about is it calling their site for the information. These guys are fanatical against any kind of external programs that run things in the game with automatic commands.

Right.. In my case the website where I was 'grabbing' the info from was purely game-related stats that were available fdor that purpose.
Since even through blitz, the effect is the same as with a browser* then there shouldn't be any problem. No activity was done to the data and nothing was sent as any form of message to the server except the standard "I am retrieving info" stuff that the Browser would do on viewing the page.

However, I'm no expert and don't know just how fanatical your games' guys are, so I agree with erring on the side of caution.

My code did not even locate or associate itself with the database per se, because it just grabbed the final pager source after phop scripts and so on had run to provide the web output.

If you would need to acccess data directly rather than from a more accessible web page, then yeah likely to be a lot more complex and risky if such methiods are frowned upon by the server people :S



_________

*That is - a connection is made through port 80 for Downloadig only, the content is read and copied to the client machine.


_PJ_(Posted 2010) [#12]
Here's the code I used anyway...

I havent made any notes or anything as it was just something 'quick and easy' for my own use. It's pretty horrible to look at, but if you need to asak anything about it, feel free :D

Graphics 640, 480, 16, 2
SetBuffer FrontBuffer()

Global Upd%=Input$("Update Frequency (Minutes): ")
Upd=Upd*60000

Global Fix$=" * "

Const JOSSH1$="http://www.jossh.com/jgeng/PilotViewer.aspx?list=onlinepilotsonly"
Const JOSSH2$="http://www.jossh.com/jgeng/PilotViewer.aspx?p="

Const TempFileName$="~temp.TMP"

Global Logfile=WriteFile("Log.txt")

Global FirstRun=True

Global StartOfSol$="td bgcolor="+Chr$(34)+"#000022"
Global StartOfOct$="td bgcolor="+Chr$(34)+"#220000"
Global StartOfQuant$="td bgcolor="+Chr$(34)+"#002200"
Const EndOfTable$="</tr>"
Const PilotStartString$="/media/registry"
Const RegistryEndString$=".gif"
Const PilotNamePrefix$="/jgeng/pilotviewer.aspx?p="
Const PilotNameSuffix$="</a><br>"

Const PilotKillSolLINEPref$=">solrain kills</td>"
Const PilotKillOctLINEPref$=">octavius kills</td>"
Const PilotKillQuantLINEPref$=">quantar kills</td>"
Const DeathLINEPref$=">deaths</td>"
Const LandingLINEPref$=">landings</td>"
Const LaunchLINEPref$=">launches</td>"
Const MissionLINEPref$=">missions complete</td>"
Const DiscoLINEPref$=">disconnects</td>"

Const ValuePref$=">"
Const ValueSuf$="</td>"

Const PilotLaunchPref$="</a><br>"
Const PilotDeathPref$="</a><br>"
Const PilotLandingPref$="</a><br>"
Const PilotDiscoPref$="</a><br>"
Const PilotMissionPref$="</a><br>"

Const FactionSol$="Solrain"
Const FactionOct$="Octavius"
Const FactionQuant$="Quantar"

Const convertCiv$="none"
Const convertHG$="honor_guard"
Const convertPirate$="pirate"

Const Reg_Civ$="Civillian"
Const Reg_HG$="Military"
Const Reg_Rat$="Pirate"

Global Pilot$
Global Faction$
Global Registry$

Global OpenTemp
Global OpenTemp2
Global delname$

Type LastPilots
	Field Name$
	Field Fact$
	Field Reg$
	Field Docked%
	Field DockCount%
	Field LaunchCount%
	Field MissionCount%
	Field DeathCount%
	Field KillCountS%
	Field KillCountO%
	Field KillCountQ%
	Field DiscoCount%
End Type

Type Pilots
	Field Name$
	Field Fact$
	Field Reg$
	Field Docked%
	Field DockCount%
	Field LaunchCount%
	Field MissionCount%
	Field DeathCount%
	Field KillCountS%
	Field KillCountO%
	Field KillCountQ%
	Field DiscoCount%
End Type

Global Begin=False
Global UpdateTime=MilliSecs()-(Upd+5000)
LogData("COMMENCE","TRACKER","START LOG","NO DATA",True)

	While Not KeyDown(1)

		Delay 5
		If ((MilliSecs()-UpdateTime)>Upd)
			UpdateTime=MilliSecs()
				
			LogData("UPDATE","CONNECTING", "JOSSH","START",True)
				
			If (FileType(CurrentDir$()+"~Temp.TMP"))
				DeleteFile CurrentDir$()+"~Temp.TMP"
			End If
						
			Download(JOSSH1$,CurrentDir$(),TempFileName$)
			
			LogData("DOWNLOADED","JOSSH SERVER", "ONLINE ONLY","END",False)
						
			OpenTemp=ReadFile(TempFileName$)

			LogData("PROCESSING","JOSSH DATA", "ALL PILOTS","START",False)

			While Not Eof(OpenTemp)
				Delay 5
				Registry$="INVALID REGISTRY ERROR"
					Pilot$=""
					t$=ReadLine$(OpenTemp)
					;t$=Lower$(t$)
					
					If Instr(Lower$(t$),StartOfSol$)
						Begin=True
						Faction$=FactionSol$
						
						LogData("RETRIEVING","JOSSH DATA", "SOLRAIN","PILOTS",False)
						
						CharPosition=FindPilotEnd(t$)
						While (Len(t$)>90)
							Delay 5
							Registry$=FindPilotReg$(t$)
							Pilot$=FindPilotName$(t$)
							Color 0,0,255
							
							LogData("ONLINE PILOT",Pilot$,Faction$,Registry$,False)
							
							OnlinePilots(Pilot$,Faction$,Registry$)
							
							t$=Right$(t$,Len(t$)-CharPosition)
							CharPosition=FindPilotEnd(t$)
						Wend
					End If
					If Instr(Lower$(t$),StartOfOct$)
						Faction$=FactionOct$
						
						LogData("RETRIEVING","JOSSH DATA", "OCTAVIUS","PILOTS",False)
						
						Color 255,0,0
						CharPosition=FindPilotEnd(t$)
						While (Len(t$)>90)
							Delay 5
							Registry$=FindPilotReg$(t$)
							Pilot$=FindPilotName$(t$)
							
							LogData("ONLINE PILOT",Pilot$,Faction$,Registry$,False)
							
							OnlinePilots(Pilot$,Faction$,Registry$)
							
							t$=Right$(t$,Len(t$)-CharPosition)
							CharPosition=FindPilotEnd(t$)
						Wend	
					EndIf
					If Instr(Lower$(t$),StartOfQuant$)
						Faction$=FactionQuant$
						
						LogData("RETRIEVING","JOSSH DATA", "QUANTAR","PILOTS",False)
						
						Color 0,255,0
						CharPosition=FindPilotEnd(t$)
						While (Len(t$)>90)
							Delay 5
							Registry$=FindPilotReg$(t$)
							Pilot$=FindPilotName$(t$)
							
							LogData("ONLINE PILOT",Pilot$,Faction$,Registry$,False)
							
							OnlinePilots(Pilot$,Faction$,Registry$)
							
							t$=Right$(t$,Len(t$)-CharPosition)
							CharPosition=FindPilotEnd(t$)
						Wend
					End If
					
					If (Instr(Lower$(t$),EndOfTable$) And (Begin))
					
						LogData("PROCESSING","JOSSH DATA", "END OF FILE","END",False)
					
						Begin=False
						SeekFile(OpenTemp,Eof(OpenTemp))
						Exit
					End If
						
			Wend
			
			Begin=False
		
			CloseFile OpenTemp
			DeleteFile TempFileName$
			
			If (FirstRun)
				FirstRun=False
			End If

			Color 255,255,255
					
			LogData("PROCESSING","JOSSH DATA", "ALL PILOTS","END",False)

			LogData("CHECKING","PILOTS", "LOGGED","OFF",False)	
				
			CheckOffline()	
					
			For ResetPs.LastPilots=Each LastPilots
				Delete ResetPs
			Next
				
			For SwapP.Pilots = Each Pilots
				Delay 5
				NewOP.LastPilots=New LastPilots
				NewOP\Name$=SwapP\Name$
				NewOP\Reg$=SwapP\Reg$	
				NewOP\Fact$=SwapP\Fact$
				NewOP\Docked%=SwapP\Docked%
				NewOP\DockCount%=SwapP\DockCount%
				NewOP\KillCountS%=SwapP\KillCountS%
				NewOP\KillCountO%=SwapP\KillCountO%
				NewOP\KillCountQ%=SwapP\KillCountQ%
				NewOP\DeathCount%=SwapP\DeathCount%
				NewOP\MissionCount%=SwapP\MissionCount%
				NewOP\LaunchCount%=SwapP\LaunchCount%
				NewOP\DiscoCount%=SwapP\DiscoCount%
			Next
					
			For ResetnPs.Pilots=Each Pilots
				Delete ResetnPs
			Next	
			
			LogData("IDLE","WAITING", "NEXT UPDATE","IDLE",True)

			Delay 45
			
		End If
				
		Delay 5
		
		;Flip
	Wend
End

Function FindPilotReg$(FactionString$)
	Delay 5
	Local nStart=Instr(Lower$(FactionString$),PilotStartString$)
	If nStart=0 Then nStart=1
	Local nEnd=Instr(Lower$(FactionString$),RegistryEndString$,nStart)
	Local Substring$=Mid$(Lower$(FactionString$),nStart,(nEnd-nStart))
	Return Convert$(Right$(Substring$,Len(Substring$)-16))
End Function

Function FindPilotName$(FactionString$)
	Delay 5
	Local nStart=Instr(Lower$(FactionString$),PilotNamePrefix$)
	nStart=nStart+26
	Local nEnd=Instr(Lower$(FactionString$),PilotNameSuffix$,nStart)
	Local Substring$=Mid$(FactionString$,nStart,(nEnd-nStart))
	Return Left$(Substring$,(Len(Substring$)/2)-1)
End Function

Function FindPilotEnd(FactionString$)
	Return Instr(Lower$(FactionString$),PilotNameSuffix$)
End Function

Function Convert$(registrystring$)
	registrystring$=Lower$(registrystring$)
	Select registrystring$
		Case convertCiv$
			Return Reg_Civ$
		Case convertHG$
			Return Reg_HG$
		Default
			Return Reg_Rat$
		End Select
End Function

Function OnlinePilots(PilotName$,PilotFact$,PilotReg$)
	Local Found=False
	Fix$=" * "
	
	If PilotReg$=Reg_Civ$
		Fix$="   "
	End If

	NewP.Pilots=New Pilots
	NewP\Name$=PilotName$
	NewP\Fact$=PilotFact$
	NewP\Reg$=PilotReg$
				
	If (FileType(CurrentDir$()+"~Temp.TMP"))
		DeleteFile CurrentDir$()+"~Temp.TMP"
	End If			
				
	UpdateKDL(NewP.Pilots)

	If (FirstRun)
			LogData(PilotName$,PilotFact$,PilotReg$,"ALREADY ON",True)
		Else	
			For CheckP.LastPilots=Each LastPilots
				If CheckP\Name$=PilotName$
				LogData(PilotName$,PilotFact$,PilotReg$,"ON PREV",False)
					Found=True
				
					CheckKDL(NewP.Pilots,CheckP.LastPilots)
													
					If PilotReg$<>CheckP\Reg$	
						LogData(PilotName$,PilotFact$,"CHANGED","REGISTRY",True)
					EndIf
					Exit
				End If
			Next		
			If Not (Found)	
				LogData(PilotName$,PilotFact$,PilotReg$,"NOT ON PRV",False)
				LogData(PilotName$,PilotFact$,PilotReg$,"NOW ONLINE",True)
			End If			
	End If
End Function

Function CheckOffline()
	For iterOld.LastPilots=Each LastPilots
		Online=False
		ThisName$=iterOld\Name$
		OldFaction$=iterOld\Fact$
		For iterNew.Pilots	=Each Pilots
		Delay 5
			If ThisName$=iterNew\Name$
				Online=True
				Exit
			End If
		Next
		If (Not(Online) )
			Select OldFaction$
				Case FactionSol$
					Color 0,0,255
				Case FactionOct$
					Color 255,0,0
				Case FactionQuant$		
					Color 0,255,0
			End Select
			LogData(ThisName$,"IS NOT","ONLINE","ANYMORE",True)
		End If
		Color 255,255,255
	Next	
End Function	

Function UpdateKDL(GetPilot.Pilots)

	Delay 5
	LogData("CONNECT","JOSSH DATA","PILOT",GetPilot\Name$,False)
	
	Download(JOSSH2$+GetPilot\Name$,CurrentDir$(),TempFileName$)

	LogData("UPDATING","JOSSH DATA","PILOT",GetPilot\Name$,False)

		OpenTemp2=ReadFile(CurrentDir$()+TempFileName$)
		
		While Not Eof(OpenTemp2)
			Delay 5
			r$=ReadLine$(OpenTemp2)
			If Instr(Lower$(r$),PilotKillSolLINEPref$)
				r2$=ReadLine$(OpenTemp2)
					GetPilot\KillCountS%=GetResult%(r2$)
					LogData("NEW DATA",GetPilot\Name$,"SOL KILLS",GetPilot\KillCountS,False)
			End If
			If Instr(Lower$(r$),PilotKillOctLINEPref$)
				r2$=ReadLine$(OpenTemp2)
					GetPilot\KillCountO%=GetResult%(r2$)
					LogData("NEW DATA",GetPilot\Name$,"OCT KILLS",GetPilot\KillCountO,False)
			End If
			If Instr(Lower$(r$),PilotKillQuantLINEPref$)
				r2$=ReadLine$(OpenTemp2)
					GetPilot\KillCountQ%=GetResult%(r2$)
					LogData("NEW DATA",GetPilot\Name$,"QUANT KILLS",GetPilot\KillCountQ,False)
			End If
			If Instr(Lower$(r$),DeathLINEPref$)
				r2$=ReadLine$(OpenTemp2)
					GetPilot\DeathCount%=GetResult%(r2$)
					LogData("NEW DATA",GetPilot\Name$,"DEATHS",GetPilot\DeathCount,False)
			End If
			If Instr(Lower$(r$),LaunchLINEPref$)
				r2$=ReadLine$(OpenTemp2)
					GetPilot\LaunchCount%=GetResult%(r2$)
					LogData("NEW DATA",GetPilot\Name$,"LAUNCHES",GetPilot\LaunchCount,False)
			End If
			If Instr(Lower$(r$),LandingLINEPref$)
				r2$=ReadLine$(OpenTemp2)
					GetPilot\DockCount%=GetResult%(r2$)
					LogData("NEW DATA",GetPilot\Name$,"LANDINGS",GetPilot\DockCount,False)
			End If
			If Instr(Lower$(r$),DiscoLINEPref$)
				r2$=ReadLine$(OpenTemp2)
					GetPilot\DiscoCount%=GetResult%(r2$)
					LogData("NEW DATA",GetPilot\Name$,"DISCONNECTS",GetPilot\DiscoCount,False)
			End If
			If Instr(Lower$(r$),MissionLINEPref$)
				r2$=ReadLine$(OpenTemp2)
					GetPilot\MissionCount%=GetResult%(r2$)
					LogData("NEW DATA",GetPilot\Name$,"MISSIONS",GetPilot\MissionCount,False)
					
					;NO MORE TO FIND
					SeekFile(OpenTemp2,FileSize(OpenTemp2))
					Exit
			End If			
		Wend
		LogData("COMPLETED","JOSSH DATA","PILOT",GetPilot\Name$,False)
		
	CloseFile OpenTemp2
	DeleteFile TempFileName$
				
End Function		

Function CheckKDL(CheckN.Pilots,CheckO.LastPilots)
	Delay 5
	
	Local KillSolDiff=0
	Local KillOctDiff=0
	Local KillQuantDiff=0
	Local LaunchDiff=0		
	Local DeathDiff=0	
	Local DockDiff=0
	Local MissionDiff=0
	Local DiscoDiff=0
		If CheckO\Name$=CheckN\Name$
		
						LogData("CHECKING",CheckN\Name$,"FOR STAT","UPDATES",False)
						
						KillSolDiff=(CheckN\KillCountS%-CheckN\KillCountS%)
						
							LogData("NEW S KILL",CheckN\KillCountS%,"OLD S KILL",CheckO\KillCountS%,False)
						
						KillOctDiff=(CheckN\KillCountO%-CheckN\KillCountO%)
						
							LogData("NEW O KILL",CheckN\KillCountO%,"OLD O KILL",CheckO\KillCountO%,False)
						
						KillQuantDiff=(CheckN\KillCountQ%-CheckN\KillCountQ%)
						
							LogData("NEW Q KILL",CheckN\KillCountQ%,"OLD Q KILL",CheckO\KillCountQ%,False)
								
						LaunchDiff=(CheckN\LaunchCount%-CheckN\LaunchCount%)
						
							LogData("NEW LAUNCH",CheckN\LaunchCount%,"OLD LAUNCH",CheckO\LaunchCount%,False)
						
						DeathDiff=(CheckN\DeathCount%-CheckN\DeathCount%)		
						
							LogData("NEW DEATH",CheckN\DeathCount%,"OLD DEATH",CheckO\DeathCount%,False)
						
						DockDiff=(CheckN\DockCount%-CheckN\DockCount%)
	
							LogData("NEW LANDING",CheckN\DockCount%,"OLD LANDING",CheckO\DockCount%,False)
			
						MissionDiff=(CheckN\MissionCount%-CheckO\MissionCount%)
						
							LogData("NEW MISSION",CheckN\MissionCount%,"OLD MISSION",CheckO\MissionCount%,False)
						
						DiscoDiff=(CheckN\DiscoCount%-CheckO\DiscoCount%)
						
							LogData("NEW DISCO",CheckN\DiscoCount%,"OLD DISCO",CheckO\DiscoCount%,False)
											
						If KillSolDiff>0
							Color 128,128,255
							LogData(CheckN\Name$,"HAS KILLED",KillSolDiff,"SOLRAINS",True)
						End If
							
						If KillOctDiff>0
							Color 255,128,128
							LogData(CheckN\Name$,"HAS KILLED",KillOctDiff,"OCTAVIANS",True)
						End If
									
						If KillQuantDiff>0
							Color 128,255,128
							LogData(CheckN\Name$,"HAS KILLED",KillQuantDiff,"QUANTARS",True)
						End If
							
						If LaunchDiff>0			
							Color 128,255,255
							LogData(CheckN\Name$,"LAUNCHED",LaunchDiff,"TIMES",True)
						EndIf
					
						If DockDiff>0			
							Color 128,255,255
							LogData(CheckN\Name$,"DOCKED",DockDiff,"TIMES",True)
						EndIf
						If DeathDiff>0					
							Color 255,255,128
							LogData(CheckN\Name$,"DIED",DeathDiff,"TIMES",True)
						EndIf
						If DiscoDiff>0				
							Color 255,128,255
							LogData(CheckN\Name$,"DISCONNECTED",DiscoDiff,"TIMES",True)
						EndIf		
						If MissionDiff>0						
							Color 128,128,128
							LogData(CheckN\Name$,"COMPLETED",MissionDiff,"MISSIONS",True)
	
						LogData("COMPARISON",CheckN\Name$,"COMPLETE","OKAY",True)
							
					EndIf		
	End If		
End Function

Function GetResult%(Statstring$)
	nstart=Instr(Lower$(Statstring$),ValuePref$)
	nend=Instr(Lower$(Statstring$),ValueSuf$)
	
		Return Int%(Mid$(Statstring$,nstart+1,((nEnd)-nStart)))
End Function




















; NETWORK CODE


;=============================================================================================


;link$      - The link. You may enter the link just like you enter it
;             in your browser. Very tolerant. No http:// required.
;savepath$  - The path where the file should be saved
;savefile$  - The filename of the saved file. When given "", it will
;             be named like the file in the link$.

Function Download(link$, savepath$ = "", savefile$ = "")
;Strip protocol and return false if not "http"
inst = Instr(link$, "://")
If inst Then
	If Lower(Trim(Left(link$, inst - 1))) <> "http" Then Return False
	link$ = Right(link$, Len(link$) - inst - 2)
EndIf

;Seperate host from link
inst = Instr(link$, "/")
If inst = 0 Then Return False
host$ = Trim(Left(link$, inst - 1))
link$ = Trim(Right(link$, Len(link$) - inst + 1))

;Seperate path and file from the link
For i = Len(link$) To 1 Step -1
	If Mid(link$, i, 1) = "/" Then
		link_path$ = Trim(Left(link$, i))
		link_file$ = Right(link$, Len(link$) - i)
		Exit
	EndIf
Next
If link_file$ = "" Then Return False
If savefile$ = "" Then savefile$ = link_file$

;Open TCP stream
tcp = OpenTCPStream(host$, 80)
If tcp = 0 Then Return False
WriteLine tcp, "GET " + link_path$ + link_file$ + " HTTP/1.1" + Chr(13) + Chr(10) + "Host: " + host$ + Chr(13) + Chr(10) + "User-Agent: Download_Function_By_DevilsChild" + Chr(13) + Chr(10)

;Download file
l$ = ReadLine(tcp)
inst1 = Instr(l$, " ")
inst2 = Instr(l$, " ", inst1 + 1)
num = Mid(l$, inst1, inst2 - inst1)
Select num
	Case 200
		conlen = -1
		chunk = False
		
		Repeat
			l$ = Trim(ReadLine(tcp))
			If l$ = "" Then Exit
			
			inst = Instr(l$, ":")
			l1$ = Trim(Left(l$, inst - 1))
			l2$ = Trim(Right(l$, Len(l$) - inst))
			Select Lower(l1$)
				Case "content-length"
					conlen = l2$
				Case "transfer-encoding"
					If Lower(l2$) = "chunked" Then chunk = True
			End Select
			checkstream(tcp)
		Forever
		
		If conlen = 0 Then
			file = WriteFile(savepath$ + savefile$)
			CloseFile file
			CloseTCPStream tcp
			Return True
		ElseIf conlen > 0 Then
			file = WriteFile(savepath$ + savefile$)
			bnk = CreateBank(4096)
			pos = 0
			Repeat
				avail = conlen - pos
				If avail > 4096 Then
					ReadBytes bnk, tcp, 0, 4096
					WriteBytes bnk, file, 0, 4096
					pos = pos + 4096
				Else
					ReadBytes bnk, tcp, 0, avail
					WriteBytes bnk, file, 0, avail
					Exit
				EndIf
				
			checkstream(tcp)
		Forever
			FreeBank bnk
			CloseFile file
			CloseTCPStream tcp
			Return True
		ElseIf chunk Then
			file = WriteFile(savepath$ + savefile$)
			bnk = CreateBank(4096)
			
			Repeat
				l$ = Trim(Upper(ReadLine(tcp)))
				ln = 0
				For i = 1 To Len(l$)
					ln = 16 * ln + Instr("123456789ABCDEF", Mid$(l$, i, 1))
				Next
				If ln = 0 Then Exit
				
				If BankSize(bnk) < ln Then ResizeBank bnk, ln
				ReadBytes bnk, tcp, 0, ln
				WriteBytes bnk, file, 0, ln
				ReadShort(tcp)
				checkstream(tcp)
			Forever
			
			FreeBank bnk
			CloseFile file
			CloseTCPStream tcp
			Return True
		Else
			CloseTCPStream tcp
			Return False
		EndIf
	Case 301, 302
		Repeat
			l$ = Trim(ReadLine(tcp))
			If l$ = "" Then Exit
			
			inst = Instr(l$, ":")
			l1$ = Trim(Left(l$, inst - 1))
			l2$ = Trim(Right(l$, Len(l$) - inst))
			Select Lower(l1$)
				Case "location"
					CloseTCPStream tcp
					Return Download(l2$, savepath$, savefile$)
			End Select
			checkstream(tcp)			
		Forever
	Default
		CloseTCPStream tcp
		Return False
End Select
End Function

Function checkstream(stream)
	Delay 5
If Eof(stream)<=-1
RuntimeError "Connection Lost. Download failed"
End
End If
End Function 

Function LogData(dt1$,dt2$,dt3$,dt4$,PrintToScreen=False)
	Local concatA$=Fix$+Chr$(9)+" "+LSet(CurrentTime$(),9)
	Local concatB$=" "+Chr$(9)+" "
	Local concatC$=LSet(dt1$,12)+concatB$
	Local concatD$=LSet(dt2$,12)+concatB$
	Local concatE$=LSet(dt3$,12)+concatB$
	Local concatF$=LSet(dt4$,12)+concatB$+Right$(Fix$,Len(Fix$)-1)

	Local Concat$=concatA$+concatB$+concatC$+concatD$+concatE$+concatF$

	Logfile=OpenFile("Log.txt")
	SeekFile(Logfile,FileSize("Log.txt"))

	WriteLine(Logfile,Concat$)
	
	CloseFile(Logfile)
	
	If (PrintToScreen)
		Print Concat$
	End If
End Function