[longomatch] Add stats for game units



commit 80cd0504ce810ae57a4d13b37ee24e9cd5ec6a55
Author: Andoni Morales Alastruey <ylatuya gmail com>
Date:   Mon Feb 6 03:03:55 2012 +0100

    Add stats for game units

 LongoMatch.Core/LongoMatch.Core.mdp     |    2 +
 LongoMatch.Core/Makefile.am             |    2 +
 LongoMatch.Core/Stats/GameUnitStats.cs  |  121 +++++++++++++++++++++++++++++++
 LongoMatch.Core/Stats/GameUnitsStats.cs |   94 ++++++++++++++++++++++++
 LongoMatch.Core/Stats/ProjectStats.cs   |   20 +++++-
 5 files changed, 237 insertions(+), 2 deletions(-)
---
diff --git a/LongoMatch.Core/LongoMatch.Core.mdp b/LongoMatch.Core/LongoMatch.Core.mdp
index 698b899..83cb0b7 100644
--- a/LongoMatch.Core/LongoMatch.Core.mdp
+++ b/LongoMatch.Core/LongoMatch.Core.mdp
@@ -96,6 +96,8 @@
     <File subtype="Code" buildaction="Compile" name="Stats/Stat.cs" />
     <File subtype="Code" buildaction="Compile" name="Stats/SubCategoryStat.cs" />
     <File subtype="Code" buildaction="Compile" name="Stats/PlayersStats.cs" />
+    <File subtype="Code" buildaction="Compile" name="Stats/GameUnitStats.cs" />
+    <File subtype="Code" buildaction="Compile" name="Stats/GameUnitsStats.cs" />
   </Contents>
   <References>
     <ProjectReference type="Gac" localcopy="True" refto="System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
diff --git a/LongoMatch.Core/Makefile.am b/LongoMatch.Core/Makefile.am
index e248df0..f8e46b0 100644
--- a/LongoMatch.Core/Makefile.am
+++ b/LongoMatch.Core/Makefile.am
@@ -41,6 +41,8 @@ SOURCES = \
 	Interfaces/ITemplatesService.cs \
 	Interfaces/ITimelineNode.cs \
 	Stats/CategoryStats.cs \
+	Stats/GameUnitStats.cs \
+	Stats/GameUnitsStats.cs \
 	Stats/PercentualStat.cs \
 	Stats/PlayersStats.cs \
 	Stats/ProjectStats.cs \
diff --git a/LongoMatch.Core/Stats/GameUnitStats.cs b/LongoMatch.Core/Stats/GameUnitStats.cs
new file mode 100644
index 0000000..dc93374
--- /dev/null
+++ b/LongoMatch.Core/Stats/GameUnitStats.cs
@@ -0,0 +1,121 @@
+// 
+//  Copyright (C) 2012 Andoni Morales Alastruey
+// 
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+// 
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//  GNU General Public License for more details.
+//  
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+// 
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using LongoMatch.Store;
+
+namespace LongoMatch.Stats
+{
+	public class GameUnitStatsNode : List<GameUnitStatsNode>
+	{
+		public GameUnitStatsNode (TimelineNode  node)
+		{
+			Node = node;
+		}
+		
+		public GameUnitStatsNode (TimelineNode  node, List<GameUnitStatsNode> list): base (list)
+		{
+			Node = node;
+		}
+		
+		public TimelineNode Node {
+			get;
+			set;
+		}
+		
+		public string Name {
+			get {
+				return Node.Name;
+			}
+		}
+		
+		public int Duration {
+			get {
+				return Node.Duration.MSeconds;
+			}
+		}
+		
+		public int PlayingTime {
+			get {
+				if (this.Count == 0) {
+					return Duration;
+				}
+				return this.Sum(n => n.PlayingTime);
+			}
+		}
+		
+		public int PausedTime {
+			get {
+				if (this.Count == 0)
+					return 0;
+				return Duration - PlayingTime;
+			}
+		}
+		
+		public double AverageDuration {
+			get {
+				if (this.Count == 0)
+					return 0;
+				return this.Average(n => n.Duration);
+			}
+		}
+		
+		public double AveragePlayingTime {
+			get {
+				if (this.Count == 0)
+					return 0;
+				return this.Average(n => n.PlayingTime);
+			}
+		}
+		
+		public double AveragePausedTime {
+			get {
+				if (this.Count == 0)
+					return 0;
+				return this.Average(n => n.PausedTime);
+			}
+		}
+		
+		public double DurationTimeStdDeviation {
+			get {
+				if (this.Count == 0)
+					return 0;
+				return Math.Sqrt(this.Average(n=>Math.Pow(n.Duration - AverageDuration,2)));	
+			}
+		}
+		
+		public double PlayingTimeStdDeviation {
+			get {
+				if (this.Count == 0)
+					return 0;
+				return Math.Sqrt(this.Average(n=>Math.Pow(n.PlayingTime - AveragePlayingTime,2)));	
+			}
+		}
+		
+		public double PausedTimeStdDeviation {
+			get {
+				if (this.Count == 0)
+					return 0;
+				return Math.Sqrt(this.Average(n=>Math.Pow(n.PausedTime - AveragePausedTime,2)));	
+			}
+		}
+	}
+}
+
diff --git a/LongoMatch.Core/Stats/GameUnitsStats.cs b/LongoMatch.Core/Stats/GameUnitsStats.cs
new file mode 100644
index 0000000..03db35a
--- /dev/null
+++ b/LongoMatch.Core/Stats/GameUnitsStats.cs
@@ -0,0 +1,94 @@
+// 
+//  Copyright (C) 2012 Andoni Morales Alastruey
+// 
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+// 
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//  GNU General Public License for more details.
+//  
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+// 
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using LongoMatch.Store;
+
+namespace LongoMatch.Stats
+{
+	public class GameUnitsStats
+	{
+		TimelineNode game;
+		GameUnitStatsNode gameNode;
+		Dictionary<GameUnit, GameUnitStatsNode> gameUnitNodes;
+		
+		const float MAX_DIFF = (float) 80 / 100; 
+		
+		public GameUnitsStats (GameUnitsList guList, int duration)
+		{
+			game = new TimelineNode{Start=new Time(0), Stop=new Time(duration)};
+			gameNode = new GameUnitStatsNode(game);
+			gameUnitNodes = new Dictionary<GameUnit, GameUnitStatsNode>();
+			GroupGameStats(guList);
+		}
+		
+		public Dictionary<GameUnit, GameUnitStatsNode> GameUnitNodes {
+			get {
+				return gameUnitNodes;
+			}
+		}
+		
+		public GameUnitStatsNode GameNode {
+			get {
+				return gameNode;
+			}
+		}
+		
+		void GroupGameStats (GameUnitsList guList)
+		{
+			List<GameUnitStatsNode> parents = new List<GameUnitStatsNode>();
+			parents.Add(gameNode);
+			
+			foreach (GameUnit gu in guList) {
+				List<GameUnitStatsNode> nextParents = new List<GameUnitStatsNode>();
+				foreach (TimelineNode tn in gu) {
+					GameUnitStatsNode node = new GameUnitStatsNode(tn);
+					nextParents.Add(node);
+					FindParent(node, parents);
+				}
+				gameUnitNodes.Add(gu, new GameUnitStatsNode(game, nextParents));
+				parents = nextParents;
+			}
+		}
+		
+		void FindParent (GameUnitStatsNode node, List<GameUnitStatsNode> parents) {
+			List <GameUnitStatsNode> candidates = parents.Where(p => Contained(node.Node, p.Node)).ToList();
+			if (candidates.Count != 1) {
+				Log.Warning(String.Format("Found {0} candidates for node {1}", candidates.Count, node));
+			}
+				
+			foreach (GameUnitStatsNode parent in candidates)
+				parent.Add(node);
+		}
+			
+		bool Contained (TimelineNode node, TimelineNode parent) {
+			if (node.Start > parent.Start && node.Stop < parent.Stop) {
+				return true;
+			} else if (node.Start > parent.Start && node.Stop > parent.Stop) {
+				return (node.Stop - parent.Stop) < node.Duration * MAX_DIFF;
+			} else if (node.Start < parent.Start && node.Stop < parent.Stop) {
+				return (parent.Start - node.Start) < node.Duration * MAX_DIFF;
+			} else {
+				return false;
+			}
+		}
+	}
+}
+
diff --git a/LongoMatch.Core/Stats/ProjectStats.cs b/LongoMatch.Core/Stats/ProjectStats.cs
index ef4d469..039378e 100644
--- a/LongoMatch.Core/Stats/ProjectStats.cs
+++ b/LongoMatch.Core/Stats/ProjectStats.cs
@@ -29,11 +29,11 @@ namespace LongoMatch.Stats
 	public class ProjectStats
 	{
 		List<CategoryStats> catStats;
+		GameUnitsStats guStats;
 		
 		public ProjectStats (Project project)
 		{
-			catStats = new List<CategoryStats>(); 
-			
+			catStats = new List<CategoryStats>();
 			
 			ProjectName = project.Description.Title;
 			Date = project.Description.MatchDate;
@@ -43,6 +43,7 @@ namespace LongoMatch.Stats
 			Season = project.Description.Season;
 			Results = String.Format("{0}-{1}", project.Description.LocalGoals, project.Description.VisitorGoals);
 			UpdateStats (project);
+			UpdateGameUnitsStats (project);
 		}
 		
 		public string ProjectName {
@@ -75,17 +76,32 @@ namespace LongoMatch.Stats
 			set;
 		}
 		
+		public string Results {
+			get;
+			set;
+		}
+		
 		public List<CategoryStats> CategoriesStats {
 			get {
 				return catStats;
 			}
 		}
 		
+		public GameUnitsStats GameUnitsStats {
+			get {
+				return guStats;
+			}
+		}
+		
 		void CountPlaysInTeam (List<Play> plays, out int localTeamCount, out int visitorTeamCount) {
 			localTeamCount = plays.Where(p => p.Team == Team.LOCAL || p.Team == Team.BOTH).Count();
 			visitorTeamCount = plays.Where(p => p.Team == Team.VISITOR || p.Team == Team.BOTH).Count();
 		}
 		
+		void UpdateGameUnitsStats (Project project) {
+			guStats = new GameUnitsStats(project.GameUnits, (int)project.Description.File.Length);
+		}
+		
 		void UpdateStats (Project project) {
 			catStats.Clear();
 			



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]