Page 1 of 1

Winning teams & Times

Posted: 05 Apr 2010, 22:57
by AF
So I need to build a widget for my AI that I can use in my write up. I need to generate graphics and statistics of played games, so I need win/losses and timings of how long each AI lasted

Since I cannot do this in Shard itself (The C++ Team and AllyTeam API is incomplete), I tried to do it with a lua widget.

What I'd do is I'd print out the results at the end of the game to a csv file, which I would then import into MS Excel and generate graphics and charts with, leaving me to simply write a small script to execute spring 100 or 200 times with aegis' widget that forces 120x speed.

Initially It didn't work out quite that way.

But then with some help from jk I fixed it! Here it is:

Code: Select all

local versionNumber = "2.0"

function widget:GetInfo()
	return {
		name      = "Shard Statistics " .. versionNumber,
		desc      = "Displays a name tag above each commander.",
		author    = "AF",
		date      = "4 April 2010",
		license   = "GNU GPL, v2 or later",
		layer     = -10,
		enabled   = true  --  loaded by default?
	}
end

local teams = {}
local Echo = Spring.Echo

--------------------------------------------------------------------------------
-- callins
--------------------------------------------------------------------------------

local function GetTimeString()
	local secs = math.floor(Spring.GetGameSeconds())
	if (timeSecs ~= secs) then
		timeSecs = secs
		local h = math.floor(secs / 3600)
		local m = math.floor(math.fmod(secs, 3600) / 60)
		local s = math.floor(math.fmod(secs, 60))
		if (h > 0) then
			timeString = string.format('%02i:%02i:%02i', h, m, s)
		else
			timeString = string.format('%02i:%02i', m, s)
		end
	end
	return timeString
end

function widget:GameStart()
	dowork = false
end

function widget:Update(dt)
	local gs = Spring.GetGameSeconds()
	if gs == 1 then
		local getTeams = Spring.GetTeamList()
		for _,teamID in pairs(getTeams) do
			local team = {}
			team.teamID,team.leader,team.isDead,team.isAiTeam,team.side,team.allyTeam,team.customTeamKeys = Spring.GetTeamInfo(teamID)
			if team.isAiTeam then
				local shortName
				local version
				_,_,_,_,shortName,version,_ = Spring.GetAIInfo(teamID)
				team.name = shortName.." "..version
				if team.name ~= nil then
					team.ID = teamID
					teams[teamID] = team
				end
			end
		end
	end
end

function widget:TeamDied(teamID)
	local t = GetTimeString()
	teams[teamID].death = t
end

function widget:GameOver()
	if # teams > 0 then
		local file = io.open ("shardstats.csv", "a")
		if  file ~= nil then
			for i,team in pairs(teams) do
				file:write(team.name)
				file:write(",");
				if team.death then
					file:write(team.death)
					file:write(",false,");
				else
					file:write(GetTimeString())
					file:write(",true,")
				end
			end
			file:write("\n")
			file:close()
		else
			Echo("failed to open shardstats.csv")
		end
	end
end

Re: Winning teams & Times

Posted: 08 Aug 2010, 23:06
by AF
*bump* some people are asking questions related to this.

Here is my current version of the Shard stats widget:

Code: Select all

local versionNumber = "2.0"

function widget:GetInfo()
	return {
		name      = "Shard Statistics " .. versionNumber,
		desc      = "Displays a name tag above each commander.",
		author    = "AF",
		date      = "4 April 2010",
		license   = "GNU GPL, v2 or later",
		layer     = -10,
		enabled   = true  --  loaded by default?
	}
end

local teams = {}
local Echo = Spring.Echo

--------------------------------------------------------------------------------
-- callins
--------------------------------------------------------------------------------

local function GetTimeString()
	local secs = math.floor(Spring.GetGameSeconds())
	if (timeSecs ~= secs) then
		timeSecs = secs
		local h = math.floor(secs / 3600)
		local m = math.floor(math.fmod(secs, 3600) / 60)
		local s = math.floor(math.fmod(secs, 60))
		if (h > 0) then
			timeString = string.format('%02i:%02i:%02i', h, m, s)
		else
			timeString = string.format('%02i:%02i', m, s)
		end
	end
	return timeString
end

function widget:GameStart()
	Spring.SetDrawGround(false)
	Spring.SetDrawWater(false)
	Spring.SetDrawSky(false)
	Echo("shard stats processing")
	local getTeams = Spring.GetTeamList()
	Echo("found "..#getTeams.." teams")
	for _,teamID in pairs(getTeams) do
		local team = {}
		team.teamID,team.leader,team.isDead,team.isAiTeam,team.side,team.allyTeam,team.customTeamKeys = Spring.GetTeamInfo(teamID)
		if team.isAiTeam then
			local shortName
			local version
			_,_,_,_,shortName,version,_ = Spring.GetAIInfo(teamID)
			team.name = shortName.." "..version
			Echo("found "..team.name)
			team.ID = teamID
			teams[teamID] = team
		end
	end
end

function widget:Update(dt)
	local gs = Spring.GetGameSeconds()
	if gs == 1 then
		
	end
end

function widget:TeamDied(teamID)
	local t = Spring.GetGameSeconds()--GetTimeString()
	local team = teams[teamID]
	if team then
		team.death = t
	end
end

function widget:GameOver()
	if # teams > 0 then
		local file = io.open ("shardstats.csv", "a")
		local file2 = io.open ("shardstats2.csv", "a")
		if  file ~= nil then
			file:write("\n")
			file2:write("\n")
			for i,team in pairs(teams) do
				file:write(team.name)
				file:write(",");
				if team.death then
					file:write(team.death)
					file:write(",false,");
				else
					file2:write(team.name)
					local s = Spring.GetGameSeconds()--GetTimeString()
					file2:write(",")
					file2:write(s)
					
					file:write(s)
					file:write(",true,")
				end
			end
			file:close()
			file2:close()
		else
			Echo("failed to open shardstats.csv")
		end
	end
end



Re: Winning teams & Times

Posted: 09 Aug 2010, 00:07
by knorke
nice but I wanted this yesterday :/

Re: Winning teams & Times

Posted: 09 Aug 2010, 10:35
by knorke
Maybe you should clean up some things a bit if you publish this lua like this.
Its nice a to have such snippets (imo a forum or wiki section would be cool) but they should be as correct and readable as possible because think of the noobs!

desc = "Displays a name tag above each commander.",
wat? :shock:

Code: Select all

   if gs == 1 then
      
   end
Something missing? The whole Update function seems to do nothing as gs is never used again.

Code: Select all

   dowork = false
Never used again.

Code: Select all

      if  file ~= nil then
Do this for file2 too.
file and file2 could use better names ie deadteams and aliveteams

Re: Winning teams & Times

Posted: 09 Aug 2010, 13:44
by AF
I doubt anybody would use the widget as is, it's more of a demo to show how to do kill loss stats

Re: Winning teams & Times

Posted: 09 Aug 2010, 17:16
by jK
Isn't it easier to check which teams are still alive at GameOver() instead of using :TeamDied()?

Re: Winning teams & Times

Posted: 09 Aug 2010, 17:39
by aegis
to get time of death?