Hi all.
HELO isn't really based on ELO (at least not our previous ELO implementation). It was written from scratch as an attempt to mimic Bungie's scoring implementation for Halo 2.
For example, while it does include a "newbie helper function" (as does Bungie's) it does not do much averaging. The point awards are determined by comparing win/loss vs each individual on the opposing team. (Allegiance has no FFA).
Here's a link to Bungie's:
http://www.bungie.net/Stats/content.aspx?link=h2statoverview. HELO is basically the same thing.
I had at one point posted all the source code, if it's still here in the forums it may have other information for you.
Cheers,
Pook
EDIT: I realized the the source that was previously posted may have been for ELO, not HELO. Here's HELO:
CODE-- RANK:
-- CONVERT(int,CONVERT(real,ELORanking) / POWER(50 + (CONVERT(real,ELORanking) / 100),1.15936))
-- GAME DURATION ISN'T CURRENTLY USED FOR SCORING
DECLARE @GameDuration real
SET @GameDuration = (SELECT DATEDIFF(second,GameStartTime,GameEndTime) FROM Game WHERE GameIdentID = @GameID)
-- WHEN GAME DOESN'T COUNT NO CHANGES ARE RECORDED
DECLARE @GameCounted int
SET @GameCounted = 1
-- TO BE OUTPUT VIA THE WEBSERVICE
DECLARE @GameReason varchar(100)
SET @GameReason = 'Game Counted'
-- SEE IF STATS WERE ENABLED IN GAME SETTINGS
DECLARE @GameStatsCounted int
SET @GameStatsCounted = (SELECT GameStatsCount FROM Game WHERE GameIdentID = @GameID)
-- OVERRIDE AND MAKE STATS ALWAYS COUNT
SET @GameStatsCounted = 1
-- SHOULDN'T HAPPEN
IF @GameDuration < 1
BEGIN
RAISERROR('Game Duration was Zero or Negative',16,1)
RETURN
END
-- WHOLE GAME LESS THAN 5 MINUTES (300 SECONDS)
IF @GameDuration < 300
BEGIN
SET @GameCounted = 0
SET @GameReason = 'Game duration was less than 5 minutes'
END
-- GAMES WITH MORE THAN 2 TEAMS CANNOT COUNT
IF (SELECT MAX(GameTeamNumber) FROM GameTeam WHERE GameID = @GameID) > 1
BEGIN
SET @GameCounted = 0
SET @GameReason = 'Game had more than 2 teams participating'
END
-- DRAWS DO NOT COUNT
IF (SELECT MAX(GameTeamWinner) FROM GameTeam WHERE GameID = @GameID) = 0
BEGIN
SET @GameCounted = 0
SET @GameReason = 'Game was a draw'
END
-- AT LEAST 10 PLAYERS THAT PLAYED AT LEAST HALF THE GAME
IF (SELECT COUNT(gtm.GameTeamMemberMemberID)
FROM GameTeamMember gtm
INNER JOIN GameTeam gt ON gt.GameTeamIdentID = gtm.GameTeamID
WHERE gt.GameID = @GameID
AND gtm.GameTeamMemberDuration > (@GameDuration / 2)) < 10
BEGIN
SET @GameCounted = 0
SET @GameReason = 'Less than 10 players that played for at least half the game'
END
-- STATS CAN BE TURNED OFF TO NOT AFFECT RATINGS
IF @GameStatsCounted <> 1
BEGIN
SET @GameCounted = 0
SET @GameReason = 'Stats were disabled in the game settings'
END
-- PLAYERS TABLE HOLDS ALL THE STATISTICS FOR THIS GAME
DECLARE @Players TABLE (Member_ID int, Callsign varchar(50), Rank int, Team int, Winner int, MinutesPlayed int, ParticipationPercentage int, Points int, Pass int)
-- GET ALL THE PLAYERS FOR THIS GAME AND INSERT THEM INTO THE TABLE (Must have played at least 5 minutes)
INSERT INTO @Players
SELECT DISTINCT
gtm.GameTeamMemberMemberID AS 'Member_ID',
gtm.GameTeamMemberCallsign AS 'Callsign',
0 AS 'Rank',
gt.GameTeamNumber AS 'Team',
gt.GameTeamWinner AS 'Winner',
gtm.GameTeamMemberDuration AS 'MinutesPlayed',
((gtm.GameTeamMemberDuration + 1) / (@GameDuration + 1) * 100) AS 'ParticipationPercentage',
0 AS 'Points',
-1 AS 'Pass'
FROM GameTeamMember gtm
INNER JOIN GameTeam gt ON gt.GameTeamIdentID = gtm.GameTeamID
WHERE gt.GameID = @GameID
AND gtm.GameTeamMemberDuration > 300
-- REMOVE DUPLICATES
DECLARE @DupCheckID int
WHILE (SELECT COUNT(*) FROM @PLAYERS WHERE Pass = -1) > 0
BEGIN
SET @DupCheckID = (SELECT TOP 1 Member_ID FROM @Players WHERE Pass = -1)
SET ROWCOUNT 1
UPDATE @PLAYERS SET Pass = 0 WHERE Member_ID = @DupCheckID
SET ROWCOUNT 0
DELETE FROM @Players WHERE Member_ID = @DupCheckID AND Pass = -1
END
-- UPDATE THE PLAYERS TABLE TO INCLUDE THEIR CURRENT RANK
UPDATE @Players
SET Rank = CONVERT(int,CONVERT(real,e.ELORanking) / POWER(50 + (CONVERT(real,e.ELORanking) / 100),1.15936))
FROM @Players p, ELO e
WHERE e.Member_ID = p.Member_ID
-- WORKAROUND FOR EARLY DURATION BUG
UPDATE @Players
SET MinutesPlayed = @GameDuration
WHERE MinutesPlayed > @GameDuration
-- PLAYERSTEMP IS USED TO COMPARE PLAYER TO PLAYER IN A LOOP
DECLARE @PlayersTemp TABLE (Member_ID int, Rank int, Team int, VsScore int, Pass int)
DECLARE @PlayerID int
DECLARE @PlayerRank int
DECLARE @PlayerWon int
DECLARE @PlayerTempID int
DECLARE @PlayerScore int
DECLARE @ScoreWin int
-- OUTER LOOP CONTROLS THE PLAYER WE'RE SCORING FOR
WHILE (SELECT COUNT(*) FROM @Players WHERE Pass = 0) > 0
BEGIN
SET @PlayerID = (SELECT TOP 1 Member_ID FROM @Players WHERE Pass = 0)
SET @PlayerRank = (SELECT TOP 1 Rank FROM @Players WHERE Member_ID = @PlayerID)
SET @PlayerWon = (SELECT TOP 1 Winner FROM @Players WHERE Member_ID = @PlayerID)
IF @PlayerWon = 0 SET @ScoreWin = -1 ELSE SET @ScoreWin = 1
-- OUTPUT FOR DEBUGGING
IF @DebugMode = 1 SELECT @PlayerID, @PlayerRank, @PlayerWon, @ScoreWin
INSERT INTO @PlayersTemp
SELECT Member_ID, Rank, Team, 0, 0
FROM @Players
WHERE Team <> (SELECT TOP 1 Team FROM @Players WHERE Member_ID = @PlayerID)
AND Member_ID <> @PlayerID
-- INNER LOOP ITERATES THROUGH THE OPPONENTS
WHILE (SELECT COUNT(*) FROM @PlayersTemp WHERE Pass < 1) > 0
BEGIN
SET @PlayerTempID = (SELECT TOP 1 Member_ID FROM @PlayersTemp WHERE Pass < 1)
UPDATE @PlayersTemp
SET VsScore = (45 + ((Rank - @PlayerRank) * @ScoreWin)) * @ScoreWin
WHERE Member_ID = @PlayerTempID
UPDATE @PlayersTemp SET Pass = 1 WHERE Member_ID = @PlayerTempID
END
-- OUTPUT FOR DEBUGGING
IF @DebugMode = 1 SELECT * FROM @PlayersTemp
-- PLAYERS SCORE IS THE AVERAGE OF THE INDIVIDUAL VS SCORES
SET @PlayerScore = (SELECT AVG(VsScore) FROM @PlayersTemp)
-- UPDATE THE PLAYERS TABLE
UPDATE @Players
SET Points = @PlayerScore,
Pass = 1
WHERE Member_ID = @PlayerID
-- CLEAR THE TABLE FOR THE NEXT ITERATION
DELETE FROM @PlayersTemp
END
-- THIS IS THE 'HELPER' THAT HELPS PEOPLE AT LOW RANKS INCREASE IN RANK
UPDATE @Players
SET Points = Points * ((CONVERT(real,Rank) + 1) / (15 + 1))
WHERE Winner = 0
AND Rank <= 15
-- OUTPUT FOR DEBUGGING
IF @DebugMode = 1 SELECT * FROM @Players
-- FAILSAFE FOR MISSING PLAYER RANK / POINTS
UPDATE @Players SET Points = 0 WHERE Points IS NULL
UPDATE @Players SET Rank = 0 WHERE Rank IS NULL
-- ARCHIVE THE INDIVIDUAL ADJUSTMENTS
INSERT INTO GamePlayerELO (GameID, GamePlayerELOMemberID, GamePlayerELORating, GamePlayerELOAdjustment, GamePlayerELOModifier)
SELECT @GameID, Member_ID, Rank, Points, 0
FROM @Players
-- CACHE KILLCOUNTS
DECLARE @AWE TABLE (Member_ID int, Kills int, Ejects int)
INSERT INTO @AWE(Member_ID, Kills, Ejects)
SELECT Member_ID, Kills, Ejects
FROM dbo.ASGSNetGetGameAWECount(@GameID)
-- MAKES UPDATING EASIER
DECLARE @ELOMemberID int
DECLARE @ELOWinner int
DECLARE @ELOScore int
DECLARE @ELOKills int
DECLARE @ELOEjects int
-- THIS LOOP UPDATES THE ELO TABLE TO TABULATE THEIR ACTUAL SCORES
WHILE (SELECT COUNT(*) FROM @Players WHERE Pass < 2) > 0
BEGIN
-- SEE HOW EASY THAT WAS
SET @ELOMemberID = (SELECT TOP 1 Member_ID FROM @Players WHERE Pass < 2)
SET @ELOWinner = (SELECT TOP 1 Winner FROM @Players WHERE Member_ID = @ELOMemberID)
SET @ELOScore = (SELECT TOP 1 Points FROM @Players WHERE Member_ID = @ELOMemberID)
SET @ELOKills = (SELECT Kills FROM @AWE WHERE Member_ID = @ELOMemberID)
SET @ELOEjects = (SELECT Ejects FROM @AWE WHERE Member_ID = @ELOMemberID)
-- IF THE PLAYER DOESN'T EXIST, INSERT A RECORD FOR THEM. (Fixes first-game-ignored bug)
IF (SELECT COUNT(*) FROM ELO WHERE Member_ID = @ELOMemberID) = 0
BEGIN
INSERT INTO ELO (Member_ID, ELORanking, ELOWins, ELOLosses, ELOExpected, ELOKills, ELOEjects, ELOCR)
VALUES (@ELOMemberID, 0, 0, 0, 0, 0, 0, 0)
END
IF @GameCounted = 1 AND @DebugMode = 0
BEGIN
-- UPDATE THE SCORE
UPDATE ELO
SET ELORanking = ELORanking + @ELOScore,
ELOWins = ELOWins + @ELOWinner,
ELOLosses = ELOLosses + 1 - @ELOWinner,
ELOKills = ELOKills + @ELOKills,
ELOEjects = ELOEjects + @ELOEjects
WHERE Member_ID = @ELOMemberID
END
-- MARK THE PLAYER AS PROCESSED AND LOOP FOR NEXT ONE
UPDATE @PLAYERS
SET Pass = 2
WHERE Member_ID = @ELOMemberID
END
-- IF ANYONE ACTUALLY WENT BELOW 0, ADJUST TO 0
UPDATE ELO
SET ELORanking = 0 WHERE ELORanking < 0
-- ARCHIVE GAME ELO HISTORY
DECLARE @TotalGamePoints int
SET @TotalGamePoints = (SELECT SUM(Points) FROM @Players)
INSERT INTO GameELO (GameID, GameELOTeamNumber, GameELORating, GameELOScore, GameELOOpponentRating, GameELOExpectedOutcome, GameELOAdjustment, GameELOCounted, GameELOReason)
SELECT @GameID, Team, SUM(Points), MAX(Winner), @TotalGamePoints - SUM(Points), -1, -1, @GameCounted, @GameReason
FROM @Players
GROUP BY Team