public RunExistingScenarioActionView(Dictionary<Guid, string> allScenarios, Guid selectedScenario)
        {
            InitializeComponent();
            foreach (var scenario in allScenarios)
            {
                listBox.Items.Add(scenario.Value);
            }

            listBox.SelectedIndexChanged += (o, e) =>
            {
                if (listBox.SelectedItem == null)
                    btSelect.Enabled = false;
                else
                {
                    btSelect.Enabled = true;
                    SelectedScenario = allScenarios.Single(x => x.Value == listBox.SelectedItem.ToString()).Key;
                }
            };

            listBox.DoubleClick += (o, e) =>
            {
                if (listBox.SelectedItem != null)
                {
                    SelectedScenario = allScenarios.Single(x => x.Value == listBox.SelectedItem.ToString()).Key;
                    DialogResult = DialogResult.OK;
                }
            };
        }
		public LabyrinthChunkGenerator(Dictionary<int, string> blocks, int width, int height, string seed)
			: base(width, height, seed)
		{
			_doorId = blocks.Single(x => x.Value == "WoodenDoor").Key;
			_floorId = blocks.Single(x => x.Value == "Stone").Key;
			_wallId = blocks.Single(x => x.Value == "Stone").Key;
		}
 public void TestStringDictionary()
 {
     var orig = new Dictionary<string,string> { {"abc","def" }};
     var clone = Serializer.DeepClone(orig).Single();
     MetaType[] types = RuntimeTypeModel.Default.GetTypes().Cast<MetaType>().ToArray();
     Assert.AreEqual(orig.Single().Key, clone.Key);
     Assert.AreEqual(orig.Single().Value, clone.Value);
 }
 internal static int DispatchCommand(Dictionary<CommandMetadata, object> commands, string[] args)
 {
     if (args == null || !args.Any()) throw new ShellHelpException();
     var commandName = args.First().ToLower();
     if (commands.All(meta => meta.Key.Name != commandName)) throw new ShellHelpException();
     var command = commands.Single(meta => meta.Key.Name == commandName).Value;
     var metadata = commands.Single(meta => meta.Key.Name == commandName).Key;
     return RunCommand(command, metadata, args.Skip(1).ToArray());
 }
		public BSPDungeonChunkGenerator(Dictionary<int, string> blocks, int width, int height, string seed, RoomGenerator roomGenerator)
			: base(width, height, seed)
		{
			_chestId = blocks.Single(x => x.Value == "Chest").Key;
			_doorId = blocks.Single(x => x.Value == "WoodenDoor").Key;
			_floorId = blocks.Single(x => x.Value == "Stone").Key;
			_wallId = blocks.Single(x => x.Value == "Stone").Key;

			_roomGenerator = roomGenerator;
		}
        /// <summary>
        ///     Initializes a new instance of the <see cref="TeamBoxScore" /> class.
        /// </summary>
        /// <param name="r">The SQLite query result row which contains the required information.</param>
        public TeamBoxScore(DataRow r, Dictionary<int, TeamStats> tst)
        {
            ID = Convert.ToInt32(r["GameID"].ToString());
            try
            {
                Team1ID = Convert.ToInt32(r["Team1ID"].ToString());
                Team2ID = Convert.ToInt32(r["Team2ID"].ToString());
            }
            catch (Exception ex)
            {
                if (ex is ArgumentException || ex is KeyNotFoundException)
                {
                    Team1ID = tst.Single(ts => ts.Value.Name == ParseCell.GetString(r, "T1Name")).Value.ID;
                    Team2ID = tst.Single(ts => ts.Value.Name == ParseCell.GetString(r, "T2Name")).Value.ID;
                }
                else
                {
                    throw;
                }
            }
            GameDate = Convert.ToDateTime(r["Date"].ToString());
            SeasonNum = Convert.ToInt32(r["SeasonNum"].ToString());
            IsPlayoff = Convert.ToBoolean(r["IsPlayoff"].ToString());
            PTS1 = Convert.ToUInt16(r["T1PTS"].ToString());
            REB1 = Convert.ToUInt16(r["T1REB"].ToString());
            AST1 = Convert.ToUInt16(r["T1AST"].ToString());
            STL1 = Convert.ToUInt16(r["T1STL"].ToString());
            BLK1 = Convert.ToUInt16(r["T1BLK"].ToString());
            TOS1 = Convert.ToUInt16(r["T1TOS"].ToString());
            FGM1 = Convert.ToUInt16(r["T1FGM"].ToString());
            FGA1 = Convert.ToUInt16(r["T1FGA"].ToString());
            TPM1 = Convert.ToUInt16(r["T13PM"].ToString());
            TPA1 = Convert.ToUInt16(r["T13PA"].ToString());
            FTM1 = Convert.ToUInt16(r["T1FTM"].ToString());
            FTA1 = Convert.ToUInt16(r["T1FTA"].ToString());
            OREB1 = Convert.ToUInt16(r["T1OREB"].ToString());
            FOUL1 = Convert.ToUInt16(r["T1FOUL"].ToString());
            MINS1 = Convert.ToUInt16(r["T1MINS"].ToString());

            PTS2 = Convert.ToUInt16(r["T2PTS"].ToString());
            REB2 = Convert.ToUInt16(r["T2REB"].ToString());
            AST2 = Convert.ToUInt16(r["T2AST"].ToString());
            STL2 = Convert.ToUInt16(r["T2STL"].ToString());
            BLK2 = Convert.ToUInt16(r["T2BLK"].ToString());
            TOS2 = Convert.ToUInt16(r["T2TOS"].ToString());
            FGM2 = Convert.ToUInt16(r["T2FGM"].ToString());
            FGA2 = Convert.ToUInt16(r["T2FGA"].ToString());
            TPM2 = Convert.ToUInt16(r["T23PM"].ToString());
            TPA2 = Convert.ToUInt16(r["T23PA"].ToString());
            FTM2 = Convert.ToUInt16(r["T2FTM"].ToString());
            FTA2 = Convert.ToUInt16(r["T2FTA"].ToString());
            OREB2 = Convert.ToUInt16(r["T2OREB"].ToString());
            FOUL2 = Convert.ToUInt16(r["T2FOUL"].ToString());
            MINS2 = Convert.ToUInt16(r["T2MINS"].ToString());
        }
		public DugoutDungeonChunkGenerator(Dictionary<int, string> blocks, int width, int height, string seed)
			: base(width, height, seed)
		{
			// Adjust the size of the map, if it's smaller or bigger than the limits.
			_rows = MathHelper.Clamp(height, 3, Height);
			_columns = width; MathHelper.Clamp(width, 3, Width);

			_chestId = blocks.Single(x => x.Value == "Chest").Key;
			_doorId = blocks.Single(x => x.Value == "WoodenDoor").Key;
			_floorId = blocks.Single(x => x.Value == "Stone").Key;
			_wallId = blocks.Single(x => x.Value == "Stone").Key;
		}
Example #8
0
        public DateTimeViewModel()
        {
            Days = new BindableCollection<int>();
            Months = new Dictionary<int, string>();
            Years = new BindableCollection<int>();
            Hours = new BindableCollection<int>();
            Minutes = new BindableCollection<int>();

            for (var i = 0; i < 24; i++)
                Hours.Add(i + 1);
            for (var i = 0; i < 60; i++)
                Minutes.Add(i);
            for (var i = DateTime.Now.Year - 20; i < DateTime.Now.Year + 20; i++)
                Years.Add(i);

            SelectedYear = DateTime.Now.Year;

            OnMonthsChanged();

            SelectedDay = DateTime.Now.Day;

            SelectedMonth = Months.Single(c => c.Key == DateTime.Now.Month);

            SelectedHour = DateTime.Now.Hour;
            SelectedMinute = DateTime.Now.Minute;
        }
        public static string GetEndGameMessage(Dictionary<ICompetitor, double> finalResult)
        {
            if (finalResult.Any(res => res.Value == 1.0))
            {
                return finalResult.Single(x => x.Value == 1.0).Key.Name + "\nWINS";
            }

            return "DRAW";
        }
 public oval_variables CreateOvalVariablesDocument(Dictionary<string, string[]> variableValues)
 {
     var newVariables = NewOvalVariables();
     
     var externalVariables = OvalDefinitions.variables.OfType<VariablesTypeVariableExternal_variable>();
     foreach (var variable in externalVariables)
     {
         var values = variableValues.Single(var => var.Key.Equals(variable.id)).Value;
         newVariables.variables.Add(new OVAL.Variables.VariableType(variable.datatype, variable.id, values));
     }
     
     return newVariables;
 }
Example #11
0
        protected override void DoAfterRead(Dictionary<string, HtmlDocument> docs)
        {
            // read topics
            var doc = docs.Single().Value;

            int i = 0;
            while (doc.DocumentNode.SafeSelectNodes(String.Format("//input[@name='topic_delete_{0:D2}']", ++i)).Any())
            {
                string index = i.ToString("D2");
                this.TopicList.Add(new Topic()
                {
                    Name = (string)GetNodeValue(doc, _nameTag + index),
                    Regexes = GetNodeListValue(doc, _regexTag + index),
                    Description = GetNodeListValue(doc, _descTag + index).Cat(),
                });
            }
        }
Example #12
0
        public static int Solution(int[] a)
        {
            Dictionary<int, int> dict = new Dictionary<int, int>();

            for (int i = 0; i < a.Length; i++)
            {
                if (dict.ContainsKey(a[i]))
                {
                    dict[a[i]]++;
                }
                else
                {
                    dict[a[i]] = 1;
                }
            }

            return dict.Single(p => p.Value == 1).Key;
        }
        /// <summary>
        /// Selects the Brush where the type matches from the Dictionary kept in the Legend.
        /// </summary>
        /// <param name="product"></param>
        /// <param name="dict"></param>
        /// <returns></returns>
        public SolidBrush SelectBrush(PlacedProduct product, Dictionary<string, SolidBrush> dict)
        {
            SolidBrush brush;
            try
            {
                CategoryModel Currentcat = product.Product.ProductCategory;

                if (Currentcat.IsSubcategoryFrom > -1 || Currentcat.IsSubcategoryFrom == null) // is a subcategory
                {
                    // gets the main category id
                    int MainId = (int) Currentcat.IsSubcategoryFrom;

                    // linq select category with the current id
                    var selectedcategory2 = CategoryModel.List
                        .Where(c => c.CatId == MainId)
                        .Select(c => c)
                        .ToList();

                    CategoryModel Main = selectedcategory2[0];

                    // gets the value (color) from the Main productcategory
                    brush = new SolidBrush(Main.Colour);
                }
                else // is a maincategory
                {
                    // give the color from the main category
                    brush = dict.Single(pair => pair.Key.Equals(product.Product.Category)).Value;
                }
            }
            catch (InvalidOperationException e)
            {
                // This means that the type is not found in the dictionary, and so I will set the Brush to Black
                brush = new SolidBrush(Color.Gray);
            }
            return brush;
        }
Example #14
0
		/// <summary>
		/// Checks the request and query strings to see if it matches the definition of having a Surface controller
		/// posted value, if so, then we return a PostedDataProxyInfo object with the correct information.
		/// </summary>
		/// <param name="requestContext"></param>
		/// <returns></returns>
		private static PostedDataProxyInfo GetPostedFormInfo(RequestContext requestContext)
		{
			if (requestContext.HttpContext.Request.RequestType != "POST")
				return null;

			//this field will contain a base64 encoded version of the surface route vals 
			if (requestContext.HttpContext.Request["uformpostroutevals"].IsNullOrWhiteSpace())
				return null;

			var encodedVal = requestContext.HttpContext.Request["uformpostroutevals"];
			var decryptedString = encodedVal.DecryptWithMachineKey();
			var parsedQueryString = HttpUtility.ParseQueryString(decryptedString);

			var decodedParts = new Dictionary<string, string>();

			foreach (var key in parsedQueryString.AllKeys)
			{
				decodedParts[key] = parsedQueryString[key];
			}

			//validate all required keys exist

			//the controller
			if (!decodedParts.Any(x => x.Key == ReservedAdditionalKeys.Controller))
				return null;
			//the action
			if (!decodedParts.Any(x => x.Key == ReservedAdditionalKeys.Action))
				return null;
			//the area
			if (!decodedParts.Any(x => x.Key == ReservedAdditionalKeys.Area))
				return null;

			////the controller type, if it contains this then it is a plugin controller, not locally declared.
			//if (decodedParts.Any(x => x.Key == "t"))
			//{
			//    return new PostedDataProxyInfo
			//    {
			//        ControllerName = requestContext.HttpContext.Server.UrlDecode(decodedParts.Single(x => x.Key == "c").Value),
			//        ActionName = requestContext.HttpContext.Server.UrlDecode(decodedParts.Single(x => x.Key == "a").Value),
			//        Area = requestContext.HttpContext.Server.UrlDecode(decodedParts.Single(x => x.Key == "ar").Value),
			//        ControllerType = requestContext.HttpContext.Server.UrlDecode(decodedParts.Single(x => x.Key == "t").Value)
			//    };				
			//}

			foreach (var item in decodedParts.Where(x => !new string[] { 
				ReservedAdditionalKeys.Controller, 
				ReservedAdditionalKeys.Action, 
				ReservedAdditionalKeys.Area }.Contains(x.Key)))
			{
				// Populate route with additional values which aren't reserved values so they eventually to action parameters
				requestContext.RouteData.Values.Add(item.Key, item.Value);
			}

			//return the proxy info without the surface id... could be a local controller.
			return new PostedDataProxyInfo
			{
				ControllerName = requestContext.HttpContext.Server.UrlDecode(decodedParts.Single(x => x.Key == ReservedAdditionalKeys.Controller).Value),
				ActionName = requestContext.HttpContext.Server.UrlDecode(decodedParts.Single(x => x.Key == ReservedAdditionalKeys.Action).Value),
				Area = requestContext.HttpContext.Server.UrlDecode(decodedParts.Single(x => x.Key == ReservedAdditionalKeys.Area).Value),
			};
		}
Example #15
0
        public override void Weave(
            TypeDefinition typeDef,
            AssemblyDefinition assemblyDefinition,
            MapDefinition mapDefinition,
            Dictionary<string, List<MapDefinition>> assemblyMapDefinitions,
            Dictionary<string, AssemblyDefinition> assemblyDefinitions) {
            var boolTypeDef = typeDef.Module.Import(typeof(bool));
            foreach (var columnDef in
                mapDefinition.ColumnDefinitions.Where(
                    c => c.Relationship == RelationshipType.ManyToOne || c.Relationship == RelationshipType.OneToOne)) {
                // remember the property may be defined on a parent class
                var propDef = this.GetProperty(typeDef, columnDef.Name);

                // add a field with DbType and DbName 
                TypeReference fkTypeReference;
                var fkPkType = columnDef.DbType.GetCLRType();
                if (fkPkType.IsValueType) {
                    fkTypeReference = typeDef.Module.Import(typeof(Nullable<>).MakeGenericType(fkPkType));
                }
                else {
                    fkTypeReference = typeDef.Module.Import(fkPkType);
                }

                var fkField = new FieldDefinition(columnDef.DbName, FieldAttributes.Public, fkTypeReference);
                if (propDef.DeclaringType.Fields.Any(f => f.Name == columnDef.DbName)) {
                    continue; // already done something here!
                }

                this.MakeNotDebuggerBrowsable(typeDef.Module, fkField);
                propDef.DeclaringType.Fields.Add(fkField);

                // override the set method to set to null
                propDef.SetMethod.Body.Instructions.Insert(0, Instruction.Create(OpCodes.Initobj, fkTypeReference));
                propDef.SetMethod.Body.Instructions.Insert(0, Instruction.Create(OpCodes.Ldflda, fkField));
                propDef.SetMethod.Body.Instructions.Insert(0, Instruction.Create(OpCodes.Ldarg_0));

                // override the get method to access this field if null and create a new instance
                // TODO solve for non auto properties
                if (!propDef.GetMethod.Body.Variables.Any()) {
                    // Release code is different to debug code!
                    propDef.GetMethod.Body.Variables.Add(new VariableDefinition(propDef.PropertyType));
                }

                propDef.GetMethod.Body.Variables.Add(new VariableDefinition(propDef.PropertyType));
                propDef.GetMethod.Body.Variables.Add(new VariableDefinition(boolTypeDef));
                propDef.GetMethod.Body.InitLocals = true;
                //propDef.GetMethod.Body.Instructions.Clear();

                var backingField = this.GetBackingField(propDef);
                var il = propDef.GetMethod.Body.Instructions;
                var lastInstr = il[0];
                var index = 0;

                // first bit does the null/hasValue checks on the backing fields
                il.Insert(index++, Instruction.Create(OpCodes.Ldarg_0));
                il.Insert(index++, Instruction.Create(OpCodes.Ldfld, backingField));

                il.Insert(index++, Instruction.Create(OpCodes.Brtrue, lastInstr));

                if (fkPkType.IsValueType) {
                    il.Insert(index++, Instruction.Create(OpCodes.Ldarg_0));
                    il.Insert(index++, Instruction.Create(OpCodes.Ldflda, fkField));
                    il.Insert(
                        index++,
                        Instruction.Create(
                            OpCodes.Call,
                            MakeGeneric(
                                typeDef.Module.Import(fkTypeReference.Resolve().GetMethods().Single(m => m.Name == "get_HasValue")),
                                typeDef.Module.Import(fkPkType))));
                }
                else {
                    il.Insert(index++, Instruction.Create(OpCodes.Ldarg_0));
                    il.Insert(index++, Instruction.Create(OpCodes.Ldfld, fkField));
                }

                il.Insert(index++, Instruction.Create(OpCodes.Brfalse, lastInstr));

                // if we have a pk but no ref we create a new instance with the primary key set
                il.Insert(index++, Instruction.Create(OpCodes.Ldarg_0));
                il.Insert(
                    index++,
                    Instruction.Create(OpCodes.Newobj, typeDef.Module.Import(propDef.PropertyType.Resolve().GetConstructors().First())));
                il.Insert(index++, Instruction.Create(OpCodes.Stloc_0));
                il.Insert(index++, Instruction.Create(OpCodes.Ldloc_0));
                il.Insert(index++, Instruction.Create(OpCodes.Ldarg_0));

                if (fkPkType.IsValueType) {
                    il.Insert(index++, Instruction.Create(OpCodes.Ldflda, fkField));
                    il.Insert(
                        index++,
                        Instruction.Create(
                            OpCodes.Call,
                            typeDef.Module.Import(
                                MakeGeneric(
                                    fkField.FieldType.Resolve().GetMethods().Single(m => m.Name == "get_Value"),
                                    typeDef.Module.Import(fkPkType)))));
                    var fkMapDef = assemblyMapDefinitions.SelectMany(am => am.Value).First(m => m.TypeFullName == columnDef.TypeFullName);
                    var assemblyDef = assemblyDefinitions.Single(ad => ad.Value.FullName == fkMapDef.AssemblyFullName).Value;
                    var fkMapTypeRef = GetTypeDefFromFullName(columnDef.TypeFullName, assemblyDef);
                    il.Insert(
                        index++,
                        Instruction.Create(
                            OpCodes.Callvirt,
                            typeDef.Module.Import(
                                this.GetProperty(fkMapTypeRef, fkMapDef.ColumnDefinitions.Single(cd => cd.IsPrimaryKey).Name).SetMethod)));
                }
                else {
                    il.Insert(index++, Instruction.Create(OpCodes.Ldfld, fkField));
                    var fkMapDef = assemblyMapDefinitions.SelectMany(am => am.Value).First(m => m.TypeFullName == columnDef.TypeFullName);
                    var assemblyDef = assemblyDefinitions.Single(ad => ad.Value.FullName == fkMapDef.AssemblyFullName).Value;
                    var fkMapTypeRef = GetTypeDefFromFullName(columnDef.TypeFullName, assemblyDef);
                    il.Insert(
                        index++,
                        Instruction.Create(
                            OpCodes.Callvirt,
                            typeDef.Module.Import(
                                this.GetProperty(fkMapTypeRef, fkMapDef.ColumnDefinitions.Single(cd => cd.IsPrimaryKey).Name).SetMethod)));
                }

                il.Insert(index++, Instruction.Create(OpCodes.Ldloc_0));
                il.Insert(index, Instruction.Create(OpCodes.Stfld, backingField));
            }
        }
Example #16
0
 public IEnumerable<ItemData> GetItemsToRecycle(Dictionary<ItemId, int> filter)
 {
     return Items
         .Where(x => filter.Any(f => f.Key == x.ItemId && x.Count > f.Value))
         .Select(
             x =>
                 new ItemData
                 {
                     ItemId = x.ItemId,
                     Count =
                         x.Count - filter.Single(f => f.Key == x.ItemId).Value,
                     Unseen = x.Unseen
                 });
 }
Example #17
0
        private void ImplementITrackedEntityForTypeDefinition(TypeDefinition typeDef, MapDefinition mapDefinition, bool notInInheritance, Dictionary<string, AssemblyDefinition> assemblyDefinitions, Dictionary<string, List<MapDefinition>> assemblyMapDefinitions) {
            if (typeDef.Methods.Any(m => m.Name == "GetDirtyProperties")) {
                return; // type already woven
            }

            if (!this.ImplementsInterface(typeDef, typeof(ITrackedEntity))) {
                this.AddInterfaceToNonObjectAncestor(typeDef, typeof(ITrackedEntity));
            }

            // some common type definitions
            var boolTypeDef = typeDef.Module.Import(typeof(bool));
            var voidTypeDef = typeDef.Module.Import(typeof(void));
            var stringTypeDef = typeDef.Module.Import(typeof(string));
            var listStringTypeDef = typeDef.Module.Import(typeof(List<>)).MakeGenericInstanceType(stringTypeDef);
            var objectTypeDef = typeDef.Module.Import(typeof(object));

            // some column names
            const string isTrackingName = "__isTracking";

            // add isTracking field if base class
            if (this.IsBaseClass(typeDef)) {
                var _isTrackingField = new FieldDefinition(isTrackingName, FieldAttributes.Family, boolTypeDef);
                this.MakeNotDebuggerBrowsable(typeDef.Module, _isTrackingField);
                typeDef.Fields.Add(_isTrackingField);
            }

            // fields for tracking state of properties on this class only
            var nonPkCols = mapDefinition.ColumnDefinitions.Where(c => !c.IsPrimaryKey && c.Relationship != RelationshipType.OneToMany).ToList();
            foreach (var columnDefinition in nonPkCols) {
                if (this.HasPropertyInInheritanceChain(typeDef, columnDefinition.Name)) {
                    var propertyDefinition = this.GetProperty(typeDef, columnDefinition.Name);
                    if (propertyDefinition.DeclaringType.FullName == typeDef.FullName) {
                        var dirtyField = new FieldDefinition(
                            string.Format("__{0}_IsDirty", columnDefinition.Name),
                            FieldAttributes.Family,
                            boolTypeDef);
                        this.MakeNotDebuggerBrowsable(typeDef.Module, dirtyField);
                        typeDef.Fields.Add(dirtyField);

                        // handle other maps, strings, valuetype, valuetype?
                        var oldValuePropType = propertyDefinition.PropertyType;
                        if (columnDefinition.Relationship == RelationshipType.None && propertyDefinition.PropertyType.IsValueType
                            && propertyDefinition.PropertyType.Name != "Nullable`1") {
                            oldValuePropType = typeDef.Module.Import(typeof(Nullable<>)).MakeGenericInstanceType(oldValuePropType);
                            // use nullable value types
                        }

                        var oldValueField = new FieldDefinition(
                            string.Format("__{0}_OldValue", columnDefinition.Name),
                            FieldAttributes.Family,
                            oldValuePropType);
                        this.MakeNotDebuggerBrowsable(typeDef.Module, oldValueField);
                        typeDef.Fields.Add(oldValueField);
                    }
                }
            }

            // insert the instructions in to the setter
            var isTrackingField = this.GetField(typeDef, isTrackingName);
            foreach (var columnDefinition in nonPkCols) {
                if (this.HasPropertyInInheritanceChain(typeDef, columnDefinition.Name)) {
                    var propertyDefinition = this.GetProperty(typeDef, columnDefinition.Name);
                    if (propertyDefinition.DeclaringType.FullName == typeDef.FullName) {
                        var backingField = this.GetBackingField(propertyDefinition);
                        var setter = propertyDefinition.SetMethod;
                        setter.Body.Variables.Add(new VariableDefinition(boolTypeDef)); // we need a local bool
                        setter.Body.InitLocals = true;
                        var setIl = setter.Body.Instructions;
                        var setIntructions = new List<Instruction>();
                        setIntructions.Add(Instruction.Create(OpCodes.Nop));
                        setIntructions.Add(Instruction.Create(OpCodes.Ldarg_0));
                        setIntructions.Add(Instruction.Create(OpCodes.Ldfld, isTrackingField));
                        setIntructions.Add(Instruction.Create(OpCodes.Ldc_I4_0));
                        setIntructions.Add(Instruction.Create(OpCodes.Ceq));
                        setIntructions.Add(Instruction.Create(OpCodes.Stloc_0));
                        setIntructions.Add(Instruction.Create(OpCodes.Ldloc_0));
                        var endNopInstr = Instruction.Create(OpCodes.Nop);
                        var endLdArgInstr = setIl.First();
                        setIntructions.Add(Instruction.Create(OpCodes.Brtrue, endLdArgInstr));
                        setIntructions.Add(Instruction.Create(OpCodes.Nop));
                        setIntructions.Add(Instruction.Create(OpCodes.Ldarg_0));
                        setIntructions.Add(
                            Instruction.Create(
                                OpCodes.Ldfld,
                                typeDef.Fields.Single(f => f.Name == string.Format("__{0}_IsDirty", columnDefinition.Name))));
                        setIntructions.Add(Instruction.Create(OpCodes.Stloc_0));
                        setIntructions.Add(Instruction.Create(OpCodes.Ldloc_0));
                        setIntructions.Add(Instruction.Create(OpCodes.Brtrue, endNopInstr));
                        setIntructions.Add(Instruction.Create(OpCodes.Nop));
                        setIntructions.Add(Instruction.Create(OpCodes.Ldarg_0));

                        if (propertyDefinition.PropertyType.IsValueType) {
                            var isEnum = propertyDefinition.PropertyType.Resolve().IsEnum;
                            if (isEnum) {
                                setIntructions.Add(Instruction.Create(OpCodes.Ldfld, backingField));
                                setIntructions.Add(Instruction.Create(OpCodes.Box, propertyDefinition.PropertyType));
                            }
                            else {
                                setIntructions.Add(Instruction.Create(OpCodes.Ldflda, backingField));
                            }

                            setIntructions.Add(Instruction.Create(OpCodes.Ldarg_1));
                            if (isEnum) {
                                setIntructions.Add(Instruction.Create(OpCodes.Box, propertyDefinition.PropertyType));
                                setIntructions.Add(
                                    Instruction.Create(
                                        OpCodes.Callvirt,
                                        typeDef.Module.Import(
                                            objectTypeDef.Resolve()
                                                         .GetMethods()
                                                         .Single(
                                                             m =>
                                                             m.Name == "Equals" && m.Parameters.Count == 1
                                                             && m.Parameters.First().ParameterType.Name.ToLowerInvariant() == "object"))));
                            }
                            else if (propertyDefinition.PropertyType.Name == "Nullable`1") {
                                setIntructions.Add(Instruction.Create(OpCodes.Box, backingField.FieldType));
                                setIntructions.Add(Instruction.Create(OpCodes.Constrained, backingField.FieldType));
                                setIntructions.Add(
                                    Instruction.Create(
                                        OpCodes.Callvirt,
                                        typeDef.Module.Import(
                                            objectTypeDef.Resolve()
                                                         .GetMethods()
                                                         .Single(
                                                             m =>
                                                             m.Name == "Equals" && m.Parameters.Count == 1
                                                             && m.Parameters.First().ParameterType.Name.ToLowerInvariant() == "object"))));
                            }
                            else {
                                setIntructions.Add(
                                    Instruction.Create(
                                        OpCodes.Call,
                                        typeDef.Module.Import(
                                            propertyDefinition.PropertyType.Resolve()
                                                              .Methods.Single(
                                                                  m =>
                                                                  m.Name == "Equals" && m.Parameters.Count == 1
                                                                  && m.Parameters.First().ParameterType.Name.ToLowerInvariant() != "object"))));
                            }

                            setIntructions.Add(Instruction.Create(OpCodes.Stloc_0));
                            setIntructions.Add(Instruction.Create(OpCodes.Ldloc_0));
                            setIntructions.Add(Instruction.Create(OpCodes.Brtrue, endNopInstr));
                        }
                        else {
                            var fkPkType = columnDefinition.DbType.GetCLRType();
                            TypeReference fkTypeReference;
                            if (fkPkType.IsValueType) {
                                fkTypeReference = typeDef.Module.Import(typeof(Nullable<>).MakeGenericType(fkPkType));
                            }
                            else {
                                fkTypeReference = typeDef.Module.Import(fkPkType);
                            }

                            setIntructions.Add(Instruction.Create(OpCodes.Ldfld, backingField));
                            var hmmInstr = Instruction.Create(OpCodes.Ldc_I4_0);
                            var hmmInstr2 = Instruction.Create(OpCodes.Ldc_I4_1);

                            if (propertyDefinition.PropertyType.Name.ToLowerInvariant() == "string") {
                                var orInstr = Instruction.Create(OpCodes.Ldarg_0);
                                setIntructions.Add(Instruction.Create(OpCodes.Brtrue, orInstr));
                                setIntructions.Add(Instruction.Create(OpCodes.Ldarg_1));
                                setIntructions.Add(Instruction.Create(OpCodes.Brtrue, hmmInstr));
                                setIntructions.Add(orInstr);
                            }
                            else {
                                var orInstr = Instruction.Create(OpCodes.Ldarg_1);
                                var orInstr2 = Instruction.Create(OpCodes.Ldarg_0);
                                setIntructions.Add(Instruction.Create(OpCodes.Brtrue, orInstr));
                                setIntructions.Add(Instruction.Create(OpCodes.Ldarg_1));
                                setIntructions.Add(Instruction.Create(OpCodes.Brtrue, hmmInstr));
                                setIntructions.Add(orInstr);
                                setIntructions.Add(Instruction.Create(OpCodes.Brtrue, orInstr2));
                                setIntructions.Add(Instruction.Create(OpCodes.Ldarg_0));

                                if (fkPkType.IsValueType) {
                                    // need to call HasValue
                                    setIntructions.Add(Instruction.Create(OpCodes.Ldflda, typeDef.Fields.Single(f => f.Name == columnDefinition.DbName)));
                                    setIntructions.Add(Instruction.Create(
                                        OpCodes.Call,
                                        MakeGeneric(
                                            typeDef.Module.Import(fkTypeReference.Resolve().GetMethods().Single(m => m.Name == "get_HasValue")),
                                            typeDef.Module.Import(fkPkType))));
                                    setIntructions.Add(Instruction.Create(OpCodes.Brtrue, hmmInstr));
                                }
                                else {
                                    // check for null
                                    setIntructions.Add(Instruction.Create(OpCodes.Ldfld, typeDef.Fields.Single(f => f.Name == columnDefinition.DbName)));
                                    setIntructions.Add(Instruction.Create(OpCodes.Brtrue, hmmInstr));
                                }

                                setIntructions.Add(orInstr2);
                            }

                            setIntructions.Add(Instruction.Create(OpCodes.Ldfld, backingField));
                            setIntructions.Add(Instruction.Create(OpCodes.Brfalse, hmmInstr2));
                            setIntructions.Add(Instruction.Create(OpCodes.Ldarg_0));
                            setIntructions.Add(Instruction.Create(OpCodes.Ldfld, backingField));
                            setIntructions.Add(Instruction.Create(OpCodes.Ldarg_1));
                            if (propertyDefinition.PropertyType.Name.ToLowerInvariant() == "string") {
                                setIntructions.Add(
                                    Instruction.Create(
                                        OpCodes.Callvirt,
                                        typeDef.Module.Import(
                                            propertyDefinition.PropertyType.Resolve()
                                                              .GetMethods()
                                                              .Single(
                                                                  m =>
                                                                  m.Name == "Equals" && m.Parameters.Count == 1
                                                                  && m.Parameters.First().ParameterType.Name.ToLowerInvariant() == "string"))));
                            }
                            else {
                                setIntructions.Add(
                                    Instruction.Create(
                                        OpCodes.Callvirt,
                                        typeDef.Module.Import(
                                            objectTypeDef.Resolve()
                                                         .GetMethods()
                                                         .Single(
                                                             m =>
                                                             m.Name == "Equals" && m.Parameters.Count == 1
                                                             && m.Parameters.First().ParameterType.Name.ToLowerInvariant() == "object"))));
                            }

                            var nopInstr = Instruction.Create(OpCodes.Nop);
                            setIntructions.Add(Instruction.Create(OpCodes.Br, nopInstr));
                            setIntructions.Add(hmmInstr2);
                            setIntructions.Add(nopInstr);
                            var nopInstr2 = Instruction.Create(OpCodes.Nop);
                            setIntructions.Add(Instruction.Create(OpCodes.Br, nopInstr2));
                            setIntructions.Add(hmmInstr);
                            setIntructions.Add(nopInstr2);
                            setIntructions.Add(Instruction.Create(OpCodes.Stloc_0));
                            setIntructions.Add(Instruction.Create(OpCodes.Ldloc_0));
                            setIntructions.Add(Instruction.Create(OpCodes.Brtrue, endNopInstr));
                            setIntructions.Add(Instruction.Create(OpCodes.Nop));
                        }

                        // it's now dirty
                        setIntructions.Add(Instruction.Create(OpCodes.Nop));

                        var topOfSetIsDirtyInstr = Instruction.Create(OpCodes.Ldarg_0);
                        if (columnDefinition.Relationship == RelationshipType.ManyToOne || columnDefinition.Relationship == RelationshipType.OneToOne) {
                            // we need to check whether the foreign key backing field has a value
                            var setToBackingFieldInstr = Instruction.Create(OpCodes.Ldarg_0);
                            setIntructions.Add(Instruction.Create(OpCodes.Ldarg_0));
                            setIntructions.Add(Instruction.Create(OpCodes.Ldfld, backingField));
                            setIntructions.Add(Instruction.Create(OpCodes.Brtrue, setToBackingFieldInstr));
                            var fkPkType = columnDefinition.DbType.GetCLRType();
                            TypeReference fkTypeReference;
                            if (fkPkType.IsValueType) {
                                fkTypeReference = typeDef.Module.Import(typeof(Nullable<>).MakeGenericType(fkPkType));
                            }
                            else {
                                fkTypeReference = typeDef.Module.Import(fkPkType);
                            }

                            var fkField = typeDef.Fields.Single(f => f.Name == columnDefinition.DbName);
                            setIntructions.Add(Instruction.Create(OpCodes.Ldarg_0));
                            if (fkPkType.IsValueType) {
                                // need to call HasValue
                                setIntructions.Add(Instruction.Create(OpCodes.Ldflda, fkField));
                                setIntructions.Add(Instruction.Create(
                                    OpCodes.Call,
                                    MakeGeneric(
                                        typeDef.Module.Import(fkTypeReference.Resolve().GetMethods().Single(m => m.Name == "get_HasValue")),
                                        typeDef.Module.Import(fkPkType))));
                                setIntructions.Add(Instruction.Create(OpCodes.Brfalse, setToBackingFieldInstr));
                            }
                            else {
                                // check for null
                                setIntructions.Add(Instruction.Create(OpCodes.Ldfld, fkField));
                                setIntructions.Add(Instruction.Create(OpCodes.Brfalse, setToBackingFieldInstr));
                            }

                            // need to add a variable to hold the new obj
                            var fkGeneratedVariableDef = new VariableDefinition(propertyDefinition.PropertyType);
                            propertyDefinition.SetMethod.Body.Variables.Add(fkGeneratedVariableDef);

                            // if we get here then we have an FK value but null in this backing field so we need to create a new instance of the FK and set that as the old value
                            setIntructions.Add(Instruction.Create(OpCodes.Ldarg_0));
                            setIntructions.Add(Instruction.Create(OpCodes.Newobj, typeDef.Module.Import(propertyDefinition.PropertyType.Resolve().GetConstructors().First())));
                            setIntructions.Add(Instruction.Create(OpCodes.Stloc, fkGeneratedVariableDef));
                            setIntructions.Add(Instruction.Create(OpCodes.Ldloc, fkGeneratedVariableDef));
                            setIntructions.Add(Instruction.Create(OpCodes.Ldarg_0));
                            if (fkPkType.IsValueType) {
                                setIntructions.Add(Instruction.Create(OpCodes.Ldflda, typeDef.Fields.Single(f => f.Name == columnDefinition.DbName)));
                                setIntructions.Add(Instruction.Create(
                                        OpCodes.Call,
                                        typeDef.Module.Import(
                                            MakeGeneric(
                                                fkField.FieldType.Resolve().GetMethods().Single(m => m.Name == "get_Value"),
                                                typeDef.Module.Import(fkPkType)))));
                                var fkMapDef = assemblyMapDefinitions.SelectMany(am => am.Value).First(m => m.TypeFullName == columnDefinition.TypeFullName);
                                var assemblyDef = assemblyDefinitions.Single(ad => ad.Value.FullName == fkMapDef.AssemblyFullName).Value;
                                var fkMapTypeRef = GetTypeDefFromFullName(columnDefinition.TypeFullName, assemblyDef);
                                setIntructions.Add(
                                    Instruction.Create(
                                        OpCodes.Callvirt,
                                        typeDef.Module.Import(
                                            this.GetProperty(fkMapTypeRef, fkMapDef.ColumnDefinitions.Single(cd => cd.IsPrimaryKey).Name).SetMethod)));
                            }
                            else {
                                setIntructions.Add(Instruction.Create(OpCodes.Ldfld, fkField));
                                var fkMapDef = assemblyMapDefinitions.SelectMany(am => am.Value).First(m => m.TypeFullName == columnDefinition.TypeFullName);
                                var assemblyDef = assemblyDefinitions.Single(ad => ad.Value.FullName == fkMapDef.AssemblyFullName).Value;
                                var fkMapTypeRef = GetTypeDefFromFullName(columnDefinition.TypeFullName, assemblyDef);
                                setIntructions.Add(Instruction.Create(
                                        OpCodes.Callvirt,
                                        typeDef.Module.Import(
                                            this.GetProperty(fkMapTypeRef, fkMapDef.ColumnDefinitions.Single(cd => cd.IsPrimaryKey).Name).SetMethod)));
                            }

                            setIntructions.Add(Instruction.Create(OpCodes.Ldloc, fkGeneratedVariableDef));
                            setIntructions.Add(Instruction.Create(OpCodes.Stfld, typeDef.Fields.Single(f => f.Name == string.Format("__{0}_OldValue", columnDefinition.Name))));
                            setIntructions.Add(Instruction.Create(OpCodes.Br, topOfSetIsDirtyInstr));

                            // set using backing field
                            setIntructions.Add(setToBackingFieldInstr);
                            setIntructions.Add(Instruction.Create(OpCodes.Ldarg_0));
                            setIntructions.Add(Instruction.Create(OpCodes.Ldfld, backingField));
                            setIntructions.Add(
                                Instruction.Create(
                                    OpCodes.Stfld,
                                    typeDef.Fields.Single(f => f.Name == string.Format("__{0}_OldValue", columnDefinition.Name))));
                        }
                        else { 
                            setIntructions.Add(Instruction.Create(OpCodes.Ldarg_0));
                            setIntructions.Add(Instruction.Create(OpCodes.Ldarg_0));
                            setIntructions.Add(Instruction.Create(OpCodes.Ldfld, backingField));
                            if (columnDefinition.Relationship == RelationshipType.None && propertyDefinition.PropertyType.IsValueType
                                && propertyDefinition.PropertyType.Name != "Nullable`1") {
                                setIntructions.Add(
                                    Instruction.Create(
                                        OpCodes.Newobj,
                                        MakeGeneric(
                                            typeDef.Module.Import(
                                                typeDef.Fields.Single(f => f.Name == string.Format("__{0}_OldValue", columnDefinition.Name))
                                                       .FieldType.Resolve()
                                                       .GetConstructors()
                                                       .First()),
                                            propertyDefinition.PropertyType)));
                            }

                            setIntructions.Add(
                                Instruction.Create(
                                    OpCodes.Stfld,
                                    typeDef.Fields.Single(f => f.Name == string.Format("__{0}_OldValue", columnDefinition.Name))));
                        }

                        setIntructions.Add(topOfSetIsDirtyInstr);
                        setIntructions.Add(Instruction.Create(OpCodes.Ldc_I4_1));
                        setIntructions.Add(
                            Instruction.Create(
                                OpCodes.Stfld,
                                typeDef.Fields.Single(f => f.Name == string.Format("__{0}_IsDirty", columnDefinition.Name))));
                        setIntructions.Add(Instruction.Create(OpCodes.Nop));
                        setIntructions.Add(endNopInstr);
                        setIntructions.Reverse();
                        foreach (var instruction in setIntructions) {
                            setIl.Insert(0, instruction);
                        }
                    }
                }
            }

            // implement the ITrackedEntity methods
            // EnableTracking
            if (this.IsBaseClass(typeDef)) {
                var enableTracking = new MethodDefinition(
                    "EnableTracking",
                    MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual
                    | MethodAttributes.Final,
                    voidTypeDef);
                enableTracking.Body.Instructions.Add(Instruction.Create(OpCodes.Nop));
                enableTracking.Body.Instructions.Add(Instruction.Create(OpCodes.Ldarg_0));
                enableTracking.Body.Instructions.Add(Instruction.Create(OpCodes.Ldc_I4_1));
                enableTracking.Body.Instructions.Add(Instruction.Create(OpCodes.Stfld, typeDef.Fields.Single(f => f.Name == isTrackingName)));
                enableTracking.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
                typeDef.Methods.Add(enableTracking);
            }

            // DisableTracking
            var disableTrackingMethodAttrs = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual;
            if (notInInheritance) {
                disableTrackingMethodAttrs = disableTrackingMethodAttrs | MethodAttributes.NewSlot | MethodAttributes.Final;
            }
            var disableTracking = new MethodDefinition("DisableTracking", disableTrackingMethodAttrs, voidTypeDef);
            var disableInstructions = disableTracking.Body.Instructions;
            disableInstructions.Add(Instruction.Create(OpCodes.Nop));
            disableInstructions.Add(Instruction.Create(OpCodes.Ldarg_0));
            disableInstructions.Add(Instruction.Create(OpCodes.Ldc_I4_0));
            disableInstructions.Add(Instruction.Create(OpCodes.Stfld, isTrackingField));
            foreach (var col in nonPkCols) {
                if (this.HasPropertyInInheritanceChain(typeDef, col.Name)) {
                    var propDef = this.GetProperty(typeDef, col.Name);

                    // reset isdirty
                    disableInstructions.Add(Instruction.Create(OpCodes.Ldarg_0));
                    disableInstructions.Add(Instruction.Create(OpCodes.Ldc_I4_0));
                    disableInstructions.Add(Instruction.Create(OpCodes.Stfld, this.GetField(typeDef, string.Format("__{0}_IsDirty", col.Name))));

                    // reset oldvalue
                    disableInstructions.Add(Instruction.Create(OpCodes.Ldarg_0));
                    var oldValueField = this.GetField(typeDef, string.Format("__{0}_OldValue", col.Name));
                    if (propDef.PropertyType.IsValueType) {
                        disableInstructions.Add(Instruction.Create(OpCodes.Ldflda, oldValueField));
                        disableInstructions.Add(Instruction.Create(OpCodes.Initobj, oldValueField.FieldType));
                    }
                    else {
                        disableInstructions.Add(Instruction.Create(OpCodes.Ldnull));
                        disableInstructions.Add(Instruction.Create(OpCodes.Stfld, oldValueField));
                    }
                }
            }

            disableInstructions.Add(Instruction.Create(OpCodes.Ret));
            typeDef.Methods.Add(disableTracking);

            // IsTrackingEnabled
            if (this.IsBaseClass(typeDef)) {
                var isTrackingEnabled = new MethodDefinition(
                    "IsTrackingEnabled",
                    MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual
                    | MethodAttributes.Final,
                    boolTypeDef);
                isTrackingEnabled.Body.Instructions.Add(Instruction.Create(OpCodes.Nop));
                isTrackingEnabled.Body.Instructions.Add(Instruction.Create(OpCodes.Ldarg_0));
                isTrackingEnabled.Body.Instructions.Add(Instruction.Create(OpCodes.Ldfld, typeDef.Fields.Single(f => f.Name == isTrackingName)));
                isTrackingEnabled.Body.Instructions.Add(Instruction.Create(OpCodes.Stloc_0));
                var loadInstr = Instruction.Create(OpCodes.Ldloc_0);
                isTrackingEnabled.Body.Instructions.Add(Instruction.Create(OpCodes.Br, loadInstr));
                isTrackingEnabled.Body.Instructions.Add(loadInstr);
                isTrackingEnabled.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
                isTrackingEnabled.Body.InitLocals = true;
                isTrackingEnabled.Body.Variables.Add(new VariableDefinition(boolTypeDef));
                typeDef.Methods.Add(isTrackingEnabled);
            }

            // GetDirtyProperties
            var getDirtyPropertiesMethodAttrs = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual;
            if (notInInheritance) {
                getDirtyPropertiesMethodAttrs = getDirtyPropertiesMethodAttrs | MethodAttributes.NewSlot | MethodAttributes.Final;
            }
            var getDirtyProperties = new MethodDefinition(
                "GetDirtyProperties",
                getDirtyPropertiesMethodAttrs,
                typeDef.Module.Import(typeof(IEnumerable<>)).MakeGenericInstanceType(stringTypeDef));
            getDirtyProperties.Body.Variables.Add(new VariableDefinition("dirtyProps", listStringTypeDef));
            getDirtyProperties.Body.Variables.Add(
                new VariableDefinition(typeDef.Module.Import(typeof(IEnumerable<>)).MakeGenericInstanceType(stringTypeDef)));
            getDirtyProperties.Body.Variables.Add(new VariableDefinition(boolTypeDef));
            getDirtyProperties.Body.InitLocals = true;
            var instructions = getDirtyProperties.Body.Instructions;
            instructions.Add(Instruction.Create(OpCodes.Nop));
            var listStringContruictor =
                MakeGeneric(
                    typeDef.Module.Import(listStringTypeDef.Resolve().GetConstructors().First(c => !c.HasParameters && !c.IsStatic && c.IsPublic)),
                    stringTypeDef);
            instructions.Add(Instruction.Create(OpCodes.Newobj, listStringContruictor));
            instructions.Add(Instruction.Create(OpCodes.Stloc_0));

            var breakToInstruction = Instruction.Create(nonPkCols.Count == 1 ? OpCodes.Ldloc_0 : OpCodes.Ldarg_0);
            var addMethod = typeDef.Module.Import(listStringTypeDef.Resolve().Methods.Single(m => m.Name == "Add"));
            addMethod = MakeGeneric(addMethod, stringTypeDef);
            var visibleCols = nonPkCols.Where(c => this.HasPropertyInInheritanceChain(typeDef, c.Name)).ToList();
            for (var i = 0; i < visibleCols.Count; i++) {
                if (i == 0) {
                    instructions.Add(Instruction.Create(OpCodes.Ldarg_0));
                }

                instructions.Add(
                    Instruction.Create(OpCodes.Ldfld, this.GetField(typeDef, string.Format("__{0}_IsDirty", visibleCols.ElementAt(i).Name))));
                instructions.Add(Instruction.Create(OpCodes.Ldc_I4_0));
                instructions.Add(Instruction.Create(OpCodes.Ceq));
                instructions.Add(Instruction.Create(OpCodes.Stloc_2));
                instructions.Add(Instruction.Create(OpCodes.Ldloc_2));
                instructions.Add(Instruction.Create(OpCodes.Brtrue, breakToInstruction));
                instructions.Add(Instruction.Create(OpCodes.Nop));
                instructions.Add(Instruction.Create(OpCodes.Ldloc_0));
                instructions.Add(Instruction.Create(OpCodes.Ldstr, visibleCols.ElementAt(i).Name));
                instructions.Add(Instruction.Create(OpCodes.Callvirt, addMethod));
                instructions.Add(Instruction.Create(OpCodes.Nop));
                instructions.Add(Instruction.Create(OpCodes.Nop));
                instructions.Add(breakToInstruction);
                breakToInstruction = Instruction.Create(i == visibleCols.Count - 2 ? OpCodes.Ldloc_0 : OpCodes.Ldarg_0);
            }

            instructions.Add(Instruction.Create(OpCodes.Stloc_1));
            var retInstr = Instruction.Create(OpCodes.Ldloc_1);
            instructions.Add(Instruction.Create(OpCodes.Br, retInstr));
            instructions.Add(retInstr);
            instructions.Add(Instruction.Create(OpCodes.Ret));
            typeDef.Methods.Add(getDirtyProperties);

            // GetOldValue
            var getOldValueMethodAttrs = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual;
            if (notInInheritance) {
                getOldValueMethodAttrs = getOldValueMethodAttrs | MethodAttributes.NewSlot | MethodAttributes.Final;
            }

            var getOldValue = new MethodDefinition("GetOldValue", getOldValueMethodAttrs, objectTypeDef);
            getOldValue.Parameters.Add(new ParameterDefinition("propertyName", ParameterAttributes.None, stringTypeDef));
            getOldValue.Body.Variables.Add(new VariableDefinition(objectTypeDef));
            getOldValue.Body.Variables.Add(new VariableDefinition(stringTypeDef));
            getOldValue.Body.Variables.Add(new VariableDefinition(boolTypeDef));
            getOldValue.Body.InitLocals = true;
            var getBodyInstructions = getOldValue.Body.Instructions;
            getBodyInstructions.Add(Instruction.Create(OpCodes.Nop));
            getBodyInstructions.Add(Instruction.Create(OpCodes.Ldarg_1));
            getBodyInstructions.Add(Instruction.Create(OpCodes.Stloc_1));
            getBodyInstructions.Add(Instruction.Create(OpCodes.Ldloc_1));

            var throwExceptionTarget = Instruction.Create(OpCodes.Ldstr, "propertyName");
            var returnTarget = Instruction.Create(OpCodes.Ldloc_0);
            getBodyInstructions.Add(Instruction.Create(OpCodes.Brfalse, throwExceptionTarget));

            var switchInstructions = new List<Instruction>();
            var opEqualityRef = typeDef.Module.Import(typeof(string).GetMethods().Single(m => m.Name == "op_Equality"));
            for (var i = 0; i < visibleCols.Count; i++) {
                // generate the switch bit
                getBodyInstructions.Add(Instruction.Create(OpCodes.Ldloc_1));
                getBodyInstructions.Add(Instruction.Create(OpCodes.Ldstr, visibleCols.ElementAt(i).Name));
                getBodyInstructions.Add(Instruction.Create(OpCodes.Call, opEqualityRef));

                // generate the if bit
                var targetInstr = Instruction.Create(OpCodes.Ldarg_0);
                getBodyInstructions.Add(Instruction.Create(OpCodes.Brtrue, targetInstr));
                switchInstructions.Add(targetInstr);
                switchInstructions.Add(
                    Instruction.Create(OpCodes.Ldfld, this.GetField(typeDef, String.Format("__{0}_IsDirty", visibleCols.ElementAt(i).Name))));
                switchInstructions.Add(Instruction.Create(OpCodes.Ldc_I4_0));
                switchInstructions.Add(Instruction.Create(OpCodes.Ceq));
                switchInstructions.Add(Instruction.Create(OpCodes.Stloc_2));
                switchInstructions.Add(Instruction.Create(OpCodes.Ldloc_2));

                // generate the return bit
                var breakInstruction = Instruction.Create(OpCodes.Br, throwExceptionTarget);
                switchInstructions.Add(Instruction.Create(OpCodes.Brtrue, breakInstruction));
                switchInstructions.Add(Instruction.Create(OpCodes.Nop));
                switchInstructions.Add(Instruction.Create(OpCodes.Ldarg_0));
                switchInstructions.Add(
                    Instruction.Create(OpCodes.Ldfld, this.GetField(typeDef, String.Format("__{0}_OldValue", visibleCols.ElementAt(i).Name))));
                if (this.GetProperty(typeDef, visibleCols.ElementAt(i).Name).PropertyType.IsValueType) {
                    switchInstructions.Add(
                        Instruction.Create(
                            OpCodes.Box,
                            this.GetField(typeDef, String.Format("__{0}_OldValue", visibleCols.ElementAt(i).Name)).FieldType));
                }

                switchInstructions.Add(Instruction.Create(OpCodes.Stloc_0));
                switchInstructions.Add(Instruction.Create(OpCodes.Br, returnTarget));
                switchInstructions.Add(breakInstruction);
            }

            // add a br
            getBodyInstructions.Add(Instruction.Create(OpCodes.Br, throwExceptionTarget));

            // run them
            foreach (var instruction in switchInstructions) {
                getBodyInstructions.Add(instruction);
            }

            // handle the exception
            getBodyInstructions.Add(Instruction.Create(OpCodes.Nop));
            getBodyInstructions.Add(throwExceptionTarget);
            getBodyInstructions.Add(
                Instruction.Create(OpCodes.Ldstr, "Either the property doesn't exist or it's not dirty. Consult GetDirtyProperties first"));
            getBodyInstructions.Add(
                Instruction.Create(
                    OpCodes.Newobj,
                    typeDef.Module.Import(
                        typeof(ArgumentOutOfRangeException).GetConstructors()
                                                           .First(
                                                               c =>
                                                               c.GetParameters().All(p => p.ParameterType == typeof(string))
                                                               && c.GetParameters().Count() == 2))));
            getBodyInstructions.Add(Instruction.Create(OpCodes.Throw));
            getBodyInstructions.Add(returnTarget);
            getBodyInstructions.Add(Instruction.Create(OpCodes.Ret));
            typeDef.Methods.Add(getOldValue);
        }
 public void SanitizePropertiesReplacesEmptyStringWithEmptyWordToEnsurePropertyValueWillBeSerializedWithoutExceptions()
 {
     var dictionary = new Dictionary<string, string> { { string.Empty, string.Empty } };
     dictionary.SanitizeProperties();
     Assert.Equal("(required property name is empty)", dictionary.Single().Key);
 }
	    /// <summary>
		/// Checks the request and query strings to see if it matches the definition of having a Surface controller
		/// posted/get value, if so, then we return a PostedDataProxyInfo object with the correct information.
		/// </summary>
		/// <param name="requestContext"></param>
		/// <returns></returns>
		private static PostedDataProxyInfo GetFormInfo(RequestContext requestContext)
		{
		    if (requestContext == null) throw new ArgumentNullException("requestContext");

		    //if it is a POST/GET then a value must be in the request
            if (requestContext.HttpContext.Request.QueryString["ufprt"].IsNullOrWhiteSpace() 
                && requestContext.HttpContext.Request.Form["ufprt"].IsNullOrWhiteSpace())
		    {
		        return null;
		    }

		    string encodedVal;
		    
		    switch (requestContext.HttpContext.Request.RequestType)
		    {
                case "POST":
                    //get the value from the request.
                    //this field will contain an encrypted version of the surface route vals.
                    encodedVal = requestContext.HttpContext.Request.Form["ufprt"];
		            break;
                case "GET":
                    //this field will contain an encrypted version of the surface route vals.
                    encodedVal = requestContext.HttpContext.Request.QueryString["ufprt"];
		            break;
                default:
		            return null;
		    }

            
            string decryptedString;
            try
            {
                decryptedString = encodedVal.DecryptWithMachineKey();
            }
            catch (FormatException)
            {
                LogHelper.Warn<RenderRouteHandler>("A value was detected in the ufprt parameter but Umbraco could not decrypt the string");
                return null;
            }

            var parsedQueryString = HttpUtility.ParseQueryString(decryptedString);
			var decodedParts = new Dictionary<string, string>();

			foreach (var key in parsedQueryString.AllKeys)
			{
				decodedParts[key] = parsedQueryString[key];
			}

			//validate all required keys exist

			//the controller
			if (decodedParts.All(x => x.Key != ReservedAdditionalKeys.Controller))
				return null;
			//the action
			if (decodedParts.All(x => x.Key != ReservedAdditionalKeys.Action))
				return null;
			//the area
			if (decodedParts.All(x => x.Key != ReservedAdditionalKeys.Area))
				return null;
            
			foreach (var item in decodedParts.Where(x => new[] { 
			    ReservedAdditionalKeys.Controller, 
			    ReservedAdditionalKeys.Action, 
			    ReservedAdditionalKeys.Area }.Contains(x.Key) == false))
			{
				// Populate route with additional values which aren't reserved values so they eventually to action parameters
			    requestContext.RouteData.Values[item.Key] = item.Value;
			}

			//return the proxy info without the surface id... could be a local controller.
			return new PostedDataProxyInfo
			{
				ControllerName = HttpUtility.UrlDecode(decodedParts.Single(x => x.Key == ReservedAdditionalKeys.Controller).Value),
                ActionName = HttpUtility.UrlDecode(decodedParts.Single(x => x.Key == ReservedAdditionalKeys.Action).Value),
                Area = HttpUtility.UrlDecode(decodedParts.Single(x => x.Key == ReservedAdditionalKeys.Area).Value),
			};
		}
 public static void InsertResult(List<FakeClient> clients, Dictionary<int, string> students)
 {
     ConnectDatabase();
     Recordset rs = null;
     try
     {
         rs = _db.OpenRecordset("SELECT * FROM Итоги", RecordsetTypeEnum.dbOpenDynaset, 0, LockTypeEnum.dbOptimistic);
         foreach (var client in clients)
         {
             var student = students.Single(x => x.Value == string.Concat(client.Person.SeconName, " ", client.Person.FirstName, " ", client.Person.ThirdName));
             if (client.Test != null)
                 foreach (var question in client.Test._data)
                 {
                     rs.AddNew();
                     (rs.Fields["IdС"] as Field2).Value = student.Key;
                     (rs.Fields["IdВ"] as Field2).Value = question.ID;
                     (rs.Fields["Балл за ответ"] as Field2).Value = question.PointQuestion;
                     rs._30_Update();
                 }
         }
         rs.Close();
     }
     catch { throw; }
     //finally
     //{
     //    rs?._30_Update();
     //    rs?.Close();
     //}
 }
Example #21
0
        protected override void DoAfterRead(Dictionary<string, HtmlDocument> docs)
        {
            var doc = docs.Single(d => d.Key == "privacy/spam").Value;

            int i = 0;
            while (doc.DocumentNode.SafeSelectNodes(String.Format("//input[@name='hdrfilter_delete_{0:D2}']", ++i)).Any())
            {
                string index = i.ToString("D2");

                this.FilterList.Add(new HeaderFilter()
                {
                    Regexes = GetNodeListValue(doc, _regexTag + index),
                    Action = GetNodeEnumValue<FilterAction>(doc, _actionTag + index)
                });
            }
        }
Example #22
0
		private LeastSquareFittedAstrometry SolveStarPairs(
			IStarMap starMap,
			Dictionary<ImagePixel, IStar> matchedPairs,
			Dictionary<int, ulong> matchedFeatureIdToStarIdIndexes,
			ThreeStarFit.StarPair pair_i,
			ThreeStarFit.StarPair pair_j,
			ThreeStarFit.StarPair pair_k,
			double fittedFocalLength,
			PyramidEntry pyramidLog, 
            int? minMatchedStars = null)
		{
			double RA0Deg, DE0Deg;

			ThreeStarFit coarseFit = new ThreeStarFit(m_PlateConfig, pair_i, pair_j, pair_k);
			if (!coarseFit.IsSolved)
			{
				if (coarseFit.IsSingularity)
				{
                    if (TangraConfig.Settings.TraceLevels.PlateSolving.TraceVerbose())
					    Trace.WriteLine("ThreeStarFit.Var1 - Singularity");

					Dictionary<ImagePixel, IStar> threeStarDict = new Dictionary<ImagePixel, IStar>();

				    try
				    {
                        threeStarDict.Add(ImagePixel.CreateImagePixelWithFeatureId(0, 255, pair_i.XImage, pair_i.YImage), pair_i.Star);
                        threeStarDict.Add(ImagePixel.CreateImagePixelWithFeatureId(1, 255, pair_j.XImage, pair_j.YImage), pair_j.Star);
                        threeStarDict.Add(ImagePixel.CreateImagePixelWithFeatureId(2, 255, pair_k.XImage, pair_k.YImage), pair_k.Star);
				    }
                    catch(ArgumentException)
                    {
                        if (pyramidLog != null) pyramidLog.FailureReason = PyramidEntryFailureReason.ThreeStarFitFailed;

                        if (TangraConfig.Settings.TraceLevels.PlateSolving.TraceVerbose())
                            Trace.WriteLine("ThreeStarFit.Var2 - Failed with ArgumentException");

                        return null;
                    }

					DirectTransRotAstrometry threeStarSolution = 
						DirectTransRotAstrometry.SolveByThreeStars(m_PlateConfig, threeStarDict, 2);

					if (threeStarSolution == null)
					{
						if (pyramidLog != null) pyramidLog.FailureReason = PyramidEntryFailureReason.ThreeStarFitFailed;

                        if (TangraConfig.Settings.TraceLevels.PlateSolving.TraceVerbose())
						    Trace.WriteLine("ThreeStarFit.Var2 - Failed");
						return null;						
					}
					else
					{
						RA0Deg = threeStarSolution.RA0Deg;
						DE0Deg = threeStarSolution.DE0Deg;
					}
				}
				else
				{
					if (pyramidLog != null) pyramidLog.FailureReason = PyramidEntryFailureReason.ThreeStarFitFailed;

                    if (TangraConfig.Settings.TraceLevels.PlateSolving.TraceVerbose())
					    Trace.WriteLine("ThreeStarFit.Var1 - Failed");
					return null;					
				}
			}
			else
			{
				if (pyramidLog != null) pyramidLog.RegisterThreeStarFit(coarseFit);
				RA0Deg = coarseFit.RA0Deg;
				DE0Deg = coarseFit.DE0Deg;
			}
			

#if DEBUG || PYRAMID_DEBUG
		    if (TangraConfig.Settings.TraceLevels.PlateSolving.TraceVerbose())
		    {
                foreach (int key in matchedFeatureIdToStarIdIndexes.Keys)
#if PYRAMID_DEBUG
                    Trace
#else
                    Debug
#endif
                    .WriteLine(string.Format("Star({0}) -> Feature({1})", matchedFeatureIdToStarIdIndexes[key], key));
		    }
#endif

            PlateConstantsSolver solver = new PlateConstantsSolver(m_PlateConfig);
			solver.InitPlateSolution(RA0Deg, DE0Deg);
		    foreach (ImagePixel feature in matchedPairs.Keys)
		    {
		        IStar star = matchedPairs[feature];
		        var kvp = matchedFeatureIdToStarIdIndexes.Single(x => x.Value == star.StarNo);
		        int featureId = kvp.Key;
                solver.AddStar(feature, star, featureId);
		    }

		    LeastSquareFittedAstrometry leastSquareFittedAstrometry = null;
			LeastSquareFittedAstrometry firstFit = null;
			try
			{
				// This is a linear regression when doing simple field alignment. We always use a Linear Fit
				leastSquareFittedAstrometry = solver.SolveWithLinearRegression(
					FitOrder.Linear,
				 	CorePyramidConfig.Default.MinPyramidAlignedStars,
					m_MaxLeastSquareResidual, 
					out firstFit);
			}
			catch (DivideByZeroException)
			{ }

			if (leastSquareFittedAstrometry != null)
			{
				if (pyramidLog != null) pyramidLog.RegisterLinearFit(leastSquareFittedAstrometry);

                if (TangraConfig.Settings.TraceLevels.PlateSolving.TraceVerbose())
				    Trace.WriteLine("Checking possible solution. ");

				List<ulong> usedStarIds = leastSquareFittedAstrometry.FitInfo.AllStarPairs
					.Where(p => p.FitInfo.UsedInSolution)
					.Select(p => p.StarNo)
					.ToList();

				int usedStars = usedStarIds.Count;

				matchedFeatureIdToStarIdIndexes = matchedFeatureIdToStarIdIndexes
					.Where(kvp => usedStarIds.Contains(kvp.Value))
					.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);

				List<double> residuals = 
					leastSquareFittedAstrometry.FitInfo.AllStarPairs
						.Where(p => !p.FitInfo.ExcludedForHighResidual)
						.Select(p => p.FitInfo.ResidualArcSec)
						.ToList();


				double secondLargeResidual = 0;

				if (residuals.Count > 0)
				{
					residuals = residuals.OrderByDescending(r => r).ToList();
					secondLargeResidual = residuals.Count > 1 ? residuals[1] : residuals[0];
				}

				double onePixDistArcSec = m_PlateConfig.GetDistanceInArcSec(0, 0, 1, 1);
				if (secondLargeResidual > onePixDistArcSec * CorePyramidConfig.Default.MaxAllowedResidualInPixelsInSuccessfulFit)
				{
					if (pyramidLog != null) pyramidLog.FailureReason = PyramidEntryFailureReason.SecondLargestResidualIsTooLarge;

                    if (TangraConfig.Settings.TraceLevels.PlateSolving.TraceVerbose())
					    Trace.WriteLine(string.Format(
						    "Failing preliminary solution because the second largest residual {0}\" is larger than {1}px",
						    secondLargeResidual.ToString("0.0"), CorePyramidConfig.Default.MaxAllowedResidualInPixelsInSuccessfulFit));

					return null;
				}

                if (minMatchedStars.HasValue)
				{
                    if (usedStars < minMatchedStars.Value)
					{
						if (pyramidLog != null) pyramidLog.FailureReason = PyramidEntryFailureReason.InsufficientStarsForCalibration;

                        if (TangraConfig.Settings.TraceLevels.PlateSolving.TraceVerbose())
						    Trace.WriteLine(string.Format(
						    "Failing preliminary solution because on {0} stars are used but {1} are required as a minimum for calibration.",
						    usedStars, CorePyramidConfig.Default.MinMatchedStarsForCalibration));

						return null;
					}
				}
			}
			else
			{
				if (pyramidLog != null) pyramidLog.FailureReason = PyramidEntryFailureReason.LinearFitFailed;

			    if (TangraConfig.Settings.TraceLevels.PlateSolving.TraceVerbose())
			    {
                    Debug.WriteLine("DistanceBasedContext.LeastSquareFittedAstrometry Failed!");

                    foreach (PlateConstStarPair pair in solver.Pairs)
                    {
#if PYRAMID_DEBUG
                        Trace
#else
                        Debug
#endif
                        .WriteLine(string.Format("{0} ({1}) -> Residuals: {2}\", {3}\"", pair.StarNo,
                                                      pair.FitInfo.UsedInSolution ? "Included" : "Excluded",
                                                      pair.FitInfo.ResidualRAArcSec.ToString("0.00"),
                                                      pair.FitInfo.ResidualDEArcSec.ToString("0.00")));
                    }

			    }
			}

			if (leastSquareFittedAstrometry != null)
			{
				leastSquareFittedAstrometry.FitInfo.FittedFocalLength = fittedFocalLength;
				if (pyramidLog != null) pyramidLog.RegisterFocalLength(fittedFocalLength);
			}

			return leastSquareFittedAstrometry;
		}
        private string getLicenceName(XElement numberElem)
        {
            var names = new Dictionary<int, string>
            {
                { 5095001, "Brant"},
                { 5098350, "Haldimand Norfolk"},
                { 5095003, "Kitchener"},
                { 5095002, "London"},
                { 5130138, "Toronto"}
            };

            int number = (int)numberElem;

            var result = names.Single(x => x.Key == number).Value;
            return result;
        }
        public IEnumerable<PersonModel> GetPeople(int summaryId, int pagesize, int offset, string orderby)
        {
            using (EnterpriseDataServiceClient proxy = new EnterpriseDataServiceClient())
              {
            Dictionary<int, string> eduLevels = new Dictionary<int, string>
                                                        {
                                                            {1, "СО"},
                                                            {2, "СПО"},
                                                            {3, "ВПО"}
                                                        };
            Dictionary<int, string> postLevels = new Dictionary<int, string>
                                                         {
                                                            {1, "АУ"},
                                                            {2, "ИТРиС"},
                                                            {3, "ОР"},
                                                            {4, "ВП"}
                                                         };

            Activity[] activities = proxy.GetActivitiesBySummary(summaryId);
            return proxy.GetPeoples(summaryId, pagesize, offset, orderby).Select(x => new PersonModel
              {
            Id = x.Id,
            SummaryId = x.SummaryId,
            ActivityId = x.ActivityId,
            ActivityTitle = activities.Single(xx => xx.Idk__BackingField == x.ActivityId).Titlek__BackingField,
            Title = x.Title,
            BirthYear = x.BirthYear,
            DismissalYear = x.DismissalYear,
            EducationLevelId = x.EducationLevelId,
            EducationLevel = eduLevels.Single(xx => xx.Key == x.EducationLevelId).Value,
            Gender = x.Gender,
            HiringYear = x.HiringYear,
            Post = x.Post,
            PostLevelId = x.PostLevelId,
            PostLevel = postLevels.Single(xx => xx.Key == x.PostLevelId).Value,
            StartPostYear = x.StartPostYear,
            WasQualificationIncrease = x.WasQualificationIncrease,
            WasValidate = x.WasValidate,
            YearSalary = x.YearSalary
              });
              }
        }
Example #25
0
        private string updateGestureText(float[] output)
        {
            Dictionary<string, float> dict = new Dictionary<string, float>();

            for (var i = 0; i < output.Length; i++)
                dict.Add(gestureWord[i], output[i]);

            try
            {
                var first = dict.Single(e => e.Value == dict.Values.Max());
                dict.Remove(first.Key);
                var sec = dict.Single(e => e.Value == dict.Values.Max());
                dict.Remove(sec.Key);
                var third = dict.Single(e => e.Value == dict.Values.Max());

                GestureText = first.Key;

                Array.Sort(output);
                this.txtSuccessRate.Text = string.Format("(1)\t{0}\t--\t{1:0.00}\n(2)\t{2}\t--\t{3:0.00}\n(3)\t{4}\t--\t{5:0.00}",
                                                           first.Key, first.Value, sec.Key, sec.Value, third.Key, third.Value);
            }
            catch
            {
                this.txtSuccessRate.Text = "N/A";
                GestureText = "";
            }

            return GestureText;
        }
Example #26
0
        private void HandleGetSimplePages(ZipArchive zip, ApplicationDbContext DB)
        {
            string RequestDomain = Globals.GetRequestDomain();
            int SiteId = DB.Sites.Single(x => x.Domain == RequestDomain).Id;

            // Handle the pages files
            var TopLevelPages = new Dictionary<int, string>();
            var PagesFiles = GetSimpleGetXmlDocuments(zip, "pages/");
            foreach (var KVP in PagesFiles.OrderBy(x => x.Value.DocumentElement.SelectSingleNode("parent").InnerText))
            {
                // Get slug so we can skip built-in pages
                string Parent = KVP.Value.DocumentElement.SelectSingleNode("parent").InnerText;
                string Url = KVP.Value.DocumentElement.SelectSingleNode("url").InnerText;
                string Slug = string.IsNullOrWhiteSpace(Parent) ? Url : Parent + "/" + Url;
                if (Slug == "index") Slug = "home";
                if (Slug == "news") Slug = "blog";
                if ((Slug == "blog") || (Slug == "contact"))
                {
                    // Only update the display order for these built-ins
                    var SP = DB.SitePages.SingleOrDefault(x => (x.Site.Domain == RequestDomain) && (x.Slug == Slug));
                    if (SP != null)
                    {
                        SP.DisplayOrder = Convert.ToInt32(KVP.Value.DocumentElement.SelectSingleNode("menuOrder").InnerText);
                        // TODO Can this be used on the blog/contact header? SP.Title = HttpUtility.HtmlDecode(KVP.Value.DocumentElement.SelectSingleNode("title").InnerText);
                        DB.SaveChanges();

                        Caching.ResetPages();
                    }
                }
                else
                {
                    // Update existing or add new page
                    // TODO GetSimple has a "meta" tag,
                    var SP = DB.SitePages.SingleOrDefault(x => (x.Site.Domain == RequestDomain) && (x.Slug == Slug)) ?? new SitePage();
                    SP.DateAdded = Convert.ToDateTime(KVP.Value.DocumentElement.SelectSingleNode("pubDate").InnerText);
                    SP.DateLastUpdated = Convert.ToDateTime(KVP.Value.DocumentElement.SelectSingleNode("pubDate").InnerText);
                    SP.DisplayOrder = Convert.ToInt32(KVP.Value.DocumentElement.SelectSingleNode("menuOrder").InnerText);
                    SP.Html = HttpUtility.HtmlDecode(KVP.Value.DocumentElement.SelectSingleNode("content").InnerText);
                    SP.ParentId = (TopLevelPages.ContainsValue(Parent)) ? TopLevelPages.Single(x => x.Value == Parent).Key : 0;
                    SP.RequireAdmin = false; // TODO "private" tag that could map to requireadmin
                    SP.RightAlign = false;
                    SP.ShowInMenu = (KVP.Value.DocumentElement.SelectSingleNode("menuStatus").InnerText == "Y");
                    SP.ShowTitleOnPage = true;
                    SP.SiteId = SiteId;
                    SP.Slug = Slug;
                    SP.LinkText = HttpUtility.HtmlDecode(KVP.Value.DocumentElement.SelectSingleNode("menu").InnerText);
                    SP.Title = HttpUtility.HtmlDecode(KVP.Value.DocumentElement.SelectSingleNode("title").InnerText);

                    if (SP.Id <= 0) DB.SitePages.Add(SP);
                    DB.SaveChanges();

                    Caching.ResetPages();

                    if (string.IsNullOrWhiteSpace(Parent)) TopLevelPages.Add(SP.Id, SP.Slug);
                }
            }
        }
Example #27
0
        /// <summary>
        /// Hàm lấy các phần tử là Enum
        /// </summary>
        /// <param name="TotalData">Class chứa tất cả các dữ liệu lấy lên để xử lý</param>
        /// <param name="listElementFormula">Lưu giá trị các thông thức đã tính rồi</param>
        /// <param name="profileItem">Nhân viên hiện tại được tính</param>
        /// <param name="CutOffDuration">Kỳ tính lương</param>
        /// <param name="formula">Công thức tính</param>
        /// <param name="listTmpDeduction">Biến tạm phục vụ cho tiền khấu trừ thâm niên của dự án SCV</param>
        /// <param name="DateClose">Ngày chốt lương</param>
        /// <returns></returns>
        public List<ElementFormula> GetStaticValues(ComputePayrollDataModel TotalData, List<ElementFormula> listElementFormula, Hre_ProfileEntity profileItem, Att_CutOffDurationEntity CutOffDuration, string ElementCode, Dictionary<Guid, ValueCount> listTmpDeduction)
        {
            Cat_ElementEntity formula = TotalData.listElement_All.Where(m => m.ElementCode == ElementCode).FirstOrDefault();
            ElementFormula item = new ElementFormula();

            #region Thêm các phần tử là loại phụ cấp
            if (CheckIsExistFormula(listElementFormula, formula, TotalData.listUsualAllowance.Select(m => m.Code).ToArray()))
            {
                foreach (var t in TotalData.listUsualAllowance)
                {
                    listElementFormula.Add(new ElementFormula(t.Code, t.Formula, 0));
                }
            }
            #endregion

            #region Quy đổi tiền tệ
            if (CheckIsExistFormula(listElementFormula, formula, TotalData.listCurrency.Select(m => m.Code + "_BUYING").ToArray()))
            {
                //list lưu các element 
                var ListExChangeRateElement = TotalData.listElement_All.Where(m => m.ElementCode.EndsWith("_BUYING") && m.GradePayrollID == null).ToList();
                //list lưu giá trị tiền tệ
                var ListExChangeRateByGrade = TotalData.listExchangeRate.Where(m => m.MonthOfEffect >= CutOffDuration.DateStart && m.MonthOfEffect <= CutOffDuration.DateEnd).ToList();
                foreach (var i in ListExChangeRateElement)
                {
                    string[] arrCurrencyCode = i.ElementCode.Split('_').ToArray();
                    if (arrCurrencyCode.Count() != 3)
                    {
                        var ExChangeRateItem = ListExChangeRateByGrade.Where(m => m.CurrencyBaseCode == arrCurrencyCode[0] && m.CurrencyDestCode == arrCurrencyCode[1]).OrderByDescending(m => m.MonthOfEffect).FirstOrDefault();
                        if (ExChangeRateItem != null)
                        {
                            item = new ElementFormula(i.ElementCode, ExChangeRateItem.BuyingRate != null ? ExChangeRateItem.BuyingRate : 0, 0);
                            listElementFormula.Add(item);
                        }
                    }
                }
            }

            if (CheckIsExistFormula(listElementFormula, formula, TotalData.listCurrency.Select(m => m.Code + "_SELLING").ToArray()))
            {
                //list lưu các element 
                var ListExChangeRateElement = TotalData.listElement_All.Where(m => m.ElementCode.EndsWith("_SELLING") && m.GradePayrollID == null).ToList();
                //list lưu giá trị tiền tệ
                var ListExChangeRateByGrade = TotalData.listExchangeRate.Where(m => m.MonthOfEffect >= CutOffDuration.DateStart && m.MonthOfEffect <= CutOffDuration.DateEnd).ToList();
                foreach (var i in ListExChangeRateElement)
                {
                    string[] arrCurrencyCode = i.ElementCode.Split('_').ToArray();
                    if (arrCurrencyCode.Count() != 3)
                    {
                        var ExChangeRateItem = ListExChangeRateByGrade.Where(m => m.CurrencyBaseCode == arrCurrencyCode[0] && m.CurrencyDestCode == arrCurrencyCode[1]).OrderByDescending(m => m.MonthOfEffect).FirstOrDefault();
                        if (ExChangeRateItem != null)
                        {
                            item = new ElementFormula(i.ElementCode, ExChangeRateItem.SellingRate != null ? ExChangeRateItem.SellingRate : 0, 0);
                            listElementFormula.Add(item);
                        }
                    }
                }
            }
            #endregion

            #region Kiểm tra xem nhân viên này có phụ cấp phát sinh trong tháng đang tính lương hay không ?
            if (CheckIsExistFormula(listElementFormula, formula, TotalData.listUnusualAllowanceCfg.Select(m => m.Code + "_T3").ToArray()))//đã lấy lên chưa ?
            {
                List<Sal_UnusualAllowanceEntity> listSal_UnusualT3 = new List<Sal_UnusualAllowanceEntity>();
                listSal_UnusualT3 = TotalData.listUnusualAllowanceT3.Where(m => m.ProfileID == profileItem.ID).ToList();
                ElementFormula _tmpitem = new ElementFormula();
                for (int j = 0; j < TotalData.listUnusualAllowanceCfg.Count; j++)
                {
                    //lay phu cap thang 3
                    _tmpitem = new ElementFormula();
                    _tmpitem.VariableName = TotalData.listUnusualAllowanceCfg[j].Code + "_T3";
                    var Sal_UnusualItem = listSal_UnusualT3.Where(m => m.UnusualEDTypeID == TotalData.listUnusualAllowanceCfg[j].ID && m.MonthStart <= CutOffDuration.DateEnd && (m.MonthEnd == null || m.MonthEnd >= CutOffDuration.DateStart)).ToList();
                    if (Sal_UnusualItem != null)
                    {
                        _tmpitem.Value = Sal_UnusualItem.Sum(m => m.Amount != null ? m.Amount : 0);
                        listElementFormula.Add(_tmpitem);
                    }
                    else
                    {
                        _tmpitem.Value = "0";
                        _tmpitem.ErrorMessage = "Không Có Phụ Cấp Trong Tháng 3";
                        listElementFormula.Add(_tmpitem);
                    }
                }
            }

            if (CheckIsExistFormula(listElementFormula, formula, TotalData.listUnusualAllowanceCfg.Select(m => m.Code + "_DAYCLOSE_N_1").ToArray()))
            {
                DateTime Dateform = CutOffDuration.DateStart.AddMonths(-1);
                DateTime DateTo = CutOffDuration.DateEnd.AddMonths(-1);

                //Lấy các phần tử tính lương nằm trong Grade của nhân viên
                Sal_GradeEntity Grade = FindGradePayrollByProfileAndMonthYear(TotalData.listGrade, profileItem.ID, Dateform, DateTo);
                //loại bỏ nhân viên có ngày vào làm sau ngày chốt lương
                Cat_GradePayrollEntity CatGrade = TotalData.listCat_GradePayroll.Where(m => m.ID == Grade.GradePayrollID).FirstOrDefault();

                //ngày bắt đầu chốt lương
                DateTime DateClose = new DateTime(CutOffDuration.MonthYear.AddMonths(-1).Year, CutOffDuration.MonthYear.AddMonths(-1).Month, CatGrade.SalaryDayClose != null ? (int)CatGrade.SalaryDayClose : 1).AddDays(1).AddMonths(-1);
                //ngày kết thúc chốt lương
                DateTime DateEndClose = new DateTime(CutOffDuration.MonthYear.AddMonths(-1).Year, CutOffDuration.MonthYear.AddMonths(-1).Month, CatGrade.SalaryDayClose != null ? (int)CatGrade.SalaryDayClose : 1);

                List<Sal_UnusualAllowanceEntity> ListUnusualAllowanceByProfile = TotalData.listSalUnusualAllowance.Where(m => m.ProfileID == profileItem.ID && m.MonthStart != null && m.MonthStart <= DateEndClose && (m.MonthEnd == null || m.MonthEnd >= DateClose)).ToList();

                ElementFormula _item = new ElementFormula();
                foreach (var i in TotalData.listUnusualAllowanceCfg)
                {
                    var listValue = ListUnusualAllowanceByProfile.Where(m => m.UnusualEDTypeID == i.ID).OrderByDescending(m => m.MonthStart).FirstOrDefault();
                    if (listValue != null)
                    {
                        _item = new ElementFormula(i.Code + "_DAYCLOSE_N_1", listValue.Amount != null ? listValue.Amount : 0, 0);
                        listElementFormula.Add(_item);
                    }
                    else
                    {
                        _item = new ElementFormula(i.Code + "_DAYCLOSE_N_1", 0, 0);
                        listElementFormula.Add(_item);
                    }
                }
            }

            if (CheckIsExistFormula(listElementFormula, formula, TotalData.listUnusualAllowanceCfg.Select(m => m.Code + "_DAYCLOSE").ToArray()))
            {
                //Lấy các phần tử tính lương nằm trong Grade của nhân viên
                Sal_GradeEntity Grade = FindGradePayrollByProfileAndMonthYear(TotalData.listGrade, profileItem.ID, CutOffDuration.DateStart, CutOffDuration.DateEnd);
                //loại bỏ nhân viên có ngày vào làm sau ngày chốt lương
                Cat_GradePayrollEntity CatGrade = TotalData.listCat_GradePayroll.Where(m => m.ID == Grade.GradePayrollID).FirstOrDefault();

                //ngày bắt đầu chốt lương
                DateTime DateClose = new DateTime(CutOffDuration.MonthYear.Year, CutOffDuration.MonthYear.Month, CatGrade.SalaryDayClose != null ? (int)CatGrade.SalaryDayClose : 1).AddDays(1).AddMonths(-1);
                //ngày kết thúc chốt lương
                DateTime DateEndClose = new DateTime(CutOffDuration.MonthYear.Year, CutOffDuration.MonthYear.Month, CatGrade.SalaryDayClose != null ? (int)CatGrade.SalaryDayClose : 1);

                List<Sal_UnusualAllowanceEntity> ListUnusualAllowanceByProfile = TotalData.listSalUnusualAllowance.Where(m => m.ProfileID == profileItem.ID && m.MonthStart != null && m.MonthStart <= DateEndClose && (m.MonthEnd == null || m.MonthEnd >= DateClose)).ToList();

                ElementFormula _item = new ElementFormula();
                foreach (var i in TotalData.listUnusualAllowanceCfg)
                {
                    var listValue = ListUnusualAllowanceByProfile.Where(m => m.UnusualEDTypeID == i.ID).OrderByDescending(m => m.MonthStart).FirstOrDefault();
                    if (listValue != null)
                    {
                        _item = new ElementFormula(i.Code + "_DAYCLOSE", listValue.Amount != null ? listValue.Amount : 0, 0);
                        listElementFormula.Add(_item);
                    }
                    else
                    {
                        _item = new ElementFormula(i.Code + "_DAYCLOSE", 0, 0);
                        listElementFormula.Add(_item);
                    }
                }
            }

            if (CheckIsExistFormula(listElementFormula, formula, TotalData.listUnusualAllowanceCfg.Select(m => m.Code + "_AMOUNTOFOFFSET_N_1").ToArray()))
            {
                DateTime Dateform = CutOffDuration.DateStart.AddMonths(-1);
                DateTime DateTo = CutOffDuration.DateEnd.AddMonths(-1);

                //Lấy các phần tử tính lương nằm trong Grade của nhân viên
                Sal_GradeEntity Grade = FindGradePayrollByProfileAndMonthYear(TotalData.listGrade, profileItem.ID, Dateform, DateTo);
                //loại bỏ nhân viên có ngày vào làm sau ngày chốt lương
                Cat_GradePayrollEntity CatGrade = TotalData.listCat_GradePayroll.Where(m => m.ID == Grade.GradePayrollID).FirstOrDefault();

                //ngày bắt đầu chốt lương
                DateTime DateClose = new DateTime(CutOffDuration.MonthYear.AddMonths(-1).Year, CutOffDuration.MonthYear.AddMonths(-1).Month, CatGrade.SalaryDayClose != null ? (int)CatGrade.SalaryDayClose : 1).AddDays(1).AddMonths(-1);
                //ngày kết thúc chốt lương
                DateTime DateEndClose = new DateTime(CutOffDuration.MonthYear.AddMonths(-1).Year, CutOffDuration.MonthYear.AddMonths(-1).Month, CatGrade.SalaryDayClose != null ? (int)CatGrade.SalaryDayClose : 1);

                List<Sal_UnusualAllowanceEntity> listUnusualAllowanceByDateClose = TotalData.listSalUnusualAllowance.Where(m => m.MonthStart <= DateEndClose && (m.MonthEnd >= DateClose || m.MonthEnd == null) && m.ProfileID == profileItem.ID).ToList();

                ElementFormula _item = new ElementFormula();
                foreach (var i in TotalData.listUnusualAllowanceCfg)
                {
                    var listValue = listUnusualAllowanceByDateClose.Where(m => m.UnusualEDTypeID == i.ID).ToList();
                    if (listValue != null)
                    {
                        _item = new ElementFormula(i.Code + "_AMOUNTOFOFFSET_N_1", listValue.Sum(m => m.AmountOfOffSet != null ? m.AmountOfOffSet : 0), 0);
                        listElementFormula.Add(_item);
                    }
                    else
                    {
                        _item = new ElementFormula(i.Code + "_AMOUNTOFOFFSET_N_1", 0, 0);
                        listElementFormula.Add(_item);
                    }
                }

            }

            //lấy mức phụ cấp theo timeline tháng n-1
            if (CheckIsExistFormula(listElementFormula, formula, TotalData.listUnusualAllowanceCfg.Select(m => m.Code + "_TIMELINE_N_1").ToArray()))
            {
                DateTime Dateform = CutOffDuration.DateStart.AddMonths(-1);
                DateTime DateTo = CutOffDuration.DateEnd.AddMonths(-1);

                //Lấy các phần tử tính lương nằm trong Grade của nhân viên
                Sal_GradeEntity Grade = FindGradePayrollByProfileAndMonthYear(TotalData.listGrade, profileItem.ID, Dateform, DateTo);
                //loại bỏ nhân viên có ngày vào làm sau ngày chốt lương
                Cat_GradePayrollEntity CatGrade = TotalData.listCat_GradePayroll.Where(m => m.ID == Grade.GradePayrollID).FirstOrDefault();

                //ngày bắt đầu chốt lương
                DateTime DateClose = new DateTime(CutOffDuration.MonthYear.AddMonths(-1).Year, CutOffDuration.MonthYear.AddMonths(-1).Month, CatGrade.SalaryDayClose != null ? (int)CatGrade.SalaryDayClose : 1).AddDays(1).AddMonths(-1);
                //ngày kết thúc chốt lương
                DateTime DateEndClose = new DateTime(CutOffDuration.MonthYear.AddMonths(-1).Year, CutOffDuration.MonthYear.AddMonths(-1).Month, CatGrade.SalaryDayClose != null ? (int)CatGrade.SalaryDayClose : 1);

                List<Cat_UnAllowCfgAmountEntity> listUnAllowCfgAmount = TotalData.listUnAllowCfgAmount.Where(m => m.FromDate <= DateEndClose && m.ToDate >= DateClose).ToList();

                ElementFormula _item = new ElementFormula();
                foreach (var i in TotalData.listUnusualAllowanceCfg)
                {
                    var listValue = listUnAllowCfgAmount.Where(m => m.UnusualAllowanceID != null && (Guid)m.UnusualAllowanceID == i.ID).ToList();
                    if (listValue != null)
                    {
                        _item = new ElementFormula(i.Code + "_TIMELINE_N_1", listValue.Sum(m => m.Amount != null ? m.Amount : 0), 0);
                        listElementFormula.Add(_item);
                    }
                    else
                    {
                        _item = new ElementFormula(i.Code + "_TIMELINE_N_1", 0, 0);
                        listElementFormula.Add(_item);
                    }
                }
            }

            //lấy mức phụ cấp theo timeline
            if (CheckIsExistFormula(listElementFormula, formula, TotalData.listUnusualAllowanceCfg.Select(m => m.Code + "_TIMELINE").ToArray()))
            {
                //Lấy các phần tử tính lương nằm trong Grade của nhân viên
                Sal_GradeEntity Grade = FindGradePayrollByProfileAndMonthYear(TotalData.listGrade, profileItem.ID, CutOffDuration.DateStart, CutOffDuration.DateEnd);
                //loại bỏ nhân viên có ngày vào làm sau ngày chốt lương
                Cat_GradePayrollEntity CatGrade = TotalData.listCat_GradePayroll.Where(m => m.ID == Grade.GradePayrollID).FirstOrDefault();

                //ngày bắt đầu chốt lương
                DateTime DateClose = new DateTime(CutOffDuration.MonthYear.Year, CutOffDuration.MonthYear.Month, CatGrade.SalaryDayClose != null ? (int)CatGrade.SalaryDayClose : 1).AddDays(1).AddMonths(-1);
                //ngày kết thúc chốt lương
                DateTime DateEndClose = new DateTime(CutOffDuration.MonthYear.Year, CutOffDuration.MonthYear.Month, CatGrade.SalaryDayClose != null ? (int)CatGrade.SalaryDayClose : 1);

                List<Cat_UnAllowCfgAmountEntity> listUnAllowCfgAmount = TotalData.listUnAllowCfgAmount.Where(m => m.FromDate <= DateEndClose && m.ToDate >= DateClose).ToList();

                ElementFormula _item = new ElementFormula();
                foreach (var i in TotalData.listUnusualAllowanceCfg)
                {
                    var listValue = listUnAllowCfgAmount.Where(m => m.UnusualAllowanceID != null && (Guid)m.UnusualAllowanceID == i.ID).ToList();
                    if (listValue != null)
                    {
                        _item = new ElementFormula(i.Code + "_TIMELINE", listValue.Sum(m => m.Amount != null ? m.Amount : 0), 0);
                        listElementFormula.Add(_item);
                    }
                    else
                    {
                        _item = new ElementFormula(i.Code + "_TIMELINE", 0, 0);
                        listElementFormula.Add(_item);
                    }
                }
            }


            if (CheckIsExistFormula(listElementFormula, formula, TotalData.listUnusualAllowanceCfg.Select(m => m.Code + "_N_1").ToArray()))//đã lấy lên chưa ?
            {
                List<Sal_UnusualAllowanceEntity> listSal_Unusual = new List<Sal_UnusualAllowanceEntity>();
                ElementFormula _tmpitem = new ElementFormula();
                listSal_Unusual = TotalData.listSalUnusualAllowance.Where(m => m.ProfileID == profileItem.ID).ToList();
                //lấy các loại phụ cấp của 6 tháng trước tháng tính lương (Honda)
                for (int j = 0; j < TotalData.listUnusualAllowanceCfg.Count; j++)
                {
                    for (int t = 1; t <= 6; t++)
                    {
                        _tmpitem = new ElementFormula();
                        _tmpitem.VariableName = TotalData.listUnusualAllowanceCfg[j].Code + "_N_" + t.ToString();
                        var Sal_UnusualItem = listSal_Unusual.Where(m => m.UnusualEDTypeID == TotalData.listUnusualAllowanceCfg[j].ID && m.MonthStart <= CutOffDuration.DateEnd.AddMonths(t * -1) && (m.MonthEnd == null || m.MonthEnd >= CutOffDuration.DateStart.AddMonths(t * -1))).ToList();
                        if (Sal_UnusualItem != null)
                        {
                            _tmpitem.Value = Sal_UnusualItem.Sum(m => m.Amount != null ? m.Amount : 0);
                            listElementFormula.Add(_tmpitem);
                        }
                        else
                        {
                            _tmpitem.Value = "0";
                            _tmpitem.ErrorMessage = "Không Có Phụ Cấp Trong Tháng";
                            listElementFormula.Add(_tmpitem);
                        }
                    }
                }
            }

            if (CheckIsExistFormula(listElementFormula, formula, TotalData.listUnusualAllowanceCfg.Select(m => m.Code).ToArray()))//đã lấy lên chưa ?
            {
                List<Sal_UnusualAllowanceEntity> listSal_Unusual = new List<Sal_UnusualAllowanceEntity>();
                // List<Sal_UnusualAllowanceEntity> listSal_UnusualT3 = new List<Sal_UnusualAllowanceEntity>();
                listSal_Unusual = TotalData.listSalUnusualAllowance.Where(m => m.ProfileID == profileItem.ID).ToList();
                // listSal_UnusualT3 = TotalData.listUnusualAllowanceT3.Where(m => m.ProfileID == profileItem.ID).ToList();
                //add loại phụ cấp bất thường vào list phần tử(listElement), các loại phụ cấp nào không có thì cho formula = 0
                for (int j = 0; j < TotalData.listUnusualAllowanceCfg.Count; j++)
                {
                    ElementFormula _tmpitem = new ElementFormula();
                    _tmpitem.VariableName = TotalData.listUnusualAllowanceCfg[j].Code;
                    var Sal_UnusualItem = listSal_Unusual.Where(m => m.UnusualEDTypeID == TotalData.listUnusualAllowanceCfg[j].ID && m.MonthStart <= CutOffDuration.DateEnd && (m.MonthEnd == null || m.MonthEnd >= CutOffDuration.DateStart)).ToList();
                    if (Sal_UnusualItem != null)
                    {
                        _tmpitem.Value = Sal_UnusualItem.Sum(m => m.Amount != null ? m.Amount : 0);
                        listElementFormula.Add(_tmpitem);
                    }
                    else
                    {
                        _tmpitem.Value = "0";
                        _tmpitem.ErrorMessage = "Không Có Phụ Cấp Trong Tháng";
                        listElementFormula.Add(_tmpitem);
                    }
                }
            }
            #endregion

            #region Lấy giá trị các phần tử là Enum

            var listAttendanceTableProCut = TotalData.listAttendanceTable.Where(m => m.ProfileID == profileItem.ID && m.DateStart <= CutOffDuration.DateEnd && m.DateEnd >= CutOffDuration.DateStart).FirstOrDefault();

            #region Enum HRE
            if (CheckIsExistFormula(listElementFormula, formula, new string[] { PayrollElement.HR_WORKINGDAY.ToString(), PayrollElement.HR_LEAVEDAY.ToString(), PayrollElement.HR_IS_LEAVEDAY.ToString(), PayrollElement.HR_IS_WORKINGDAY.ToString() }))
            {
                //Ngày vào làm
                item = new ElementFormula(PayrollElement.HR_WORKINGDAY.ToString(), profileItem.DateHire, 0);
                listElementFormula.Add(item);

                //Ngày nghỉ việc
                item = new ElementFormula(PayrollElement.HR_LEAVEDAY.ToString(), profileItem.DateQuit != null ? profileItem.DateQuit : DateTime.MinValue, 0, profileItem.DateQuit != null ? "" : "Null");
                listElementFormula.Add(item);

                //NV có ngày nghỉ việc trong tháng
                item = new ElementFormula(PayrollElement.HR_IS_LEAVEDAY.ToString(), (profileItem.DateQuit <= CutOffDuration.DateEnd && profileItem.DateQuit >= CutOffDuration.DateStart) == true ? 0 : 1, 0);
                listElementFormula.Add(item);

                //NV có ngày vào làm trong tháng
                item = new ElementFormula(PayrollElement.HR_IS_WORKINGDAY.ToString(), (profileItem.DateHire <= CutOffDuration.DateEnd && profileItem.DateHire >= CutOffDuration.DateStart) == true ? 1 : 0, 0);
                listElementFormula.Add(item);

            }

            ////Bậc / Hệ số lương (Code)
            //item = new ElementFormula(PayrollElement.HR_SALARYCLASSNAME.ToString(), profileItem.SalaryClassID != null ? profileItem.SalaryClassName : "", 0);
            //listElementFormula.Add(item);


            //Số ngày từ ngày vào đến cuối tháng, không tính những ngày dayoff từ ngày vào đến cuối tháng (VD: vào ngày 05/01, số ngày dayoff từ mùng 5 đến 31 = 6 => trả về: 31 (số ngày trong tháng) - 5 (ngày vào) + 1 (từ 5 đến 31 là 27 ngày nên phải + thêm 1) - 6 (số ngày dayoff từ ngày 05/01 đến 31/01) = 21)
            if (CheckIsExistFormula(listElementFormula, formula, PayrollElement.HR_COUNT_DAY_TO_DATEEND_CUTOFF.ToString()))
            {
                if (profileItem.DateHire != null && profileItem.DateHire >= new DateTime(CutOffDuration.MonthYear.Year, CutOffDuration.MonthYear.Month, 1))
                {
                    DateTime DateStart = new DateTime(CutOffDuration.MonthYear.Year, CutOffDuration.MonthYear.Month, 1);
                    DateTime DateEnd = DateStart.AddMonths(1).AddDays(-1);
                    //số ngày trong tháng
                    double dayInCutoff = DateEnd.Subtract(profileItem.DateHire.Value).TotalDays + 1;
                    double dayOff = TotalData.listDayOff.Where(m => m.DateOff <= DateEnd && m.DateOff >= profileItem.DateHire.Value).Count();

                    item = new ElementFormula(PayrollElement.HR_COUNT_DAY_TO_DATEEND_CUTOFF.ToString(), dayInCutoff - dayOff, 0);
                    listElementFormula.Add(item);
                }
                else
                {
                    item = new ElementFormula(PayrollElement.HR_COUNT_DAY_TO_DATEEND_CUTOFF.ToString(), 0, 0);
                    listElementFormula.Add(item);
                }
            }

            //Số ngày trong tháng tính lương - tổng số ngày dayoff trong tháng tính lương (VD: tháng 1 có 31 ngày - 8 ngày dayoff = 23)
            if (CheckIsExistFormula(listElementFormula, formula, PayrollElement.HR_COUNT_DAY_IN_CUTOFF.ToString()))
            {
                DateTime DateStart = new DateTime(CutOffDuration.MonthYear.Year, CutOffDuration.MonthYear.Month, 1);
                DateTime DateEnd = DateStart.AddMonths(1).AddDays(-1);

                double dayInCutoff = DateEnd.Subtract(DateStart).TotalDays + 1;
                double dayOff = TotalData.listDayOff.Where(m => m.DateOff <= DateEnd && m.DateOff >= DateStart).Count();

                item = new ElementFormula(PayrollElement.HR_COUNT_DAY_IN_CUTOFF.ToString(), dayInCutoff - dayOff, 0);
                listElementFormula.Add(item);
            }

            //Số ngày dayoff từ ngày 1 tháng tính lương đến ngày vào làm (VD: vào làm ngày 05/01, 01/01, 02/01 là ngày dayoff => trả về 2)
            if (CheckIsExistFormula(listElementFormula, formula, PayrollElement.HR_COUNT_DAYOFF_TO_DATEHIRE.ToString()))
            {
                //ngày đầu tháng tính lương
                DateTime DateStart = new DateTime(CutOffDuration.MonthYear.Year, CutOffDuration.MonthYear.Month, 1);
                //nếu ngày làm việc lớn hơn ngày đầu tháng
                if (profileItem.DateHire != null && profileItem.DateHire >= DateStart)
                {
                    int DayNumber = TotalData.listDayOff.Where(m => m.DateOff <= profileItem.DateHire.Value && m.DateOff >= DateStart).Count();
                    item = new ElementFormula(PayrollElement.HR_COUNT_DAYOFF_TO_DATEHIRE.ToString(), DayNumber, 0);
                    listElementFormula.Add(item);
                }
                else
                {
                    item = new ElementFormula(PayrollElement.HR_COUNT_DAYOFF_TO_DATEHIRE.ToString(), 0, 0);
                    listElementFormula.Add(item);
                }
            }

            //Nhân viên có ngày vào làm hoặc ngày đi làm lại trong khoảng từ ngày 1 đến ngày chốt lương trong tháng tính lương thì trả về 1, nếu không trả về 0
            if (CheckIsExistFormula(listElementFormula, formula, PayrollElement.HR_IS_BACK_TO_WORK.ToString()))
            {
                //Lấy các phần tử tính lương nằm trong Grade của nhân viên
                Sal_GradeEntity Grade = FindGradePayrollByProfileAndMonthYear(TotalData.listGrade, profileItem.ID, CutOffDuration.DateStart, CutOffDuration.DateEnd);
                //loại bỏ nhân viên có ngày vào làm sau ngày chốt lương
                Cat_GradePayrollEntity CatGrade = TotalData.listCat_GradePayroll.Where(m => m.ID == Grade.GradePayrollID).FirstOrDefault();
                //kiểm tra ngày đi làm
                if (profileItem.DateHire != null && profileItem.DateHire.Value.Month == CutOffDuration.MonthYear.Month && profileItem.DateHire.Value.Year == CutOffDuration.MonthYear.Year)
                {
                    if (CatGrade.SalaryDayClose != null && profileItem.DateHire.Value.Day <= CatGrade.SalaryDayClose)
                    {
                        item = new ElementFormula(PayrollElement.HR_IS_BACK_TO_WORK.ToString(), 1, 0);
                        listElementFormula.Add(item);
                    }
                    else
                    {
                        item = new ElementFormula(PayrollElement.HR_IS_BACK_TO_WORK.ToString(), 0, 0);
                        listElementFormula.Add(item);
                    }
                }
                else//kiểm tra có ngày vào làm lại hay không
                {
                    if (CatGrade.SalaryDayClose != null)
                    {
                        List<Hre_WorkHistoryEntity> listWorkHistoryByProfile = TotalData.listWorkHistory.Where(m => m.ProfileID == profileItem.ID && m.DateComeBack != null && m.DateComeBack <= new DateTime(CutOffDuration.MonthYear.Year, CutOffDuration.MonthYear.Month, (int)CatGrade.SalaryDayClose)).ToList();
                        if (listWorkHistoryByProfile.Count > 0)
                        {
                            item = new ElementFormula(PayrollElement.HR_IS_BACK_TO_WORK.ToString(), 1, 0);
                            listElementFormula.Add(item);
                        }
                        else
                        {
                            item = new ElementFormula(PayrollElement.HR_IS_BACK_TO_WORK.ToString(), 0, 0);
                            listElementFormula.Add(item);
                        }
                    }
                    else
                    {
                        item = new ElementFormula(PayrollElement.HR_IS_BACK_TO_WORK.ToString(), 0, 0);
                        listElementFormula.Add(item);
                    }
                }
            }

            //Nhân viên có trong  doanh sách kỷ luật trong tháng tính lương
            if (CheckIsExistFormula(listElementFormula, formula, PayrollElement.HR_NUMBER_DAY_BEFORE_WORK.ToString()))
            {
                double CountDay = 0;
                //nếu ngày vào làm lớn hơn
                if (profileItem.DateHire != null && profileItem.DateHire > CutOffDuration.DateStart && profileItem.DateHire <= CutOffDuration.DateEnd)
                {
                    DateTime dateStart = new DateTime(profileItem.DateHire.Value.Year, profileItem.DateHire.Value.Month, 1);
                    CountDay = profileItem.DateHire.Value.Subtract(dateStart).TotalDays;

                    int DayOff = TotalData.listDayOff.Where(m => ((m.OrgStructureID == null || m.OrgStructureID == profileItem.OrgStructureID) || m.OrgStructureID == profileItem.OrgStructureID) && m.DateOff >= dateStart && m.DateOff < profileItem.DateHire).Count();
                    CountDay -= DayOff;
                }

                //kiểm tra xem có vào làm lại hay không
                Hre_StopWorkingEntity StopWorkingByProfile = TotalData.listHre_StopWorking.Where(m => m.ProfileID != null && m.DateComeBack != null && m.ProfileID == profileItem.ID && m.DateComeBack >= CutOffDuration.DateStart && m.DateComeBack <= CutOffDuration.DateEnd).OrderByDescending(m => m.DateComeBack).FirstOrDefault();
                if (StopWorkingByProfile != null && StopWorkingByProfile.DateComeBack != null)
                {
                    DateTime dateStart = new DateTime(StopWorkingByProfile.DateComeBack.Value.Year, StopWorkingByProfile.DateComeBack.Value.Month, 1);
                    CountDay = StopWorkingByProfile.DateComeBack.Value.Subtract(dateStart).TotalDays;

                    int DayOff = TotalData.listDayOff.Where(m => (m.OrgStructureID == null || m.OrgStructureID == profileItem.OrgStructureID) && m.DateOff >= dateStart && m.DateOff < profileItem.DateHire).Count();
                    CountDay -= DayOff;
                }

                item = new ElementFormula(PayrollElement.HR_NUMBER_DAY_BEFORE_WORK.ToString(), CountDay, 0);
                listElementFormula.Add(item);
            }

            //Nhân viên có trong  doanh sách kỷ luật trong tháng tính lương
            if (CheckIsExistFormula(listElementFormula, formula, PayrollElement.HR_NUMBER_DAY_BEFORE_WORK_PREV.ToString()))
            {
                DateTime DateStartPrev = CutOffDuration.DateStart.AddMonths(-1);
                DateTime DateEndPrev = CutOffDuration.DateEnd.AddMonths(-1);
                double CountDay = 0;
                int DayClose = 1;

                //Lấy các phần tử tính lương nằm trong Grade của nhân viên
                Sal_GradeEntity Grade = FindGradePayrollByProfileAndMonthYear(TotalData.listGrade, profileItem.ID, CutOffDuration.DateStart, CutOffDuration.DateEnd);
                Cat_GradePayrollEntity CatGrade = TotalData.listCat_GradePayroll.Where(m => m.ID == Grade.GradePayrollID).FirstOrDefault();
                if (CatGrade != null && CatGrade.SalaryDayClose != null)
                {
                    DayClose = (int)CatGrade.SalaryDayClose;
                }

                //nếu ngày vào làm lớn hơn
                if (profileItem.DateHire != null && profileItem.DateHire > DateStartPrev && profileItem.DateHire <= DateEndPrev && profileItem.DateHire.Value.Day > DayClose)
                {
                    CountDay = new DateTime(profileItem.DateHire.Value.Year, profileItem.DateHire.Value.Month, 1).AddMonths(1).AddDays(-1).Subtract(profileItem.DateHire.Value).TotalDays + 1;
                    DateStartPrev = new DateTime(profileItem.DateHire.Value.Year, profileItem.DateHire.Value.Month, 1).AddMonths(1).AddDays(-1);
                    int DayOff = TotalData.listDayOff.Where(m => (m.OrgStructureID == null || m.OrgStructureID == profileItem.OrgStructureID) && m.DateOff <= DateStartPrev && m.DateOff >= profileItem.DateHire).Count();
                    CountDay -= DayOff;
                }

                //kiểm tra xem có vào làm lại hay không
                Hre_StopWorkingEntity StopWorkingByProfile = TotalData.listHre_StopWorking.Where(m => m.ProfileID != null && m.DateComeBack != null && m.ProfileID == profileItem.ID && m.DateComeBack >= DateStartPrev && m.DateComeBack <= DateEndPrev).OrderByDescending(m => m.DateComeBack).FirstOrDefault();
                if (StopWorkingByProfile != null && StopWorkingByProfile.DateComeBack != null)
                {
                    CountDay = new DateTime(StopWorkingByProfile.DateComeBack.Value.Year, StopWorkingByProfile.DateComeBack.Value.Month, 1).AddMonths(1).AddDays(-1).Subtract(StopWorkingByProfile.DateComeBack.Value).TotalDays + 1;
                    DateStartPrev = new DateTime(profileItem.DateHire.Value.Year, profileItem.DateHire.Value.Month, 1).AddMonths(1).AddDays(-1);
                    int DayOff = TotalData.listDayOff.Where(m => (m.OrgStructureID == null || m.OrgStructureID == profileItem.OrgStructureID) && m.DateOff <= DateStartPrev && m.DateOff >= profileItem.DateHire).Count();
                    CountDay -= DayOff;
                }

                item = new ElementFormula(PayrollElement.HR_NUMBER_DAY_BEFORE_WORK_PREV.ToString(), CountDay, 0);
                listElementFormula.Add(item);
            }


            //Nhân viên có trong  doanh sách kỷ luật trong tháng tính lương
            if (CheckIsExistFormula(listElementFormula, formula, PayrollElement.HR_IS_DISCIPLINE.ToString()))//đã lấy lên chưa ?
            {
                DateTime datefrom = new DateTime(CutOffDuration.MonthYear.Year - 1, 4, 1);
                DateTime dateto = new DateTime(CutOffDuration.MonthYear.Year, 3, 31);
                var listDisciplineProfile = TotalData.listDiscipline.Where(m => m.ProfileID == profileItem.ID && m.DateOfEffective >= datefrom && m.DateOfEffective <= dateto).FirstOrDefault();

                item = new ElementFormula(PayrollElement.HR_IS_DISCIPLINE.ToString(), listDisciplineProfile != null ? 1 : 0, 0);
                listElementFormula.Add(item);
            }

            //Phần tử tổng thời gian tạm hoãn công việc tính tới cuối kỳ lương
            if (CheckIsExistFormula(listElementFormula, formula, PayrollElement.HR_TOTAL_DAY_STOP_WORKING.ToString()))//đã lấy lên chưa ?
            {
                item = new ElementFormula(PayrollElement.HR_TOTAL_DAY_STOP_WORKING.ToString(), SumStopWorkingDay(TotalData.listHre_StopWorking.Where(m => m.ProfileID == profileItem.ID).ToList(), CutOffDuration.DateEnd), 0);
                listElementFormula.Add(item);
            }

            //Nhân viên có được tính trợ cấp hay không (Có ngày vào làm từ 1996<=N<=31/12/2008)
            if (CheckIsExistFormula(listElementFormula, formula, PayrollElement.HR_IS_COMPUTE_SUBSIDIZE.ToString()))
            {
                DateTime from = new DateTime(1996, 1, 1);
                DateTime to = new DateTime(2008, 12, 31);
                item = new ElementFormula(PayrollElement.HR_IS_COMPUTE_SUBSIDIZE.ToString(), (profileItem.DateHire <= to && profileItem.DateHire >= from) == true ? 1 : 0, 0);
                listElementFormula.Add(item);
            }

            //Lấy thông tin hợp đồng
            if (CheckIsExistFormula(listElementFormula, formula, PayrollElement.HR_CONSTRACT_TYPE.ToString()))
            {
                //TotalData.
            }

            #region HDT JOB

            #region Ngày vào làm và ngày kết thúc HDT JOB tháng N
            if (CheckIsExistFormula(listElementFormula, formula, PayrollElement.HR_START_DATE_HDTJOB.ToString()) || CheckIsExistFormula(listElementFormula, formula, PayrollElement.HR_END_DATE_HDTJOB.ToString()))//đã lấy lên chưa ?
            {
                Hre_HDTJobEntity HDTJOB_DateFrom = new Hre_HDTJobEntity();
                //Ngày vào làm HDT JOB
                HDTJOB_DateFrom = TotalData.listHre_HDTJob_All.Where(m => m.ProfileID == profileItem.ID && m.DateFrom <= CutOffDuration.DateEnd && (m.DateTo >= CutOffDuration.DateStart || m.DateTo == null) && m.Status == HDTJobStatus.E_APPROVE.ToString()).OrderBy(m => m.DateFrom).FirstOrDefault();
                if (HDTJOB_DateFrom != null)
                {
                    DateTime form = HDTJOB_DateFrom.DateFrom != null ? (DateTime)HDTJOB_DateFrom.DateFrom : DateTime.MinValue;
                    DateTime to = HDTJOB_DateFrom.DateTo != null ? (DateTime)HDTJOB_DateFrom.DateTo : CutOffDuration.DateEnd;

                    item = new ElementFormula(PayrollElement.HR_START_DATE_HDTJOB.ToString(), form, 0);
                    listElementFormula.Add(item);

                    item = new ElementFormula(PayrollElement.HR_END_DATE_HDTJOB.ToString(), to, 0);
                    listElementFormula.Add(item);
                }
                else
                {
                    item = new ElementFormula(PayrollElement.HR_START_DATE_HDTJOB.ToString(), DateTime.MinValue, 0, "Null");
                    listElementFormula.Add(item);

                    item = new ElementFormula(PayrollElement.HR_END_DATE_HDTJOB.ToString(), DateTime.MinValue, 0, "Null");
                    listElementFormula.Add(item);
                }
            }

            #endregion

            #region Ngày vào làm và ngày kết thúc HDT JOB tháng N-1
            if (CheckIsExistFormula(listElementFormula, formula, new string[] { PayrollElement.HR_END_DATE_HDTJOB_PREV.ToString(), PayrollElement.HR_START_DATE_HDTJOB_PREV.ToString() }))
            {
                var CutOffDuration_Prev = TotalData.listCutOffDuration.Where(m => m.MonthYear == CutOffDuration.MonthYear.AddMonths(-1)).OrderByDescending(m => m.MonthYear).FirstOrDefault();

                if (CutOffDuration_Prev != null)
                {
                    List<Hre_HDTJobEntity> listHre_HDTJob_Prev = new List<Hre_HDTJobEntity>();
                    Hre_HDTJobEntity HDTJOB_DateFrom = new Hre_HDTJobEntity();
                    //Ngày vào làm HDT JOB
                    HDTJOB_DateFrom = TotalData.listHre_HDTJob_All.Where(m => m.ProfileID == profileItem.ID && m.DateFrom <= CutOffDuration_Prev.DateEnd && (m.DateTo >= CutOffDuration_Prev.DateStart || m.DateTo == null) && m.Status == HDTJobStatus.E_APPROVE.ToString()).OrderBy(m => m.DateFrom).FirstOrDefault();
                    if (HDTJOB_DateFrom != null)
                    {
                        DateTime form = HDTJOB_DateFrom.DateFrom != null ? (DateTime)HDTJOB_DateFrom.DateFrom : DateTime.MinValue;
                        DateTime to = HDTJOB_DateFrom.DateTo != null ? (DateTime)HDTJOB_DateFrom.DateTo : CutOffDuration.DateEnd;

                        item = new ElementFormula(PayrollElement.HR_START_DATE_HDTJOB_PREV.ToString(), form, 0);
                        listElementFormula.Add(item);

                        item = new ElementFormula(PayrollElement.HR_END_DATE_HDTJOB_PREV.ToString(), to, 0);
                        listElementFormula.Add(item);
                    }
                    else
                    {
                        item = new ElementFormula(PayrollElement.HR_START_DATE_HDTJOB_PREV.ToString(), DateTime.MinValue, 0, "Null");
                        listElementFormula.Add(item);

                        item = new ElementFormula(PayrollElement.HR_END_DATE_HDTJOB_PREV.ToString(), DateTime.MinValue, 0, "Null");
                        listElementFormula.Add(item);
                    }
                }
                else
                {
                    item = new ElementFormula(PayrollElement.HR_START_DATE_HDTJOB_PREV.ToString(), DateTime.MinValue, 0, "Không tồn tại kỳ N-1");
                    listElementFormula.Add(item);

                    item = new ElementFormula(PayrollElement.HR_END_DATE_HDTJOB_PREV.ToString(), DateTime.MinValue, 0, "Không tồn tại kỳ N-1");
                    listElementFormula.Add(item);
                }

            }


            #endregion

            #region Tính số ngày công đi làm HDT JOB Tháng N

            if (CheckIsExistFormula(listElementFormula, formula, PayrollElement.ATT_WORKDAY_HDTJOB_4.ToString()) || CheckIsExistFormula(listElementFormula, formula, PayrollElement.ATT_WORKDAY_HDTJOB_5.ToString()))//đã lấy lên chưa ?
            {
                double HDTJobDay = 0;
                if (listAttendanceTableProCut != null)
                {
                    if (listAttendanceTableProCut.HDTJobType1 != null && listAttendanceTableProCut.HDTJobType1 == EnumDropDown.HDTJobType.E_TYPE4.ToString())
                    {
                        HDTJobDay += listAttendanceTableProCut.HDTJobDayCount1 != null ? (int)listAttendanceTableProCut.HDTJobDayCount1 : 0;
                    }
                    if (listAttendanceTableProCut.HDTJobType2 != null && listAttendanceTableProCut.HDTJobType2 == EnumDropDown.HDTJobType.E_TYPE4.ToString())
                    {
                        HDTJobDay += listAttendanceTableProCut.HDTJobDayCount2 != null ? (int)listAttendanceTableProCut.HDTJobDayCount2 : 0;
                    }
                    if (listAttendanceTableProCut.HDTJobType3 != null && listAttendanceTableProCut.HDTJobType3 == EnumDropDown.HDTJobType.E_TYPE4.ToString())
                    {
                        HDTJobDay += listAttendanceTableProCut.HDTJobDayCount3 != null ? (int)listAttendanceTableProCut.HDTJobDayCount3 : 0;
                    }
                }

                //Số ngày công làm HDT Job Loại 4 (tháng N)
                item = new ElementFormula(PayrollElement.ATT_WORKDAY_HDTJOB_4.ToString(), HDTJobDay, 0);
                listElementFormula.Add(item);

                HDTJobDay = 0;
                if (listAttendanceTableProCut != null)
                {
                    if (listAttendanceTableProCut.HDTJobType1 != null && listAttendanceTableProCut.HDTJobType1 == EnumDropDown.HDTJobType.E_TYPE5.ToString())
                    {
                        HDTJobDay += listAttendanceTableProCut.HDTJobDayCount1 != null ? (int)listAttendanceTableProCut.HDTJobDayCount1 : 0;
                    }
                    if (listAttendanceTableProCut.HDTJobType2 != null && listAttendanceTableProCut.HDTJobType2 == EnumDropDown.HDTJobType.E_TYPE5.ToString())
                    {
                        HDTJobDay += listAttendanceTableProCut.HDTJobDayCount2 != null ? (int)listAttendanceTableProCut.HDTJobDayCount2 : 0;
                    }
                    if (listAttendanceTableProCut.HDTJobType3 != null && listAttendanceTableProCut.HDTJobType3 == EnumDropDown.HDTJobType.E_TYPE5.ToString())
                    {
                        HDTJobDay += listAttendanceTableProCut.HDTJobDayCount3 != null ? (int)listAttendanceTableProCut.HDTJobDayCount3 : 0;
                    }
                }

                //Số ngày công làm HDT Job Loại 5 (tháng N)
                item = new ElementFormula(PayrollElement.ATT_WORKDAY_HDTJOB_5.ToString(), HDTJobDay, 0);
                listElementFormula.Add(item);
            }

            #endregion

            #region Tính số ngày công đi làm HDT JOB Tháng N-1

            if (CheckIsExistFormula(listElementFormula, formula, new string[] { PayrollElement.ATT_WORKDAY_HDTJOB_PREV_4.ToString(), PayrollElement.ATT_WORKDAY_HDTJOB_PREV_5.ToString() }))
            {
                //lấy dữ liệu công tháng N-1
                var listAttendanceTableProCut_Prev = TotalData.Att_AttendanceTable_Prev.Where(m => m.ProfileID == profileItem.ID).FirstOrDefault();

                double HDTJobDay = 0;
                if (listAttendanceTableProCut_Prev != null && listAttendanceTableProCut_Prev.HDTJobType1 != null && listAttendanceTableProCut_Prev.HDTJobType1 == EnumDropDown.HDTJobType.E_TYPE4.ToString())
                {
                    HDTJobDay += listAttendanceTableProCut_Prev.HDTJobDayCount1 != null ? (int)listAttendanceTableProCut_Prev.HDTJobDayCount1 : 0;
                }
                if (listAttendanceTableProCut_Prev != null && listAttendanceTableProCut_Prev.HDTJobType2 != null && listAttendanceTableProCut_Prev.HDTJobType2 == EnumDropDown.HDTJobType.E_TYPE4.ToString())
                {
                    HDTJobDay += listAttendanceTableProCut_Prev.HDTJobDayCount2 != null ? (int)listAttendanceTableProCut_Prev.HDTJobDayCount2 : 0;
                }
                if (listAttendanceTableProCut_Prev != null && listAttendanceTableProCut_Prev.HDTJobType3 != null && listAttendanceTableProCut_Prev.HDTJobType3 == EnumDropDown.HDTJobType.E_TYPE4.ToString())
                {
                    HDTJobDay += listAttendanceTableProCut_Prev.HDTJobDayCount3 != null ? (int)listAttendanceTableProCut_Prev.HDTJobDayCount3 : 0;
                }

                //Số ngày công làm HDT Job Loại 4 (tháng N)
                item = new ElementFormula(PayrollElement.ATT_WORKDAY_HDTJOB_PREV_4.ToString(), HDTJobDay, 0);
                listElementFormula.Add(item);

                HDTJobDay = 0;
                if (listAttendanceTableProCut_Prev != null && listAttendanceTableProCut_Prev.HDTJobType1 != null && listAttendanceTableProCut_Prev.HDTJobType1 == EnumDropDown.HDTJobType.E_TYPE5.ToString())
                {
                    HDTJobDay += listAttendanceTableProCut_Prev.HDTJobDayCount1 != null ? (int)listAttendanceTableProCut_Prev.HDTJobDayCount1 : 0;
                }
                if (listAttendanceTableProCut_Prev != null && listAttendanceTableProCut_Prev.HDTJobType2 != null && listAttendanceTableProCut_Prev.HDTJobType2 == EnumDropDown.HDTJobType.E_TYPE5.ToString())
                {
                    HDTJobDay += listAttendanceTableProCut_Prev.HDTJobDayCount2 != null ? (int)listAttendanceTableProCut_Prev.HDTJobDayCount2 : 0;
                }
                if (listAttendanceTableProCut_Prev != null && listAttendanceTableProCut_Prev.HDTJobType3 != null && listAttendanceTableProCut_Prev.HDTJobType3 == EnumDropDown.HDTJobType.E_TYPE5.ToString())
                {
                    HDTJobDay += listAttendanceTableProCut_Prev.HDTJobDayCount3 != null ? (int)listAttendanceTableProCut_Prev.HDTJobDayCount3 : 0;
                }

                //Số ngày công làm HDT Job Loại 5 (tháng N)
                item = new ElementFormula(PayrollElement.ATT_WORKDAY_HDTJOB_PREV_5.ToString(), HDTJobDay, 0);
                listElementFormula.Add(item);
            }

            #endregion

            #region Phần tử kiểm tra có ngày ra HDT hay không tháng N và tháng N-1

            if (CheckIsExistFormula(listElementFormula, formula, new string[] { PayrollElement.ATT_HDT_IS_DATE_END.ToString(), PayrollElement.ATT_HDT_IS_DATE_END_N_1.ToString() }))
            {


                #region Tháng N
                List<Hre_HDTJobEntity> HDTJOBByProfile = new List<Hre_HDTJobEntity>();
                HDTJOBByProfile = TotalData.listHre_HDTJob_All.Where(m => m.ProfileID == profileItem.ID && m.DateFrom <= CutOffDuration.DateEnd && (m.DateTo >= CutOffDuration.DateStart || m.DateTo == null) && m.Status == HDTJobStatus.E_APPROVE.ToString()).ToList();
                if (HDTJOBByProfile.Any(m => m.DateTo == null))
                {
                    item = new ElementFormula(PayrollElement.ATT_HDT_IS_DATE_END.ToString(), 1, 0);
                    listElementFormula.Add(item);
                }
                else
                {
                    item = new ElementFormula(PayrollElement.ATT_HDT_IS_DATE_END.ToString(), 0, 0);
                    listElementFormula.Add(item);
                }
                #endregion

                #region Tháng N-1

                DateTime DateStartN1 = CutOffDuration.DateStart.AddMonths(-1);
                DateTime DateEndN1 = CutOffDuration.DateEnd.AddMonths(-1);

                HDTJOBByProfile = TotalData.listHre_HDTJob_All.Where(m => m.ProfileID == profileItem.ID && m.DateFrom <= DateEndN1 && (m.DateTo >= DateStartN1 || m.DateTo == null) && m.Status == HDTJobStatus.E_APPROVE.ToString()).ToList();
                if (HDTJOBByProfile.Any(m => m.DateTo == null))
                {
                    item = new ElementFormula(PayrollElement.ATT_HDT_IS_DATE_END.ToString(), 1, 0);
                    listElementFormula.Add(item);
                }
                else
                {
                    item = new ElementFormula(PayrollElement.ATT_HDT_IS_DATE_END.ToString(), 0, 0);
                    listElementFormula.Add(item);
                }
                #endregion


            }

            #endregion

            #region Số ngày làm HDT loại 4 và 5 trừ ngày DayOff (tháng N và tháng N-1)
            if (CheckIsExistFormula(listElementFormula, formula, new string[] { PayrollElement.ATT_WORKDAY_HDT_NOT_DAYOFF_4.ToString(), PayrollElement.ATT_WORKDAY_HDT_NOT_DAYOFF_5.ToString(), PayrollElement.ATT_WORKDAY_HDT_NOT_DAYOFF_4_N_1.ToString(), PayrollElement.ATT_WORKDAY_HDT_NOT_DAYOFF_5_N_1.ToString() }))
            {
                DateTime DateStartN1 = CutOffDuration.DateStart.AddMonths(-1);
                DateTime DateEndN1 = CutOffDuration.DateEnd.AddMonths(-1);

                List<Hre_HDTJobEntity> ListHDTByProfile = TotalData.listHre_HDTJob_All.Where(m => m.ProfileID == profileItem.ID && m.Status == HDTJobStatus.E_APPROVE.ToString()).ToList();
                List<Hre_HDTJobEntity> ListHDTByProfileN = ListHDTByProfile.Where(m => m.DateFrom <= CutOffDuration.DateEnd && (m.DateTo >= CutOffDuration.DateStart || m.DateTo == null)).ToList();
                List<Hre_HDTJobEntity> ListHDTByProfileN1 = ListHDTByProfile.Where(m => m.DateFrom <= DateEndN1 && (m.DateTo >= DateStartN1 || m.DateTo == null)).ToList();

                double ListDayOff = TotalData.listDayOff.Count(m => m.DateOff <= CutOffDuration.DateEnd && m.DateOff >= CutOffDuration.DateStart);
                double ListDayOffN1 = TotalData.listDayOff.Count(m => m.DateOff <= DateEndN1 && m.DateOff >= DateStartN1);

                #region tính số ngày làm HDT loại 4
                List<Hre_HDTJobEntity> ListHDTByProfileN_Type4 = ListHDTByProfileN.Where(m => m.Type == EnumDropDown.HDTJobType.E_TYPE4.ToString()).ToList();
                double Day_Type4 = 0;
                DateTime _tmp = new DateTime();
                foreach (var i in ListHDTByProfileN_Type4)
                {
                    _tmp = i.DateTo != null ? i.DateTo.Value : CutOffDuration.DateEnd;
                    if (i.DateFrom != null)
                    {
                        Day_Type4 += _tmp.Subtract(i.DateFrom.Value).TotalDays + 1;
                    }
                }
                item = new ElementFormula(PayrollElement.ATT_WORKDAY_HDT_NOT_DAYOFF_4.ToString(), Day_Type4, 0);
                listElementFormula.Add(item);
                #endregion

                #region tính số ngày làm HDT loại 5
                List<Hre_HDTJobEntity> ListHDTByProfileN_Type5 = ListHDTByProfileN.Where(m => m.Type == EnumDropDown.HDTJobType.E_TYPE5.ToString()).ToList();
                double Day_Type5 = 0;
                foreach (var i in ListHDTByProfileN_Type5)
                {
                    _tmp = i.DateTo != null ? i.DateTo.Value : CutOffDuration.DateEnd;
                    if (i.DateFrom != null)
                    {
                        Day_Type5 += _tmp.Subtract(i.DateFrom.Value).TotalDays + 1;
                    }
                }
                item = new ElementFormula(PayrollElement.ATT_WORKDAY_HDT_NOT_DAYOFF_5.ToString(), Day_Type5, 0);
                listElementFormula.Add(item);
                #endregion

                #region tính số ngày làm HDT loại 4 tháng N-1
                ListHDTByProfileN_Type4 = ListHDTByProfileN1.Where(m => m.Type == EnumDropDown.HDTJobType.E_TYPE4.ToString()).ToList();
                Day_Type4 = 0;
                _tmp = new DateTime();
                foreach (var i in ListHDTByProfileN_Type4)
                {
                    _tmp = i.DateTo != null ? i.DateTo.Value : CutOffDuration.DateEnd;
                    if (i.DateFrom != null)
                    {
                        Day_Type4 += _tmp.Subtract(i.DateFrom.Value).TotalDays + 1;
                    }
                }
                item = new ElementFormula(PayrollElement.ATT_WORKDAY_HDT_NOT_DAYOFF_4_N_1.ToString(), Day_Type4, 0);
                listElementFormula.Add(item);
                #endregion

                #region tính số ngày làm HDT loại 5 tháng N-1
                ListHDTByProfileN_Type5 = ListHDTByProfileN1.Where(m => m.Type == EnumDropDown.HDTJobType.E_TYPE5.ToString()).ToList();
                Day_Type5 = 0;
                foreach (var i in ListHDTByProfileN_Type5)
                {
                    _tmp = i.DateTo != null ? i.DateTo.Value : CutOffDuration.DateEnd;
                    if (i.DateFrom != null)
                    {
                        Day_Type5 += _tmp.Subtract(i.DateFrom.Value).TotalDays + 1;
                    }
                }
                item = new ElementFormula(PayrollElement.ATT_WORKDAY_HDT_NOT_DAYOFF_5_N_1.ToString(), Day_Type5, 0);
                listElementFormula.Add(item);
                #endregion

            }
            #endregion

            #region Số ngày Day Off từ đầu tháng đến ngày vào HDT

            if (CheckIsExistFormula(listElementFormula, formula, new string[] { PayrollElement.ATT_DAYOFF_STARTMONTH_STARTHDT.ToString(), PayrollElement.ATT_DAYOFF_STARTMONTH_STARTHDT_N_1.ToString() }))
            {
                #region Tháng N
                Hre_HDTJobEntity ListHDTByProfile = TotalData.listHre_HDTJob_All.Where(m => m.ProfileID == profileItem.ID && m.Status == HDTJobStatus.E_APPROVE.ToString() && m.DateTo != null && m.DateFrom != null && m.DateFrom <= CutOffDuration.DateEnd && m.DateTo >= CutOffDuration.DateStart).OrderBy(m => m.DateFrom).FirstOrDefault();

                if (ListHDTByProfile != null)
                {
                    double DayOff = TotalData.listDayOff.Count(m => m.DateOff <= ListHDTByProfile.DateFrom && m.DateOff >= CutOffDuration.DateStart);
                    item = new ElementFormula(PayrollElement.ATT_DAYOFF_STARTMONTH_STARTHDT.ToString(), DayOff, 0);
                    listElementFormula.Add(item);
                }
                else
                {
                    item = new ElementFormula(PayrollElement.ATT_DAYOFF_STARTMONTH_STARTHDT.ToString(), 0, 0, "null");
                    listElementFormula.Add(item);
                }
                #endregion

                #region Tháng N-1
                DateTime DateStartN1 = CutOffDuration.DateStart.AddMonths(-1);
                DateTime DateEndN1 = CutOffDuration.DateEnd.AddMonths(-1);
                ListHDTByProfile = TotalData.listHre_HDTJob_All.Where(m => m.ProfileID == profileItem.ID && m.Status == HDTJobStatus.E_APPROVE.ToString() && m.DateTo != null && m.DateFrom != null && m.DateFrom <= DateEndN1 && m.DateTo >= DateStartN1).OrderBy(m => m.DateFrom).FirstOrDefault();

                if (ListHDTByProfile != null)
                {
                    double DayOff = TotalData.listDayOff.Count(m => m.DateOff <= ListHDTByProfile.DateFrom && m.DateOff >= DateStartN1);
                    item = new ElementFormula(PayrollElement.ATT_DAYOFF_STARTMONTH_STARTHDT_N_1.ToString(), DayOff, 0);
                    listElementFormula.Add(item);
                }
                else
                {
                    item = new ElementFormula(PayrollElement.ATT_DAYOFF_STARTMONTH_STARTHDT_N_1.ToString(), 0, 0, "null");
                    listElementFormula.Add(item);
                }
                #endregion
            }

            #endregion

            #region số ngày từ ngày vào hdt đến cuối tháng trừ số ngày dayoff từ ngày vào đến cuối tháng(tháng N và tháng N-1)

            if (CheckIsExistFormula(listElementFormula, formula, new string[] { PayrollElement.ATT_WORKDAY_STARTHDT_MONTHEND.ToString(), PayrollElement.ATT_WORKDAY_STARTHDT_MONTHEND_N_1.ToString() }))
            {
                double WorkDay = 0;
                double DayOff = 0;
                #region Tháng N
                List<Hre_HDTJobEntity> ListHDTByProfile = TotalData.listHre_HDTJob_All.Where(m => m.ProfileID == profileItem.ID && m.Status == HDTJobStatus.E_APPROVE.ToString() && m.DateTo != null && m.DateFrom != null && m.DateFrom <= CutOffDuration.DateEnd && m.DateTo >= CutOffDuration.DateStart).OrderBy(m => m.DateFrom).ToList();

                if (ListHDTByProfile.Count > 0)
                {
                    foreach (var i in ListHDTByProfile)
                    {
                        if (i.DateFrom != null && i.DateTo != null)
                        {
                            if (i.DateTo < CutOffDuration.DateEnd)
                            {
                                WorkDay += i.DateTo.Value.Subtract(i.DateFrom.Value).TotalDays + 1;
                            }
                            else
                            {
                                WorkDay += CutOffDuration.DateEnd.Subtract(i.DateFrom.Value).TotalDays + 1;
                            }
                        }
                    }
                    DayOff = TotalData.listDayOff.Count(m => m.DateOff >= ListHDTByProfile.FirstOrDefault().DateFrom && m.DateOff <= CutOffDuration.DateEnd);
                    item = new ElementFormula(PayrollElement.ATT_WORKDAY_STARTHDT_MONTHEND.ToString(), WorkDay - DayOff, 0);
                    listElementFormula.Add(item);
                }
                else
                {
                    item = new ElementFormula(PayrollElement.ATT_WORKDAY_STARTHDT_MONTHEND.ToString(), 0, 0, "null");
                    listElementFormula.Add(item);
                }
                #endregion

                #region Tháng N-1
                DateTime DateStartN1 = CutOffDuration.DateStart.AddMonths(-1);
                DateTime DateEndN1 = CutOffDuration.DateEnd.AddMonths(-1);
                WorkDay = 0;
                DayOff = 0;
                ListHDTByProfile = TotalData.listHre_HDTJob_All.Where(m => m.ProfileID == profileItem.ID && m.Status == HDTJobStatus.E_APPROVE.ToString() && m.DateTo != null && m.DateFrom != null && m.DateFrom <= DateEndN1 && m.DateTo >= DateStartN1).OrderBy(m => m.DateFrom).ToList();

                if (ListHDTByProfile.Count > 0)
                {
                    foreach (var i in ListHDTByProfile)
                    {
                        if (i.DateFrom != null && i.DateTo != null)
                        {
                            if (i.DateTo < CutOffDuration.DateEnd)
                            {
                                WorkDay += i.DateTo.Value.Subtract(i.DateFrom.Value).TotalDays + 1;
                            }
                            else
                            {
                                WorkDay += CutOffDuration.DateEnd.Subtract(i.DateFrom.Value).TotalDays + 1;
                            }
                        }
                    }
                    DayOff = TotalData.listDayOff.Count(m => m.DateOff >= ListHDTByProfile.FirstOrDefault().DateFrom && m.DateOff <= CutOffDuration.DateEnd);
                    item = new ElementFormula(PayrollElement.ATT_WORKDAY_STARTHDT_MONTHEND_N_1.ToString(), WorkDay - DayOff, 0);
                    listElementFormula.Add(item);
                }
                else
                {
                    item = new ElementFormula(PayrollElement.ATT_WORKDAY_STARTHDT_MONTHEND_N_1.ToString(), 0, 0, "null");
                    listElementFormula.Add(item);
                }

                #endregion
            }

            #endregion

            #region số ngày từ ngày vào hdt tháng N-1 đến ngày ra hdt tháng N-1 trừ ngày dayoff tháng N-1 và N-2
            if (CheckIsExistFormula(listElementFormula, formula, new string[] { PayrollElement.ATT_WORKDAY_STARTHDT_ENDHDT_N_1.ToString(), PayrollElement.ATT_WORKDAY_STARTHDT_ENDHDT_N_2.ToString() }))
            {
                DateTime DateStartN1 = CutOffDuration.DateStart.AddMonths(-1);
                DateTime DateEndN1 = CutOffDuration.DateEnd.AddMonths(-1);
                DateTime DateStartN2 = CutOffDuration.DateStart.AddMonths(-2);
                DateTime DateEndN2 = CutOffDuration.DateEnd.AddMonths(-2);
                double workDayHDT = 0;
                double DayOff = TotalData.listDayOff.Count(m => m.DateOff <= DateEndN1 && m.DateOff >= DateStartN1);

                #region Tháng N-1
                List<Hre_HDTJobEntity> ListHDTByProfile = TotalData.listHre_HDTJob_All.Where(m => m.ProfileID == profileItem.ID && m.Status == HDTJobStatus.E_APPROVE.ToString() && m.DateTo != null && m.DateFrom != null && m.DateFrom <= DateEndN1 && m.DateTo >= DateStartN1).OrderBy(m => m.DateFrom).ToList();
                foreach (var i in ListHDTByProfile)
                {
                    workDayHDT += i.DateTo.Value.Subtract(i.DateFrom.Value).TotalDays + 1;
                }
                item = new ElementFormula(PayrollElement.ATT_WORKDAY_STARTHDT_ENDHDT_N_1.ToString(), workDayHDT - DayOff, 0);
                listElementFormula.Add(item);

                #endregion

                #region Tháng N-2
                workDayHDT = 0;
                DayOff = TotalData.listDayOff.Count(m => m.DateOff <= DateEndN2 && m.DateOff >= DateStartN2);
                ListHDTByProfile = TotalData.listHre_HDTJob_All.Where(m => m.ProfileID == profileItem.ID && m.Status == HDTJobStatus.E_APPROVE.ToString() && m.DateTo != null && m.DateFrom != null && m.DateFrom <= DateEndN2 && m.DateTo >= DateStartN2).OrderBy(m => m.DateFrom).ToList();
                foreach (var i in ListHDTByProfile)
                {
                    workDayHDT += i.DateTo.Value.Subtract(i.DateFrom.Value).TotalDays + 1;
                }
                item = new ElementFormula(PayrollElement.ATT_WORKDAY_STARTHDT_ENDHDT_N_2.ToString(), workDayHDT - DayOff, 0);
                listElementFormula.Add(item);
                #endregion

            }
            #endregion

            #region Ngày vào HDT tháng N-1 và N-2

            if (CheckIsExistFormula(listElementFormula, formula, new string[] { PayrollElement.ATT_STARTDATE_HDT_N_1.ToString(), PayrollElement.ATT_STARTDATE_HDT_N_2.ToString() }))
            {
                DateTime DateStartN1 = CutOffDuration.DateStart.AddMonths(-1);
                DateTime DateEndN1 = CutOffDuration.DateEnd.AddMonths(-1);
                DateTime DateStartN2 = CutOffDuration.DateStart.AddMonths(-2);
                DateTime DateEndN2 = CutOffDuration.DateEnd.AddMonths(-2);

                Hre_HDTJobEntity ListHDTByProfile = TotalData.listHre_HDTJob_All.Where(m => m.ProfileID == profileItem.ID && m.Status == HDTJobStatus.E_APPROVE.ToString() && m.DateTo != null && m.DateFrom != null && m.DateFrom <= DateEndN1 && m.DateTo >= DateStartN1).OrderBy(m => m.DateFrom).FirstOrDefault();
                if (ListHDTByProfile != null)
                {
                    item = new ElementFormula(PayrollElement.ATT_WORKDAY_STARTHDT_ENDHDT_N_1.ToString(), ListHDTByProfile.DateFrom, 0);
                    listElementFormula.Add(item);
                }
                else
                {
                    item = new ElementFormula(PayrollElement.ATT_WORKDAY_STARTHDT_ENDHDT_N_1.ToString(), 0, 0);
                    listElementFormula.Add(item);
                }

                ListHDTByProfile = TotalData.listHre_HDTJob_All.Where(m => m.ProfileID == profileItem.ID && m.Status == HDTJobStatus.E_APPROVE.ToString() && m.DateTo != null && m.DateFrom != null && m.DateFrom <= DateEndN2 && m.DateTo >= DateStartN2).OrderBy(m => m.DateFrom).FirstOrDefault();
                if (ListHDTByProfile != null)
                {
                    item = new ElementFormula(PayrollElement.ATT_WORKDAY_STARTHDT_ENDHDT_N_2.ToString(), ListHDTByProfile.DateFrom, 0);
                    listElementFormula.Add(item);
                }
                else
                {
                    item = new ElementFormula(PayrollElement.ATT_WORKDAY_STARTHDT_ENDHDT_N_2.ToString(), 0, 0);
                    listElementFormula.Add(item);
                }


            }

            #endregion

            #endregion

            #endregion

            #region Enum phần tử lương
            //Có tham gia công đoàn
            if (CheckIsExistFormula(listElementFormula, formula, PayrollElement.IS_HRE_TRADEUNION.ToString()))
            {
                var ProfilePartyUnion = TotalData.listProfilePartyUnion.Where(m => m.ProfileID == profileItem.ID && m.IsTradeUnionist == true && m.TradeUnionistEnrolledDate != null && m.TradeUnionistEnrolledDate.Value <= CutOffDuration.DateEnd).FirstOrDefault();

                item = new ElementFormula(PayrollElement.IS_HRE_TRADEUNION.ToString(), ProfilePartyUnion != null ? 1 : 0, 0);
                listElementFormula.Add(item);
            }

            //Người phụ thuộc
            if (CheckIsExistFormula(listElementFormula, formula, PayrollElement.SAL_DEPENDENT.ToString()))
            {
                item = new ElementFormula(PayrollElement.SAL_DEPENDENT.ToString(), GetDependantNumber(TotalData.listDependant, profileItem.ID, CutOffDuration.DateStart, CutOffDuration.DateEnd), 0);
                listElementFormula.Add(item);
            }

            //Mức lương HDT
            if (CheckIsExistFormula(listElementFormula, formula, new string[] { PayrollElement.SAL_SALARY_HDT.ToString(), PayrollElement.SAL_SALARY_HDT_N_1.ToString() }))
            {
                var Insurence = TotalData.listInsurance.Where(m => m.ProfileID == profileItem.ID && m.MonthYear != null && m.MonthYear.Value.Year == CutOffDuration.MonthYear.Year && m.MonthYear.Value.Month == CutOffDuration.MonthYear.Month).FirstOrDefault();
                item = new ElementFormula(PayrollElement.SAL_SALARY_HDT.ToString(), Insurence != null && Insurence.AmountChargeIns != null ? Insurence.AmountChargeIns : 0, 0);
                listElementFormula.Add(item);

                DateTime MonthYearPrev = new DateTime(CutOffDuration.MonthYear.Year, CutOffDuration.MonthYear.Month, CutOffDuration.MonthYear.Day).AddMonths(-1);
                Insurence = TotalData.listInsurance.Where(m => m.ProfileID == profileItem.ID && m.MonthYear != null && m.MonthYear.Value.Year == MonthYearPrev.Year && m.MonthYear.Value.Month == MonthYearPrev.Month).FirstOrDefault();
                item = new ElementFormula(PayrollElement.SAL_SALARY_HDT_N_1.ToString(), Insurence != null && Insurence.AmountChargeIns != null ? Insurence.AmountChargeIns : 0, 0);
                listElementFormula.Add(item);
            }

            //Luong co ban thang 3
            if (CheckIsExistFormula(listElementFormula, formula, PayrollElement.SAL_BASIC_SALARY_T3.ToString()))
            {
                item = new ElementFormula(PayrollElement.SAL_BASIC_SALARY_T3.ToString(), TotalData.listBasicSalaryT3.Where(m => m.ProfileID == profileItem.ID).OrderByDescending(m => m.DateOfEffect).FirstOrDefault().GrossAmount, 0);
                listElementFormula.Add(item);
            }

            //Bậc lương
            if (CheckIsExistFormula(listElementFormula, formula, PayrollElement.SAL_SALARY_RANK_NAME.ToString()))
            {
                Sal_BasicSalaryEntity BasicSalarybyProfile = new Sal_BasicSalaryEntity();
                BasicSalarybyProfile = TotalData.listBasicSalary.Where(m => m.ProfileID == profileItem.ID).OrderByDescending(m => m.DateOfEffect).FirstOrDefault();
                item = new ElementFormula(PayrollElement.SAL_SALARY_RANK_NAME.ToString(), BasicSalarybyProfile != null ? BasicSalarybyProfile.SalaryRankName : "", 0);
                listElementFormula.Add(item);
            }

            //Bậc lương (class)
            if (CheckIsExistFormula(listElementFormula, formula, PayrollElement.SAL_SALARY_CLASS_NAME.ToString()))
            {
                Sal_BasicSalaryEntity BasicSalarybyProfile = new Sal_BasicSalaryEntity();
                BasicSalarybyProfile = TotalData.listBasicSalary.Where(m => m.ProfileID == profileItem.ID).OrderByDescending(m => m.DateOfEffect).FirstOrDefault();
                item = new ElementFormula(PayrollElement.SAL_SALARY_CLASS_NAME.ToString(), BasicSalarybyProfile != null ? BasicSalarybyProfile.SalaryClassName : "", 0);
                listElementFormula.Add(item);
            }

            //Hệ số lương nhân viên
            if (CheckIsExistFormula(listElementFormula, formula, PayrollElement.SAL_BASIC_PERSONALRATE.ToString()))
            {
                List<Sal_BasicSalaryEntity> SalaryProfile = new List<Sal_BasicSalaryEntity>();
                SalaryProfile = TotalData.listBasicSalary.Where(m => m.ProfileID == profileItem.ID).OrderByDescending(m => m.DateOfEffect).ToList();
                item = new ElementFormula(PayrollElement.SAL_BASIC_PERSONALRATE.ToString(), SalaryProfile.FirstOrDefault().PersonalRate != null ? SalaryProfile.FirstOrDefault().PersonalRate : 0, 0, "Null");
                listElementFormula.Add(item);
            }

            if (CheckIsExistFormula(listElementFormula, formula, new string[] { PayrollElement.SAL_BASIC_SALARY_DATECLOSE.ToString(), PayrollElement.SAL_BASIC_SALARY_DATECLOSE_N_1.ToString() }))
            {
                List<Sal_BasicSalaryEntity> ListSalaryProfile = new List<Sal_BasicSalaryEntity>();
                ListSalaryProfile = TotalData.listBasicSalary.Where(m => m.ProfileID == profileItem.ID).OrderByDescending(m => m.DateOfEffect).ToList();
                if (ListSalaryProfile.Count > 0)
                {
                    //Lấy các phần tử tính lương nằm trong Grade của nhân viên
                    Sal_GradeEntity Grade = FindGradePayrollByProfileAndMonthYear(TotalData.listGrade, profileItem.ID, CutOffDuration.DateStart, CutOffDuration.DateEnd);
                    //loại bỏ nhân viên có ngày vào làm sau ngày chốt lương
                    Cat_GradePayrollEntity CatGrade = TotalData.listCat_GradePayroll.Where(m => m.ID == Grade.GradePayrollID).FirstOrDefault();

                    //ngày bắt đầu chốt lương
                    DateTime DateClose = new DateTime(CutOffDuration.MonthYear.Year, CutOffDuration.MonthYear.Month, CatGrade.SalaryDayClose != null ? (int)CatGrade.SalaryDayClose : 1).AddDays(1).AddMonths(-1);
                    //ngày kết thúc chốt lương
                    DateTime DateEndClose = new DateTime(CutOffDuration.MonthYear.Year, CutOffDuration.MonthYear.Month, CatGrade.SalaryDayClose != null ? (int)CatGrade.SalaryDayClose : 1);

                    //lọc lại lương cơ bản theo kỳ chốt
                    ListSalaryProfile = ListSalaryProfile.Where(m => m.DateOfEffect <= DateEndClose).ToList();

                    //lương cơ bản gần nhất
                    Sal_BasicSalaryEntity SalaryProfile = ListSalaryProfile.FirstOrDefault();

                    //nếu ngày thay đổi lương nằm trong kỳ chốt lương thì lấy 2 mức
                    if (SalaryProfile.DateOfEffect >= DateClose && SalaryProfile.DateOfEffect <= DateEndClose)
                    {
                        item = new ElementFormula(PayrollElement.SAL_BASIC_SALARY_DATECLOSE.ToString(), SalaryProfile.GrossAmount, 0);
                        listElementFormula.Add(item);

                        Sal_BasicSalaryEntity SalaryProfile_Prev = ListSalaryProfile.Where(m => m.DateOfEffect < DateClose).OrderByDescending(m => m.DateOfEffect).FirstOrDefault();
                        item = new ElementFormula(PayrollElement.SAL_BASIC_SALARY_DATECLOSE_N_1.ToString(), SalaryProfile_Prev != null ? SalaryProfile_Prev.GrossAmount : "0", 0);
                        listElementFormula.Add(item);
                    }
                    else//chỉ áp dụng 1 mức lương
                    {
                        item = new ElementFormula(PayrollElement.SAL_BASIC_SALARY_DATECLOSE.ToString(), SalaryProfile.GrossAmount, 0);
                        listElementFormula.Add(item);
                        item = new ElementFormula(PayrollElement.SAL_BASIC_SALARY_DATECLOSE_N_1.ToString(), SalaryProfile.GrossAmount, 0);
                        listElementFormula.Add(item);
                    }
                }
                else
                {
                    item = new ElementFormula(PayrollElement.SAL_BASIC_SALARY_DATECLOSE.ToString(), 0, 0, "Không có lương cơ bản !");
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.SAL_BASIC_SALARY_DATECLOSE_N_1.ToString(), 0, 0, "Không có thay đổi lương trong tháng !");
                    listElementFormula.Add(item);
                }
            }

            //Lương cơ bản
            if (CheckIsExistFormula(listElementFormula, formula, new string[] { PayrollElement.SAL_BASIC_SALARY.ToString(), PayrollElement.HR_SALARYCLASSNAME.ToString(), PayrollElement.SAL_BASIC_SALARY2.ToString(), PayrollElement.SAL_BASIC_SALARY1.ToString(), PayrollElement.SAL_BASIC_SALARY_N_1.ToString(), PayrollElement.SAL_BASIC_SALARY_N_2.ToString(), PayrollElement.SAL_BASIC_SALARY_N_3.ToString(), PayrollElement.SAL_BASIC_SALARY_N_4.ToString(), PayrollElement.SAL_BASIC_SALARY_N_5.ToString(), PayrollElement.SAL_BASIC_SALARY_N_6.ToString(), PayrollElement.SAL_INCENTIVE.ToString() }))
            {
                using (var context = new VnrHrmDataContext())
                {
                    var unitOfWork = (IUnitOfWork)(new UnitOfWork(context));
                    List<Sal_BasicSalaryEntity> SalaryProfile = new List<Sal_BasicSalaryEntity>();
                    SalaryProfile = TotalData.listBasicSalary.Where(m => m.ProfileID == profileItem.ID).OrderByDescending(m => m.DateOfEffect).ToList();
                    if (SalaryProfile != null && SalaryProfile.Count > 0)//có lương cơ bản
                    {
                        //bật lương
                        item = new ElementFormula(PayrollElement.HR_SALARYCLASSNAME.ToString(), SalaryProfile.FirstOrDefault().SalaryClassCode, 0, "Null");
                        listElementFormula.Add(item);

                        //lương cơ bản tháng hiện tại
                        if (SalaryProfile.FirstOrDefault().DateOfEffect <= CutOffDuration.DateStart)//chỉ có 1 mức lương trong tháng
                        {
                            item = new ElementFormula(PayrollElement.SAL_BASIC_SALARY.ToString(), SalaryProfile.OrderByDescending(m => m.DateOfEffect).FirstOrDefault().GrossAmount, 0);
                            listElementFormula.Add(item);
                            item = new ElementFormula(PayrollElement.SAL_INCENTIVE.ToString(), 0, 0);
                            listElementFormula.Add(item);
                        }
                        else//2 mức lương trong tháng
                        {
                            item = new ElementFormula(PayrollElement.SAL_BASIC_SALARY.ToString(), 0, 0, "Null");
                            listElementFormula.Add(item);

                            item = new ElementFormula(PayrollElement.SAL_BASIC_SALARY2.ToString(), SalaryProfile.FirstOrDefault().GrossAmount, 0);
                            listElementFormula.Add(item);
                            if (SalaryProfile.Count > 1)
                            {
                                item = new ElementFormula(PayrollElement.SAL_BASIC_SALARY1.ToString(), SalaryProfile[1].GrossAmount, 0);
                            }
                            else
                            {
                                item = new ElementFormula(PayrollElement.SAL_BASIC_SALARY1.ToString(), 0, 0, "Null");
                            }

                            listElementFormula.Add(item);

                            #region Tính số ngày thay đổi lương
                            List<Att_RosterEntity> listRosterProfile = new List<Att_RosterEntity>();
                            //Lọc ra các roster thuộc nhân viên và nằm trong tháng tính lương
                            listRosterProfile = TotalData.listRoster.Where(m => m.ProfileID == profileItem.ID).ToList();

                            int totalLeave = 0;
                            foreach (var j in listRosterProfile)
                            {
                                DateTime _tmp = j.DateStart;
                                while (true)
                                {
                                    if (_tmp > CutOffDuration.DateEnd)
                                    {
                                        break;
                                    }
                                    if (_tmp >= SalaryProfile.FirstOrDefault().DateOfEffect)
                                    {
                                        int day = (int)_tmp.DayOfWeek;
                                        switch (day)
                                        {
                                            case 0://CN
                                                if (j.SunShiftID != null)
                                                {
                                                    totalLeave++;
                                                }
                                                break;
                                            case 1://T2
                                                if (j.MonShiftID != null)
                                                {
                                                    totalLeave++;
                                                }
                                                break;
                                            case 2:
                                                if (j.TueShiftID != null)
                                                {
                                                    totalLeave++;
                                                }
                                                break;
                                            case 3:
                                                if (j.WedShiftID != null)
                                                {
                                                    totalLeave++;
                                                }
                                                break;
                                            case 4:
                                                if (j.ThuShiftID != null)
                                                {
                                                    totalLeave++;
                                                }
                                                break;
                                            case 5:
                                                if (j.FriShiftID != null)
                                                {
                                                    totalLeave++;
                                                }
                                                break;
                                            case 6:
                                                if (j.SatShiftID != null)
                                                {
                                                    totalLeave++;
                                                }
                                                break;
                                            default:

                                                break;
                                        }
                                    }
                                    _tmp = _tmp.AddDays(1);
                                }
                            }
                            //cập nhật lại giá trị cho enum số ngày thay đổi lương
                            int days = (CutOffDuration.DateEnd - SalaryProfile.FirstOrDefault().DateOfEffect).Days;
                            days = days - totalLeave;
                            item = new ElementFormula(PayrollElement.SAL_INCENTIVE.ToString(), days, 0);
                            listElementFormula.Add(item);
                            //item = listElementFormula.Where(m => m.VariableName == PayrollElement.SAL_INCENTIVE.ToString()).FirstOrDefault();
                            //item.Value = days;
                            #endregion
                        }

                        #region lương cơ bản 6 tháng trước đó
                        var _basicsalaryPrevCurrentMonth = SalaryProfile.Where(m => m.DateOfEffect <= CutOffDuration.DateEnd.AddMonths(-1)).OrderByDescending(m => m.DateOfEffect).ToList();
                        if (_basicsalaryPrevCurrentMonth.Count > 0)
                        {
                            item = new ElementFormula(PayrollElement.SAL_BASIC_SALARY_N_1.ToString(), _basicsalaryPrevCurrentMonth.FirstOrDefault().GrossAmount, 0);
                            listElementFormula.Add(item);
                        }
                        else
                        {
                            item = new ElementFormula(PayrollElement.SAL_BASIC_SALARY_N_1.ToString(), 0, 0, "Null");
                            listElementFormula.Add(item);
                        }
                        _basicsalaryPrevCurrentMonth = SalaryProfile.Where(m => m.DateOfEffect <= CutOffDuration.DateEnd.AddMonths(-2)).OrderByDescending(m => m.DateOfEffect).ToList();
                        if (_basicsalaryPrevCurrentMonth.Count > 0)
                        {
                            item = new ElementFormula(PayrollElement.SAL_BASIC_SALARY_N_2.ToString(), _basicsalaryPrevCurrentMonth.FirstOrDefault().GrossAmount, 0);
                            listElementFormula.Add(item);
                        }
                        else
                        {
                            item = new ElementFormula(PayrollElement.SAL_BASIC_SALARY_N_2.ToString(), 0, 0, "Null");
                            listElementFormula.Add(item);
                        }
                        _basicsalaryPrevCurrentMonth = SalaryProfile.Where(m => m.DateOfEffect <= CutOffDuration.DateEnd.AddMonths(-3)).OrderByDescending(m => m.DateOfEffect).ToList();
                        if (_basicsalaryPrevCurrentMonth.Count > 0)
                        {
                            item = new ElementFormula(PayrollElement.SAL_BASIC_SALARY_N_3.ToString(), _basicsalaryPrevCurrentMonth.FirstOrDefault().GrossAmount, 0);
                            listElementFormula.Add(item);
                        }
                        else
                        {
                            item = new ElementFormula(PayrollElement.SAL_BASIC_SALARY_N_3.ToString(), 0, 0, "Null");
                            listElementFormula.Add(item);
                        }
                        _basicsalaryPrevCurrentMonth = SalaryProfile.Where(m => m.DateOfEffect <= CutOffDuration.DateEnd.AddMonths(-4)).OrderByDescending(m => m.DateOfEffect).ToList();
                        if (_basicsalaryPrevCurrentMonth.Count > 0)
                        {
                            item = new ElementFormula(PayrollElement.SAL_BASIC_SALARY_N_4.ToString(), _basicsalaryPrevCurrentMonth.FirstOrDefault().GrossAmount, 0);
                            listElementFormula.Add(item);
                        }
                        else
                        {
                            item = new ElementFormula(PayrollElement.SAL_BASIC_SALARY_N_4.ToString(), 0, 0, "Null");
                            listElementFormula.Add(item);
                        }
                        _basicsalaryPrevCurrentMonth = SalaryProfile.Where(m => m.DateOfEffect <= CutOffDuration.DateEnd.AddMonths(-5)).OrderByDescending(m => m.DateOfEffect).ToList();
                        if (_basicsalaryPrevCurrentMonth.Count > 0)
                        {
                            item = new ElementFormula(PayrollElement.SAL_BASIC_SALARY_N_5.ToString(), _basicsalaryPrevCurrentMonth.FirstOrDefault().GrossAmount, 0);
                            listElementFormula.Add(item);
                        }
                        else
                        {
                            item = new ElementFormula(PayrollElement.SAL_BASIC_SALARY_N_5.ToString(), 0, 0, "Null");
                            listElementFormula.Add(item);
                        }
                        _basicsalaryPrevCurrentMonth = SalaryProfile.Where(m => m.DateOfEffect <= CutOffDuration.DateEnd.AddMonths(-6)).OrderByDescending(m => m.DateOfEffect).ToList();
                        if (_basicsalaryPrevCurrentMonth.Count > 0)
                        {
                            item = new ElementFormula(PayrollElement.SAL_BASIC_SALARY_N_6.ToString(), _basicsalaryPrevCurrentMonth.FirstOrDefault().GrossAmount, 0);
                            listElementFormula.Add(item);
                        }
                        else
                        {
                            item = new ElementFormula(PayrollElement.SAL_BASIC_SALARY_N_6.ToString(), 0, 0, "Null");
                            listElementFormula.Add(item);
                        }
                        #endregion
                    }
                    else//không có lương cơ bản
                    {
                        item = new ElementFormula(PayrollElement.SAL_BASIC_SALARY.ToString(), 0, 0, "Không có lương cơ bản tháng N");
                        listElementFormula.Add(item);
                        item = new ElementFormula(PayrollElement.SAL_BASIC_SALARY_N_1.ToString(), 0, 0, "Không có lương cơ bản tháng N-1");
                        listElementFormula.Add(item);
                        item = new ElementFormula(PayrollElement.SAL_BASIC_SALARY_N_2.ToString(), 0, 0, "Không có lương cơ bản tháng N-2");
                        listElementFormula.Add(item);
                        item = new ElementFormula(PayrollElement.SAL_BASIC_SALARY_N_3.ToString(), 0, 0, "Không có lương cơ bản tháng N-3");
                        listElementFormula.Add(item);
                        item = new ElementFormula(PayrollElement.SAL_BASIC_SALARY_N_4.ToString(), 0, 0, "Không có lương cơ bản tháng N-4");
                        listElementFormula.Add(item);
                        item = new ElementFormula(PayrollElement.SAL_BASIC_SALARY_N_5.ToString(), 0, 0, "Không có lương cơ bản tháng N-5");
                        listElementFormula.Add(item);
                        item = new ElementFormula(PayrollElement.SAL_BASIC_SALARY_N_6.ToString(), 0, 0, "Không có lương cơ bản tháng N-6");
                        listElementFormula.Add(item);
                        item = new ElementFormula(PayrollElement.SAL_BASIC_SALARY1.ToString(), 0, 0, "Không có lương cơ bản tháng N");
                        listElementFormula.Add(item);
                        item = new ElementFormula(PayrollElement.SAL_BASIC_SALARY2.ToString(), 0, 0, "Không có lương cơ bản tháng N");
                        listElementFormula.Add(item);
                        item = new ElementFormula(PayrollElement.SAL_INCENTIVE.ToString(), 0, 0, "Không có thay đổi lương tháng N");
                        listElementFormula.Add(item);
                        item = new ElementFormula(PayrollElement.HR_SALARYCLASSNAME.ToString(), 0, 0, "Không có Bậc / Hệ số lương tháng N");
                        listElementFormula.Add(item);
                    }
                }
            }

            if (CheckIsExistFormula(listElementFormula, formula, new string[] { PayrollElement.SAL_UNUSUALALLOWANCE_MONTHSTART.ToString(), PayrollElement.SAL_UNUSUALALLOWANCE_MONTHEND.ToString(), PayrollElement.SAL_UNUSUALALLOWANCE_YEARSTART.ToString(), PayrollElement.SAL_UNUSUALALLOWANCE_YEAREND.ToString(), PayrollElement.SAL_UNUSUALALLOWANCE_NOCOMPENSATION.ToString() }))
            {
                Sal_UnusualAllowanceEntity SalUnusualAllowanceProfile = TotalData.listSalUnusualAllowance.Where(m => m.ProfileID == profileItem.ID && m.MonthStart <= CutOffDuration.DateEnd && (m.MonthEnd == null || m.MonthEnd >= CutOffDuration.DateStart)).FirstOrDefault();

                //Tháng bắt đầu hưởng PC
                item = new ElementFormula(PayrollElement.SAL_UNUSUALALLOWANCE_MONTHSTART.ToString(), SalUnusualAllowanceProfile != null ? SalUnusualAllowanceProfile.MonthStart != null ? SalUnusualAllowanceProfile.MonthStart : DateTime.MinValue : DateTime.MinValue, 0);
                listElementFormula.Add(item);

                //Tháng kết thúc hưởng PC
                item = new ElementFormula(PayrollElement.SAL_UNUSUALALLOWANCE_MONTHEND.ToString(), SalUnusualAllowanceProfile != null ? SalUnusualAllowanceProfile.MonthEnd != null ? SalUnusualAllowanceProfile.MonthEnd : DateTime.MinValue : DateTime.MinValue, 0);
                listElementFormula.Add(item);

                //Năm bắt đầu hưởng PC
                item = new ElementFormula(PayrollElement.SAL_UNUSUALALLOWANCE_YEARSTART.ToString(), SalUnusualAllowanceProfile != null ? SalUnusualAllowanceProfile.MonthStart != null ? SalUnusualAllowanceProfile.MonthStart.Value.Year : 0 : 0, 0);
                listElementFormula.Add(item);

                //Năm kết thúc hưởng PC
                item = new ElementFormula(PayrollElement.SAL_UNUSUALALLOWANCE_YEAREND.ToString(), SalUnusualAllowanceProfile != null ? SalUnusualAllowanceProfile.MonthEnd != null ? SalUnusualAllowanceProfile.MonthEnd.Value.Year : 0 : 0, 0);
                listElementFormula.Add(item);

                //Số tháng bù
                item = new ElementFormula(PayrollElement.SAL_UNUSUALALLOWANCE_NOCOMPENSATION.ToString(), SalUnusualAllowanceProfile != null ? SalUnusualAllowanceProfile.NoCompensation != null ? SalUnusualAllowanceProfile.NoCompensation : 0 : 0, 0);
                listElementFormula.Add(item);
            }

            //// Mức phụ cấp con nhỏ mỗi tháng
            //item = new ElementFormula(PayrollElement.SAL_UNUSUALALLOWANCE_NOCOMPENSATION.ToString(), 0, 0);
            //listElementFormula.Add(item);

            //Thánh tính lương
            if (CheckIsExistFormula(listElementFormula, formula, PayrollElement.ATT_CUTOFFDURATION_MONTH.ToString()))
            {
                item = new ElementFormula(PayrollElement.ATT_CUTOFFDURATION_MONTH.ToString(), CutOffDuration.DateStart, 0);
                listElementFormula.Add(item);
            }

            //Tổng lương bộ phận của nhân viên
            if (CheckIsExistFormula(listElementFormula, formula, PayrollElement.SAL_SALARY_DEPARTMENT.ToString()))
            {
                if (TotalData.listSal_SalaryDepartmentItem.Any(m => m.ProfileID == profileItem.ID))
                {
                    var AmountSalary = TotalData.listSal_SalaryDepartmentItem.Where(m => m.ProfileID == profileItem.ID).FirstOrDefault().AmoutSalary;
                    item = new ElementFormula(PayrollElement.SAL_SALARY_DEPARTMENT.ToString(), AmountSalary != null ? AmountSalary : 0, 0);
                    listElementFormula.Add(item);
                }
                else
                {
                    item = new ElementFormula(PayrollElement.SAL_SALARY_DEPARTMENT.ToString(), 0, 0, "Null");
                    listElementFormula.Add(item);
                }
            }

            if (CheckIsExistFormula(listElementFormula, formula, PayrollElement.SAL_SALARY_DATE_CLOSE.ToString()))
            {
                Cat_GradePayrollEntity CatGradePayrollItem = TotalData.listCat_GradePayroll.Where(m => m.ID == FindGradePayrollByProfileAndMonthYear(TotalData.listGrade, profileItem.ID, CutOffDuration.DateStart, CutOffDuration.DateEnd).ID).FirstOrDefault();
                if (CatGradePayrollItem != null && CatGradePayrollItem.SalaryDayClose != null)
                {
                    item = new ElementFormula(PayrollElement.SAL_SALARY_DATE_CLOSE.ToString(), CatGradePayrollItem.SalaryDayClose, 0);
                    listElementFormula.Add(item);
                }
                else
                {
                    item = new ElementFormula(PayrollElement.SAL_SALARY_DATE_CLOSE.ToString(), 0, 0, "Null");
                    listElementFormula.Add(item);
                }
            }

            //Giữ lương
            if (CheckIsExistFormula(listElementFormula, formula, new string[] { PayrollElement.SAL_HOLD_SALARY.ToString(), PayrollElement.SAL_HOLD_SALARY_AFTERTAX.ToString() }))
            {
                DateTime _tmpCutoffDuration = CutOffDuration.MonthYear.AddMonths(-1);
                Sal_HoldSalaryEntity holdSalaryItem = TotalData.listSal_HoldSalary.Where(m => m.ProfileID == profileItem.ID
                    && m.MonthEndSalary != null
                    && m.Status == EnumDropDown.WorkdayStatus.E_APPROVED.ToString()
                    && m.MonthEndSalary.Value.Month == _tmpCutoffDuration.Month
                    && m.MonthEndSalary.Value.Year == _tmpCutoffDuration.Year).FirstOrDefault();

                if (holdSalaryItem != null)
                {
                    item = new ElementFormula(PayrollElement.SAL_HOLD_SALARY.ToString(), holdSalaryItem.AmountSalary, 0);
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.SAL_HOLD_SALARY_AFTERTAX.ToString(), holdSalaryItem.AmountSalaryAfterTax, 0);
                    listElementFormula.Add(item);
                }
                else
                {
                    item = new ElementFormula(PayrollElement.SAL_HOLD_SALARY.ToString(), 0, 0, "null");
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.SAL_HOLD_SALARY_AFTERTAX.ToString(), 0, 0, "null");
                    listElementFormula.Add(item);
                }
            }

            if (CheckIsExistFormula(listElementFormula, formula, new string[] { PayrollElement.SAL_SALARY_ACCOUNT_NO.ToString(), PayrollElement.SAL_SALARY_GROUP_BANK.ToString(), PayrollElement.SAL_SALARY_BANK_NAME.ToString() }))
            {
                Sal_SalaryInformationEntity SalaryInfomationByProfile = TotalData.listSalaryInformation.FirstOrDefault(m => m.ProfileID == profileItem.ID);
                if (SalaryInfomationByProfile != null)
                {
                    item = new ElementFormula(PayrollElement.SAL_SALARY_ACCOUNT_NO.ToString(), SalaryInfomationByProfile.AccountNo, 0);
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.SAL_SALARY_GROUP_BANK.ToString(), SalaryInfomationByProfile.GroupBank, 0);
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.SAL_SALARY_BANK_NAME.ToString(), SalaryInfomationByProfile.BankName, 0);
                    listElementFormula.Add(item);
                }
                else
                {
                    item = new ElementFormula(PayrollElement.SAL_SALARY_ACCOUNT_NO.ToString(), "", 0, "Null");
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.SAL_SALARY_GROUP_BANK.ToString(), "", 0, "Null");
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.SAL_SALARY_BANK_NAME.ToString(), "", 0, "Null");
                    listElementFormula.Add(item);
                }
            }

            #endregion

            #region Enum phần tử công

            #region Phần tử công tháng trước (N-1)
            if (CheckIsExistFormula(listElementFormula, formula, new string[] { PayrollElement.ATT_WORKING_DAY_PREV.ToString(), PayrollElement.ATT_STD_DAY_PREV.ToString() }))
            {
                if (TotalData.Att_AttendanceTable_Prev != null)
                {
                    Att_AttendanceTableEntity _tmp = TotalData.Att_AttendanceTable_Prev.Where(m => m.ProfileID == profileItem.ID).FirstOrDefault();
                    if (_tmp != null)
                    {
                        item = new ElementFormula(PayrollElement.ATT_WORKING_DAY_PREV.ToString(), _tmp.RealWorkDayCount, 0);
                        listElementFormula.Add(item);
                        item = new ElementFormula(PayrollElement.ATT_STD_DAY_PREV.ToString(), _tmp.StdWorkDayCount, 0);
                        listElementFormula.Add(item);
                    }
                    else
                    {
                        item = new ElementFormula(PayrollElement.ATT_WORKING_DAY_PREV.ToString(), 0, 0, "Null");
                        listElementFormula.Add(item);
                        item = new ElementFormula(PayrollElement.ATT_STD_DAY_PREV.ToString(), 0, 0, "Null");
                        listElementFormula.Add(item);
                    }
                }
                else
                {
                    item = new ElementFormula(PayrollElement.ATT_WORKING_DAY_PREV.ToString(), 0, 0, "Null");
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.ATT_STD_DAY_PREV.ToString(), 0, 0, "Null");
                    listElementFormula.Add(item);
                }
            }
            #endregion

            #region Ngày công đi làm thực tế
            if (CheckIsExistFormula(listElementFormula, formula, new string[] { PayrollElement.ATT_WORKING_DAY.ToString(), PayrollElement.ATT_WORKING_DAY_AFTER.ToString() }))
            {
                using (var context = new VnrHrmDataContext())
                {
                    var unitOfWork = (IUnitOfWork)new UnitOfWork(context);

                    //lấy lương cơ bản của nhân viên
                    List<Sal_BasicSalaryEntity> SalaryProfile = new List<Sal_BasicSalaryEntity>();
                    SalaryProfile = TotalData.listBasicSalary.Where(m => m.ProfileID == profileItem.ID).OrderByDescending(m => m.DateOfEffect).ToList();

                    if (SalaryProfile.Count > 0 && SalaryProfile.FirstOrDefault().DateOfEffect > CutOffDuration.DateStart)//có thay đổi lương trong tháng
                    {
                        //ngày bắt đầu mức lương 1 và ngày bắt đầu mức lương 2
                        DateTime dateStart1 = CutOffDuration.DateStart;
                        DateTime dateStart2 = SalaryProfile.FirstOrDefault().DateOfEffect;

                        //lấy dữ liệu công theo cutoff
                        List<Att_AttendanceTableItemEntity> listAttTableItem = TotalData.listAttendanceTableItem.Where(m => m.ProfileID == profileItem.ID).ToList();

                        item = new ElementFormula(PayrollElement.ATT_WORKING_DAY.ToString(), listAttTableItem.Where(m => m.WorkDate < dateStart2).Count(), 0);
                        listElementFormula.Add(item);
                        item = new ElementFormula(PayrollElement.ATT_WORKING_DAY_AFTER.ToString(), listAttTableItem.Where(m => m.WorkDate >= dateStart2).Count(), 0);
                        listElementFormula.Add(item);
                    }
                    else
                    {
                        item = new ElementFormula(PayrollElement.ATT_WORKING_DAY.ToString(), listAttendanceTableProCut.RealWorkDayCount, 0);
                        listElementFormula.Add(item);
                        item = new ElementFormula(PayrollElement.ATT_WORKING_DAY_AFTER.ToString(), 0, 0);
                        listElementFormula.Add(item);
                    }
                }
            }
            #endregion

            #region Ngày công đi làm tính lương

            if (CheckIsExistFormula(listElementFormula, formula, new string[] { PayrollElement.ATT_WORKING_PAIDLEAVE_DAY.ToString(), PayrollElement.ATT_WORKING_PAIDLEAVE_DAY_AFTER.ToString() }))
            {
                using (var context = new VnrHrmDataContext())
                {
                    var unitOfWork = (IUnitOfWork)new UnitOfWork(context);


                    //lấy lương cơ bản của nhân viên
                    List<Sal_BasicSalaryEntity> SalaryProfile = new List<Sal_BasicSalaryEntity>();
                    SalaryProfile = TotalData.listBasicSalary.Where(m => m.ProfileID == profileItem.ID).OrderByDescending(m => m.DateOfEffect).ToList();

                    if (SalaryProfile.Count > 0 && SalaryProfile.FirstOrDefault().DateOfEffect > CutOffDuration.DateStart)//có thay đổi lương trong tháng
                    {
                        //ngày bắt đầu mức lương 1 và ngày bắt đầu mức lương 2
                        DateTime dateStart1 = CutOffDuration.DateStart;
                        DateTime dateStart2 = SalaryProfile.FirstOrDefault().DateOfEffect;

                        //lưu số ngày công tính lương trước và sau khi thay đổi lương
                        double workpaid = 0;
                        double workpaid_after = 0;

                        //lấy dữ liệu công theo cutoff
                        List<Att_AttendanceTableItemEntity> listAttTableItem = TotalData.listAttendanceTableItem.Where(m => m.ProfileID == profileItem.ID).ToList();

                        //duyệt wa tất cả các dòng
                        foreach (var tableItem in listAttTableItem)
                        {
                            if (tableItem.WorkDate < dateStart2)//trước khi điều chỉnh
                            {
                                workpaid += tableItem.WorkPaidHours / tableItem.AvailableHours;
                            }
                            if (tableItem.WorkDate >= dateStart2)//sau khi điều chỉnh
                            {
                                workpaid_after += tableItem.WorkPaidHours / tableItem.AvailableHours;
                            }
                        }

                        item = new ElementFormula(PayrollElement.ATT_WORKING_PAIDLEAVE_DAY.ToString(), listAttTableItem.Where(m => m.WorkDate < dateStart2).Count(), 0);
                        listElementFormula.Add(item);
                        item = new ElementFormula(PayrollElement.ATT_WORKING_PAIDLEAVE_DAY_AFTER.ToString(), listAttTableItem.Where(m => m.WorkDate >= dateStart2).Count(), 0);
                        listElementFormula.Add(item);
                    }
                    else
                    {
                        item = new ElementFormula(PayrollElement.ATT_WORKING_PAIDLEAVE_DAY.ToString(), listAttendanceTableProCut.RealWorkDayCount, 0);
                        listElementFormula.Add(item);
                        item = new ElementFormula(PayrollElement.ATT_WORKING_PAIDLEAVE_DAY_AFTER.ToString(), 0, 0);
                        listElementFormula.Add(item);
                    }
                }
            }

            #endregion

            #region Số ngày phép năm cộng dồn - Số ngày phép ốm cộng dồn
            if (CheckIsExistFormula(listElementFormula, formula, new string[] { PayrollElement.ATT_ANNUAL_INCREMENTAL.ToString(), PayrollElement.ATT_SICK_INCREMENTAL.ToString() }))
            {
                List<Att_AnnualDetailEntity> AnnualDetailByProfile = TotalData.listAnnualDetail.Where(m => m.ProfileID == profileItem.ID).ToList();

                if (AnnualDetailByProfile != null && AnnualDetailByProfile.Count <= 0)
                {
                    var ANNUAL = AnnualDetailByProfile.FirstOrDefault(m => m.Type == AnnualLeaveDetailType.E_ANNUAL_LEAVE.ToString());
                    var SICK = AnnualDetailByProfile.FirstOrDefault(m => m.Type == AnnualLeaveDetailType.E_SICK_LEAVE.ToString());
                    item = new ElementFormula(PayrollElement.ATT_ANNUAL_INCREMENTAL.ToString(), ANNUAL != null ? ANNUAL.InitAvailable != null ? ANNUAL.InitAvailable : 0 : 0, 0);
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.ATT_SICK_INCREMENTAL.ToString(), SICK != null ? SICK.InitAvailable != null ? SICK.InitAvailable : 0 : 0, 0);
                    listElementFormula.Add(item);
                }
                else
                {
                    item = new ElementFormula(PayrollElement.ATT_ANNUAL_INCREMENTAL.ToString(), 0, 0, "Null");
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.ATT_SICK_INCREMENTAL.ToString(), 0, 0, "Null");
                    listElementFormula.Add(item);
                }
            }

            #endregion

            //Phần tử công tháng hiện tại
            if (CheckIsExistFormula(listElementFormula, formula, new string[] { PayrollElement.ATT_STD_DAY.ToString(), PayrollElement.ATT_HOURS_PER_DAY.ToString(), PayrollElement.ATT_OVERTIME_PIT_HOURS.ToString(), PayrollElement.ATT_TOTAL_ANNUALLEAVE_AVAILABLE.ToString(), PayrollElement.ATT_ANNUALLEAVE_ADJACENT.ToString(), PayrollElement.ATT_TOTAL_SICK_AVAILABLE.ToString(), PayrollElement.ATT_SICK_ADJACENT.ToString(), PayrollElement.ATT_ANNUALLEAVE.ToString(), PayrollElement.ATT_SICKLEAVE.ToString(), PayrollElement.ATT_WORKING_NIGHTSHIFT.ToString() }))
            {
                if (listAttendanceTableProCut != null)
                {
                    //item = new ElementFormula(PayrollElement.ATT_WORKING_DAY.ToString(), listAttendanceTableProCut.RealWorkDayCount, 0);
                    //listElementFormula.Add(item);

                    item = new ElementFormula(PayrollElement.ATT_STD_DAY.ToString(), listAttendanceTableProCut.StdWorkDayCount, 0);
                    listElementFormula.Add(item);

                    item = new ElementFormula(PayrollElement.ATT_HOURS_PER_DAY.ToString(), listAttendanceTableProCut.HourPerDay, 0);
                    listElementFormula.Add(item);

                    //item = new ElementFormula(PayrollElement.ATT_WORKING_PAIDLEAVE_DAY.ToString(), listAttendanceTableProCut.TotalPaidWorkDayCount, 0);
                    //listElementFormula.Add(item);

                    item = new ElementFormula(PayrollElement.ATT_WORKING_NIGHTSHIFT.ToString(), listAttendanceTableProCut.NightShiftHours, 0);
                    listElementFormula.Add(item);

                    item = new ElementFormula(PayrollElement.ATT_TOTAL_ANNUALLEAVE_AVAILABLE.ToString(), listAttendanceTableProCut.TotalAnlDayAvailable != null ? listAttendanceTableProCut.TotalAnlDayAvailable : 0, 0);
                    listElementFormula.Add(item);

                    item = new ElementFormula(PayrollElement.ATT_ANNUALLEAVE_ADJACENT.ToString(), listAttendanceTableProCut.AnlDayAdjacent, 0);
                    listElementFormula.Add(item);

                    item = new ElementFormula(PayrollElement.ATT_ANNUALLEAVE.ToString(), listAttendanceTableProCut.AnlDayTaken, 0);
                    listElementFormula.Add(item);

                    item = new ElementFormula(PayrollElement.ATT_SICKLEAVE.ToString(), listAttendanceTableProCut.SickDayTaken, 0);
                    listElementFormula.Add(item);

                    item = new ElementFormula(PayrollElement.ATT_TOTAL_SICK_AVAILABLE.ToString(), listAttendanceTableProCut.TotalSickDayAvailable, 0);
                    listElementFormula.Add(item);

                    item = new ElementFormula(PayrollElement.ATT_SICK_ADJACENT.ToString(), listAttendanceTableProCut.SickDayAdjacent, 0);
                    listElementFormula.Add(item);
                }
                else
                {
                    //item = new ElementFormula(PayrollElement.ATT_WORKING_DAY.ToString(), 0, 0, "Null");
                    //listElementFormula.Add(item);

                    item = new ElementFormula(PayrollElement.ATT_STD_DAY.ToString(), 0, 0, "Null");
                    listElementFormula.Add(item);

                    item = new ElementFormula(PayrollElement.ATT_HOURS_PER_DAY.ToString(), 0, 0, "Null");
                    listElementFormula.Add(item);

                    //item = new ElementFormula(PayrollElement.ATT_WORKING_PAIDLEAVE_DAY.ToString(), 0, 0, "Null");
                    //listElementFormula.Add(item);

                    item = new ElementFormula(PayrollElement.ATT_WORKING_NIGHTSHIFT.ToString(), 0, 0, "Null");
                    listElementFormula.Add(item);

                    item = new ElementFormula(PayrollElement.ATT_TOTAL_ANNUALLEAVE_AVAILABLE.ToString(), 0, 0, "Null");
                    listElementFormula.Add(item);

                    item = new ElementFormula(PayrollElement.ATT_ANNUALLEAVE_ADJACENT.ToString(), 0, 0, "Null");
                    listElementFormula.Add(item);

                    item = new ElementFormula(PayrollElement.ATT_TOTAL_SICK_AVAILABLE.ToString(), 0, 0, "Null");
                    listElementFormula.Add(item);

                    item = new ElementFormula(PayrollElement.ATT_SICK_ADJACENT.ToString(), 0, 0, "Null");
                    listElementFormula.Add(item);

                    item = new ElementFormula(PayrollElement.ATT_SICKLEAVE.ToString(), 0, 0, "Null");
                    listElementFormula.Add(item);

                    item = new ElementFormula(PayrollElement.ATT_ANNUALLEAVE.ToString(), 0, 0, "Null");
                    listElementFormula.Add(item);
                }
            }


            //Số ngày nghỉ có trả lương
            if (CheckIsExistFormula(listElementFormula, formula, new string[] { PayrollElement.ATT_TOTAL_PAID_LEAVEDAY_DAY.ToString(), PayrollElement.ATT_TOTAL_PAID_LEAVEDAY_DAY_NOT_PAY.ToString() }))
            {
                using (var context = new VnrHrmDataContext())
                {
                    var unitOfWork = (IUnitOfWork)new UnitOfWork(context);
                    //Guid AttendanceTableItemByAttID = Guid.Empty;
                    double Total_LeaveDay = 0;
                    double Total_LeaveDay_NotPay = 0;
                    if (listAttendanceTableProCut != null)
                    {
                        // AttendanceTableItemByAtt = repoAttendanceTable.FindBy(m => m.IsDelete != true && m.ID == listAttendanceTableProCut.ID).FirstOrDefault();
                        //AttendanceTableItemByAttID = unitOfWork.CreateQueryable<Att_AttendanceTable>(m => m.ID == listAttendanceTableProCut.ID).Select(m => m.ID).FirstOrDefault();
                        //  var AttendanceTableItem = repoAttendanceTableItem.FindBy(m => m.IsDelete != true && m.AttendanceTableID == AttendanceTableItemByAttID).ToList();
                        var AttendanceTableItem = TotalData.listAttendanceTableItem.Where(m => m.AttendanceTableID == listAttendanceTableProCut.ID).ToList();

                        for (int j = 0; j < AttendanceTableItem.Count; j++)
                        {
                            if (AttendanceTableItem[j].LeaveTypeID != null)
                            {
                                var LeaveDay = TotalData.listLeavedayType.Where(m => m.ID == AttendanceTableItem[j].LeaveTypeID).FirstOrDefault();
                                if (LeaveDay != null)
                                {
                                    //code của là so sánh với IsWorkDay
                                    if (LeaveDay.IsAnnualLeave || LeaveDay.PaidRate >= 1)
                                    {
                                        Total_LeaveDay += AttendanceTableItem[j].PaidLeaveHours / AttendanceTableItem[j].AvailableHours;
                                    }
                                    else if (!LeaveDay.IsAnnualLeave && LeaveDay.PaidRate <= 0)
                                    {
                                        //Total_LeaveDay_NotPay += AttendanceTableItem[j].PaidLeaveHours / AttendanceTableItem[j].AvailableHours; 
                                        Total_LeaveDay_NotPay++;
                                    }
                                }
                            }
                        }
                    }
                    item = new ElementFormula(PayrollElement.ATT_TOTAL_PAID_LEAVEDAY_DAY.ToString(), Total_LeaveDay, 0);
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.ATT_TOTAL_PAID_LEAVEDAY_DAY_NOT_PAY.ToString(), Total_LeaveDay_NotPay, 0);
                    listElementFormula.Add(item);
                }
            }

            //Tổng số ngày công trong năm
            if (CheckIsExistFormula(listElementFormula, formula, new string[] { PayrollElement.ATT_TOTAL_WORKDAY_IN_YEAR.ToString() }))
            {
                var Attantendence = TotalData.listAttendanceTable.Where(m => m.ProfileID == profileItem.ID).ToList();
                item = new ElementFormula(PayrollElement.ATT_TOTAL_WORKDAY_IN_YEAR.ToString(), Attantendence.Sum(m => m.StdWorkDayCount), 0);
                listElementFormula.Add(item);
            }

            //Tổng số ngày công thực tế trong năm
            if (CheckIsExistFormula(listElementFormula, formula, new string[] { PayrollElement.ATT_TOTAL_REALITYWORKDAY_IN_YEAR.ToString() }))
            {
                var Attantendence = TotalData.listAttendanceTable.Where(m => m.ProfileID == profileItem.ID).ToList();
                item = new ElementFormula(PayrollElement.ATT_TOTAL_REALITYWORKDAY_IN_YEAR.ToString(), Attantendence.Sum(m => m.RealWorkDayCount), 0);
                listElementFormula.Add(item);
            }

            //Tổng số ngày làm việc trong năm (365-dayoff)
            if (CheckIsExistFormula(listElementFormula, formula, new string[] { PayrollElement.ATT_TOTAL_DAY_NOT_DAYOFF_IN_YEAR.ToString() }))
            {
                DateTime form = new DateTime(CutOffDuration.MonthYear.Year - 1, 4, 1);
                DateTime to = new DateTime(CutOffDuration.MonthYear.Year, 3, 31);
                int days = new DateTime(CutOffDuration.MonthYear.Year, 12, 31).DayOfYear;
                int dayOff = TotalData.listDayOff.Where(m => m.DateOff >= form && m.DateOff <= to && m.OrgStructureID == null).Count();
                item = new ElementFormula(PayrollElement.ATT_TOTAL_DAY_NOT_DAYOFF_IN_YEAR.ToString(), days - dayOff, 0);
                listElementFormula.Add(item);
            }


            #endregion

            #region Enum phần tử bảo hiểm
            if (CheckIsExistFormula(listElementFormula, formula, new string[] { PayrollElement.INS_HEALTH_INSURANCE.ToString(), PayrollElement.INS_SALARY_INSURANCE.ToString(), PayrollElement.INS_SOCIAL_INSURANCE.ToString(), PayrollElement.INS_UNEMP_INSURANCE.ToString(), PayrollElement.INS_SOCIAL_INSURANCE_PROFILE.ToString(), PayrollElement.INS_SOCIAL_INSURANCE_COMPANY.ToString(), PayrollElement.INS_UNEMP_INSURANCE_PROFILE.ToString(), PayrollElement.INS_UNEMP_INSURANCE_COMPANY.ToString(), PayrollElement.INS_HEALTH_INSURANCE_PROFILE.ToString(), PayrollElement.INS_HEALTH_INSURANCE_COMPANY.ToString() }))
            {
                Ins_ProfileInsuranceMonthlyEntity InsItem = TotalData.listInsurance.Where(m => m.ProfileID == profileItem.ID && m.MonthYear != null && m.MonthYear.Value.Year == CutOffDuration.MonthYear.Year && m.MonthYear.Value.Month == CutOffDuration.MonthYear.Month).FirstOrDefault();
                if (InsItem != null)
                {
                    item = new ElementFormula(PayrollElement.INS_HEALTH_INSURANCE.ToString(), InsItem.MoneyHealthInsurance == null ? null : InsItem.MoneyHealthInsurance, 0);
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.INS_SALARY_INSURANCE.ToString(), InsItem.SalaryInsurance == null ? null : InsItem.SalaryInsurance, 0);
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.INS_SOCIAL_INSURANCE.ToString(), InsItem.MoneySocialInsurance == null ? null : InsItem.MoneySocialInsurance, 0);
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.INS_UNEMP_INSURANCE.ToString(), InsItem.MoneyUnEmpInsurance == null ? null : InsItem.MoneyUnEmpInsurance, 0);
                    listElementFormula.Add(item);

                    item = new ElementFormula(PayrollElement.INS_SOCIAL_INSURANCE_PROFILE.ToString(), InsItem.SocialInsEmpAmount == null ? null : InsItem.SocialInsEmpAmount, 0);
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.INS_SOCIAL_INSURANCE_COMPANY.ToString(), InsItem.SocialInsComAmount == null ? null : InsItem.SocialInsComAmount, 0);
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.INS_UNEMP_INSURANCE_PROFILE.ToString(), InsItem.UnemployEmpAmount == null ? null : InsItem.UnemployEmpAmount, 0);
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.INS_UNEMP_INSURANCE_COMPANY.ToString(), InsItem.UnemployComAmount == null ? null : InsItem.UnemployComAmount, 0);
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.INS_HEALTH_INSURANCE_PROFILE.ToString(), InsItem.HealthInsEmpAmount == null ? null : InsItem.HealthInsEmpAmount, 0);
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.INS_HEALTH_INSURANCE_COMPANY.ToString(), InsItem.HealthInsComAmount == null ? null : InsItem.HealthInsComAmount, 0);
                    listElementFormula.Add(item);

                }
                else//nếu không có bảo hiểm thì cập nhất value = 0
                {
                    item = new ElementFormula(PayrollElement.INS_HEALTH_INSURANCE.ToString(), 0, 0, "Null");
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.INS_SALARY_INSURANCE.ToString(), 0, 0, "Null");
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.INS_SOCIAL_INSURANCE.ToString(), 0, 0, "Null");
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.INS_UNEMP_INSURANCE.ToString(), 0, 0, "Null");
                    listElementFormula.Add(item);

                    item = new ElementFormula(PayrollElement.INS_SOCIAL_INSURANCE_PROFILE.ToString(), 0, 0, "Null");
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.INS_SOCIAL_INSURANCE_COMPANY.ToString(), 0, 0, "Null");
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.INS_UNEMP_INSURANCE_PROFILE.ToString(), 0, 0, "Null");
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.INS_UNEMP_INSURANCE_COMPANY.ToString(), 0, 0, "Null");
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.INS_HEALTH_INSURANCE_PROFILE.ToString(), 0, 0, "Null");
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.INS_HEALTH_INSURANCE_COMPANY.ToString(), 0, 0, "Null");
                    listElementFormula.Add(item);
                }
            }

            #endregion

            #region Enum phần tử hoa hồng

            //Lấy taget & actual của shop
            if (CheckIsExistFormula(listElementFormula, formula, new string[] { PayrollElement.SAL_COM_TAGET_SHOP.ToString(), PayrollElement.SAL_COM_ACTUAL_SHOP.ToString(), PayrollElement.SAL_COM_PRECENT_REVENUE.ToString() }))
            {
                Sal_RevenueForShopEntity RevenueForShopItem = TotalData.listRevenueForShop.Where(m => m.ShopID == profileItem.ShopID && m.KPIBonusID == TotalData.listKPIBonus.Where(t => t.IsTotalRevenue == true).FirstOrDefault().ID && m.DateFrom <= CutOffDuration.DateEnd && m.DateTo >= CutOffDuration.DateStart).FirstOrDefault();
                if (RevenueForShopItem != null)
                {
                    item = new ElementFormula(PayrollElement.SAL_COM_TAGET_SHOP.ToString(), RevenueForShopItem.Target, 0);
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.SAL_COM_ACTUAL_SHOP.ToString(), RevenueForShopItem.Actual, 0);
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.SAL_COM_PRECENT_REVENUE.ToString(), RevenueForShopItem.Actual / RevenueForShopItem.Target, 0);
                    listElementFormula.Add(item);
                }
                else
                {
                    item = new ElementFormula(PayrollElement.SAL_COM_TAGET_SHOP.ToString(), 0, 0, "Null");
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.SAL_COM_ACTUAL_SHOP.ToString(), 0, 0, "Null");
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.SAL_COM_PRECENT_REVENUE.ToString(), 0, 0, "Null");
                    listElementFormula.Add(item);
                }
            }


            //Lấy tên cửa hàng
            if (CheckIsExistFormula(listElementFormula, formula, PayrollElement.SAL_COM_SHOPNAME.ToString()))
            {
                item = new ElementFormula(PayrollElement.SAL_COM_SHOPNAME.ToString(), profileItem.ShopName == null ? "" : profileItem.ShopName, 0);
                listElementFormula.Add(item);
            }


            //Lấy taget & actual của nhân viên
            if (CheckIsExistFormula(listElementFormula, formula, new string[] { PayrollElement.SAL_COM_TAGET_CUSTOMER.ToString(), PayrollElement.SAL_COM_ACTUAL_CUSTOMER.ToString() }))
            {
                Sal_RevenueForProfileEntity RevenueForProfileItem = new Sal_RevenueForProfileEntity();
                RevenueForProfileItem = TotalData.listRevenueForProfile.Where(m => m.ProfileID == profileItem.ID && m.DateFrom <= CutOffDuration.DateEnd && m.DateTo >= CutOffDuration.DateStart).FirstOrDefault();
                if (RevenueForProfileItem != null)
                {
                    item = new ElementFormula(PayrollElement.SAL_COM_TAGET_CUSTOMER.ToString(), RevenueForProfileItem.Target, 0);
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.SAL_COM_ACTUAL_CUSTOMER.ToString(), RevenueForProfileItem.Actual, 0);
                    listElementFormula.Add(item);
                }
                else
                {
                    item = new ElementFormula(PayrollElement.SAL_COM_TAGET_CUSTOMER.ToString(), 0, 0, "Null");
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.SAL_COM_ACTUAL_CUSTOMER.ToString(), 0, 0, "Null");
                    listElementFormula.Add(item);
                }
            }


            //Số tháng làm việc
            if (CheckIsExistFormula(listElementFormula, formula, PayrollElement.SAL_COM_WORKINGMONTH.ToString()))
            {
                double CountMonth = ((CutOffDuration.MonthYear.Year - profileItem.DateHire.Value.Year) * 12) + CutOffDuration.MonthYear.Month - profileItem.DateHire.Value.Month + (profileItem.DateHire.Value.Day < CutOffDuration.DateEnd.Day ? 1 : 0);
                item = new ElementFormula(PayrollElement.SAL_COM_WORKINGMONTH.ToString(), CountMonth, 0);
                listElementFormula.Add(item);
            }

            //tổng số nhân viên của cửa hàng
            if (CheckIsExistFormula(listElementFormula, formula, PayrollElement.SAL_COM_COUNT_SHOPMEMBER.ToString()))
            {
                using (var context = new VnrHrmDataContext())
                {
                    var unitOfWork = (IUnitOfWork)(new UnitOfWork(context));
                    var repoProfile = new CustomBaseRepository<Hre_Profile>(unitOfWork);
                    int TotalProfileForShop = repoProfile.FindBy(m => m.ShopID == profileItem.ShopID).Count();
                    item = new ElementFormula(PayrollElement.SAL_COM_COUNT_SHOPMEMBER.ToString(), TotalProfileForShop, 0);
                    listElementFormula.Add(item);
                }
            }

            //Chức danh
            if (CheckIsExistFormula(listElementFormula, formula, PayrollElement.SAL_COM_JOBTITLE.ToString()))
            {
                item = new ElementFormula(PayrollElement.SAL_COM_JOBTITLE.ToString(), profileItem.PositionCode == null ? "" : profileItem.PositionCode, 0);
                listElementFormula.Add(item);
            }

            //Số lượng ca trưởng trong cửa hàng
            if (CheckIsExistFormula(listElementFormula, formula, new string[] { PayrollElement.SAL_COM_COUNT_SL.ToString(), PayrollElement.SAL_COM_RANK.ToString() }))
            {
                if (profileItem.ShopID != null)
                {
                    int Count_SL = (int)TotalData.listShop.Single(m => m.ID == profileItem.ShopID).NoShiftLeader;
                    item = new ElementFormula(PayrollElement.SAL_COM_COUNT_SL.ToString(), Count_SL, 0);
                    listElementFormula.Add(item);

                    //cấp bậc của cửa hàng
                    item = new ElementFormula(PayrollElement.SAL_COM_RANK.ToString(), TotalData.listShop.Single(m => m.ID == profileItem.ShopID).Rank, 0);
                    listElementFormula.Add(item);
                }
                else
                {
                    item = new ElementFormula(PayrollElement.SAL_COM_COUNT_SL.ToString(), 0, 0, "Null");
                    listElementFormula.Add(item);

                    item = new ElementFormula(PayrollElement.SAL_COM_RANK.ToString(), 0, 0, "Null");
                    listElementFormula.Add(item);
                }
            }

            //Tổng doanh thu của tất cả nhân viên trong shop
            if (CheckIsExistFormula(listElementFormula, formula, PayrollElement.SAL_TOTAL_ACTUAL_PROFILE_SHOP.ToString()))
            {
                using (var context = new VnrHrmDataContext())
                {
                    var unitOfWork = (IUnitOfWork)(new UnitOfWork(context));
                    var repoProfile = new CustomBaseRepository<Hre_Profile>(unitOfWork);
                    var TotalPRofileInShop = repoProfile.FindBy(m => m.ShopID == profileItem.ShopID).ToList();
                    var RevenueForProfileInShop = TotalData.listRevenueForProfile.Where(m => TotalPRofileInShop.Any(t => t.ID == m.ProfileID) && m.DateFrom <= CutOffDuration.DateEnd && m.DateTo >= CutOffDuration.DateStart).ToList();
                    item = new ElementFormula(PayrollElement.SAL_TOTAL_ACTUAL_PROFILE_SHOP.ToString(), RevenueForProfileInShop.Sum(m => m.Actual), 0);
                    listElementFormula.Add(item);
                }

            }
            #endregion

            #region Enum phần tử đánh giá

            //Loại đánh giá
            if (CheckIsExistFormula(listElementFormula, formula, new string[] { PayrollElement.EVA_PERFORMANCE_TYPE_CODE.ToString(), PayrollElement.EVA_PERFORMANCE_LEVEL_NAME.ToString() }))
            {
                var PerformentceProfile = TotalData.listEva_Performance.Where(m => m.ProfileID == profileItem.ID && m.PeriodFromDate <= CutOffDuration.DateEnd && m.PeriodToDate >= CutOffDuration.DateStart).FirstOrDefault();

                item = new ElementFormula(PayrollElement.EVA_PERFORMANCE_TYPE_CODE.ToString(), PerformentceProfile != null ? PerformentceProfile.PerformanceTypeCode : "", 0);
                listElementFormula.Add(item);

                //Cấp độ đánh giá
                item = new ElementFormula(PayrollElement.EVA_PERFORMANCE_LEVEL_NAME.ToString(), PerformentceProfile != null ? PerformentceProfile.Level1Name : "", 0);
                listElementFormula.Add(item);
            }

            if (CheckIsExistFormula(listElementFormula, formula, CatElementType.Evaluation.ToString().ToUpper() + "_PERFORMANCETYPE_", TotalData.listPerformanceType.Select(m => m.Code).ToArray()))
            {
                DateTime YearStart = new DateTime(CutOffDuration.MonthYear.Year, 1, 1);
                DateTime YearEnd = new DateTime(CutOffDuration.MonthYear.Year, 12, 31);
                var PerformentceByProfile = TotalData.listEva_Performance.Where(m => m.ProfileID == profileItem.ID && m.DateEffect <= YearEnd && m.DateEffect >= YearStart).OrderByDescending(m => m.DateEffect).ToList();
                if (PerformentceByProfile != null)
                {
                    foreach (var i in TotalData.listPerformanceType)
                    {
                        var PerformentceByProfileAndType = PerformentceByProfile.FirstOrDefault(m => m.PerformanceTypeID == i.ID);
                        if (PerformentceByProfileAndType != null)
                        {
                            item = new ElementFormula(CatElementType.Evaluation.ToString().ToUpper() + "_PERFORMANCETYPE_" + i.Code, PerformentceByProfileAndType.Level1Name != null ? PerformentceByProfileAndType.Level1Name : "", 0);
                            listElementFormula.Add(item);
                        }
                        else
                        {
                            item = new ElementFormula(CatElementType.Evaluation.ToString().ToUpper() + "_PERFORMANCETYPE_" + i.Code, "", 0, "null");
                            listElementFormula.Add(item);
                        }
                    }
                }
                else
                {
                    foreach (var i in TotalData.listPerformanceType)
                    {
                        item = new ElementFormula(CatElementType.Evaluation.ToString().ToUpper() + "_PERFORMANCETYPE_" + i.Code, "", 0, "null");
                        listElementFormula.Add(item);
                    }
                }
            }

            #endregion

            #region Enum phần tử CanTeen

            if (CheckIsExistFormula(listElementFormula, formula, new string[] { PayrollElement.CAN_SUMAMOUNT_N_1.ToString(), PayrollElement.CAN_AMOUNTEATNOTSTANDAR_N_1.ToString(), PayrollElement.CAN_AMOUNTCARDMORE_N_1.ToString(), PayrollElement.CAN_AMOUNTNOTWORKHASEAT_N_1.ToString(), PayrollElement.CAN_AMOUNTHDTJOB_N_1.ToString(), PayrollElement.CAN_AMOUNTNOTWORKBUTHASHDT_N_1.ToString(), PayrollElement.CAN_AMOUNTSUBTRACTWRONGSTANDARHDT_N_1.ToString() }))
            {
                DateTime DateStart = CutOffDuration.DateStart.AddMonths(-1);
                DateTime DateEnd = CutOffDuration.DateEnd.AddMonths(-1);

                var SumryMealRecordByRrofile = TotalData.listSumryMealRecord.Where(m => m.ProfileID == profileItem.ID && (m.DateFrom != null && m.DateTo != null) && m.DateFrom <= DateEnd && m.DateTo >= DateStart).OrderByDescending(m => m.DateFrom).FirstOrDefault();
                if (SumryMealRecordByRrofile != null)
                {
                    item = new ElementFormula(PayrollElement.CAN_SUMAMOUNT_N_1.ToString(), SumryMealRecordByRrofile.SumAmount != null ? SumryMealRecordByRrofile.SumAmount : 0, 0);
                    listElementFormula.Add(item);

                    item = new ElementFormula(PayrollElement.CAN_AMOUNTEATNOTSTANDAR_N_1.ToString(), SumryMealRecordByRrofile.AmountEatNotStandar != null ? SumryMealRecordByRrofile.AmountEatNotStandar : 0, 0);
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.CAN_AMOUNTCARDMORE_N_1.ToString(), SumryMealRecordByRrofile.SumAmountCardMore != null ? SumryMealRecordByRrofile.SumAmountCardMore : 0, 0);
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.CAN_AMOUNTNOTWORKHASEAT_N_1.ToString(), SumryMealRecordByRrofile.AmountNotWorkHasEat != null ? SumryMealRecordByRrofile.AmountNotWorkHasEat : 0, 0);
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.CAN_AMOUNTHDTJOB_N_1.ToString(), SumryMealRecordByRrofile.AmountHDTJob != null ? SumryMealRecordByRrofile.AmountHDTJob : 0, 0);
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.CAN_AMOUNTNOTWORKBUTHASHDT_N_1.ToString(), SumryMealRecordByRrofile.AmountNotWorkButHasHDT != null ? SumryMealRecordByRrofile.AmountNotWorkButHasHDT : 0, 0);
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.CAN_AMOUNTSUBTRACTWRONGSTANDARHDT_N_1.ToString(), SumryMealRecordByRrofile.AmountSubtractWorngStandarHDT != null ? SumryMealRecordByRrofile.AmountSubtractWorngStandarHDT : 0, 0);
                    listElementFormula.Add(item);
                }
                else
                {
                    item = new ElementFormula(PayrollElement.CAN_SUMAMOUNT_N_1.ToString(), 0, 0, "Không có dữ liệu trong kỳ tính lương !");
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.CAN_AMOUNTEATNOTSTANDAR_N_1.ToString(), 0, 0, "Không có dữ liệu trong kỳ tính lương !");
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.CAN_AMOUNTCARDMORE_N_1.ToString(), 0, 0, "Không có dữ liệu trong kỳ tính lương !");
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.CAN_AMOUNTNOTWORKHASEAT_N_1.ToString(), 0, 0, "Không có dữ liệu trong kỳ tính lương !");
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.CAN_AMOUNTHDTJOB_N_1.ToString(), 0, 0, "Không có dữ liệu trong kỳ tính lương !");
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.CAN_AMOUNTNOTWORKBUTHASHDT_N_1.ToString(), 0, 0, "Không có dữ liệu trong kỳ tính lương !");
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.CAN_AMOUNTSUBTRACTWRONGSTANDARHDT_N_1.ToString(), 0, 0, "Không có dữ liệu trong kỳ tính lương !");
                    listElementFormula.Add(item);
                }

            }



            if (CheckIsExistFormula(listElementFormula, formula, new string[] { PayrollElement.CAN_SUMAMOUNT.ToString(), PayrollElement.CAN_AMOUNTEATNOTSTANDAR.ToString(), PayrollElement.CAN_AMOUNTCARDMORE.ToString(), PayrollElement.CAN_AMOUNTNOTWORKHASEAT.ToString(), PayrollElement.CAN_AMOUNTHDTJOB.ToString(), PayrollElement.CAN_AMOUNTNOTWORKBUTHASHDT.ToString(), PayrollElement.CAN_AMOUNTSUBTRACTWRONGSTANDARHDT.ToString() }))
            {
                var SumryMealRecordByRrofile = TotalData.listSumryMealRecord.Where(m => m.ProfileID == profileItem.ID && (m.DateFrom != null && m.DateTo != null) && m.DateFrom <= CutOffDuration.DateEnd && m.DateTo >= CutOffDuration.DateStart).OrderByDescending(m => m.DateFrom).FirstOrDefault();
                if (SumryMealRecordByRrofile != null)
                {
                    item = new ElementFormula(PayrollElement.CAN_SUMAMOUNT.ToString(), SumryMealRecordByRrofile.SumAmount != null ? SumryMealRecordByRrofile.SumAmount : 0, 0);
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.CAN_AMOUNTEATNOTSTANDAR.ToString(), SumryMealRecordByRrofile.AmountEatNotStandar != null ? SumryMealRecordByRrofile.AmountEatNotStandar : 0, 0);
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.CAN_AMOUNTCARDMORE.ToString(), SumryMealRecordByRrofile.SumAmountCardMore != null ? SumryMealRecordByRrofile.SumAmountCardMore : 0, 0);
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.CAN_AMOUNTNOTWORKHASEAT.ToString(), SumryMealRecordByRrofile.AmountNotWorkHasEat != null ? SumryMealRecordByRrofile.AmountNotWorkHasEat : 0, 0);
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.CAN_AMOUNTHDTJOB.ToString(), SumryMealRecordByRrofile.AmountHDTJob != null ? SumryMealRecordByRrofile.AmountHDTJob : 0, 0);
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.CAN_AMOUNTNOTWORKBUTHASHDT.ToString(), SumryMealRecordByRrofile.AmountNotWorkButHasHDT != null ? SumryMealRecordByRrofile.AmountNotWorkButHasHDT : 0, 0);
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.CAN_AMOUNTSUBTRACTWRONGSTANDARHDT.ToString(), SumryMealRecordByRrofile.AmountSubtractWorngStandarHDT != null ? SumryMealRecordByRrofile.AmountSubtractWorngStandarHDT : 0, 0);
                    listElementFormula.Add(item);
                }
                else
                {
                    item = new ElementFormula(PayrollElement.CAN_SUMAMOUNT.ToString(), 0, 0, "Không có dữ liệu trong kỳ tính lương !");
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.CAN_AMOUNTEATNOTSTANDAR.ToString(), 0, 0, "Không có dữ liệu trong kỳ tính lương !");
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.CAN_AMOUNTCARDMORE.ToString(), 0, 0, "Không có dữ liệu trong kỳ tính lương !");
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.CAN_AMOUNTNOTWORKHASEAT.ToString(), 0, 0, "Không có dữ liệu trong kỳ tính lương !");
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.CAN_AMOUNTHDTJOB.ToString(), 0, 0, "Không có dữ liệu trong kỳ tính lương !");
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.CAN_AMOUNTNOTWORKBUTHASHDT.ToString(), 0, 0, "Không có dữ liệu trong kỳ tính lương !");
                    listElementFormula.Add(item);
                    item = new ElementFormula(PayrollElement.CAN_AMOUNTSUBTRACTWRONGSTANDARHDT.ToString(), 0, 0, "Không có dữ liệu trong kỳ tính lương !");
                    listElementFormula.Add(item);
                }

            }

            #endregion

            #endregion

            #region Các phần tử động
            if (CheckIsExistFormula(listElementFormula, formula, PayrollElement.DYN_COUNTDAYOVERTIMEBYTYPE_.ToString(), new string[] { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" }))
            {
                using (var context = new VnrHrmDataContext())
                {
                    var unitOfWork = (IUnitOfWork)new UnitOfWork(context);
                    //var repoAttendanceTable = new CustomBaseRepository<Att_AttendanceTable>(unitOfWork);
                    //var repoAttOvertime = new CustomBaseRepository<Att_Overtime>(unitOfWork);

                    //tách phần tử ra để lấy tham số
                    string Parameter = string.Empty;
                    var ttt = ParseFormulaToList(formula.Formula);
                    List<string> ListFormula = ParseFormulaToList(formula.Formula).Where(m => m.IndexOf('[') != -1 && m.IndexOf(']') != -1 && m.StartsWith("[" + PayrollElement.DYN_COUNTDAYOVERTIMEBYTYPE_.ToString())).ToList();

                    //Att_AttendanceTable listAttTable = TotalData.listAttendanceTable.Where(m => m.CutOffDurationID == CutOffDuration.ID && m.ProfileID == profileItem.ID && m.IsDelete != true).FirstOrDefault();
                    List<Att_AttendanceTableItemEntity> listAttTableItem = TotalData.listAttendanceTableItem.Where(m => m.AttendanceTableID == listAttendanceTableProCut.ID).ToList();

                    //lấy danh sách đăng ký tăng ca
                    List<Att_OvertimeEntity> listOverTime = TotalData.listOverTime.Where(m => m.ProfileID == profileItem.ID).ToList();

                    //duyệt qua các phần tử động để lấy tham số
                    foreach (var i in ListFormula)
                    {
                        string[] listParam = i.Split('_');
                        if (listParam.Count() >= 3)//nếu là 3 phần tử là đúng công thức, ngược lại là sai
                        {
                            string OtTypeCode = i.Replace(PayrollElement.DYN_COUNTDAYOVERTIMEBYTYPE_.ToString(), "").Replace("_" + listParam.LastOrDefault(), "").Replace("]", "").Replace("[", "");
                            double number = 0;
                            double CountOtDay = 0;
                            Cat_OvertimeTypeEntity OTType = TotalData.listOvertimeType.Where(m => m.Code == OtTypeCode).FirstOrDefault();

                            List<Att_OvertimeEntity> listOverTimeByTableItem = new List<Att_OvertimeEntity>();
                            Att_OvertimeEntity OverTimeItem = new Att_OvertimeEntity();
                            Cat_Shift ShiftItem = new Cat_Shift();

                            if (double.TryParse(listParam.LastOrDefault().Replace("]", "").Replace("[", ""), out number) && OTType != null)
                            {
                                number = number / 10;
                                CountOtDay = 0;
                                //lọc ra các loại OT theo loại
                                foreach (var tableItem in listAttTableItem)
                                {
                                    listOverTimeByTableItem = listOverTime.Where(m => m.WorkDate.Date == tableItem.WorkDate.Date).ToList();
                                    if (tableItem.OvertimeTypeID != null && tableItem.OvertimeTypeID == OTType.ID)
                                    {
                                        OverTimeItem = listOverTimeByTableItem.Where(m => m.OvertimeTypeID == (Guid)tableItem.OvertimeTypeID).FirstOrDefault();
                                        if (OverTimeItem != null && OverTimeItem.ShiftID != null)
                                        {
                                            ShiftItem = TotalData.listCat_Shift.Where(m => m.ID == (Guid)OverTimeItem.ShiftID).FirstOrDefault().Copy<Cat_Shift>();
                                            CountOtDay += tableItem.OvertimeHours / ShiftItem.udAvailableHours >= number ? 1 : 0;
                                        }
                                    }
                                    else if (tableItem.ExtraOvertimeTypeID != null && tableItem.ExtraOvertimeTypeID == OTType.ID)
                                    {
                                        OverTimeItem = listOverTimeByTableItem.Where(m => m.OvertimeTypeID == (Guid)tableItem.ExtraOvertimeTypeID).FirstOrDefault();
                                        if (OverTimeItem != null && OverTimeItem.ShiftID != null)
                                        {
                                            ShiftItem = TotalData.listCat_Shift.Where(m => m.ID == (Guid)OverTimeItem.ShiftID).FirstOrDefault().Copy<Cat_Shift>();
                                            CountOtDay += tableItem.ExtraOvertimeHours / ShiftItem.udAvailableHours >= number ? 1 : 0;
                                        }
                                    }
                                    else if (tableItem.ExtraOvertimeType2ID != null && tableItem.ExtraOvertimeType2ID == OTType.ID)
                                    {
                                        OverTimeItem = listOverTimeByTableItem.Where(m => m.OvertimeTypeID == (Guid)tableItem.ExtraOvertimeType2ID).FirstOrDefault();
                                        if (OverTimeItem != null && OverTimeItem.ShiftID != null)
                                        {
                                            ShiftItem = TotalData.listCat_Shift.Where(m => m.ID == (Guid)OverTimeItem.ShiftID).FirstOrDefault().Copy<Cat_Shift>();
                                            CountOtDay += tableItem.ExtraOvertimeHours2 / ShiftItem.udAvailableHours >= number ? 1 : 0;
                                        }
                                    }
                                    else if (tableItem.ExtraOvertimeType3ID != null && tableItem.ExtraOvertimeType3ID == OTType.ID)
                                    {
                                        OverTimeItem = listOverTimeByTableItem.Where(m => m.OvertimeTypeID == (Guid)tableItem.ExtraOvertimeType3ID).FirstOrDefault();
                                        if (OverTimeItem != null && OverTimeItem.ShiftID != null)
                                        {
                                            ShiftItem = TotalData.listCat_Shift.Where(m => m.ID == (Guid)OverTimeItem.ShiftID).FirstOrDefault().Copy<Cat_Shift>();
                                            CountOtDay += tableItem.ExtraOvertimeHours3 / ShiftItem.udAvailableHours >= number ? 1 : 0;
                                        }
                                    }
                                }
                                item = new ElementFormula(i.Replace("]", "").Replace("[", ""), CountOtDay, 0);
                                listElementFormula.Add(item);
                            }
                            else//sai công thức , không convert đc số giờ
                            {
                                item = new ElementFormula(i.Replace("]", "").Replace("[", ""), 0, 0, "Công thức động sai !");
                                listElementFormula.Add(item);
                            }
                        }
                        else
                        {
                            item = new ElementFormula(i.Replace("]", "").Replace("[", ""), 0, 0, "Công thức động sai !");
                            listElementFormula.Add(item);
                        }
                    }
                }
            }
            #endregion

            #region Lấy giá trị cho các phần tử là các loại OT và LeaveDay

            #region Lấy OT theo từng loại và lấy tổng số giờ tăng ca đã quy đổi ra hệ số 1

            #region OT tháng N


            List<Cat_ElementEntity> listElement_OT = new List<Cat_ElementEntity>();
            if (CheckIsExistFormula(listElementFormula, formula, "ATT_OVERTIME_", "_HOURS"))
            {
                using (var context = new VnrHrmDataContext())
                {
                    var unitOfWork = (IUnitOfWork)new UnitOfWork(context);
                    //var repoAttendanceTable = new CustomBaseRepository<Att_AttendanceTable>(unitOfWork);

                    //double SumOvertime = 0;
                    //double SumOvertimeInsurance = 0;

                    //lấy lương cơ bản của nhân viên
                    List<Sal_BasicSalaryEntity> SalaryProfile = new List<Sal_BasicSalaryEntity>();
                    SalaryProfile = TotalData.listBasicSalary.Where(m => m.ProfileID == profileItem.ID).OrderByDescending(m => m.DateOfEffect).ToList();

                    //có thay đổi lương trong tháng
                    if (SalaryProfile.Count > 0 && SalaryProfile.FirstOrDefault().DateOfEffect > CutOffDuration.DateStart)//có thay đổi lương trong tháng
                    {
                        double OtHour = 0;
                        //ngày bắt đầu mức lương 1 và ngày bắt đầu mức lương 2
                        DateTime dateStart1 = CutOffDuration.DateStart;
                        DateTime dateStart2 = SalaryProfile.FirstOrDefault().DateOfEffect;

                        //lấy dữ liệu công theo cutoff
                        List<Att_AttendanceTableItemEntity> listAttTableItem = TotalData.listAttendanceTableItem.Where(m => m.ProfileID == profileItem.ID).ToList();

                        if (listAttTableItem != null && listAttTableItem.Count > 0)
                        {
                            listAttTableItem = listAttTableItem.Where(m => m.WorkDate < dateStart2).ToList();
                            //duyệt wa các loại ot
                            foreach (var OTType in TotalData.listOvertimeType)
                            {
                                OtHour = 0;
                                //tính số giờ OT của từng loại
                                foreach (var tableItem in listAttTableItem)
                                {
                                    if (tableItem.OvertimeTypeID != null && tableItem.OvertimeTypeID == OTType.ID)
                                    {
                                        OtHour += tableItem.OvertimeHours;
                                    }
                                    else if (tableItem.ExtraOvertimeTypeID != null && tableItem.ExtraOvertimeTypeID == OTType.ID)
                                    {
                                        OtHour += tableItem.ExtraOvertimeHours;
                                    }
                                    else if (tableItem.ExtraOvertimeType2ID != null && tableItem.ExtraOvertimeType2ID == OTType.ID)
                                    {
                                        OtHour += tableItem.ExtraOvertimeHours2;
                                    }
                                    else if (tableItem.ExtraOvertimeType3ID != null && tableItem.ExtraOvertimeType3ID == OTType.ID)
                                    {
                                        OtHour += tableItem.ExtraOvertimeHours3;
                                    }
                                }
                                item = new ElementFormula("ATT_OVERTIME_" + OTType.Code + "_HOURS", OtHour, 0);
                                listElementFormula.Add(item);
                            }
                        }
                        else
                        {
                            foreach (var OTType in TotalData.listOvertimeType)
                            {
                                item = new ElementFormula("ATT_OVERTIME_" + OTType.Code + "_HOURS", 0, 0);
                                listElementFormula.Add(item);
                            }
                        }
                    }
                    else//không thay đổi lương trong tháng
                    {
                        listElement_OT = TotalData.listElement_All.Where(m => m.ElementCode.StartsWith("ATT_OVERTIME_") && m.ElementCode.EndsWith("_HOURS")).ToList();
                        foreach (var OT in listElement_OT)
                        {
                            var itemOverTime = TotalData.listOvertimeType.Where(m => m.Code == OT.ElementCode.Replace("ATT_OVERTIME_", "").Replace("_HOURS", "")).FirstOrDefault();

                            double value = 0;
                            if (itemOverTime != null && listAttendanceTableProCut != null)
                            {
                                if (listAttendanceTableProCut.Overtime1Type != null && listAttendanceTableProCut.Overtime1Type == itemOverTime.ID)
                                {
                                    value += listAttendanceTableProCut.Overtime1Hours;
                                }
                                if (listAttendanceTableProCut.Overtime2Type != null && listAttendanceTableProCut.Overtime2Type == itemOverTime.ID)
                                {
                                    value += listAttendanceTableProCut.Overtime2Hours;
                                }
                                if (listAttendanceTableProCut.Overtime3Type != null && listAttendanceTableProCut.Overtime3Type == itemOverTime.ID)
                                {
                                    value += listAttendanceTableProCut.Overtime3Hours;
                                }
                                if (listAttendanceTableProCut.Overtime4Type != null && listAttendanceTableProCut.Overtime4Type == itemOverTime.ID)
                                {
                                    value += listAttendanceTableProCut.Overtime4Hours;
                                }
                                if (listAttendanceTableProCut.Overtime5Type != null && listAttendanceTableProCut.Overtime5Type == itemOverTime.ID)
                                {
                                    value += listAttendanceTableProCut.Overtime5Hours;
                                }
                                if (listAttendanceTableProCut.Overtime6Type != null && listAttendanceTableProCut.Overtime6Type == itemOverTime.ID)
                                {
                                    value += listAttendanceTableProCut.Overtime6Hours;
                                }
                            }
                            item = new ElementFormula(OT.ElementCode, value, 0);
                            listElementFormula.Add(item);

                            //if (itemOverTime != null)
                            //{
                            //    SumOvertimeInsurance += value * itemOverTime.TaxRate;//Tính số giờ tăng ca có chịu thuế
                            //    SumOvertime += value * itemOverTime.Rate;//tính hệ số và lưu vào biến tổng số giờ tăng ca
                            //}
                        }
                        ////Lưu giá trị cho Enum tổng số giớ tăng ca trong tháng
                        //item = new ElementFormula(PayrollElement.ATT_OVERTIME_HOURS.ToString(), SumOvertime, 0);
                        //listElementFormula.Add(item);

                        ////Lưu giá trị cho Enum tổng số giớ tăng ca trong tháng có tính thuế
                        //item = new ElementFormula(PayrollElement.ATT_OVERTIME_PIT_HOURS.ToString(), SumOvertimeInsurance, 0);
                        //listElementFormula.Add(item);
                    }
                }
            }
            #endregion

            #region Tổng giờ tăng ca trong tháng và tổng giờ tăng ca trong tháng có tính thuế

            if (CheckIsExistFormula(listElementFormula, formula, new string[] { PayrollElement.ATT_OVERTIME_PIT_HOURS.ToString(), PayrollElement.ATT_OVERTIME_HOURS.ToString() }))
            {
                double SumOvertime = 0;
                double SumOvertimeInsurance = 0;

                foreach (var itemOverTime in TotalData.listOvertimeType)
                {
                    double value = 0;
                    if (itemOverTime != null && listAttendanceTableProCut != null)
                    {
                        if (listAttendanceTableProCut.Overtime1Type != null && listAttendanceTableProCut.Overtime1Type == itemOverTime.ID)
                        {
                            value += listAttendanceTableProCut.Overtime1Hours;
                        }
                        if (listAttendanceTableProCut.Overtime2Type != null && listAttendanceTableProCut.Overtime2Type == itemOverTime.ID)
                        {
                            value += listAttendanceTableProCut.Overtime2Hours;
                        }
                        if (listAttendanceTableProCut.Overtime3Type != null && listAttendanceTableProCut.Overtime3Type == itemOverTime.ID)
                        {
                            value += listAttendanceTableProCut.Overtime3Hours;
                        }
                        if (listAttendanceTableProCut.Overtime4Type != null && listAttendanceTableProCut.Overtime4Type == itemOverTime.ID)
                        {
                            value += listAttendanceTableProCut.Overtime4Hours;
                        }
                        if (listAttendanceTableProCut.Overtime5Type != null && listAttendanceTableProCut.Overtime5Type == itemOverTime.ID)
                        {
                            value += listAttendanceTableProCut.Overtime5Hours;
                        }
                        if (listAttendanceTableProCut.Overtime6Type != null && listAttendanceTableProCut.Overtime6Type == itemOverTime.ID)
                        {
                            value += listAttendanceTableProCut.Overtime6Hours;
                        }
                    }

                    if (itemOverTime != null)
                    {
                        SumOvertimeInsurance += value * itemOverTime.TaxRate;//Tính số giờ tăng ca có chịu thuế
                        SumOvertime += value * itemOverTime.Rate;//tính hệ số và lưu vào biến tổng số giờ tăng ca
                    }
                }
                //Lưu giá trị cho Enum tổng số giớ tăng ca trong tháng
                item = new ElementFormula(PayrollElement.ATT_OVERTIME_HOURS.ToString(), SumOvertime, 0);
                listElementFormula.Add(item);

                //Lưu giá trị cho Enum tổng số giớ tăng ca trong tháng có tính thuế
                item = new ElementFormula(PayrollElement.ATT_OVERTIME_PIT_HOURS.ToString(), SumOvertimeInsurance, 0);
                listElementFormula.Add(item);
            }

            #endregion

            #region Các loại OT nếu có thay đổi lương trong tháng

            if (CheckIsExistFormula(listElementFormula, formula, "ATT_OVERTIME_", "_HOURS_AFTER"))
            {
                using (var context = new VnrHrmDataContext())
                {
                    var unitOfWork = (IUnitOfWork)new UnitOfWork(context);
                    //var repoAttendanceTable = new CustomBaseRepository<Att_AttendanceTable>(unitOfWork);
                    //lấy lương cơ bản của nhân viên
                    List<Sal_BasicSalaryEntity> SalaryProfile = new List<Sal_BasicSalaryEntity>();
                    SalaryProfile = TotalData.listBasicSalary.Where(m => m.ProfileID == profileItem.ID).OrderByDescending(m => m.DateOfEffect).ToList();

                    if (SalaryProfile.Count > 0 && SalaryProfile.FirstOrDefault().DateOfEffect > CutOffDuration.DateStart)//có thay đổi lương trong tháng
                    {
                        double OtHour = 0;
                        //ngày bắt đầu mức lương 1 và ngày bắt đầu mức lương 2
                        DateTime dateStart1 = CutOffDuration.DateStart;
                        DateTime dateStart2 = SalaryProfile.FirstOrDefault().DateOfEffect;

                        //lấy dữ liệu công theo cutoff
                        List<Att_AttendanceTableItemEntity> listAttTableItem = TotalData.listAttendanceTableItem.Where(m => m.ProfileID == profileItem.ID).ToList();

                        if (listAttTableItem != null && listAttTableItem.Count > 0)
                        {
                            listAttTableItem = listAttTableItem.Where(m => m.WorkDate >= dateStart2).ToList();
                            //duyệt wa các loại ot
                            foreach (var OTType in TotalData.listOvertimeType)
                            {
                                OtHour = 0;
                                //tính số giờ OT của từng loại
                                foreach (var tableItem in listAttTableItem)
                                {
                                    if (tableItem.OvertimeTypeID != null && tableItem.OvertimeTypeID == OTType.ID)
                                    {
                                        OtHour += tableItem.OvertimeHours;
                                    }
                                    else if (tableItem.ExtraOvertimeTypeID != null && tableItem.ExtraOvertimeTypeID == OTType.ID)
                                    {
                                        OtHour += tableItem.ExtraOvertimeHours;
                                    }
                                    else if (tableItem.ExtraOvertimeType2ID != null && tableItem.ExtraOvertimeType2ID == OTType.ID)
                                    {
                                        OtHour += tableItem.ExtraOvertimeHours2;
                                    }
                                    else if (tableItem.ExtraOvertimeType3ID != null && tableItem.ExtraOvertimeType3ID == OTType.ID)
                                    {
                                        OtHour += tableItem.ExtraOvertimeHours3;
                                    }
                                }
                                item = new ElementFormula("ATT_OVERTIME_" + OTType.Code + "_HOURS_AFTER", OtHour, 0);
                                listElementFormula.Add(item);
                            }
                        }
                        else
                        {
                            foreach (var OTType in TotalData.listOvertimeType)
                            {
                                item = new ElementFormula("ATT_OVERTIME_" + OTType.Code + "_HOURS_AFTER", 0, 0);
                                listElementFormula.Add(item);
                            }
                        }
                    }
                    else//không có lương cơ bản hoặc không có thay đổi lương trong tháng
                    {
                        foreach (var OTType in TotalData.listOvertimeType)
                        {
                            item = new ElementFormula("ATT_OVERTIME_" + OTType.Code + "_HOURS_AFTER", 0, 0);
                            listElementFormula.Add(item);
                        }
                    }
                }
            }

            #endregion

            #region OT tháng N-1
            if (CheckIsExistFormula(listElementFormula, formula, "ATT_OVERTIME_", "_HOURS_PREV"))
            {
                listElement_OT = TotalData.listElement_All.Where(m => m.ElementCode.StartsWith("ATT_OVERTIME_") && m.ElementCode.EndsWith("_HOURS_PREV")).ToList();
                if (listElement_OT != null && listElement_OT.Count > 0)
                {
                    foreach (var OT in listElement_OT)
                    {
                        var itemOverTime = TotalData.listOvertimeType.Where(m => m.Code == OT.ElementCode.Replace("ATT_OVERTIME_", "").Replace("_HOURS_PREV", "")).FirstOrDefault();

                        double value = 0;
                        var _tmpAttendanceTable = TotalData.Att_AttendanceTable_Prev.Where(m => m.ProfileID == profileItem.ID).FirstOrDefault();
                        if (itemOverTime != null && _tmpAttendanceTable != null)
                        {
                            if (_tmpAttendanceTable.Overtime1Type != null && _tmpAttendanceTable.Overtime1Type == itemOverTime.ID)
                            {
                                value += _tmpAttendanceTable.Overtime1Hours;
                            }
                            if (_tmpAttendanceTable.Overtime2Type != null && _tmpAttendanceTable.Overtime2Type == itemOverTime.ID)
                            {
                                value += _tmpAttendanceTable.Overtime2Hours;
                            }
                            if (_tmpAttendanceTable.Overtime3Type != null && _tmpAttendanceTable.Overtime3Type == itemOverTime.ID)
                            {
                                value += _tmpAttendanceTable.Overtime3Hours;
                            }
                            if (_tmpAttendanceTable.Overtime4Type != null && _tmpAttendanceTable.Overtime4Type == itemOverTime.ID)
                            {
                                value += _tmpAttendanceTable.Overtime4Hours;
                            }
                            if (_tmpAttendanceTable.Overtime5Type != null && _tmpAttendanceTable.Overtime5Type == itemOverTime.ID)
                            {
                                value += _tmpAttendanceTable.Overtime5Hours;
                            }
                            if (_tmpAttendanceTable.Overtime6Type != null && _tmpAttendanceTable.Overtime6Type == itemOverTime.ID)
                            {
                                value += _tmpAttendanceTable.Overtime6Hours;
                            }
                        }
                        item = new ElementFormula(OT.ElementCode, value, 0);
                        listElementFormula.Add(item);
                    }
                }
            }

            #endregion

            #endregion

            #region Lấy LeaveDay theo từng loại và lấy tổng nghỉ
            double SumLeaveday = 0;
            double SumLeavedayIsSalary = 0;

            //N-1
            double SumLeaveday_Prev = 0;
            double SumLeavedayIsSalary_Prev = 0;

            List<Cat_ElementEntity> listElement_Leave = new List<Cat_ElementEntity>();
            if (CheckIsExistFormula(listElementFormula, formula, "ATT_LEAVE_", "_HOURS") || CheckIsExistFormula(listElementFormula, formula, new string[] { PayrollElement.ATT_LEAVE_HOURS.ToString(), PayrollElement.ATT_TOTAL_PAID_LEAVEDAY_HOURS.ToString() }))
            {
                listElement_Leave = TotalData.listElement_All.Where(m => m.ElementCode.StartsWith("ATT_LEAVE_") && m.ElementCode.EndsWith("_HOURS")).ToList();

                foreach (var LD in listElement_Leave)
                {
                    var itemLeaveday = TotalData.listLeavedayType.Where(m => m.Code == LD.ElementCode.Replace("ATT_LEAVE_", "").Replace("_HOURS", "")).FirstOrDefault();

                    double value = 0;
                    if (itemLeaveday != null && listAttendanceTableProCut != null)
                    {
                        if (listAttendanceTableProCut.LeaveDay1Type != null && listAttendanceTableProCut.LeaveDay1Type == itemLeaveday.ID)
                        {
                            value += listAttendanceTableProCut.LeaveDay1Hours;
                        }
                        if (listAttendanceTableProCut.LeaveDay2Type != null && listAttendanceTableProCut.LeaveDay2Type == itemLeaveday.ID)
                        {
                            value += listAttendanceTableProCut.LeaveDay2Hours;
                        }
                        if (listAttendanceTableProCut.LeaveDay3Type != null && listAttendanceTableProCut.LeaveDay3Type == itemLeaveday.ID)
                        {
                            value += listAttendanceTableProCut.LeaveDay3Hours;
                        }
                        if (listAttendanceTableProCut.LeaveDay4Type != null && listAttendanceTableProCut.LeaveDay4Type == itemLeaveday.ID)
                        {
                            value += listAttendanceTableProCut.LeaveDay4Hours;
                        }
                    }
                    item = new ElementFormula(LD.ElementCode, value, 0);
                    listElementFormula.Add(item);


                    SumLeaveday += value;//Tổng giờ nghỉ trong tháng
                    if (itemLeaveday != null)
                    {
                        SumLeavedayIsSalary += value * itemLeaveday.PaidRate;//tổng giờ nghỉ có trả lương
                    }

                    #region Lấy LeaveDay theo từng lại và lấy tổng ngày nghỉ tháng N - 1

                    value = 0;
                    var _tmpAttendanceTable = TotalData.Att_AttendanceTable_Prev.Where(m => m.ProfileID == profileItem.ID).FirstOrDefault();
                    if (itemLeaveday != null && _tmpAttendanceTable != null)
                    {
                        if (_tmpAttendanceTable.LeaveDay1Type != null && _tmpAttendanceTable.LeaveDay1Type == itemLeaveday.ID)
                        {
                            value += _tmpAttendanceTable.LeaveDay1Hours;
                        }
                        if (_tmpAttendanceTable.LeaveDay2Type != null && _tmpAttendanceTable.LeaveDay2Type == itemLeaveday.ID)
                        {
                            value += _tmpAttendanceTable.LeaveDay2Hours;
                        }
                        if (_tmpAttendanceTable.LeaveDay3Type != null && _tmpAttendanceTable.LeaveDay3Type == itemLeaveday.ID)
                        {
                            value += _tmpAttendanceTable.LeaveDay3Hours;
                        }
                        if (_tmpAttendanceTable.LeaveDay4Type != null && _tmpAttendanceTable.LeaveDay4Type == itemLeaveday.ID)
                        {
                            value += _tmpAttendanceTable.LeaveDay4Hours;
                        }
                    }
                    SumLeaveday_Prev += value;//Tổng giờ nghỉ trong tháng
                    if (itemLeaveday != null)
                    {
                        SumLeavedayIsSalary_Prev += value * itemLeaveday.PaidRate;//tổng giờ nghỉ có trả lương
                    }
                    #endregion
                }

                //tạo phần tử Enum tổng số giờ nghỉ trong tháng
                item = new ElementFormula(PayrollElement.ATT_LEAVE_HOURS.ToString(), SumLeaveday, 0);
                listElementFormula.Add(item);

                //tạo phần tử Enum tổng số giờ nghỉ trong tháng có tính lương
                item = new ElementFormula(PayrollElement.ATT_TOTAL_PAID_LEAVEDAY_HOURS.ToString(), SumLeavedayIsSalary, 0);
                listElementFormula.Add(item);
            }

            //Số ngày nghỉ tháng N-1
            if (CheckIsExistFormula(listElementFormula, formula, "ATT_LEAVE_", "_DAY_PREV"))
            {
                listElement_Leave = TotalData.listElement_All.Where(m => m.ElementCode.StartsWith("ATT_LEAVE_") && m.ElementCode.EndsWith("_DAY_PREV")).ToList();
                var _tmpAttendanceTable = TotalData.Att_AttendanceTable_Prev.Where(m => m.ProfileID == profileItem.ID).FirstOrDefault();
                foreach (var LD in listElement_Leave)
                {
                    var itemLeaveday = TotalData.listLeavedayType.Where(m => m.Code == LD.ElementCode.Replace("ATT_LEAVE_", "").Replace("_DAY_PREV", "")).FirstOrDefault();

                    double value = 0;
                    if (itemLeaveday != null && _tmpAttendanceTable != null)
                    {
                        if (_tmpAttendanceTable.LeaveDay1Type != null && _tmpAttendanceTable.LeaveDay1Type == itemLeaveday.ID)
                        {
                            value += _tmpAttendanceTable.LeaveDay1Days != null ? (double)_tmpAttendanceTable.LeaveDay1Days : 0;
                        }
                        if (_tmpAttendanceTable.LeaveDay2Type != null && _tmpAttendanceTable.LeaveDay2Type == itemLeaveday.ID)
                        {
                            value += _tmpAttendanceTable.LeaveDay2Days != null ? (double)_tmpAttendanceTable.LeaveDay2Days : 0;
                        }
                        if (_tmpAttendanceTable.LeaveDay3Type != null && _tmpAttendanceTable.LeaveDay3Type == itemLeaveday.ID)
                        {
                            value += _tmpAttendanceTable.LeaveDay3Days != null ? (double)_tmpAttendanceTable.LeaveDay3Days : 0;
                        }
                        if (_tmpAttendanceTable.LeaveDay4Type != null && _tmpAttendanceTable.LeaveDay4Type == itemLeaveday.ID)
                        {
                            value += _tmpAttendanceTable.LeaveDay4Days != null ? (double)_tmpAttendanceTable.LeaveDay4Days : 0;
                        }
                    }
                    item = new ElementFormula(LD.ElementCode, value, 0);
                    listElementFormula.Add(item);
                }
            }

            //Tổng số Ngày Nghỉ từng loại trong năm
            if (CheckIsExistFormula(listElementFormula, formula, "ATT_LEAVE_", "_DAY_INYEAR"))
            {
                using (var context = new VnrHrmDataContext())
                {
                    string status = string.Empty;
                    var unitOfWork = (IUnitOfWork)new UnitOfWork(context);
                    var repoSys_AttendanceTable = new CustomBaseRepository<Att_AttendanceTable>(unitOfWork);
                    var repoSys_AttendanceTableItem = new CustomBaseRepository<Att_AttendanceTableItem>(unitOfWork);

                    DateTime from = new DateTime(CutOffDuration.MonthYear.Year - 1, 4, 1);
                    DateTime to = new DateTime(CutOffDuration.MonthYear.Year, 3, 31);

                    List<Att_AttendanceTable> listAttendanceTableByProfile = repoSys_AttendanceTable.FindBy(m => m.IsDelete != true && m.ProfileID == profileItem.ID && m.MonthYear != null && m.MonthYear.Value >= from && m.MonthYear.Value <= to).ToList();

                    listElement_Leave = TotalData.listElement_All.Where(m => m.ElementCode.StartsWith("ATT_LEAVE_") && m.ElementCode.EndsWith("_DAY_INYEAR")).ToList();

                    foreach (var LD in listElement_Leave)
                    {
                        var itemLeaveday = TotalData.listLeavedayType.Where(m => m.Code == LD.ElementCode.Replace("ATT_LEAVE_", "").Replace("_DAY_INYEAR", "")).FirstOrDefault();

                        double value = 0;
                        foreach (var _tmpAttendanceTable in listAttendanceTableByProfile)
                        {
                            if (itemLeaveday != null && _tmpAttendanceTable != null)
                            {
                                if (_tmpAttendanceTable.LeaveDay1Type != null && _tmpAttendanceTable.LeaveDay1Type == itemLeaveday.ID)
                                {
                                    value += _tmpAttendanceTable.LeaveDay1Days != null ? (double)_tmpAttendanceTable.LeaveDay1Days : 0;
                                }
                                if (_tmpAttendanceTable.LeaveDay2Type != null && _tmpAttendanceTable.LeaveDay2Type == itemLeaveday.ID)
                                {
                                    value += _tmpAttendanceTable.LeaveDay2Days != null ? (double)_tmpAttendanceTable.LeaveDay2Days : 0;
                                }
                                if (_tmpAttendanceTable.LeaveDay3Type != null && _tmpAttendanceTable.LeaveDay3Type == itemLeaveday.ID)
                                {
                                    value += _tmpAttendanceTable.LeaveDay3Days != null ? (double)_tmpAttendanceTable.LeaveDay3Days : 0;
                                }
                                if (_tmpAttendanceTable.LeaveDay4Type != null && _tmpAttendanceTable.LeaveDay4Type == itemLeaveday.ID)
                                {
                                    value += _tmpAttendanceTable.LeaveDay4Days != null ? (double)_tmpAttendanceTable.LeaveDay4Days : 0;
                                }
                            }
                        }
                        item = new ElementFormula(LD.ElementCode, value, 0);
                        listElementFormula.Add(item);
                    }
                }
            }


            #region N-1
            if (CheckIsExistFormula(listElementFormula, formula, new string[] { PayrollElement.ATT_LEAVE_HOURS_PREV.ToString(), PayrollElement.ATT_TOTAL_PAID_LEAVEDAY_HOURS_PREV.ToString() }))
            {
                //Tổng số giờ nghỉ trong tháng N-1
                item = new ElementFormula(PayrollElement.ATT_LEAVE_HOURS_PREV.ToString(), SumLeaveday_Prev, 0);
                listElementFormula.Add(item);

                //Tổng số giờ nghỉ trong tháng có tính lương N-1
                item = new ElementFormula(PayrollElement.ATT_TOTAL_PAID_LEAVEDAY_HOURS_PREV.ToString(), SumLeavedayIsSalary_Prev, 0);
                listElementFormula.Add(item);
            }
            #endregion
            #endregion

            #endregion

            #region  Honda - tổng số ngày làm việc theo từng ca của nhân viên trong tháng
            if (CheckIsExistFormula(listElementFormula, formula, "ATT_SHIFT_", "_HOURS"))
            {
                using (var context = new VnrHrmDataContext())
                {
                    string status = string.Empty;
                    var unitOfWork = (IUnitOfWork)new UnitOfWork(context);
                    //var repoAtt_AttendanceTableItem = new CustomBaseRepository<Att_AttendanceTableItem>(unitOfWork);

                    List<Att_AttendanceTableItemEntity> listAttTableItemByShift = new List<Att_AttendanceTableItemEntity>();
                    List<Att_AttendanceTableItemEntity> listAttendanceTableItemByAtt = TotalData.listAttendanceTableItem.Where(m => m.AttendanceTableID == listAttendanceTableProCut.ID).ToList();

                    for (int j = 0; j < TotalData.listCat_Shift.Count; j++)
                    {
                        listAttTableItemByShift = listAttendanceTableItemByAtt.Where(m => m.ShiftID != null && m.ShiftID == TotalData.listCat_Shift[j].ID).ToList();
                        item = new ElementFormula("ATT_SHIFT_" + TotalData.listCat_Shift[j].Code + "_HOURS", listAttTableItemByShift.Sum(m => m.AvailableHours), 0);
                        listElementFormula.Add(item);
                    }
                }
            }


            if (CheckIsExistFormula(listElementFormula, formula, "ATT_SHIFT_", "_DAY"))
            {
                using (var context = new VnrHrmDataContext())
                {
                    string status = string.Empty;
                    var unitOfWork = (IUnitOfWork)new UnitOfWork(context);
                    //var repoAtt_AttendanceTableItem = new CustomBaseRepository<Att_AttendanceTableItem>(unitOfWork);

                    List<Att_AttendanceTableItemEntity> listAttTableItemByShift = new List<Att_AttendanceTableItemEntity>();
                    List<Att_AttendanceTableItemEntity> listAttendanceTableItemByAtt = TotalData.listAttendanceTableItem.Where(m => m.AttendanceTableID == listAttendanceTableProCut.ID).ToList();
                    List<Att_AttendanceTableItemEntity> listAttendanceTableItemByAtt_Prev = new List<Att_AttendanceTableItemEntity>();
                    if (TotalData.Att_AttendanceTable_Prev.Count() >= 0)
                    {

                        Att_AttendanceTableEntity _tmp = TotalData.Att_AttendanceTable_Prev.Where(t => t.ProfileID == profileItem.ID).FirstOrDefault();
                        Guid _tmpID = Guid.Empty;
                        if (_tmp != null)
                        {
                            _tmpID = _tmp.ID;
                        }
                        listAttendanceTableItemByAtt_Prev = TotalData.listAttendanceTableItem.Where(m => m.AttendanceTableID == _tmpID).ToList();
                    }

                    for (int j = 0; j < TotalData.listCat_Shift.Count; j++)
                    {
                        listAttTableItemByShift = listAttendanceTableItemByAtt.Where(m => m.ShiftID != null && m.ShiftID == TotalData.listCat_Shift[j].ID).ToList();
                        if (listAttTableItemByShift != null && listAttTableItemByShift.Count > 0)
                        {
                            item = new ElementFormula("ATT_SHIFT" + "_" + TotalData.listCat_Shift[j].Code + "_" + "DAY", listAttTableItemByShift.Where(d => d.AvailableHours > 0).Sum(d => (d.WorkPaidHours + d.LateEarlyMinutes / 60.0) / d.AvailableHours), 0);
                            listElementFormula.Add(item);
                        }
                        else
                        {
                            item = new ElementFormula("ATT_SHIFT" + "_" + TotalData.listCat_Shift[j].Code + "_" + "DAY", 0, 0);
                            listElementFormula.Add(item);
                        }

                        //tháng N-1
                        listAttTableItemByShift = listAttendanceTableItemByAtt_Prev.Where(m => m.ShiftID != null && m.ShiftID == TotalData.listCat_Shift[j].ID).ToList();
                        if (listAttTableItemByShift != null && listAttTableItemByShift.Count > 0)
                        {
                            item = new ElementFormula("ATT_SHIFT" + "_" + TotalData.listCat_Shift[j].Code + "_" + "DAY_PREV", listAttTableItemByShift.Where(d => d.AvailableHours > 0).Sum(d => (d.WorkPaidHours + d.LateEarlyMinutes / 60.0) / d.AvailableHours), 0);
                            listElementFormula.Add(item);
                        }
                        else
                        {
                            item = new ElementFormula("ATT_SHIFT" + "_" + TotalData.listCat_Shift[j].Code + "_" + "DAY_PREV", 0, 0);
                            listElementFormula.Add(item);
                        }
                    }
                }

            }

            #endregion

            #region Lấy giá trị cho các loại phần tử là Hoa Hồng

            if (CheckIsExistFormula(listElementFormula, formula, CatElementType.Comission.ToString().ToUpper(), ""))
            {
                //lấy doanh thu của shop trong tháng
                List<Sal_RevenueRecordEntity> revenueShopInMonth = new List<Sal_RevenueRecordEntity>();
                if (profileItem.ShopID != null)
                {
                    revenueShopInMonth = TotalData.listRevenueRecord.Where(m => m.ShopID == profileItem.ShopID).ToList();
                }

                if (TotalData.listKPIBonus != null && TotalData.listKPIBonus.Count > 0)
                {
                    foreach (var j in TotalData.listKPIBonus)
                    {
                        if (revenueShopInMonth.Any(m => m.KPIBonusID == j.ID))
                        {
                            listElementFormula.Add(new ElementFormula(CatElementType.Comission.ToString().ToUpper() + "_" + j.Code, revenueShopInMonth.Where(m => m.KPIBonusID == j.ID).FirstOrDefault().Amount, 0));
                        }
                        else
                        {
                            listElementFormula.Add(new ElementFormula(CatElementType.Comission.ToString().ToUpper() + "_" + j.Code, 0, 0));
                        }
                    }
                }
            }

            #region Phần tử lương hoa hồng đã tính được, trong bảng Sal_PaycCommission
            if (CheckIsExistFormula(listElementFormula, formula, "ELEMENT" + CatElementType.Comission.ToString().ToUpper() + "_", ""))
            {
                List<Cat_ElementEntity> listElementByCommission = TotalData.listElement_All.Where(m => m.GradePayrollID == null && m.MethodPayroll == MethodPayroll.E_COMMISSION_PAYMENT.ToString()).ToList();
                if (TotalData.listPayCommissionItem != null)
                {
                    //duyệt wa tất cả các phần tử
                    foreach (var element in listElementByCommission)
                    {
                        string elementCode = element.ElementCode.Replace("ELEMENT" + CatElementType.Comission.ToString().ToUpper() + "_", "");
                        Sal_PayCommissionItemEntity PayCommissionItem = TotalData.listPayCommissionItem.Where(m => m.ProfileID != null && m.Code.ReplaceSpace() == elementCode.ReplaceSpace()).FirstOrDefault();
                        if (PayCommissionItem != null)
                        {
                            item = new ElementFormula(element.ElementCode, PayCommissionItem.Value, 0);
                            listElementFormula.Add(item);
                        }
                        else
                        {
                            item = new ElementFormula(element.ElementCode, 0, 0);
                            listElementFormula.Add(item);
                        }
                    }
                }
                else
                {
                    foreach (var element in listElementByCommission)
                    {
                        item = new ElementFormula(element.ElementCode, 0, 0);
                        listElementFormula.Add(item);
                    }
                }
            }
            #endregion

            #region Lấy dữ liệu các phần tử là tổng số lượng chức vụ (Position) trong shop
            if (CheckIsExistFormula(listElementFormula, formula, CatElementType.Comission.ToString().ToUpper() + "_COUNTPOSITION_", ""))
            {
                using (var context = new VnrHrmDataContext())
                {
                    var unitOfWork = (IUnitOfWork)(new UnitOfWork(context));
                    var repoProfile = new CustomBaseRepository<Hre_Profile>(unitOfWork);
                    if (TotalData.listPosition != null && TotalData.listPosition.Count > 0)
                    {
                        var lstProfile = repoProfile.FindBy(m => m.ShopID == profileItem.ShopID).ToList();
                        foreach (var j in TotalData.listPosition)
                        {
                            listElementFormula.Add(new ElementFormula(CatElementType.Comission.ToString().ToUpper() + "_COUNTPOSITION_" + j.Code, lstProfile.Where(m => m.PositionID == j.ID).Count(), 0));
                        }
                    }
                }
            }
            #endregion

            #region Lấy giá trị cho 2 enum là dòng sản phẩm và sản phẩm
            if (CheckIsExistFormula(listElementFormula, formula, new string[] { PayrollElement.SAL_COM_PERCENT_SHOP_LINEITEM.ToString(), PayrollElement.SAL_COM_PERCENT_SHOP_ITEM.ToString() }))
            {
                //lấy doanh thu của shop trong tháng
                List<Sal_RevenueRecordEntity> revenueShopInMonth = new List<Sal_RevenueRecordEntity>();
                if (profileItem.ShopID != null)
                {
                    revenueShopInMonth = TotalData.listRevenueRecord.Where(m => m.ShopID == profileItem.ShopID).ToList();
                }

                //SAL_COM_PERCENT_SHOP_5
                if (revenueShopInMonth.Any(m => m.Type == EnumDropDown.SalesType.E_LINEITEM_MAJOR.ToString()))
                {
                    listElementFormula.Add(new ElementFormula(PayrollElement.SAL_COM_PERCENT_SHOP_LINEITEM.ToString(), revenueShopInMonth.Where(m => m.Type == EnumDropDown.SalesType.E_LINEITEM_MAJOR.ToString()).FirstOrDefault().Amount, 0));
                }
                else
                {
                    listElementFormula.Add(new ElementFormula(PayrollElement.SAL_COM_PERCENT_SHOP_LINEITEM.ToString(), 0, 0));
                }

                //SAL_COM_PERCENT_SHOP_6
                if (revenueShopInMonth.Any(m => m.Type == EnumDropDown.SalesType.E_ITEM_MAJOR.ToString()))
                {
                    listElementFormula.Add(new ElementFormula(PayrollElement.SAL_COM_PERCENT_SHOP_ITEM.ToString(), revenueShopInMonth.Where(m => m.Type == EnumDropDown.SalesType.E_ITEM_MAJOR.ToString()).FirstOrDefault().Amount, 0));
                }
                else
                {
                    listElementFormula.Add(new ElementFormula(PayrollElement.SAL_COM_PERCENT_SHOP_ITEM.ToString(), 0, 0));
                }
            }


            #endregion

            #region Tính giá trị cho phần tử khấu trừ khi có nhân viên ko đủ thâm niên trong shop
            if (CheckIsExistFormula(listElementFormula, formula, PayrollElement.SAL_COM_BONUS_SCV.ToString()))
            {
                using (var context = new VnrHrmDataContext())
                {
                    var unitOfWork = (IUnitOfWork)(new UnitOfWork(context));
                    var repoProfile = new CustomBaseRepository<Hre_Profile>(unitOfWork);
                    if (profileItem.ShopID != null)
                    {
                        //tính tiền khấu trừ khi khong đủ thâm niên
                        double Money_Deduction = 0;
                        try
                        {
                            //Hiện tại đang lấy trong webconfig, sau này sẻ lấy trong bảng setting
                            Money_Deduction = (double)GetObjectValue(TotalData.listElement_All, listElementFormula, TotalData.listElement_All.Where(m => m.ElementCode == ConstantPathWeb.Hrm_Sal_ElementName_Comission).FirstOrDefault().Formula);
                        }
                        catch { }

                        if (Money_Deduction != 0)//nhân viên này không đủ thâm niên
                        {
                            if (listTmpDeduction.Any(m => m.Key == profileItem.ShopID))//đã có nhân viên ko đủ thâm niên trong shop trước đó
                            {
                                double _tmp = listTmpDeduction.Single(m => m.Key == profileItem.ShopID).Value.Value;
                                int countValue = listTmpDeduction.Single(m => m.Key == profileItem.ShopID).Value.Count;
                                listTmpDeduction.Remove((Guid)profileItem.ShopID);//xóa phần tử trước đó
                                listTmpDeduction.Add((Guid)profileItem.ShopID, new ValueCount(Money_Deduction + _tmp, countValue++));//thêm lại phần tử đó và cập nhật lại value
                            }
                            else//là nhân viên ko đủ thâm niên đầu tiên trong shop
                            {
                                listTmpDeduction.Add((Guid)profileItem.ShopID, new ValueCount(Money_Deduction, 1));//thêm lại phần tử đó và cập nhật lại value
                            }
                            item = new ElementFormula(PayrollElement.SAL_COM_BONUS_SCV.ToString(), 0, 0);
                            listElementFormula.Add(item);
                        }
                        else//nhân viên này đủ thâm niên, kiểm tra xem shop của nhân viên này có nhân viên nào ko đủ thâm niên hay không
                        {
                            if (listTmpDeduction.Any(m => m.Key == profileItem.ShopID))//đã có nhân viên ko đủ thâm niên trong shop trước đó
                            {
                                int CountProfile = repoProfile.FindBy(m => m.ShopID == profileItem.ShopID).Count() - listTmpDeduction.Single(m => m.Key == profileItem.ShopID).Value.Count;
                                item = new ElementFormula(PayrollElement.SAL_COM_BONUS_SCV.ToString(), listTmpDeduction.Single(m => m.Key == profileItem.ShopID).Value.Value / CountProfile, 0);
                                listElementFormula.Add(item);
                            }
                            else
                            {
                                item = new ElementFormula(PayrollElement.SAL_COM_BONUS_SCV.ToString(), 0, 0);
                                listElementFormula.Add(item);
                            }
                        }
                    }
                    else
                    {
                        item = new ElementFormula(PayrollElement.SAL_COM_BONUS_SCV.ToString(), 0, 0);
                        listElementFormula.Add(item);
                    }
                }
            }

            #endregion

            #endregion

            #region lấy các phần tử Đánh Giá

            if (CheckIsExistFormula(listElementFormula, formula, CatElementType.Evaluation.ToString().ToUpper(), ""))
            {
                IList<string> List_EvaBonusType = Enum.GetValues(typeof(EvaBonusType))
                                          .Cast<EvaBonusType>()
                                          .Select(x => x.ToString())
                                          .ToList();

                if (TotalData.listSalesType != null && TotalData.listSalesType.Count > 0)
                {
                    foreach (var j in TotalData.listSalesType)
                    {
                        foreach (var t in List_EvaBonusType)
                        {
                            try
                            {
                                Eva_BonusSalaryEntity BonusSalaryITem = TotalData.listEva_BonusSalary.Where(m => m.ProfileID == profileItem.ID
                                    && m.SalesTypeID == j.ID
                                    && m.Type == t).FirstOrDefault();
                                if (BonusSalaryITem != null && BonusSalaryITem.Bonus != null)
                                {
                                    item = new ElementFormula(CatElementType.Evaluation.ToString().ToUpper() + "_" + j.Code + "_" + t, BonusSalaryITem.Bonus, 0);
                                    listElementFormula.Add(item);
                                }
                                else
                                {
                                    item = new ElementFormula(CatElementType.Evaluation.ToString().ToUpper() + "_" + j.Code + "_" + t, 0, 0);
                                    listElementFormula.Add(item);
                                }
                            }
                            catch
                            {
                                item = new ElementFormula(CatElementType.Evaluation.ToString().ToUpper() + "_" + j.Code + "_" + t, 0, 0);
                                listElementFormula.Add(item);
                            }
                        }
                    }
                }
            }
            #endregion

            #region Vietject

            #region Lấy các phần tử đơn giá theo vai trò (Vietject)

            if (CheckIsExistFormula(listElementFormula, formula, CatElementType.FLIGHT.ToString() + "_", "_HOURS") ||
                CheckIsExistFormula(listElementFormula, formula, CatElementType.FLIGHT.ToString() + "_", "_ROUTES") ||
                CheckIsExistFormula(listElementFormula, formula, CatElementType.FLIGHT.ToString() + "_", "_AMOUNT"))
            {
                List<Att_TimeSheetEntity> Att_TimeSheetItem = TotalData.listAtt_TimeSheet.Where(m => m.ProfileID == profileItem.ID && m.Date <= CutOffDuration.DateEnd && m.Date >= CutOffDuration.DateStart).OrderByDescending(m => m.Date).ToList();
                List<Cat_UnitPriceEntity> Cat_UnitPrice = TotalData.listCat_UnitPrice.Where(m => m.Date <= CutOffDuration.DateEnd).OrderByDescending(m => m.Date).ToList();
                if (TotalData.listCat_Role != null && TotalData.listCat_Role.Count > 0 && TotalData.listCat_JobType != null && TotalData.listCat_JobType.Count > 0)
                {
                    foreach (var Role in TotalData.listCat_Role)
                    {
                        foreach (var JobType in TotalData.listCat_JobType)
                        {
                            var Att_TimeSheetItemByItem = Att_TimeSheetItem.Where(m => m.RoleID == Role.ID && m.JobTypeID == JobType.ID).OrderByDescending(m => m.Date).ToList();
                            var Cat_UnitPriceByItem = Cat_UnitPrice.Where(m => m.RoleID == Role.ID && m.JobTypeID == JobType.ID).OrderByDescending(m => m.Date).FirstOrDefault();
                            //số giờ bay
                            item = new ElementFormula(CatElementType.FLIGHT.ToString() + "_" + Role.Code.ReplaceSpace() + "_" + JobType.Code.ReplaceSpace() + "_HOURS", Att_TimeSheetItemByItem.Sum(m => m.NoHour), 0);
                            listElementFormula.Add(item);
                            //số chặn bay
                            item = new ElementFormula(CatElementType.FLIGHT.ToString() + "_" + Role.Code.ReplaceSpace() + "_" + JobType.Code.ReplaceSpace() + "_ROUTES", Att_TimeSheetItemByItem.Sum(m => m.Sector), 0);
                            listElementFormula.Add(item);

                            //số tiền
                            double Amount = Cat_UnitPriceByItem != null && Cat_UnitPriceByItem.Amount != null ? (double)Cat_UnitPriceByItem.Amount : 0;
                            item = new ElementFormula(CatElementType.FLIGHT.ToString() + "_" + Role.Code.ReplaceSpace() + "_" + JobType.Code.ReplaceSpace() + "_AMOUNT", Amount, 0);
                            listElementFormula.Add(item);
                        }
                    }
                }
            }
            #endregion

            #endregion

            return listElementFormula.Distinct().ToList();
        }
        public void ProcessGroundForcesWikiHtmlFiles(ConcurrentDictionary<string, HtmlDocument> vehicleWikiPagesContent, ConcurrentDictionary<string, string> localFileChanges, Dictionary<string, GroundVehicle> vehicleDetails, List<HtmlNode> vehicleWikiEntryLinks, List<string> errorsList, int indexPosition, int expectedNumberOfLinks, bool createJsonFiles, bool createHtmlFiles, bool createExcelFile)
        {
            try
            {
                _consoleManager.WriteLineInColour(ConsoleColor.Yellow, "Press ENTER to begin extracting data from the vehicle pages.");
                _consoleManager.WaitUntilKeyIsPressed(ConsoleKey.Enter);

                foreach (string vehicleWikiPageLinkTitle in vehicleWikiPagesContent.Keys)
                {
                    // Page to traverse
                    HtmlDocument vehicleWikiPage = vehicleWikiPagesContent.Single(x => x.Key == vehicleWikiPageLinkTitle).Value;
                    // Get the header that holds the page title | document.getElementsByClassName('firstHeading')[0].firstChild.innerText
                    HtmlNode pageTitle = vehicleWikiPage.DocumentNode.Descendants().Single(d => d.Id == "firstHeading").FirstChild;
                    // Get the div that holds all of the content under the title section | document.getElementById('bodyContent')
                    HtmlNode wikiBody = vehicleWikiPage.DocumentNode.Descendants().Single(d => d.Id == "bodyContent");
                    // Get the div that holds the content on the RHS of the page where the information table is | document.getElementById('bodyContent').getElementsByClassName('right-area')
                    HtmlNode rightHandContent = wikiBody.Descendants("div").SingleOrDefault(d => d.Attributes["class"] != null && d.Attributes["class"].Value.Contains("right-area"));

                    // Get the able that holds all of the vehicle information | document.getElementsByClassName('flight-parameters')[0]
                    HtmlNode infoBox = rightHandContent != null
                        ? rightHandContent.Descendants("table").SingleOrDefault(d => d.Attributes["class"].Value.Contains("flight-parameters"))
                        : null;

                    // Name
                    string vehicleName = _stringHelper.RemoveInvalidCharacters(System.Net.WebUtility.HtmlDecode(vehicleWikiPageLinkTitle));

                    // Link
                    HtmlNode urlNode = vehicleWikiEntryLinks.SingleOrDefault(v => v.InnerText.Equals(vehicleName));
                    string relativeUrl = urlNode != null
                        ? urlNode.Attributes["href"].Value.ToString()
                        : "";
                    string vehicleWikiEntryFullUrl = new Uri(new Uri(ConfigurationManager.AppSettings["BaseWikiUrl"]), relativeUrl).ToString();

                    // Fail fast and create error if there is no info box
                    if (infoBox == null)
                    {
                        _consoleManager.WriteLineInColour(ConsoleColor.Red, $"Error processing item {indexPosition} of {expectedNumberOfLinks}", false);
                        _consoleManager.WriteBlankLine();

                        errorsList.Add($"No Information found for '{vehicleName}' - {vehicleWikiEntryFullUrl}");

                        _consoleManager.ResetConsoleTextColour();
                        indexPosition++;
                        continue;
                    }
                    else
                    {
                        // Setup local vars
                        Dictionary<string, string> vehicleAttributes = new Dictionary<string, string>();
                        HtmlNodeCollection rows = infoBox.SelectNodes("tr");

                        _consoleManager.WriteTextLine($"The following values were found for {vehicleName}");

                        _webCrawler.GetAttributesFromInfoBox(vehicleAttributes, rows);

                        _consoleManager.ResetConsoleTextColour();

                        // Country
                        string countryRawValue = vehicleAttributes.Single(k => k.Key == "Country").Value.ToString();
                        CountryEnum vehicleCountry = _vehicleCountryHelper.GetVehicleCountryFromName(countryRawValue).CountryEnum;

                        // Weight
                        string weightRawValue = vehicleAttributes.Single(k => k.Key == "Weight").Value.ToString();
                        int weightWithoutUnits = int.Parse(Regex.Match(weightRawValue, @"\d+").Value);
                        string weightUnitsAbbreviation = (Regex.Matches(weightRawValue, @"\D+").Cast<Match>()).Last().Value.Trim();
                        VehicleWeightUnitHelper vehicleWeightUnit = _vehicleWeightUnitHelper.GetWeightUnitFromAbbreviation(weightUnitsAbbreviation);

                        // Vehicle class
                        string typeRawValue = vehicleAttributes.Single(k => k.Key == "Type").Value.ToString();
                        GroundVehicleTypeHelper vehicleType = _vehicleTypeHelper.GetGroundVehicleTypeFromName(typeRawValue);

                        // Rank
                        int rankRawValue = int.Parse(vehicleAttributes.Single(k => k.Key == "Rank").Value.ToString());
                        int vehicleRank = rankRawValue;

                        // Battle rating
                        double ratingRawValue = double.Parse(vehicleAttributes.Single(k => k.Key == "Rating").Value.ToString());
                        double vehicleBattleRating = ratingRawValue;

                        // Engine power
                        string enginePowerRawValue = vehicleAttributes.Single(k => k.Key == "Engine power").Value.ToString();
                        int enginePowerWithoutUnits = int.Parse(Regex.Match(enginePowerRawValue, @"\d+").Value);
                        string enginePowerUnitsAbbreviation = (Regex.Matches(enginePowerRawValue, @"\D+").Cast<Match>()).Last().Value.Trim();
                        VehicleEnginePowerUnitHelper vehicleEngineUnit = _vehicleEnginePowerUnitHelper.GetEngineUnitFromAbbreviation(enginePowerUnitsAbbreviation);

                        // Max speed
                        string maxSpeedRawValue = vehicleAttributes.Single(k => k.Key == "Max speed").Value.ToString();
                        double maxSpeedWithoutUnits = double.Parse(Regex.Match(maxSpeedRawValue, @"\d+\.*\d*").Value);
                        string maxSpeedUnits = (Regex.Matches(maxSpeedRawValue, @"\D+").Cast<Match>()).Last().Value.Trim();
                        VehicleSpeedUnitHelper vehicleSpeedUnit = _vehicleSpeedUnitHelper.GetSpeedUnitFromAbbreviation(maxSpeedUnits);

                        // Hull armour
                        string hullArmourRawValue = vehicleAttributes.Single(k => k.Key == "Hull armour thickness").Value.ToString();
                        string vehicleHullArmourThickness = hullArmourRawValue;

                        // Superstructure armour
                        string superstructureArmourRawValue = vehicleAttributes.Single(k => k.Key == "Superstructure armour thickness").Value.ToString();
                        string vehicleSuperstructureArmourThickness = superstructureArmourRawValue;

                        // Repair time
                        string freeRepairTimeRawValue = vehicleAttributes.Single(k => k.Key == "Time for free repair").Value.ToString();
                        List<Match> freeRepairTimeList = (Regex.Matches(freeRepairTimeRawValue, @"\d+").Cast<Match>()).ToList();
                        int freeRepairTimeHours = int.Parse(freeRepairTimeList.First().Value);
                        int freeRepairTimeMinutes = int.Parse(freeRepairTimeList.Last().Value);
                        TimeSpan vehicleFreeRepairTime = new TimeSpan(freeRepairTimeHours, freeRepairTimeMinutes, 0);

                        // Max repair cost
                        string maxRepairCostRawValue = vehicleAttributes.Single(k => k.Key == "Max repair cost*").Value.ToString();
                        string maxRepairCostWithoutUnits = Regex.Match(maxRepairCostRawValue, @"\d+").Value;
                        string maxRepairCostUnits = (Regex.Matches(maxRepairCostRawValue, @"\D+").Cast<Match>()).Last().Value.Trim();
                        long vehicleMaxRepairCost = long.Parse(maxRepairCostWithoutUnits);
                        VehicleCostUnitHelper vehicleRepairCostUnit = _vehicleCostUnitHelper.GetCostUnitFromAbbreviation(maxRepairCostUnits);

                        // Purchase cost
                        string purchaseCostRawValue = vehicleAttributes.Single(k => k.Key == "Cost*").Value.ToString();
                        string purchaseCostWithoutUnits = Regex.Match(purchaseCostRawValue, @"\d+").Value;
                        string purchaseCostUnits = (Regex.Matches(purchaseCostRawValue, @"\D+").Cast<Match>()).Last().Value.Trim();
                        long vehiclePurchaseCost = long.Parse(purchaseCostWithoutUnits);
                        VehicleCostUnitHelper vehiclePurchaseCostUnit = _vehicleCostUnitHelper.GetCostUnitFromAbbreviation(purchaseCostUnits);

                        // Last modified
                        HtmlNode lastModifiedSection = vehicleWikiPage.DocumentNode.Descendants().SingleOrDefault(x => x.Id == ConfigurationManager.AppSettings["LastModifiedSectionId"]);
                        string lastModified = lastModifiedSection?.InnerHtml;

                        // Populate objects
                        GroundVehicle groundVehicle = new GroundVehicle
                        {
                            Name = vehicleName,
                            Country = vehicleCountry,
                            Weight = weightWithoutUnits,
                            VehicleType = (VehicleTypeEnum)vehicleType.Id,
                            Rank = vehicleRank,
                            BattleRating = vehicleBattleRating,
                            EnginePower = enginePowerWithoutUnits,
                            MaxSpeed = maxSpeedWithoutUnits,
                            HullArmourThickness = vehicleHullArmourThickness,
                            SuperstructureArmourThickness = vehicleSuperstructureArmourThickness,
                            TimeForFreeRepair = vehicleFreeRepairTime,
                            MaxRepairCost = vehicleMaxRepairCost,
                            PurchaseCost = vehiclePurchaseCost,
                            PurchaseCostUnit = vehiclePurchaseCostUnit,
                            MaxRepairCostUnit = vehicleRepairCostUnit,
                            MaxSpeedUnit = vehicleSpeedUnit,
                            WeightUnit = vehicleWeightUnit,
                            EnginePowerUnit = vehicleEngineUnit,
                            LastModified = lastModified
                        };

                        // Update the local storage if requested
                        if (createJsonFiles)
                        {
                            _logger.UpdateLocalStorageForOfflineUse(localFileChanges, vehicleWikiPage, vehicleName, LocalWikiFileTypeEnum.JSON, groundVehicle);
                        }

                        if (createHtmlFiles)
                        {
                            _logger.UpdateLocalStorageForOfflineUse(localFileChanges, vehicleWikiPage, vehicleName, LocalWikiFileTypeEnum.HTML, null);
                        }

                        //WikiEntry entry = new WikiEntry(vehicleName, vehicleWikiEntryFullUrl, VehicleTypeEnum.Ground, vehicleInfo);

                        // Add the found information to the master list
                        vehicleDetails.Add(vehicleName, groundVehicle);

                        _consoleManager.WriteLineInColour(ConsoleColor.Green, $"Processed item {indexPosition} of {expectedNumberOfLinks} successfully");
                        _consoleManager.WriteBlankLine();
                    }

                    indexPosition++;
                }

                if (createExcelFile)
                {
                    _excelLogger.CreateExcelFile(vehicleDetails);
                }
            }
            catch (Exception ex)
            {
                _consoleManager.WriteException(ex.Message);
            }
        }
Example #29
0
        static void Main()
        {
            var connectedPlayers = 0;

            var config = new NetPeerConfiguration("romero");
            config.EnableMessageType(NetIncomingMessageType.DiscoveryRequest);
            config.Port = 14242;

            var PlayerNames = new Dictionary<long, string>();

            //var xinput = 0;
            //var yinput = 0;
            var dummyName = string.Empty;
            float angle = 0;

            // create and start server
            var server = new NetServer(config);
            server.Start();
            Console.WriteLine("Server online");

            // schedule initial sending of position updates
            var nextSendUpdates = NetTime.Now;

            // run until escape is pressed
            while (!Console.KeyAvailable || Console.ReadKey().Key != ConsoleKey.Escape)
            {
                NetIncomingMessage msg;
                while ((msg = server.ReadMessage()) != null)
                {


                    switch (msg.MessageType)
                    {
                        case NetIncomingMessageType.DiscoveryRequest:
                            //
                            // Server received a discovery request from a client; send a discovery response (with no extra data attached)
                            //
                            var om = server.CreateMessage();

                            if (connectedPlayers < 4)
                            {
                                om.Write(true);
                                server.SendDiscoveryResponse(om, msg.SenderEndpoint);

                            }
                            else
                            {
                                om.Write(false);
                                server.SendDiscoveryResponse(om, msg.SenderEndpoint);
                            }

                            break;
                        case NetIncomingMessageType.VerboseDebugMessage:
                        case NetIncomingMessageType.DebugMessage:
                        case NetIncomingMessageType.WarningMessage:
                        case NetIncomingMessageType.ErrorMessage:
                            //
                            // Just print diagnostic messages to console
                            //
                            Console.WriteLine(msg.ReadString());
                            break;
                        case NetIncomingMessageType.StatusChanged:
                            var status = (NetConnectionStatus)msg.ReadByte();

                            if (status == NetConnectionStatus.Connected)
                            {
                                //
                                // A new player just connected!
                                //

                                Console.WriteLine(msg.SenderConnection.RemoteUniqueIdentifier + " connected. (IP Address: " + msg.SenderEndpoint.Address + ")");
                                connectedPlayers++;
                                Console.WriteLine(connectedPlayers + " players ingame");
                            };

                            if (status == NetConnectionStatus.Disconnected)
                            {
                                Console.WriteLine(msg.SenderConnection.RemoteUniqueIdentifier + " disconnected. (IP Address: " + msg.SenderEndpoint.Address + ")");
                                connectedPlayers--;
                                Console.WriteLine(connectedPlayers + " players ingame");
                            }


                            break;
                        case NetIncomingMessageType.Data:
                            //
                            // The client sent input to the server
                            //

                            dummyName = msg.ReadString();
                            if (!PlayerNames.ContainsKey(msg.SenderConnection.RemoteUniqueIdentifier))
                            {
                                  PlayerNames.Add(msg.SenderConnection.RemoteUniqueIdentifier, dummyName);
                            }
                          

                            // fancy movement logic goes here

                            var xinput = msg.ReadInt32();
                            var yinput = msg.ReadInt32();
                            var playerAngle = msg.ReadFloat();

                            var pos = msg.SenderConnection.Tag as float[];

                            if (pos != null)
                            {
                                pos[0] = xinput;
                                pos[1] = yinput;
                                pos[2] = playerAngle;
                            }


                            break;

                    }

                    //
                    // send position updates 60 times per second
                    //
                    var now = NetTime.Now;
                    if (now > nextSendUpdates)
                    {
                        // Yes, it's time to send position updates

                        // for each player...


                        foreach (var player in server.Connections)
                        {
                            // ... send information about every other player (actually including self)
                            foreach (var otherPlayer in server.Connections)
                            {
                                // send position update about 'otherPlayer' to 'player'
                                var om = server.CreateMessage();
                                if (otherPlayer != null)
                                {
                                    // write who this position is for
                                    om.Write(otherPlayer.RemoteUniqueIdentifier);
                                    if (PlayerNames.ContainsKey(otherPlayer.RemoteUniqueIdentifier))
                                    {
                                        om.Write(PlayerNames.Single(i => i.Key == otherPlayer.RemoteUniqueIdentifier).Value);
                                    }


                                    if (otherPlayer.Tag == null)
                                        otherPlayer.Tag = new float[3];

                                    var pos = otherPlayer.Tag as float[];

                                    om.Write(pos[0]);
                                    om.Write(pos[1]);
                                    om.Write(pos[2]);

                                    // send message
                                    server.SendMessage(om, player, NetDeliveryMethod.Unreliable);
                                }

                            }
                        }

                        // schedule next update
                        nextSendUpdates += (1.0 / 60.0);
                    }
                }

                // sleep to allow other processes to run smoothly
                Thread.Sleep(1);
            }
            Console.WriteLine("Server powering down..");
            server.Shutdown("bye");
        }
Example #30
0
 private static string GetDictValue(Dictionary<string, string> dictionary, string key)
 {
     return dictionary.Single(kv => kv.Key.Replace("\"", string.Empty) == key).Value;
 }