-- tap note types
local TNSTypes = {
	"TapNoteScore_W1",
	"TapNoteScore_W2",
	"TapNoteScore_W3",
	"TapNoteScore_W4",
	"TapNoteScore_W5",
	"TapNoteScore_Miss",
};
-- tap note locations
local TNSLocations = {
	-16, -- 226
	14, -- 256
	44, -- 286
	74, -- 316
	104, -- 346
	134, -- 376
};
-- tap note judge number font
--[[
local JudgeNumberFont = Def.RollingNumbers{
	File=THEME:GetPathF("_popstar","combo");
	InitCommand=cmd(shadowlength,0;zoom,0.6);
};
]]
local JudgeNumberFont = LoadFont("_popstar","combo")..{
	InitCommand=cmd(shadowlength,0;zoom,0.6);
};

local function JudgeNumbers()
	local r = Def.ActorFrame{};
	-- judge numbers
	for pn in ivalues(PlayerNumber) do
		--local flip = (pn == PLAYER_1) and 96 or 384;
		local flip = (pn == PLAYER_1) and SCREEN_CENTER_X-160 or SCREEN_CENTER_X+160;
		for i = 1,#TNSTypes do
			-- get stats
			local stats = STATSMAN:GetPlayedStageStats(1):GetPlayerStageStats(pn);
			local yPos = TNSLocations[i];
			local approach = 1;
			
			if TNSTypes[i] == "TapNoteScore_Miss" then
				approach = 2;
			end;
			r[#r+1] = JudgeNumberFont .. {
				Name="Judge"..i;
				Text=stats:GetTapNoteScores(TNSTypes[i]);
				--TargetNumber=stats:GetTapNoteScores(TNSTypes[i]);
				--ApproachSeconds=approach;
				InitCommand=function(self)
					self:y(SCREEN_CENTER_Y+yPos);
					self:x(flip);
					self:halign(0.5);
				end;
				BeginCommand=cmd(diffuse,JudgeColor(TNSTypes[i]));
				OnCommand=function(self)
					if not GAMESTATE:IsHumanPlayer(pn) then
						self:visible(false);
						return;
					end;
					self:visible(true);
				end;
				OffCommand=cmd(linear,0.2;diffusealpha,0);
			};
		end;
	end;
	return r;
end;

local function OKNumbers()
	local r = Def.ActorFrame{};
	for pn in ivalues(PlayerNumber) do
		-- both start at y=406
		local flip = (pn == PLAYER_1) and SCREEN_CENTER_X-160 or SCREEN_CENTER_X+160;
		-- get stats
		local stats = STATSMAN:GetPlayedStageStats(1):GetPlayerStageStats(pn);
		-- get okay
		local OK = stats:GetHoldNoteScores('HoldNoteScore_Held');
		local NG = stats:GetHoldNoteScores('HoldNoteScore_LetGo');
		local lenOK = string.len(OK);
		local lenNG = string.len(NG);
		
		local attribOK = {
			Length = lenOK;
			Diffuse = JudgeColor('TapNoteScore_W1');
		};
		local attribSlash = {
			Length = 1;
			Diffuse = color("1,1,1,1");
		};
		local attribNG = {
			Length = lenNG;
			Diffuse = JudgeColor('TapNoteScore_Miss');
		};
		
		r[#r+1] = JudgeNumberFont..{
			Text=OK..":"..NG;
			InitCommand=function(self)
				self:y(SCREEN_CENTER_Y+166);
				self:x(flip);
				self:diffusealpha(0);
				self:linear(0.2);
				self:diffusealpha(1);
			end;
			BeginCommand=function(self)
				self:AddAttribute(0,attribOK);
				self:AddAttribute(lenOK,attribSlash);
				self:AddAttribute(lenOK+1,attribNG);
			end;
			OnCommand=function(self)
				if not GAMESTATE:IsHumanPlayer(pn) then
					self:visible(false);
					return;
				end;
				self:visible(true);
			end;
			OffCommand=cmd(linear,0.2;diffusealpha,0);
		};
	end;
	return r;
end;

-- determine if the text should glow based on a full combo
-- borrowed from DWI for SM4 (originally by AJ; he's told me I can use almost)
-- whatever code he has available and hasn't explicitly said that it's not for
-- use anywhere (these are likely due to their incompleteness)
local function MaxComboGlow(pn)
	local bMaxComboObtained = STATSMAN:GetCurStageStats():GetPlayerStageStats(pn):FullCombo();
	if not bMaxComboObtained then return;
	else return cmd(glowshift);
	end;
end;

local t = Def.ActorFrame{
	-- judge labels
	LoadActor("_judge labels")..{
		InitCommand=cmd(x,SCREEN_CENTER_X;y,SCREEN_CENTER_Y+77);
		BeginCommand=cmd(diffusealpha,0);
		OnCommand=cmd(linear,0.2;diffusealpha,1);
		OffCommand=cmd(linear,0.2;diffusealpha,0);
	};
	
	-- judgment numbers
	JudgeNumbers();
	-- okay/NG numbers
	OKNumbers();
	
	-- XXX: ugly, replace with function (which I don't want to write)
	LoadFont("_myriadblack","gradbev")..{
		Text="Max Combo";
		InitCommand=cmd(x,SCREEN_CENTER_X;y,SCREEN_CENTER_Y+196;shadowlength,0;zoom,0.8);
		BeginCommand=cmd(diffusealpha,0);
		OnCommand=cmd(linear,0.2;diffusealpha,1);
		OffCommand=cmd(linear,0.2;diffusealpha,0);
	};
	
	LoadFont("_popstar","combo")..{
		Name="P1MaxCombo";
		Text=STATSMAN:GetCurStageStats():GetPlayerStageStats(PLAYER_1):MaxCombo();
		InitCommand=cmd(x,SCREEN_CENTER_X-160;y,SCREEN_CENTER_Y+196;zoom,0.5;diffusealpha,0;shadowlength,0);
		BeginCommand=function(self)
			if not GAMESTATE:IsHumanPlayer(PLAYER_1) then self:visible(false); return; end;
			self:visible(true);
		end;
		OnCommand=cmd(linear,0.2;diffusealpha,1;playcommand,"GlowCheck");
		GlowCheckCommand=MaxComboGlow(PLAYER_1);
		OffCommand=cmd(linear,0.2;diffusealpha,0);
	};
	
	LoadFont("_popstar","combo")..{
		Name="P2MaxCombo";
		Text=STATSMAN:GetCurStageStats():GetPlayerStageStats(PLAYER_2):MaxCombo();
		InitCommand=cmd(x,SCREEN_CENTER_X+160;y,SCREEN_CENTER_Y+196;zoom,0.5;diffusealpha,0;shadowlength,0);
		BeginCommand=function(self)
			if not GAMESTATE:IsHumanPlayer(PLAYER_2) then self:visible(false); return; end;
			self:visible(true);
		end;
		OnCommand=cmd(linear,0.2;diffusealpha,1;playcommand,"GlowCheck");
		GlowCheckCommand=MaxComboGlow(PLAYER_2);
		OffCommand=cmd(linear,0.2;diffusealpha,0);
	};
	
	-- player 1 judge bar
	LoadActor("bar",PLAYER_1);
	-- player 1 percentage
	LoadActor("grade",PLAYER_1);
	
	-- player 2 judge bar
	LoadActor("bar",PLAYER_2);
	-- player 2 percentage
	LoadActor("grade",PLAYER_2);
	
	-- other fun mods!
	LoadFont("_Arial","14 shadow")..{
		Text=GAMESTATE:GetSongOptionsString();
		InitCommand=cmd(x,SCREEN_CENTER_X;y,SCREEN_CENTER_Y-112;zoom,0.5;shadowlength,0);
		OffCommand=cmd(linear,0.2;diffusealpha,0);
	};
};

return t;

-- code by naket coder