diff --git a/VECTOAux/BusAuxiliaries/DownstreamModules/Impl/AlternatorMap.cs b/VECTOAux/BusAuxiliaries/DownstreamModules/Impl/AlternatorMap.cs
new file mode 100644
index 0000000000000000000000000000000000000000..2909cd614a71debc40151dee8e69fce754bb2916
--- /dev/null
+++ b/VECTOAux/BusAuxiliaries/DownstreamModules/Impl/AlternatorMap.cs
@@ -0,0 +1,446 @@
+// Copyright 2017 European Union.
+// Licensed under the EUPL (the 'Licence');
+// 
+// * You may not use this work except in compliance with the Licence.
+// * You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl
+// * Unless required by applicable law or agreed to in writing,
+// software distributed under the Licence is distributed on an "AS IS" basis,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// 
+// See the LICENSE.txt for the specific language governing permissions and limitations.
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Security;
+using System.Text;
+using System.Threading.Tasks;
+using Microsoft.VisualBasic;
+using DownstreamModules.Electrics;
+using TUGraz.VectoCommon.Utils;
+using TUGraz.VectoCore.BusAuxiliaries.Interfaces;
+using TUGraz.VectoCore.BusAuxiliaries.Interfaces.DownstreamModules.Electrics;
+
+namespace Electrics
+{
+	public class AlternatorMap : IAlternatorMap
+	{
+		private readonly string filePath;
+
+		private List<MapPoint> _map = new List<MapPoint>();
+		private List<double> _yRange;
+		private List<double> _xRange;
+		private double _minX, _minY, _maxX, _maxY;
+
+		// Required Action Test or Interpolation Type
+		public bool OnBoundaryYInterpolatedX(double x, double y)
+		{
+			return _yRange.Contains(y) && !_xRange.Contains(x);
+		}
+
+		public bool OnBoundaryXInterpolatedY(double x, double y)
+		{
+			return !_yRange.Contains(y) && _xRange.Contains(x);
+		}
+
+		public bool ONBoundaryXY(double x, double y)
+		{
+			return (from sector in _map
+					where sector.Y == y && sector.x == x
+					select sector).Count() == 1;
+		}
+
+		// Determine Value Methods
+		private double GetOnBoundaryXY(double x, double y)
+		{
+			return (from sector in _map
+					where sector.Y == y && sector.x == x
+					select sector).First().v;
+		}
+
+		private double GetOnBoundaryYInterpolatedX(double x, double y)
+		{
+			double x0, x1, v0, v1, slope, dx;
+
+			x0 = (from p in _xRange
+				  orderby p
+				  where p < x
+				  select p).Last();
+			x1 = (from p in _xRange
+				  orderby p
+				  where p > x
+				  select p).First();
+			dx = x1 - x0;
+
+			v0 = GetOnBoundaryXY(x0, y);
+			v1 = GetOnBoundaryXY(x1, y);
+
+			slope = (v1 - v0) / (x1 - x0);
+
+			return v0 + ((x - x0) * slope);
+		}
+
+		private double GetOnBoundaryXInterpolatedY(double x, double y)
+		{
+			double y0, y1, v0, v1, dy, v, slope;
+
+			y0 = (from p in _yRange
+				  orderby p
+				  where p < y
+				  select p).Last();
+			y1 = (from p in _yRange
+				  orderby p
+				  where p > y
+				  select p).First();
+			dy = y1 - y0;
+
+			v0 = GetOnBoundaryXY(x, y0);
+			v1 = GetOnBoundaryXY(x, y1);
+
+			slope = (v1 - v0) / (y1 - y0);
+
+			v = v0 + ((y - y0) * slope);
+
+			return v;
+		}
+
+		private double GetBiLinearInterpolatedValue(double x, double y)
+		{
+			double q11, q12, q21, q22, x1, x2, y1, y2, r1, r2, p;
+
+			y1 = (from mapSector in _map
+				  where mapSector.Y < y
+				  select mapSector).Last().Y;
+			y2 = (from mapSector in _map
+				  where mapSector.Y > y
+				  select mapSector).First().Y;
+
+			x1 = (from mapSector in _map
+				  where mapSector.x < x
+				  select mapSector).Last().x;
+			x2 = (from mapSector in _map
+				  where mapSector.x > x
+				  select mapSector).First().x;
+
+			q11 = GetOnBoundaryXY(x1, y1);
+			q12 = GetOnBoundaryXY(x1, y2);
+
+			q21 = GetOnBoundaryXY(x2, y1);
+			q22 = GetOnBoundaryXY(x2, y2);
+
+			r1 = ((x2 - x) / (x2 - x1)) * q11 + ((x - x1) / (x2 - x1)) * q21;
+
+			r2 = ((x2 - x) / (x2 - x1)) * q12 + ((x - x1) / (x2 - x1)) * q22;
+
+
+			p = ((y2 - y) / (y2 - y1)) * r1 + ((y - y1) / (y2 - y1)) * r2;
+
+
+			return p;
+		}
+
+		// Utilities
+		private void fillMapWithDefaults()
+		{
+			_map.Add(new MapPoint(10, 1500, 0.615));
+			_map.Add(new MapPoint(27, 1500, 0.7));
+			_map.Add(new MapPoint(53, 1500, 0.1947));
+			_map.Add(new MapPoint(63, 1500, 0.0));
+			_map.Add(new MapPoint(68, 1500, 0.0));
+			_map.Add(new MapPoint(125, 1500, 0.0));
+			_map.Add(new MapPoint(136, 1500, 0.0));
+			_map.Add(new MapPoint(10, 2000, 0.62));
+			_map.Add(new MapPoint(27, 2000, 0.7));
+			_map.Add(new MapPoint(53, 2000, 0.3));
+			_map.Add(new MapPoint(63, 2000, 0.1462));
+			_map.Add(new MapPoint(68, 2000, 0.692));
+			_map.Add(new MapPoint(125, 2000, 0.0));
+			_map.Add(new MapPoint(136, 2000, 0.0));
+			_map.Add(new MapPoint(10, 4000, 0.64));
+			_map.Add(new MapPoint(27, 4000, 0.6721));
+			_map.Add(new MapPoint(53, 4000, 0.7211));
+			_map.Add(new MapPoint(63, 4000, 0.74));
+			_map.Add(new MapPoint(68, 4000, 0.7352));
+			_map.Add(new MapPoint(125, 4000, 0.68));
+			_map.Add(new MapPoint(136, 4000, 0.6694));
+			_map.Add(new MapPoint(10, 6000, 0.53));
+			_map.Add(new MapPoint(27, 6000, 0.5798));
+			_map.Add(new MapPoint(53, 6000, 0.656));
+			_map.Add(new MapPoint(63, 6000, 0.6853));
+			_map.Add(new MapPoint(68, 6000, 0.7));
+			_map.Add(new MapPoint(125, 6000, 0.6329));
+			_map.Add(new MapPoint(136, 6000, 0.62));
+			_map.Add(new MapPoint(10, 7000, 0.475));
+			_map.Add(new MapPoint(27, 7000, 0.5337));
+			_map.Add(new MapPoint(53, 7000, 0.6235));
+			_map.Add(new MapPoint(63, 7000, 0.658));
+			_map.Add(new MapPoint(68, 7000, 0.6824));
+			_map.Add(new MapPoint(125, 7000, 0.6094));
+			_map.Add(new MapPoint(136, 7000, 0.5953));
+		}
+
+		private void getMapRanges()
+		{
+			;/* Cannot convert AssignmentStatementSyntax, System.NotImplementedException: Conversion for query clause with kind 'DistinctClause' not implemented
+   at ICSharpCode.CodeConverter.CSharp.VisualBasicConverter.NodesVisitor.<>c__DisplayClass99_0.<ConvertQueryBodyClause>b__0(QueryClauseSyntax _)
+   at ICSharpCode.CodeConverter.Util.ObjectExtensions.TypeSwitch[TBaseType,TDerivedType1,TDerivedType2,TDerivedType3,TDerivedType4,TResult](TBaseType obj, Func`2 matchFunc1, Func`2 matchFunc2, Func`2 matchFunc3, Func`2 matchFunc4, Func`2 defaultFunc)
+   at ICSharpCode.CodeConverter.CSharp.VisualBasicConverter.NodesVisitor.ConvertQueryBodyClause(QueryClauseSyntax node)
+   at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
+   at Microsoft.CodeAnalysis.SyntaxList`1.CreateNode(IEnumerable`1 nodes)
+   at ICSharpCode.CodeConverter.CSharp.VisualBasicConverter.NodesVisitor.VisitQueryExpression(QueryExpressionSyntax node)
+   at Microsoft.CodeAnalysis.VisualBasic.Syntax.QueryExpressionSyntax.Accept[TResult](VisualBasicSyntaxVisitor`1 visitor)
+   at Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxVisitor`1.Visit(SyntaxNode node)
+   at ICSharpCode.CodeConverter.CSharp.CommentConvertingNodesVisitor.DefaultVisit(SyntaxNode node)
+   at Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxVisitor`1.VisitQueryExpression(QueryExpressionSyntax node)
+   at Microsoft.CodeAnalysis.VisualBasic.Syntax.QueryExpressionSyntax.Accept[TResult](VisualBasicSyntaxVisitor`1 visitor)
+   at ICSharpCode.CodeConverter.CSharp.VisualBasicConverter.NodesVisitor.VisitParenthesizedExpression(ParenthesizedExpressionSyntax node)
+   at Microsoft.CodeAnalysis.VisualBasic.Syntax.ParenthesizedExpressionSyntax.Accept[TResult](VisualBasicSyntaxVisitor`1 visitor)
+   at Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxVisitor`1.Visit(SyntaxNode node)
+   at ICSharpCode.CodeConverter.CSharp.CommentConvertingNodesVisitor.DefaultVisit(SyntaxNode node)
+   at Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxVisitor`1.VisitParenthesizedExpression(ParenthesizedExpressionSyntax node)
+   at Microsoft.CodeAnalysis.VisualBasic.Syntax.ParenthesizedExpressionSyntax.Accept[TResult](VisualBasicSyntaxVisitor`1 visitor)
+   at ICSharpCode.CodeConverter.CSharp.VisualBasicConverter.NodesVisitor.VisitMemberAccessExpression(MemberAccessExpressionSyntax node)
+   at Microsoft.CodeAnalysis.VisualBasic.Syntax.MemberAccessExpressionSyntax.Accept[TResult](VisualBasicSyntaxVisitor`1 visitor)
+   at Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxVisitor`1.Visit(SyntaxNode node)
+   at ICSharpCode.CodeConverter.CSharp.CommentConvertingNodesVisitor.DefaultVisit(SyntaxNode node)
+   at Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxVisitor`1.VisitMemberAccessExpression(MemberAccessExpressionSyntax node)
+   at Microsoft.CodeAnalysis.VisualBasic.Syntax.MemberAccessExpressionSyntax.Accept[TResult](VisualBasicSyntaxVisitor`1 visitor)
+   at ICSharpCode.CodeConverter.CSharp.VisualBasicConverter.NodesVisitor.VisitInvocationExpression(InvocationExpressionSyntax node)
+   at Microsoft.CodeAnalysis.VisualBasic.Syntax.InvocationExpressionSyntax.Accept[TResult](VisualBasicSyntaxVisitor`1 visitor)
+   at Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxVisitor`1.Visit(SyntaxNode node)
+   at ICSharpCode.CodeConverter.CSharp.CommentConvertingNodesVisitor.DefaultVisit(SyntaxNode node)
+   at Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxVisitor`1.VisitInvocationExpression(InvocationExpressionSyntax node)
+   at Microsoft.CodeAnalysis.VisualBasic.Syntax.InvocationExpressionSyntax.Accept[TResult](VisualBasicSyntaxVisitor`1 visitor)
+   at ICSharpCode.CodeConverter.CSharp.VisualBasicConverter.MethodBodyVisitor.VisitAssignmentStatement(AssignmentStatementSyntax node)
+   at Microsoft.CodeAnalysis.VisualBasic.Syntax.AssignmentStatementSyntax.Accept[TResult](VisualBasicSyntaxVisitor`1 visitor)
+   at Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxVisitor`1.Visit(SyntaxNode node)
+   at ICSharpCode.CodeConverter.CSharp.CommentConvertingMethodBodyVisitor.ConvertWithTrivia(SyntaxNode node)
+   at ICSharpCode.CodeConverter.CSharp.CommentConvertingMethodBodyVisitor.DefaultVisit(SyntaxNode node)
+
+Input: 
+
+			_yRange = (From coords As MapPoint In _map Order By coords.Y Select coords.Y Distinct).ToList()
+
+ */
+			;/* Cannot convert AssignmentStatementSyntax, System.NotImplementedException: Conversion for query clause with kind 'DistinctClause' not implemented
+   at ICSharpCode.CodeConverter.CSharp.VisualBasicConverter.NodesVisitor.<>c__DisplayClass99_0.<ConvertQueryBodyClause>b__0(QueryClauseSyntax _)
+   at ICSharpCode.CodeConverter.Util.ObjectExtensions.TypeSwitch[TBaseType,TDerivedType1,TDerivedType2,TDerivedType3,TDerivedType4,TResult](TBaseType obj, Func`2 matchFunc1, Func`2 matchFunc2, Func`2 matchFunc3, Func`2 matchFunc4, Func`2 defaultFunc)
+   at ICSharpCode.CodeConverter.CSharp.VisualBasicConverter.NodesVisitor.ConvertQueryBodyClause(QueryClauseSyntax node)
+   at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
+   at Microsoft.CodeAnalysis.SyntaxList`1.CreateNode(IEnumerable`1 nodes)
+   at ICSharpCode.CodeConverter.CSharp.VisualBasicConverter.NodesVisitor.VisitQueryExpression(QueryExpressionSyntax node)
+   at Microsoft.CodeAnalysis.VisualBasic.Syntax.QueryExpressionSyntax.Accept[TResult](VisualBasicSyntaxVisitor`1 visitor)
+   at Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxVisitor`1.Visit(SyntaxNode node)
+   at ICSharpCode.CodeConverter.CSharp.CommentConvertingNodesVisitor.DefaultVisit(SyntaxNode node)
+   at Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxVisitor`1.VisitQueryExpression(QueryExpressionSyntax node)
+   at Microsoft.CodeAnalysis.VisualBasic.Syntax.QueryExpressionSyntax.Accept[TResult](VisualBasicSyntaxVisitor`1 visitor)
+   at ICSharpCode.CodeConverter.CSharp.VisualBasicConverter.NodesVisitor.VisitParenthesizedExpression(ParenthesizedExpressionSyntax node)
+   at Microsoft.CodeAnalysis.VisualBasic.Syntax.ParenthesizedExpressionSyntax.Accept[TResult](VisualBasicSyntaxVisitor`1 visitor)
+   at Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxVisitor`1.Visit(SyntaxNode node)
+   at ICSharpCode.CodeConverter.CSharp.CommentConvertingNodesVisitor.DefaultVisit(SyntaxNode node)
+   at Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxVisitor`1.VisitParenthesizedExpression(ParenthesizedExpressionSyntax node)
+   at Microsoft.CodeAnalysis.VisualBasic.Syntax.ParenthesizedExpressionSyntax.Accept[TResult](VisualBasicSyntaxVisitor`1 visitor)
+   at ICSharpCode.CodeConverter.CSharp.VisualBasicConverter.NodesVisitor.VisitMemberAccessExpression(MemberAccessExpressionSyntax node)
+   at Microsoft.CodeAnalysis.VisualBasic.Syntax.MemberAccessExpressionSyntax.Accept[TResult](VisualBasicSyntaxVisitor`1 visitor)
+   at Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxVisitor`1.Visit(SyntaxNode node)
+   at ICSharpCode.CodeConverter.CSharp.CommentConvertingNodesVisitor.DefaultVisit(SyntaxNode node)
+   at Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxVisitor`1.VisitMemberAccessExpression(MemberAccessExpressionSyntax node)
+   at Microsoft.CodeAnalysis.VisualBasic.Syntax.MemberAccessExpressionSyntax.Accept[TResult](VisualBasicSyntaxVisitor`1 visitor)
+   at ICSharpCode.CodeConverter.CSharp.VisualBasicConverter.NodesVisitor.VisitInvocationExpression(InvocationExpressionSyntax node)
+   at Microsoft.CodeAnalysis.VisualBasic.Syntax.InvocationExpressionSyntax.Accept[TResult](VisualBasicSyntaxVisitor`1 visitor)
+   at Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxVisitor`1.Visit(SyntaxNode node)
+   at ICSharpCode.CodeConverter.CSharp.CommentConvertingNodesVisitor.DefaultVisit(SyntaxNode node)
+   at Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxVisitor`1.VisitInvocationExpression(InvocationExpressionSyntax node)
+   at Microsoft.CodeAnalysis.VisualBasic.Syntax.InvocationExpressionSyntax.Accept[TResult](VisualBasicSyntaxVisitor`1 visitor)
+   at ICSharpCode.CodeConverter.CSharp.VisualBasicConverter.MethodBodyVisitor.VisitAssignmentStatement(AssignmentStatementSyntax node)
+   at Microsoft.CodeAnalysis.VisualBasic.Syntax.AssignmentStatementSyntax.Accept[TResult](VisualBasicSyntaxVisitor`1 visitor)
+   at Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxVisitor`1.Visit(SyntaxNode node)
+   at ICSharpCode.CodeConverter.CSharp.CommentConvertingMethodBodyVisitor.ConvertWithTrivia(SyntaxNode node)
+   at ICSharpCode.CodeConverter.CSharp.CommentConvertingMethodBodyVisitor.DefaultVisit(SyntaxNode node)
+
+Input: 
+			_xRange = (From coords As MapPoint In _map Order By coords.x Select coords.x Distinct).ToList()
+
+ */
+			_minX = _xRange.First();
+			_maxX = _xRange.Last();
+			_minY = _yRange.First();
+			_maxY = _yRange.Last();
+		}
+
+		// Single entry point to determine Value on map
+		public double GetValue(double x, double y)
+		{
+			if (x < _minX || x > _maxX || y < _minY || y > _maxY) {
+
+				// OnAuxiliaryEvent(String.Format("Alternator Map Limiting : RPM{0}, AMPS{1}",x,y),AdvancedAuxiliaryMessageType.Warning)
+
+
+				// Limiting
+				if (x < _minX)
+					x = _minX;
+				if (x > _maxX)
+					x = _maxX;
+				if (y < _minY)
+					y = _minY;
+				if (y > _maxY)
+					y = _maxY;
+			}
+
+
+			// Satisfies both data points - non interpolated value
+			if (ONBoundaryXY(x, y))
+				return GetOnBoundaryXY(x, y);
+
+			// Satisfies only x or y - single interpolation value
+			if (OnBoundaryXInterpolatedY(x, y))
+				return GetOnBoundaryXInterpolatedY(x, y);
+			if (OnBoundaryYInterpolatedX(x, y))
+				return GetOnBoundaryYInterpolatedX(x, y);
+
+			// satisfies no data points - Bi-Linear interpolation
+			return GetBiLinearInterpolatedValue(x, y);
+		}
+
+		public string ReturnDefaultMapValueTests()
+		{
+			var sb = new StringBuilder();
+
+			// All Sector Values
+			sb.AppendLine("All Values From Map");
+			sb.AppendLine("-------------------");
+			foreach (var xr in _xRange) {
+				foreach (var yr in _yRange)
+					sb.AppendLine(string.Format("X:{0}, Y:{1}, V:{2}", xr, yr, GetValue(xr, yr)));
+			}
+
+			sb.AppendLine("");
+			sb.AppendLine("Four Corners with interpolated other");
+			sb.AppendLine("-------------------");
+			var x = 1500.0;
+			var y = 18.5;
+			sb.AppendLine(string.Format("X:{0}, Y:{1}, V:{2}", x, y, GetValue(x, y)));
+			x = 7000;
+			y = 96.5;
+			sb.AppendLine(string.Format("X:{0}, Y:{1}, V:{2}", x, y, GetValue(x, y)));
+			x = 1750;
+			y = 10;
+			sb.AppendLine(string.Format("X:{0}, Y:{1}, V:{2}", x, y, GetValue(x, y)));
+			x = 6500;
+			y = 10;
+			sb.AppendLine(string.Format("X:{0}, Y:{1}, V:{2}", x, y, GetValue(x, y)));
+
+			sb.AppendLine("");
+			sb.AppendLine("Interpolated both");
+			sb.AppendLine("-------------------");
+
+			double mx, my;
+			int x2, y2;
+			for (x2 = 0; x2 <= _xRange.Count - 2; x2++) {
+				for (y2 = 0; y2 <= _yRange.Count - 2; y2++) {
+					mx = _xRange[x2] + (_xRange[x2 + 1] - _xRange[x2]) / 2;
+					my = _yRange[y2] + (_yRange[y2 + 1] - _yRange[y2]) / 2;
+
+					sb.AppendLine(string.Format("X:{0}, Y:{1}, V:{2}", mx, my, GetValue(mx, my)));
+				}
+			}
+
+			sb.AppendLine("");
+			sb.AppendLine("MIKE -> 40 & 1000");
+			sb.AppendLine("-------------------");
+			x = 1000;
+			y = 40;
+			sb.AppendLine(string.Format("X:{0}, Y:{1}, V:{2}", x, y, GetValue(x, y)));
+
+
+			return sb.ToString();
+		}
+
+		// Constructors
+		public AlternatorMap(string filepath)
+		{
+			this.filePath = filepath;
+
+			Initialise();
+
+			getMapRanges();
+		}
+
+		private class MapPoint
+		{
+			public double Y;
+			public double x;
+			public double v;
+
+			public MapPoint(double y, double x, double v)
+			{
+				this.Y = y;
+				this.x = x;
+				this.v = v;
+			}
+		}
+
+		// Get Alternator Efficiency
+		public AlternatorMapValues GetEfficiency(double rpm, Ampere amps)
+		{
+			return new AlternatorMapValues(GetValue(rpm, amps.Value()));
+		}
+
+		// Initialises the map.
+		public bool Initialise()
+		{
+			if (File.Exists(filePath)) {
+				using (StreamReader sr = new StreamReader(filePath)) {
+					// get array og lines fron csv
+					var lines = sr.ReadToEnd().Split(new [] {Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries);
+
+					// Must have at least 2 entries in map to make it usable [dont forget the header row]
+					if (lines.Count() < 3)
+						throw new ArgumentException("Insufficient rows in csv to build a usable map");
+
+					_map = new List<MapPoint>();
+					var firstline = true;
+
+					foreach (var line in lines) {
+						if (!firstline) {
+
+							// Advanced Alternator Source Check.
+							if (line.Contains("[MODELSOURCE"))
+								break;
+
+							// split the line
+							string[] elements = line.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
+							// 3 entries per line required
+							if ((elements.Length != 3))
+								throw new ArgumentException("Incorrect number of values in csv file");
+							// add values to map
+
+							// Create AlternatorKey
+							var newPoint = new MapPoint(float.Parse(elements[0], CultureInfo.InvariantCulture), float.Parse(elements[1], CultureInfo.InvariantCulture), float.Parse(elements[2], CultureInfo.InvariantCulture));
+							_map.Add(newPoint);
+						} 
+						firstline = false;
+					}
+				}
+				return true;
+			} 
+			throw new ArgumentException("Supplied input file does not exist");
+		}
+
+
+		// Public Events
+		public event AuxiliaryEventEventHandler AuxiliaryEvent;
+
+		//public delegate void AuxiliaryEventEventHandler(ref object sender, string message, AdvancedAuxiliaryMessageType messageType);
+
+		protected void OnAuxiliaryEvent(string message, AdvancedAuxiliaryMessageType messageType)
+		{
+			object alternatorMap = this;
+			AuxiliaryEvent?.Invoke(ref alternatorMap, message, messageType);
+		}
+	}
+}
diff --git a/VECTOAux/BusAuxiliaries/DownstreamModules/Impl/Electrics/Alternator.cs b/VECTOAux/BusAuxiliaries/DownstreamModules/Impl/Electrics/Alternator.cs
new file mode 100644
index 0000000000000000000000000000000000000000..0d563b0884250c51d95bfa84e6306d81df93ace5
--- /dev/null
+++ b/VECTOAux/BusAuxiliaries/DownstreamModules/Impl/Electrics/Alternator.cs
@@ -0,0 +1,329 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Security;
+using System.Text;
+using System.Threading.Tasks;
+using Microsoft.VisualBasic;
+using DownstreamModules.Electrics;
+
+namespace Electrics
+{
+	// Model based on CombinedALTS_V02_Editable.xlsx
+	public class Alternator : IAlternator
+	{
+		private ICombinedAlternatorSignals signals;
+
+		// D6
+		public string AlternatorName { get; set; }
+
+		// G6
+		public double PulleyRatio { get; set; }
+
+		// C10-D15
+		public List<AltUserInput> InputTable2000 { get; set; } = new List<AltUserInput>();
+
+		// F10-G15
+		public List<AltUserInput> InputTable4000 { get; set; } = new List<AltUserInput>();
+
+		// I10-J15
+		public List<AltUserInput> InputTable6000 { get; set; } = new List<AltUserInput>();
+
+		// M10-N15
+		public List<Table4Row> RangeTable { get; set; } = new List<Table4Row>();
+
+		// S9
+		public double SpindleSpeed
+		{
+			get { return signals.CrankRPM * PulleyRatio; }
+		}
+
+		// S10
+		public double Efficiency
+		{
+			get {
+				// First build RangeTable, table 4
+				InitialiseRangeTable();
+				CalculateRangeTable();
+
+				// Calculate ( Interpolate ) Efficiency
+				var range = RangeTable.Select(s => new AltUserInput(s.RPM, s.Efficiency)).ToList();
+
+				return Alternator.Iterpolate(range, Convert.ToSingle(SpindleSpeed));
+			}
+		}
+
+
+		// Constructors
+		public Alternator() { }
+
+		public Alternator(ICombinedAlternatorSignals isignals, List<ICombinedAlternatorMapRow> inputs)
+		{
+			if (isignals == null)
+				throw new ArgumentException("Alternator - ISignals supplied is nothing");
+
+			signals = isignals;
+
+			AlternatorName = inputs.First().AlternatorName;
+			PulleyRatio = inputs.First().PulleyRatio;
+
+			var values2k = inputs.Where(x => x.RPM == 2000)
+														.Select(x => new KeyValuePair<double, double>(x.Amps, x.Efficiency))
+														.ToDictionary(x => x.Key, x => x.Value);
+			var values4k = inputs.Where(x => x.RPM == 4000)
+														.Select(x => new KeyValuePair<double, double>(x.Amps, x.Efficiency))
+														.ToDictionary(x => x.Key, x => x.Value);
+			var values6k = inputs.Where(x => x.RPM == 6000)
+														.Select(x => new KeyValuePair<double, double>(x.Amps, x.Efficiency))
+														.ToDictionary(x => x.Key, x => x.Value);
+
+			BuildInputTable(values2k, InputTable2000);
+			BuildInputTable(values4k, InputTable4000);
+			BuildInputTable(values6k, InputTable6000);
+
+			CreateRangeTable();
+		}
+
+		public static double Iterpolate(List<AltUserInput> values, double x)
+		{
+			var lowestX = values.Min(m => m.Amps);
+			var highestX = values.Max(m => m.Amps);
+
+			// Out of range, returns efficiency for lowest
+			if (x < lowestX)
+				return values.First(f => f.Amps == lowestX).Eff;
+
+			// Out of range, efficiency for highest
+			if (x > highestX)
+				return values.First(f => f.Amps == highestX).Eff;
+
+			// On Bounds check
+			if (values.Where(w => w.Amps == x).Count() == 1)
+				return values.First(w => w.Amps == x).Eff;
+
+			// OK, we need to interpolate.
+			var preKey = values.Last(l => l.Amps < x).Amps;
+			var postKey = values.First(l => l.Amps > x).Amps;
+			var preEff = values.First(f => f.Amps == preKey).Eff;
+			var postEff = values.First(f => f.Amps == postKey).Eff;
+
+			var deltaX = postKey - preKey;
+			var deltaEff = postEff - preEff;
+
+			// slopes
+			var effSlope = deltaEff / deltaX;
+
+			var retVal = ((x - preKey) * effSlope) + preEff;
+
+			return retVal;
+		}
+
+		private void CalculateRangeTable()
+		{
+			// M10=Row0-Rpm - N10=Row0-Eff
+			// M11=Row1-Rpm - N11=Row1-Eff
+			// M12=Row2-Rpm - N12=Row2-Eff - 2000
+			// M13=Row3-Rpm - N13=Row3-Eff - 4000
+			// M14=Row4-Rpm - N14=Row4-Eff - 6000
+			// M15=Row5-Rpm - N15=Row5-Eff
+			// M16=Row6-Rpm - N16=Row6-Eff
+
+			double N10, N11, N12, N13, N14, N15, N16;
+			double M10, M11, M12, M13, M14, M15, M16;
+
+			// EFFICIENCY
+
+			// 2000
+			N12 = Alternator.Iterpolate(InputTable2000, signals.CurrentDemandAmps.Value());
+			RangeTable[2].Efficiency = N12;
+
+			// 4000
+			N13 = Alternator.Iterpolate(InputTable4000, signals.CurrentDemandAmps.Value());
+			RangeTable[3].Efficiency = N13;
+
+			// 6000
+			N14 = Alternator.Iterpolate(InputTable6000, signals.CurrentDemandAmps.Value());
+			RangeTable[4].Efficiency = N14;
+
+			// Row0 & Row1 Efficiency  =IF(N13>N12,0,MAX(N12:N14)) - Example Alt 1 N13=
+			N11 = N13 > N12 ? 0 : Math.Max(Math.Max(N12, N13), N14);
+			RangeTable[1].Efficiency = N11;
+			N10 = N11;
+			RangeTable[0].Efficiency = N10;
+
+			// Row 5 Efficiency
+			N15 = N13 > N14 ? 0 : Math.Max(Math.Max(N12, N13), N14);
+			RangeTable[5].Efficiency = N15;
+
+			// Row 6 - Efficiency
+			N16 = N15;
+			RangeTable[6].Efficiency = N16;
+
+			// RPM
+
+			// 2000 Row 2 - RPM
+			M12 = 2000;
+			RangeTable[2].RPM = M12;
+
+			// 4000 Row 3 - RPM
+			M13 = 4000;
+			RangeTable[3].RPM = M13;
+
+			// 6000 Row 4 - RPM
+			M14 = 6000;
+			RangeTable[4].RPM = M14;
+
+			// Row 1 - RPM
+			// NOTE: Update to reflect CombineALternatorSchematicV02 20150429
+			// IF(M12=IF(N12>N13,M12-((M12-M13)/(N12-N13))*(N12-N11),M12-((M12-M13)/(N12-N13))*(N12-N11)), M12-0.01, IF(N12>N13,M12-((M12-M13)/(N12-N13))*(N12-N11),M12-((M12-M13)/(N12-N13))*(N12-N11)))
+			M11 =
+				Convert.ToSingle(
+					N12 - N13 == 0
+						? 0
+						: (
+							M12 == (N12 > N13
+								? M12 - (M12 - M13) / (N12 - N13) * (N12 - N11)
+								: M12 - (M12 - M13) / (N12 - N13) * (N12 - N11))
+								? M12 - 0.01
+								: (N12 > N13
+									? M12 - (M12 - M13) / (N12 - N13) * (N12 - N11)
+									: M12 - (M12 - M13) / (N12 - N13) * (N12 - N11))));
+
+			RangeTable[1].RPM = M11;
+
+			// Row 0 - RPM
+			M10 = M11 < 1500 ? M11 - 1 : 1500;
+			RangeTable[0].RPM = M10;
+
+			// Row 5 - RPM
+			M15 =
+				Convert.ToSingle(
+					M14 == (N14 == 0 || N14 == N13
+						? M14 + 1
+						: (N13 > N14 ? (M14 - M13) / (N13 - N14) * N14 + M14 : (M14 - M13) / (N13 - N14) * (N14 - N15) + M14)
+					)
+						? M14 + 0.01
+						: (N14 == 0 || N14 == N13
+							? M14 + 1
+							: (N13 > N14 ? (M14 - M13) / (N13 - N14) * N14 + M14 : (M14 - M13) / (N13 - N14) * (N14 - N15) + M14)));
+
+			RangeTable[5].RPM = M15;
+
+			// Row 6 - RPM
+			M16 = M15 > 10000 ? M15 + 1 : 10000;
+			RangeTable[6].RPM = M16;
+		}
+
+		private void InitialiseRangeTable()
+		{
+			RangeTable[0].RPM = 0;
+			RangeTable[0].Efficiency = 0;
+			RangeTable[1].RPM = 0;
+			RangeTable[0].Efficiency = 0;
+			RangeTable[2].RPM = 2000;
+			RangeTable[0].Efficiency = 0;
+			RangeTable[3].RPM = 4000;
+			RangeTable[0].Efficiency = 0;
+			RangeTable[4].RPM = 6000;
+			RangeTable[0].Efficiency = 0;
+			RangeTable[5].RPM = 0;
+			RangeTable[0].Efficiency = 0;
+			RangeTable[6].RPM = 0;
+			RangeTable[0].Efficiency = 0;
+		}
+
+		private void CreateRangeTable()
+		{
+			RangeTable.Clear();
+
+			RangeTable.Add(new Table4Row(0, 0));
+			RangeTable.Add(new Table4Row(0, 0));
+			RangeTable.Add(new Table4Row(0, 0));
+			RangeTable.Add(new Table4Row(0, 0));
+			RangeTable.Add(new Table4Row(0, 0));
+			RangeTable.Add(new Table4Row(0, 0));
+			RangeTable.Add(new Table4Row(0, 0));
+		}
+
+		public void BuildInputTable(Dictionary<double, double> inputs, List<AltUserInput> targetTable)
+		{
+			double C11, C12, C13, C14, C15, D11, D12, D13, D14, D15;
+			targetTable.Clear();
+
+			// Row0
+			D14 = 0;
+			targetTable.Add(new AltUserInput(0, D14));
+
+			// Row1
+			targetTable.Add(new AltUserInput(inputs.OrderBy(x => x.Key).First().Key, inputs.OrderBy(x => x.Key).First().Value));
+
+			// Row2
+			targetTable.Add(
+				new AltUserInput(inputs.OrderBy(x => x.Key).Skip(1).First().Key, inputs.OrderBy(x => x.Key).Skip(1).First().Value));
+
+			// Row3
+			targetTable.Add(
+				new AltUserInput(inputs.OrderBy(x => x.Key).Skip(2).First().Key, inputs.OrderBy(x => x.Key).Skip(2).First().Value));
+
+			C11 = targetTable[1].Amps;
+			C12 = targetTable[2].Amps;
+			C13 = targetTable[3].Amps;
+
+			D11 = targetTable[1].Eff;
+			D12 = targetTable[2].Eff;
+			D13 = targetTable[3].Eff;
+
+			D14 = D12 > D13 ? 0 : Math.Max(Math.Max(D11, D12), D13);
+
+			// Row4  - Eff
+			targetTable.Add(new AltUserInput(0, D14));
+
+			// Row4  - Amps
+			// Should probably refactor this into some sort of helper/extension method
+			var numarray = new[] { D11, D12, D13 };
+			var maxD11_D13 = numarray.Max();
+
+			// =IF(OR(D13=0,D13=D12),C13+1,IF(D12>D13,((((C13-C12)/(D12-D13))*D13)+C13),((((C13-C12)/(D12-D13))*(D13-D14))+C13)))
+			C14 = (D13 == 0 || D13 == D12 || D13 == maxD11_D13)
+				? C13 + 1
+				: D12 > D13
+					? ((((C13 - C12) / (D12 - D13)) * D13) + C13)
+					: ((((C13 - C12) / (D12 - D13)) * (D13 - D14)) + C13);
+			targetTable[4].Amps = C14;
+
+			// Row5 
+			C15 = C14 > 200 ? C14 + 1 : 200;
+			D15 = D14;
+			targetTable.Add(new AltUserInput(C15, D15));
+
+			// Row0
+			targetTable[0].Eff = D11;
+		}
+
+		public bool IsEqualTo(IAlternator other)
+		{
+			if (AlternatorName != other.AlternatorName) {
+				return false;
+			}
+			if (PulleyRatio != other.PulleyRatio) {
+				return false;
+			}
+
+			for (var i = 1; i <= 3; i++) {
+				if (InputTable2000[i].Eff != other.InputTable2000[i].Eff)
+					return false;
+				if (InputTable4000[i].Eff != other.InputTable4000[i].Eff)
+					return false;
+				if (InputTable6000[i].Eff != other.InputTable6000[i].Eff)
+					return false;
+			}
+
+			return true;
+		}
+	}
+}
diff --git a/VECTOAux/BusAuxiliaries/DownstreamModules/Impl/Electrics/CombinedAlternator.cs b/VECTOAux/BusAuxiliaries/DownstreamModules/Impl/Electrics/CombinedAlternator.cs
new file mode 100644
index 0000000000000000000000000000000000000000..de15bb33d8be780b1e0abd559df6abafc0bb5fb4
--- /dev/null
+++ b/VECTOAux/BusAuxiliaries/DownstreamModules/Impl/Electrics/CombinedAlternator.cs
@@ -0,0 +1,401 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Security;
+using System.Text;
+using System.Threading.Tasks;
+using Microsoft.VisualBasic;
+using DownstreamModules.Electrics;
+using TUGraz.VectoCommon.Utils;
+using TUGraz.VectoCore.BusAuxiliaries.Interfaces;
+using TUGraz.VectoCore.BusAuxiliaries.Interfaces.DownstreamModules.Electrics;
+
+
+namespace Electrics
+{
+	public class CombinedAlternator : IAlternatorMap, ICombinedAlternator
+	{
+		private List<ICombinedAlternatorMapRow> map = new List<ICombinedAlternatorMapRow>();
+		public List<IAlternator> Alternators { get; set; } = new List<IAlternator>();
+		private List<IAlternator> OriginalAlternators = new List<IAlternator>();
+		private string FilePath;
+		private ICombinedAlternatorSignals altSignals;
+		private ISignals Signals;
+		private AlternatorMapValues AverageAlternatorsEfficiency;
+
+		// Interface Implementation
+		public AlternatorMapValues GetEfficiency(double CrankRPM, Ampere Amps)
+		{
+			altSignals.CrankRPM = CrankRPM;
+			altSignals.CurrentDemandAmps = (Amps.Value() / (double)Alternators.Count).SI<Ampere>();
+
+			AlternatorMapValues alternatorMapValues; /* TODO Change to default(_) if this is not a reference type */;
+
+			if (Signals == null || Signals.RunningCalc)
+				// If running calc cycle get efficiency from interpolation function
+				alternatorMapValues = new AlternatorMapValues(Convert.ToSingle(Alternators.Average(a => a.Efficiency) / (double)100));
+			else
+				// If running Pre calc cycle get an average of inputs
+				alternatorMapValues = AverageAlternatorsEfficiency;
+
+			if (alternatorMapValues.Efficiency <= 0)
+				alternatorMapValues = new AlternatorMapValues(0.01);
+
+			return alternatorMapValues;
+		}
+
+		public bool Initialise()
+		{
+
+			// From the map we construct this CombinedAlternator object and original CombinedAlternator Object
+
+			Alternators.Clear();
+			OriginalAlternators.Clear();
+
+
+			foreach (var alt in map.GroupBy(g => g.AlternatorName)) {
+				var altName = alt.First().AlternatorName;
+				var pulleyRatio = alt.First().PulleyRatio;
+
+
+				IAlternator alternator = new Alternator(altSignals, alt.ToList());
+
+				Alternators.Add(alternator);
+			}
+
+			return true;
+		}
+
+		// Constructors
+		public CombinedAlternator(string filePath, ISignals signals = null/* TODO Change to default(_) if this is not a reference type */)
+		{
+			string feedback = string.Empty;
+			this.Signals = signals;
+
+			if (!FilePathUtils.ValidateFilePath(filePath, ".aalt", ref feedback))
+				throw new ArgumentException(string.Format("Combined Alternator requires a valid .AALT filename. : {0}", feedback));
+			else
+				this.FilePath = filePath;
+
+
+			this.altSignals = new CombinedAlternatorSignals();
+
+
+			// IF file exists then read it otherwise create a default.
+
+			if (File.Exists(filePath) && InitialiseMap(filePath))
+				Initialise();
+			else {
+				// Create Default Map
+				CreateDefaultMap();
+				Initialise();
+			}
+
+			// Calculate alternators average which is used only in the pre-run
+			var efficiencySum = 0.0;
+			
+			foreach (IAlternator alt in Alternators) {
+				efficiencySum += alt.InputTable2000.ElementAt(1).Eff;
+				efficiencySum += alt.InputTable2000.ElementAt(2).Eff;
+				efficiencySum += alt.InputTable2000.ElementAt(3).Eff;
+
+				efficiencySum += alt.InputTable4000.ElementAt(1).Eff;
+				efficiencySum += alt.InputTable4000.ElementAt(2).Eff;
+				efficiencySum += alt.InputTable4000.ElementAt(3).Eff;
+
+				efficiencySum += alt.InputTable6000.ElementAt(1).Eff;
+				efficiencySum += alt.InputTable6000.ElementAt(2).Eff;
+				efficiencySum += alt.InputTable6000.ElementAt(3).Eff;
+			}
+
+			var efficiencyAverage = efficiencySum / (Alternators.Count * 9);
+			AverageAlternatorsEfficiency = new AlternatorMapValues(efficiencyAverage / 100);
+		}
+
+		event TUGraz.VectoCore.BusAuxiliaries.Interfaces.AuxiliaryEventEventHandler IAuxiliaryEvent.AuxiliaryEvent
+		{
+			add {
+				throw new NotImplementedException();
+			}
+
+			remove {
+				throw new NotImplementedException();
+			}
+		}
+
+		// Helpers
+		private void CreateDefaultMap()
+		{
+			map.Clear();
+
+			map.Add(new CombinedAlternatorMapRow("Alt1", 2000, 10, 62, 3.6));
+			map.Add(new CombinedAlternatorMapRow("Alt1", 2000, 27, 70, 3.6));
+			map.Add(new CombinedAlternatorMapRow("Alt1", 2000, 53, 30, 3.6));
+
+			map.Add(new CombinedAlternatorMapRow("Alt1", 4000, 10, 64, 3.6));
+			map.Add(new CombinedAlternatorMapRow("Alt1", 4000, 63, 74, 3.6));
+			map.Add(new CombinedAlternatorMapRow("Alt1", 4000, 125, 68, 3.6));
+
+			map.Add(new CombinedAlternatorMapRow("Alt1", 6000, 10, 53, 3.6));
+			map.Add(new CombinedAlternatorMapRow("Alt1", 6000, 68, 70, 3.6));
+			map.Add(new CombinedAlternatorMapRow("Alt1", 6000, 136, 62, 3.6));
+
+			map.Add(new CombinedAlternatorMapRow("Alt2", 2000, 10, 62, 3));
+			map.Add(new CombinedAlternatorMapRow("Alt2", 2000, 27, 70, 3));
+			map.Add(new CombinedAlternatorMapRow("Alt2", 2000, 53, 30, 3));
+
+			map.Add(new CombinedAlternatorMapRow("Alt2", 4000, 10, 64, 3));
+			map.Add(new CombinedAlternatorMapRow("Alt2", 4000, 63, 74, 3));
+			map.Add(new CombinedAlternatorMapRow("Alt2", 4000, 125, 68, 3));
+
+			map.Add(new CombinedAlternatorMapRow("Alt2", 6000, 10, 53, 3));
+			map.Add(new CombinedAlternatorMapRow("Alt2", 6000, 68, 70, 3));
+			map.Add(new CombinedAlternatorMapRow("Alt2", 6000, 136, 62, 3));
+		}
+
+		// Grid Management
+		private bool AddNewAlternator(List<ICombinedAlternatorMapRow> list, ref string feeback)
+		{
+			var altName = list.First().AlternatorName;
+			var pulleyRatio = list.First().PulleyRatio;
+
+			// Check alt does not already exist in list
+			if (Alternators.Any(w => w.AlternatorName == altName)) {
+				feeback = "This alternator already exists in in the list, operation not completed.";
+				return false;
+			}
+
+			IAlternator alternator = new Alternator(altSignals, list.ToList());
+
+			Alternators.Add(alternator);
+
+
+			return true;
+		}
+
+		public bool AddAlternator(List<ICombinedAlternatorMapRow> rows, ref string feedback)
+		{
+			if (!AddNewAlternator(rows, ref feedback)) {
+				feedback = string.Format("Unable to add new alternator : {0}", feedback);
+				return false;
+			}
+
+			return true;
+		}
+
+		public bool DeleteAlternator(string alternatorName, ref string feedback, bool CountValidation)
+		{
+
+			// Is this the last alternator, if so deny the user the right to remove it.
+			if (CountValidation && Alternators.Count < 2) {
+				feedback = "There must be at least one alternator remaining, operation aborted.";
+				return false;
+			}
+
+			if (Alternators.All(w => w.AlternatorName != alternatorName)) {
+				feedback = "This alternator does not exist";
+				return false;
+			}
+
+			IAlternator altToRemove = Alternators.First(w => w.AlternatorName == alternatorName);
+			int numAlternators = Alternators.Count;
+
+			Alternators.Remove(altToRemove);
+
+			if (Alternators.Count == numAlternators - 1) {
+				return true;
+			}
+
+			feedback = string.Format("The alternator {0} could not be removed : {1}", alternatorName, feedback);
+			return false;
+		}
+		
+
+		public bool Save(string aaltPath)
+		{
+			var sb = new StringBuilder();
+			
+			// write headers  
+			sb.AppendLine("[AlternatorName],[RPM],[Amps],[Efficiency],[PulleyRatio]");
+
+			// write details
+			foreach (IAlternator alt in Alternators.OrderBy(o => o.AlternatorName)) {
+				// 2000 - IE Alt1,2000,10,50,3
+				for (var row = 1; row <= 3; row++) {
+					var amps = alt.InputTable2000[row].Amps;
+					var eff = alt.InputTable2000[row].Eff;
+					sb.Append(alt.AlternatorName + ",2000," + amps.ToString("0.000") + "," + eff.ToString("0.000") + "," + alt.PulleyRatio.ToString("0.000"));
+					sb.AppendLine("");
+				}
+
+				// 4000 - IE Alt1,2000,10,50,3
+				for (var row = 1; row <= 3; row++) {
+					var amps = alt.InputTable4000[row].Amps;
+					var eff = alt.InputTable4000[row].Eff;
+					sb.Append(alt.AlternatorName + ",4000," + amps.ToString("0.000") + "," + eff.ToString("0.000") + "," + alt.PulleyRatio.ToString("0.000"));
+					sb.AppendLine("");
+				}
+
+				// 6000 - IE Alt1,2000,10,50,3
+				for (var row = 1; row <= 3; row++) {
+					var amps = alt.InputTable6000[row].Amps;
+					var eff = alt.InputTable6000[row].Eff;
+					sb.Append(alt.AlternatorName + ",6000," + amps.ToString("0.000") + "," + eff.ToString("0.000") + "," + alt.PulleyRatio.ToString("0.000"));
+					sb.AppendLine("");
+				}
+			}
+
+			// Add Model Source
+			sb.AppendLine("[MODELSOURCE]");
+			sb.Append(ToString());
+
+			// Write the stream cotnents to a new file named "AllTxtFiles.txt" 
+			using (StreamWriter outfile = new StreamWriter(aaltPath)) {
+				outfile.Write(sb.ToString());
+			}
+
+			return true;
+		}
+
+		private bool Load()
+		{
+			if (!InitialiseMap(FilePath))
+				return false;
+
+
+			return true;
+		}
+
+		// Initialises the map, only valid when loadingUI for first time in edit mode or always in operational mode.
+		private bool InitialiseMap(string filePath)
+		{
+			bool returnValue = false;
+			string[] elements;
+
+			if (File.Exists(filePath)) {
+				using (StreamReader sr = new StreamReader(filePath)) {
+					// get array og lines fron csv
+					string[] lines = sr.ReadToEnd().Split(new[] { Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries);
+
+					// Must have at least 2 entries in map to make it usable [dont forget the header row]
+					if ((lines.Count() < 10))
+						throw new ArgumentException("Insufficient rows in csv to build a usable map");
+
+					map = new List<ICombinedAlternatorMapRow>();
+
+					bool firstline = true;
+
+					foreach (string line in lines) {
+						if (!firstline) {
+
+							// Advanced Alternator Source Check.
+							if (line.Contains("[MODELSOURCE"))
+								break;
+
+							// split the line
+							elements = line.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
+							// 3 entries per line required
+							if ((elements.Length != 5))
+								throw new ArgumentException("Incorrect number of values in csv file");
+							// add values to map
+
+							map.Add(new CombinedAlternatorMapRow(elements[0], float.Parse(elements[1], CultureInfo.InvariantCulture), float.Parse(elements[2], CultureInfo.InvariantCulture), float.Parse(elements[3], CultureInfo.InvariantCulture), float.Parse(elements[4], CultureInfo.InvariantCulture)));
+						} else
+							firstline = false;
+					}
+				}
+				return true;
+			} else
+				throw new ArgumentException("Supplied input file does not exist");
+
+			return returnValue;
+		}
+
+		// Can be used to send messages to Vecto.
+		public event AuxiliaryEventEventHandler AuxiliaryEvent;
+
+		public delegate void AuxiliaryEventEventHandler(ref object sender, string message, AdvancedAuxiliaryMessageType messageType);
+
+		// This is used to generate a diagnostics output which enables the user to 
+		// Determine if they beleive the resulting map is what is expected
+		// Basically it is a check against the model/Spreadsheet
+		public override string ToString()
+		{
+			StringBuilder sb = new StringBuilder();
+			string a1, a2, a3, e1, e2, e3;
+
+			const string vbTab = "\t";
+			foreach (Alternator alt in Alternators.OrderBy(o => o.AlternatorName)) {
+				sb.AppendLine("");
+				sb.AppendFormat("** {0} ** , PulleyRatio {1}", alt.AlternatorName, alt.PulleyRatio);
+				sb.AppendLine("");
+				sb.AppendLine("******************************************************************");
+				sb.AppendLine("");
+
+				int i = 1;
+				sb.AppendLine("Table 1 (2000)" + vbTab + "Table 2 (4000)" + vbTab + "Table 3 (6000)");
+				sb.AppendLine("Amps" + vbTab + "Eff" + vbTab + "Amps" + vbTab + "Eff" + vbTab + "Amps" + vbTab + "Eff" + vbTab);
+				sb.AppendLine("");
+				for (i = 1; i <= 3; i++) {
+					a1 = alt.InputTable2000[i].Amps.ToString("0");
+					e1 = alt.InputTable2000[i].Eff.ToString("0.000");
+					a2 = alt.InputTable4000[i].Amps.ToString("0");
+					e2 = alt.InputTable4000[i].Eff.ToString("0.000");
+					a3 = alt.InputTable6000[i].Amps.ToString("0");
+					e3 = alt.InputTable6000[i].Eff.ToString("0.000");
+					sb.AppendLine(a1 + vbTab + e1 + vbTab + a2 + vbTab + e2 + vbTab + a3 + vbTab + e3 + vbTab);
+				}
+			}
+
+			// sb.AppendLine("")
+			// sb.AppendLine("********* COMBINED EFFICIENCY VALUES **************")
+			// sb.AppendLine("")
+			// sb.AppendLine(vbTab + "RPM VALUES")
+			// sb.AppendLine("AMPS" + vbTab + "500" + vbTab + "1500" + vbTab + "2500" + vbTab + "3500" + vbTab + "4500" + vbTab + "5500" + vbTab + "6500" + vbTab + "7500")
+			// For a As Single = 1 To Alternators.Count * 50
+
+			// sb.Append(a.ToString("0") + vbTab)
+			// For Each r As Single In {500, 1500, 2500, 3500, 4500, 5500, 6500, 7500}
+
+			// Dim eff As Single = GetEfficiency(r, a).Efficiency
+
+			// sb.Append(eff.ToString("0.000") + vbTab)
+
+			// Next
+			// sb.AppendLine("")
+
+			// Next
+
+
+			return sb.ToString();
+		}
+
+
+		// Equality
+		public bool IsEqualTo(ICombinedAlternator other)
+		{
+
+			// Count Check.
+			if (this.Alternators.Count != other.Alternators.Count)
+				return false;
+
+			foreach (IAlternator alt in this.Alternators) {
+
+				// Can we find the same alternatorName in other
+				if (other.Alternators.Where(f => f.AlternatorName == alt.AlternatorName).Count() != 1)
+					return false;
+
+				// get the alternator to compare and compare it.
+				if (!alt.IsEqualTo(other.Alternators.First(f => f.AlternatorName == alt.AlternatorName)))
+					return false;
+			}
+
+			return true;
+		}
+	}
+}
diff --git a/VECTOAux/BusAuxiliaries/DownstreamModules/Impl/Electrics/CombinedAlternatorMapRow.cs b/VECTOAux/BusAuxiliaries/DownstreamModules/Impl/Electrics/CombinedAlternatorMapRow.cs
new file mode 100644
index 0000000000000000000000000000000000000000..bf92600190ea7a800bf539695fa68014eebcb22a
--- /dev/null
+++ b/VECTOAux/BusAuxiliaries/DownstreamModules/Impl/Electrics/CombinedAlternatorMapRow.cs
@@ -0,0 +1,52 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Security;
+using System.Text;
+using System.Threading.Tasks;
+using Microsoft.VisualBasic;
+using DownstreamModules.Electrics;
+
+namespace Electrics
+{
+	// This class is reflective of the stored entries for the combined alternator
+	// And is used by the Combined Alternator Form and any related classes.
+
+	public class CombinedAlternatorMapRow : ICombinedAlternatorMapRow
+	{
+		public string AlternatorName { get; set; }
+		public double RPM { get; set; }
+		public double Amps { get; set; }
+		public double Efficiency { get; set; }
+		public double PulleyRatio { get; set; }
+
+		// Constructors
+		public CombinedAlternatorMapRow()
+		{
+		}
+
+		public CombinedAlternatorMapRow(string alternatorName, double rpm, double amps, double efficiency, double pulleyRatio)
+		{
+
+			// Sanity Check
+			if (alternatorName.Trim().Length == 0)
+				throw new ArgumentException("Alternator name cannot be zero length");
+			if (efficiency < 0 | efficiency > 100)
+				throw new ArgumentException("Alternator Efficiency must be between 0 and 100");
+			if (pulleyRatio <= 0)
+				throw new ArgumentException("Alternator Pully ratio must be a positive number");
+
+			// Assignments
+			AlternatorName = alternatorName;
+			RPM = rpm;
+			Amps = amps;
+			Efficiency = efficiency;
+			PulleyRatio = pulleyRatio;
+		}
+	}
+}
diff --git a/VECTOAux/BusAuxiliaries/DownstreamModules/Impl/Electrics/CombinedAlternatorSignals.cs b/VECTOAux/BusAuxiliaries/DownstreamModules/Impl/Electrics/CombinedAlternatorSignals.cs
new file mode 100644
index 0000000000000000000000000000000000000000..7133c281b8bbcf7154a286d93cf6c1dbb2fd9f03
--- /dev/null
+++ b/VECTOAux/BusAuxiliaries/DownstreamModules/Impl/Electrics/CombinedAlternatorSignals.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Security;
+using System.Text;
+using System.Threading.Tasks;
+using Microsoft.VisualBasic;
+using DownstreamModules.Electrics;
+using TUGraz.VectoCommon.Utils;
+
+namespace Electrics
+{
+	// Used by the CombinedAlternator class and any other related classes.
+	public class CombinedAlternatorSignals : ICombinedAlternatorSignals
+	{
+		public double CrankRPM { get; set; }
+
+		public Ampere CurrentDemandAmps { get; set; }
+
+		// Number of alternators in the Combined Alternator
+		public int NumberOfAlternators { get; set; }
+	}
+}
diff --git a/VECTOAux/BusAuxiliaries/DownstreamModules/Impl/Electrics/ElectricalConsumer.cs b/VECTOAux/BusAuxiliaries/DownstreamModules/Impl/Electrics/ElectricalConsumer.cs
new file mode 100644
index 0000000000000000000000000000000000000000..4fa98ab74e92b1c846f3aab2e0f8616a24de4ac9
--- /dev/null
+++ b/VECTOAux/BusAuxiliaries/DownstreamModules/Impl/Electrics/ElectricalConsumer.cs
@@ -0,0 +1,209 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Security;
+using System.Text;
+using System.Threading.Tasks;
+using Microsoft.VisualBasic;
+using System.ComponentModel;
+using DownstreamModules.Electrics;
+using TUGraz.VectoCommon.Utils;
+
+// Copyright 2017 European Union.
+// Licensed under the EUPL (the 'Licence');
+// 
+// * You may not use this work except in compliance with the Licence.
+// * You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl
+// * Unless required by applicable law or agreed to in writing,
+// software distributed under the Licence is distributed on an "AS IS" basis,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// 
+// See the LICENSE.txt for the specific language governing permissions and limitations.
+
+namespace Electrics
+{
+	/// <summary>
+	/// 	''' Described a consumer of Alternator electrical power
+	/// 	''' </summary>
+	/// 	''' <remarks></remarks>
+	public class ElectricalConsumer : IElectricalConsumer
+	{
+
+		// Fields
+		private bool _BaseVehicle;
+		private string _Category;
+		private string _ConsumerName;
+		private double _NominalConsumptionAmps;
+		private int _NumberInActualVehicle;
+		private double _PhaseIdle_TractionOn;
+		private double _PowerNetVoltage;
+		private string _Info;
+
+		// Calculated
+		public double AvgConsumptionAmps { get; set; }
+
+		// Properties
+		public bool BaseVehicle
+		{
+			get {
+				return _BaseVehicle;
+			}
+			set {
+				_BaseVehicle = value;
+				NotifyPropertyChanged("BaseVehicle");
+			}
+		}
+
+		public string Category
+		{
+			get {
+				return _Category;
+			}
+			set {
+				_Category = value;
+				NotifyPropertyChanged("Category");
+			}
+		}
+
+		public string ConsumerName
+		{
+			get {
+				return _ConsumerName;
+			}
+			set {
+				_ConsumerName = value;
+				NotifyPropertyChanged("ConsumerName");
+			}
+		}
+
+		public double NominalConsumptionAmps
+		{
+			get {
+				return _NominalConsumptionAmps;
+			}
+			set {
+				_NominalConsumptionAmps = value;
+				NotifyPropertyChanged("NominalConsumptionAmps");
+			}
+		}
+
+		public int NumberInActualVehicle
+		{
+			get {
+				return _NumberInActualVehicle;
+			}
+			set {
+				_NumberInActualVehicle = value;
+				NotifyPropertyChanged("NumberInActualVehicle");
+			}
+		}
+
+		public double PhaseIdle_TractionOn
+		{
+			get {
+				return _PhaseIdle_TractionOn;
+			}
+			set {
+				_PhaseIdle_TractionOn = value;
+				NotifyPropertyChanged("PhaseIdle_TractionOn");
+			}
+		}
+
+		public double PowerNetVoltage
+		{
+			get {
+				return _PowerNetVoltage;
+			}
+			set {
+				_PowerNetVoltage = value;
+				NotifyPropertyChanged("PowerNetVoltage");
+			}
+		}
+
+		public string Info
+		{
+			get {
+				return _Info;
+			}
+			set {
+				_Info = value;
+				NotifyPropertyChanged("Info");
+			}
+		}
+
+
+		// Public class outputs
+		public Ampere TotalAvgConumptionAmps(double PhaseIdle_TractionOnBasedOnCycle = default(Double))
+		{
+			if (ConsumerName == "Doors per Door")
+				return NominalConsumptionAmps.SI<Ampere>() * (NumberInActualVehicle * PhaseIdle_TractionOnBasedOnCycle);
+			else
+				return NominalConsumptionAmps.SI<Ampere>() * (NumberInActualVehicle * PhaseIdle_TractionOn);
+		}
+
+		public Watt TotalAvgConsumptionInWatts(double PhaseIdle_TractionOnBasedOnCycle = 0.0)
+		{
+			return TotalAvgConumptionAmps(PhaseIdle_TractionOnBasedOnCycle) * PowerNetVoltage.SI<Volt>();
+		}
+
+		// Constructor
+		public ElectricalConsumer(bool BaseVehicle, string Category, string ConsumerName, double NominalConsumptionAmps, double PhaseIdle_TractionOn, double PowerNetVoltage, int numberInVehicle, string info)
+		{
+
+			// Illegal Value Check.
+			if (Category.Trim().Length == 0)
+				throw new ArgumentException("Category Name cannot be empty");
+			if (ConsumerName.Trim().Length == 0)
+				throw new ArgumentException("ConsumerName Name cannot be empty");
+			if (PhaseIdle_TractionOn < ElectricConstants.PhaseIdleTractionOnMin | PhaseIdle_TractionOn > ElectricConstants.PhaseIdleTractionMax)
+				throw new ArgumentException("PhaseIdle_TractionOn must have a value between 0 and 1");
+			if (NominalConsumptionAmps < ElectricConstants.NonminalConsumerConsumptionAmpsMin | NominalConsumptionAmps > ElectricConstants.NominalConsumptionAmpsMax)
+				throw new ArgumentException("NominalConsumptionAmps must have a value between 0 and 100");
+			if (PowerNetVoltage < ElectricConstants.PowenetVoltageMin | PowerNetVoltage > ElectricConstants.PowenetVoltageMax)
+				throw new ArgumentException("PowerNetVoltage must have a value between 6 and 48");
+			if (numberInVehicle < 0)
+				throw new ArgumentException("Cannot have less than 0 consumers in the vehicle");
+
+			// Good, now assign.
+			this.BaseVehicle = BaseVehicle;
+			this.Category = Category;
+			this.ConsumerName = ConsumerName;
+			this.NominalConsumptionAmps = NominalConsumptionAmps;
+			this.PhaseIdle_TractionOn = PhaseIdle_TractionOn;
+			this.PowerNetVoltage = PowerNetVoltage;
+			this.NumberInActualVehicle = numberInVehicle;
+			this.Info = info;
+		}
+
+		// Comparison Overrides
+		public override bool Equals(object obj)
+		{
+			if (obj == null || GetType() != obj.GetType())
+				return false;
+
+			IElectricalConsumer other = (IElectricalConsumer)obj;
+
+
+			return this.ConsumerName == other.ConsumerName;
+		}
+
+		[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
+		public override int GetHashCode()
+		{
+			return 0;
+		}
+
+
+		public event PropertyChangedEventHandler PropertyChanged;
+
+		private void NotifyPropertyChanged(string p)
+		{
+			PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(p));
+		}
+	}
+}
diff --git a/VECTOAux/BusAuxiliaries/DownstreamModules/Impl/Electrics/ElectricalConsumerList.cs b/VECTOAux/BusAuxiliaries/DownstreamModules/Impl/Electrics/ElectricalConsumerList.cs
new file mode 100644
index 0000000000000000000000000000000000000000..f5bf2b460689927c4fba0ca3a7f7c30352e3650b
--- /dev/null
+++ b/VECTOAux/BusAuxiliaries/DownstreamModules/Impl/Electrics/ElectricalConsumerList.cs
@@ -0,0 +1,177 @@
+// Copyright 2017 European Union.
+// Licensed under the EUPL (the 'Licence');
+// 
+// * You may not use this work except in compliance with the Licence.
+// * You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl
+// * Unless required by applicable law or agreed to in writing,
+// software distributed under the Licence is distributed on an "AS IS" basis,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// 
+// See the LICENSE.txt for the specific language governing permissions and limitations.
+
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Security;
+using System.Text;
+using System.Threading.Tasks;
+using Microsoft.VisualBasic;
+using DownstreamModules.Electrics;
+using TUGraz.VectoCommon.Utils;
+
+namespace Electrics
+{
+	public class ElectricalConsumerList : IElectricalConsumerList
+	{
+		private List<IElectricalConsumer> _items = new List<IElectricalConsumer>();
+		private double _powernetVoltage;
+		private double _doorDutyCycleZeroToOne;
+
+
+		// Constructor
+		public ElectricalConsumerList(double powernetVoltage, double doorDutyCycle_ZeroToOne, bool createDefaultList = false)
+		{
+			_powernetVoltage = powernetVoltage;
+
+			if (createDefaultList)
+				_items = GetDefaultConsumerList();
+
+
+			_doorDutyCycleZeroToOne = doorDutyCycle_ZeroToOne;
+		}
+
+		// Transfers the Info comments from a default set of consumables to a live set.
+		// This way makes the comments not dependent on saved data.
+		public void MergeInfoData()
+		{
+			if (_items.Count != GetDefaultConsumerList().Count)
+				return;
+
+			List<IElectricalConsumer> dflt = GetDefaultConsumerList();
+
+			for (int idx = 0; idx <= _items.Count - 1; idx++)
+
+				_items[idx].Info = dflt[idx].Info;
+		}
+
+		// Initialise default set of consumers
+		public List<IElectricalConsumer> GetDefaultConsumerList()
+		{
+
+			// This populates the default settings as per engineering spreadsheet.
+			// Vehicle Basic Equipment' category can be added or remove by customers.
+			// At some time in the future, this may be removed and replace with file based consumer lists.
+
+			List<IElectricalConsumer> items = new List<IElectricalConsumer>();
+
+			IElectricalConsumer c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20;
+
+			c1 = (IElectricalConsumer)new ElectricalConsumer(false, "Doors", "Doors per Door", 3.0, 0.096339, _powernetVoltage, 3, "");
+			c2 = (IElectricalConsumer)new ElectricalConsumer(true, "Veh Electronics &Engine", "Controllers,Valves etc", 25.0, 1.0, _powernetVoltage, 1, "");
+			c3 = (IElectricalConsumer)new ElectricalConsumer(false, "Vehicle basic equipment", "Radio City", 2.0, 0.8, _powernetVoltage, 1, "");
+			c4 = (IElectricalConsumer)new ElectricalConsumer(false, "Vehicle basic equipment", "Radio Intercity", 5.0, 0.8, _powernetVoltage, 0, "");
+			c5 = (IElectricalConsumer)new ElectricalConsumer(false, "Vehicle basic equipment", "Radio/Audio Tourism", 9.0, 0.8, _powernetVoltage, 0, "");
+			c6 = (IElectricalConsumer)new ElectricalConsumer(false, "Vehicle basic equipment", "Fridge", 4.0, 0.5, _powernetVoltage, 0, "");
+			c7 = (IElectricalConsumer)new ElectricalConsumer(false, "Vehicle basic equipment", "Kitchen Standard", 67.0, 0.05, _powernetVoltage, 0, "");
+			c8 = (IElectricalConsumer)new ElectricalConsumer(false, "Vehicle basic equipment", "Interior lights City/ Intercity + Doorlights [Should be 1/m]", 1.0, 0.7, _powernetVoltage, 12, "1 Per metre length of bus");
+			c9 = (IElectricalConsumer)new ElectricalConsumer(false, "Vehicle basic equipment", "LED Interior lights ceiling city/Intercity + door [Should be 1/m]", 0.6, 0.7, _powernetVoltage, 0, "1 Per metre length of bus");
+			c10 = (IElectricalConsumer)new ElectricalConsumer(false, "Vehicle basic equipment", "Interior lights Tourism + reading [1/m]", 1.1, 0.7, _powernetVoltage, 0, "1 Per metre length of bus");
+			c11 = (IElectricalConsumer)new ElectricalConsumer(false, "Vehicle basic equipment", "LED Interior lights ceiling Tourism + LED reading [Should be 1/m]", 0.66, 0.7, _powernetVoltage, 0, "1 Per metre length of bus");
+			c12 = (IElectricalConsumer)new ElectricalConsumer(false, "Customer Specific Equipment", "External Displays Font/Side/Rear", 2.65017667844523, 1.0, _powernetVoltage, 4, "");
+			c13 = (IElectricalConsumer)new ElectricalConsumer(false, "Customer Specific Equipment", "Internal display per unit ( front side rear)", 1.06007067137809, 1.0, _powernetVoltage, 1, "");
+			c14 = (IElectricalConsumer)new ElectricalConsumer(false, "Customer Specific Equipment", "CityBus Ref EBSF Table4 Devices ITS No Displays", 9.3, 1.0, _powernetVoltage, 1, "");
+			c15 = (IElectricalConsumer)new ElectricalConsumer(false, "Lights", "Exterior Lights BULB", 7.4, 1.0, _powernetVoltage, 1, "");
+			c16 = (IElectricalConsumer)new ElectricalConsumer(false, "Lights", "Day running lights LED bonus", -0.723, 1.0, _powernetVoltage, 1, "");
+			c17 = (IElectricalConsumer)new ElectricalConsumer(false, "Lights", "Antifog rear lights LED bonus", -0.17, 1.0, _powernetVoltage, 1, "");
+			c18 = (IElectricalConsumer)new ElectricalConsumer(false, "Lights", "Position lights LED bonus", -1.2, 1.0, _powernetVoltage, 1, "");
+			c19 = (IElectricalConsumer)new ElectricalConsumer(false, "Lights", "Direction lights LED bonus", -0.3, 1.0, _powernetVoltage, 1, "");
+			c20 = (IElectricalConsumer)new ElectricalConsumer(false, "Lights", "Brake Lights LED bonus", -1.2, 1.0, _powernetVoltage, 1, "");
+
+			items.Add(c1);
+			items.Add(c2);
+			items.Add(c3);
+			items.Add(c4);
+			items.Add(c5);
+			items.Add(c6);
+			items.Add(c7);
+			items.Add(c8);
+			items.Add(c9);
+			items.Add(c10);
+			items.Add(c11);
+			items.Add(c12);
+			items.Add(c13);
+			items.Add(c14);
+			items.Add(c15);
+			items.Add(c16);
+			items.Add(c17);
+			items.Add(c18);
+			items.Add(c19);
+			items.Add(c20);
+
+			return items;
+		}
+
+
+		// Interface implementation
+		public double DoorDutyCycleFraction
+		{
+			get {
+				return _doorDutyCycleZeroToOne;
+			}
+			set {
+				_doorDutyCycleZeroToOne = value;
+			}
+		}
+
+		public List<IElectricalConsumer> Items
+		{
+			get {
+				return _items;
+			}
+		}
+
+		public void AddConsumer(IElectricalConsumer consumer)
+		{
+			if (!_items.Contains(consumer))
+				_items.Add(consumer);
+			else
+				throw new ArgumentException("Consumer Already Present in the list");
+		}
+
+		public void RemoveConsumer(IElectricalConsumer consumer)
+		{
+			if (_items.Contains(consumer))
+				_items.Remove(consumer);
+			else
+				throw new ArgumentException("Consumer Not In List");
+		}
+
+
+		public Ampere GetTotalAverageDemandAmps(bool excludeOnBase)
+		{
+			Ampere Amps;
+
+			if (excludeOnBase)
+
+				Amps = Items.Where(x => x.BaseVehicle == false)
+							.Sum(consumer => consumer.TotalAvgConumptionAmps(DoorDutyCycleFraction));
+
+			// Aggregate item In Items Where item.BaseVehicle = False Into Sum(item.TotalAvgConumptionAmps(DoorDutyCycleFraction))
+
+
+			else
+
+				Amps = Items.Sum(x => x.TotalAvgConumptionAmps(DoorDutyCycleFraction));
+					//Aggregate item In Items Into Sum(item.TotalAvgConumptionAmps(DoorDutyCycleFraction))
+
+ 
+			return Amps;
+		}
+	}
+}
diff --git a/VECTOAux/BusAuxiliaries/DownstreamModules/Impl/Electrics/ElectricsUserInputsConfig.cs b/VECTOAux/BusAuxiliaries/DownstreamModules/Impl/Electrics/ElectricsUserInputsConfig.cs
new file mode 100644
index 0000000000000000000000000000000000000000..ab170636b3575763369d6b9e5ec97222cc089556
--- /dev/null
+++ b/VECTOAux/BusAuxiliaries/DownstreamModules/Impl/Electrics/ElectricsUserInputsConfig.cs
@@ -0,0 +1,66 @@
+// Copyright 2017 European Union.
+// Licensed under the EUPL (the 'Licence');
+// 
+// * You may not use this work except in compliance with the Licence.
+// * You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl
+// * Unless required by applicable law or agreed to in writing,
+// software distributed under the Licence is distributed on an "AS IS" basis,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// 
+// See the LICENSE.txt for the specific language governing permissions and limitations.
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Security;
+using System.Text;
+using System.Threading.Tasks;
+using Microsoft.VisualBasic;
+using DownstreamModules.Electrics;
+using TUGraz.VectoCore.BusAuxiliaries.Interfaces;
+using TUGraz.VectoCore.BusAuxiliaries.Interfaces.DownstreamModules.Electrics;
+
+namespace Electrics
+{
+	public class ElectricsUserInputsConfig : IElectricsUserInputsConfig
+	{
+		public double PowerNetVoltage { get; set; }
+		public string AlternatorMap { get; set; }
+		public double AlternatorGearEfficiency { get; set; }
+
+		public IElectricalConsumerList ElectricalConsumers { get; set; }
+
+		public int DoorActuationTimeSecond { get; set; }
+		public double StoredEnergyEfficiency { get; set; }
+
+		public IResultCard ResultCardIdle { get; set; }
+		public IResultCard ResultCardTraction { get; set; }
+		public IResultCard ResultCardOverrun { get; set; }
+
+		public bool SmartElectrical { get; set; }
+
+		public ElectricsUserInputsConfig(bool setToDefaults = false, VectoInputs vectoInputs = null/* TODO Change to default(_) if this is not a reference type */)
+		{
+			if (setToDefaults)
+				SetPropertiesToDefaults(vectoInputs);
+		}
+
+		public void SetPropertiesToDefaults(VectoInputs vectoInputs)
+		{
+			DoorActuationTimeSecond = 4;
+			StoredEnergyEfficiency = 0.935;
+			AlternatorGearEfficiency = 0.92;
+			PowerNetVoltage = vectoInputs.PowerNetVoltage.Value();
+			ResultCardIdle = new ResultCard(new List<SmartResult>());
+			ResultCardOverrun = new ResultCard(new List<SmartResult>());
+			ResultCardTraction = new ResultCard(new List<SmartResult>());
+			SmartElectrical = false;
+			AlternatorMap = string.Empty;
+		}
+	}
+}
diff --git a/VECTOAux/BusAuxiliaries/DownstreamModules/Impl/Electrics/ResultCard.cs b/VECTOAux/BusAuxiliaries/DownstreamModules/Impl/Electrics/ResultCard.cs
new file mode 100644
index 0000000000000000000000000000000000000000..10376e08cb2b4b32591dbc358fd8c0344a118aee
--- /dev/null
+++ b/VECTOAux/BusAuxiliaries/DownstreamModules/Impl/Electrics/ResultCard.cs
@@ -0,0 +1,182 @@
+// Copyright 2017 European Union.
+// Licensed under the EUPL (the 'Licence');
+// 
+// * You may not use this work except in compliance with the Licence.
+// * You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl
+// * Unless required by applicable law or agreed to in writing,
+// software distributed under the Licence is distributed on an "AS IS" basis,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// 
+// See the LICENSE.txt for the specific language governing permissions and limitations.
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Security;
+using System.Text;
+using System.Threading.Tasks;
+using Microsoft.VisualBasic;
+using DownstreamModules.Electrics;
+using TUGraz.VectoCommon.Utils;
+using TUGraz.VectoCore.BusAuxiliaries.Interfaces.DownstreamModules.Electrics;
+
+namespace Electrics
+{
+	public class ResultCard : IResultCard
+	{
+		private List<SmartResult> _results;
+
+		// Constructor
+		public ResultCard(List<SmartResult> results)
+		{
+			if (results == null)
+				throw new ArgumentException("A list of smart results must be supplied.");
+
+			_results = results;
+		}
+
+
+		// Public class outputs
+		public List<SmartResult> Results
+		{
+			get { return _results; }
+		}
+
+		public Ampere GetSmartCurrentResult(Ampere Amps)
+		{
+			if (_results.Count < 2)
+				return 10.SI<Ampere>();
+
+			return GetOrInterpolate(Amps.Value()).SI<Ampere>();
+		}
+
+
+		// Helpers
+		/// <summary>
+		///         ''' Gets or interpolates value (A)
+		///         ''' </summary>
+		///         ''' <param name="amps"></param>
+		///         ''' <returns></returns>
+		///         ''' <remarks></remarks>
+		private double GetOrInterpolate(double amps)
+		{
+			double pre;
+			double post;
+			double dAmps;
+			double dSmartAmps;
+			double smartAmpsSlope;
+			double smartAmps;
+			double maxKey;
+			double minKey;
+
+			maxKey = _results.Max().Amps;
+			minKey = _results.Min().Amps;
+
+			SmartResult compareKey = new SmartResult(amps, 0);
+
+			// Is on boundary check
+			if (_results.Contains(compareKey))
+				return _results.OrderBy(x => x.Amps).First(x => x.Amps == compareKey.Amps).SmartAmps;
+
+			// Is over map - Extrapolate
+			if (amps > maxKey) {
+				// get the entries before and after the supplied key
+				pre = (from a in _results
+						orderby a.Amps
+						where a.Amps < maxKey
+						select a).Last().Amps;
+				post = maxKey;
+
+				// get the delta values 
+				dAmps = post - pre;
+				dSmartAmps = (from da in _results
+							orderby da.Amps
+							where da.Amps == post
+							select da).First().SmartAmps - (from da in _results
+															orderby da.Amps
+															where da.Amps == pre
+															select da).First().SmartAmps;
+
+				// calculate the slopes
+				smartAmpsSlope = dSmartAmps / dAmps;
+
+				// calculate the new values
+				smartAmps = ((amps - post) * smartAmpsSlope) + (from da in _results
+																orderby da.Amps
+																where da.Amps == post
+																select da).First().SmartAmps;
+
+				return smartAmps;
+			}
+
+			// Is under map - Extrapolate
+			if (amps < minKey) {
+				// get the entries before and after the supplied key
+				// Post is the first entry and pre is the penultimate to first entry
+				post = minKey;
+				pre = (from k in _results
+						orderby k.Amps
+						where k.Amps > minKey
+						select k).First().Amps;
+
+				// get the delta values 
+				dAmps = post - pre;
+				dSmartAmps = (from da in _results
+							orderby da.Amps
+							where da.Amps == post
+							select da).First().SmartAmps - (from da in _results
+															orderby da.Amps
+															where da.Amps == pre
+															select da).First().SmartAmps;
+
+				// calculate the slopes
+				smartAmpsSlope = dSmartAmps / dAmps;
+
+				// calculate the new values
+				smartAmps = ((amps - post) * smartAmpsSlope) + (from da in _results
+																orderby da.Amps
+																where da.Amps == post
+																select da).First().SmartAmps;
+
+				return smartAmps;
+			}
+
+			// Is Inside map - Interpolate
+
+			// get the entries before and after the supplied rpm
+			pre = (from m in _results
+					orderby m.Amps
+					where m.Amps < amps
+					select m).Last().Amps;
+			post = (from m in _results
+					where m.Amps > amps
+					select m).First().Amps;
+
+			// get the delta values for rpm and the map values
+			dAmps = post - pre;
+			dSmartAmps = (from da in _results
+						orderby da.Amps
+						where da.Amps == post
+						select da).First().SmartAmps - (from da in _results
+														orderby da.Amps
+														where da.Amps == pre
+														select da).First().SmartAmps;
+
+			// calculate the slopes
+			smartAmpsSlope = dSmartAmps / dAmps;
+
+			// calculate the new values
+			smartAmps = ((amps - post) * smartAmpsSlope) + (from da in _results
+															orderby da.Amps
+															where da.Amps == post
+															select da).First().SmartAmps;
+
+			return smartAmps;
+		}
+	}
+}
diff --git a/VECTOAux/BusAuxiliaries/Util/FilePathUtils.cs b/VECTOAux/BusAuxiliaries/Util/FilePathUtils.cs
new file mode 100644
index 0000000000000000000000000000000000000000..4cbe6fe130a95f166552b2cbf18783a046c8f94c
--- /dev/null
+++ b/VECTOAux/BusAuxiliaries/Util/FilePathUtils.cs
@@ -0,0 +1,148 @@
+using System;
+using System.IO;
+using System.Linq;
+using Microsoft.VisualBasic;
+
+public class FilePathUtils
+{
+
+	public static string Left(string str, int length)
+	{
+		return str.Substring(0, Math.Min(length, str.Length));
+	}
+
+	public static string Right(string value, int length)
+	{
+		if (string.IsNullOrEmpty(value)) return string.Empty;
+
+		return value.Length <= length ? value : value.Substring(value.Length - length);
+	}
+
+	public static bool ValidateFilePath(string filePath, string expectedExtension, ref string message)
+	{
+		char[] illegalFileNameCharacters = new[] { '<', '>', ':', '"', '/', '\\', '|', '?', '*', '~' };
+		string detectedExtention = fileExtentionOnly(filePath);
+		string pathOnly = filePathOnly(filePath);
+		string fileNameOnlyWithExtension = fileNameOnly(filePath, true);
+		string fileNameOnlyNoExtension = fileNameOnly(filePath, false);
+
+		// Is this filePath empty
+		if (filePath.Trim().Length == 0 || Right(filePath, 1) == @"\") {
+			message = "A filename cannot be empty";
+			return false;
+		}
+
+
+		// Extension Expected, but not match
+		if (expectedExtension.Trim().Length > 0) {
+			if (string.Compare(expectedExtension, detectedExtention, true) != 0) {
+				message = string.Format("The file extension type does not match the expected type of {0}", expectedExtension);
+				return false;
+			}
+		}
+
+		// Extension Not Expected, but was supplied
+		if (expectedExtension.Trim().Length > 0) {
+			if (detectedExtention.Length == 0) {
+				message = string.Format("No Extension was supplied, but an extension of {0}, this is not required", detectedExtention);
+				return false;
+			}
+		}
+
+
+		// Illegal characters
+		if (!fileNameLegal(fileNameOnlyWithExtension)) {
+			message = string.Format("The filenames have one or more illegal characters");
+			return false;
+		}
+
+
+		message = "OK";
+		return true;
+	}
+
+
+	public static bool fileNameLegal(string fileName)
+	{
+		char[] illegalFileNameCharacters = new[] { '<', '>', ':', '"', '/', '\\', '|', '?', '*', '~' };
+
+
+		// Illegal characters
+		foreach (char ch in illegalFileNameCharacters) {
+			if (fileName.Contains(ch))
+				return false;
+		}
+		return true;
+	}
+
+
+	public static string ResolveFilePath(string vectoPath, string filename)
+	{
+
+		// No Vecto Path supplied
+		if (vectoPath == "")
+			return filename;
+
+		// This is not relative
+		if (filename.Contains(@":\"))
+
+			// Filepath is already absolute
+			return filename;
+		else
+			return Path.Combine(vectoPath, filename);// vectoPath & filename
+	}
+
+
+	/// <summary>
+	/// 	''' File name without the path    "C:\temp\TEST.txt"  >>  "TEST.txt" oder "TEST"
+	/// 	''' </summary>
+	/// 	''' <param name="filePath"></param>
+	/// 	''' <param name="WithExtention"></param>
+	/// 	''' <returns>Return file portion of the path, with or without the extension</returns>
+	/// 	''' <remarks></remarks>
+	public static string fileNameOnly(string filePath, bool WithExtention)
+	{
+		int x;
+		x = filePath.LastIndexOf(@"\") + 1;
+		filePath = Right(filePath, filePath.Length - x);
+		if (!WithExtention) {
+			x = filePath.LastIndexOf(".");
+			if (x > 0)
+				filePath = Left(filePath, x);
+		}
+		return filePath;
+	}
+
+
+	/// <summary>
+	/// 	''' Extension alone      "C:\temp\TEST.txt" >> ".txt"
+	/// 	''' </summary>
+	/// 	''' <param name="filePath"></param>
+	/// 	''' <returns>Extension alone Including the dot IE  .EXT</returns>
+	/// 	''' <remarks></remarks>
+	public static string fileExtentionOnly(string filePath)
+	{
+		int x;
+		x = filePath.LastIndexOf(".");
+		if (x == -1)
+			return "";
+		else
+			return Right(filePath, filePath.Length - x);
+	}
+
+	/// <summary>
+	/// 	''' File Path alone   "C:\temp\TEST.txt"  >>  "C:\temp\"
+	/// 	'''                   "TEST.txt"          >>  ""
+	/// 	''' </summary>
+	/// 	''' <param name="filePath"></param>
+	/// 	''' <returns>Filepath without the extension</returns>
+	/// 	''' <remarks></remarks>
+	public static string filePathOnly(string filePath)
+	{
+		int x;
+		if (filePath == null || filePath.Length < 3 || filePath.Substring(1, 2) != @":\")
+			return "";
+		x = filePath.LastIndexOf(@"\");
+		return Left(filePath, x + 1);
+	}
+}