Exemplo n.º 1
0
        /// <summary>
        /// Checks if the "extended" requirements that change due to expressions.
        /// </summary>
        /// <param name="contract">The contract</param>
        /// <returns>Whether the contract can be offered.</returns>
        public bool MeetExtendedRequirements(ConfiguredContract contract, ContractType contractType)
        {
            LoggingUtil.LogLevel origLogLevel = LoggingUtil.logLevel;
            try
            {
                // Turn tracing on
                if (trace)
                {
                    LoggingUtil.logLevel = LoggingUtil.LogLevel.VERBOSE;
                    LoggingUtil.LogWarning(this, "Tracing enabled for contract type " + name);
                }

                // Hash check
                if (contract.ContractState == Contract.State.Offered && contract.hash != hash)
                {
                    throw new ContractRequirementException("Contract definition changed.");
                }

                // Check prestige
                if (prestige.Count > 0 && !prestige.Contains(contract.Prestige))
                {
                    throw new ContractRequirementException("Wrong prestige level.");
                }

                // Do a Research Bodies check, if applicable
                ResearchBodiesCheck(contract);

                // Check special values are not null
                if (contract.contractType == null)
                {
                    foreach (KeyValuePair <string, DataValueInfo> pair in dataValues)
                    {
                        // Only check if it is a required value
                        if (pair.Value.required)
                        {
                            CheckRequiredValue(pair.Key);
                        }
                    }
                }

                if (contract.contractType == null || contract.ContractState == Contract.State.Generated || contract.ContractState == Contract.State.Withdrawn)
                {
                    // Check for unique values against other contracts of the same type
                    foreach (KeyValuePair <string, DataNode.UniquenessCheck> pair in uniquenessChecks.Where(p => contract.uniqueData.ContainsKey(p.Key)))
                    {
                        string key = pair.Key;
                        DataNode.UniquenessCheck uniquenessCheck = pair.Value;

                        LoggingUtil.LogVerbose(this, "Doing unique value check for " + key);

                        // Get the active/offered contract lists
                        IEnumerable <ConfiguredContract> contractList = ConfiguredContract.CurrentContracts.
                                                                        Where(c => c != null && c.contractType != null && c != contract);

                        // Add in finished contracts
                        if (uniquenessCheck == DataNode.UniquenessCheck.CONTRACT_ALL || uniquenessCheck == DataNode.UniquenessCheck.GROUP_ALL)
                        {
                            contractList = contractList.Union(ContractSystem.Instance.ContractsFinished.OfType <ConfiguredContract>().
                                                              Where(c => c != null && c.contractType != null && c != contract));
                        }

                        // Filter anything that doesn't have our key
                        contractList = contractList.Where(c => c.uniqueData.ContainsKey(key));

                        // Check for contracts of the same type
                        if (uniquenessCheck == DataNode.UniquenessCheck.CONTRACT_ALL || uniquenessCheck == DataNode.UniquenessCheck.CONTRACT_ACTIVE)
                        {
                            contractList = contractList.Where(c => c.contractType.name == name);
                        }
                        // Check for a shared group
                        else if (contractType.group != null)
                        {
                            contractList = contractList.Where(c => c.contractType.group != null && c.contractType.group.name == contractType.group.name);
                        }
                        // Shared lack of group
                        else
                        {
                            contractList = contractList.Where(c => c.contractType.group == null);
                        }

                        object val = contract.uniqueData[key];
                        if (val != null)
                        {
                            // Special case for vessels - convert to the Guid
                            Vessel vessel = val as Vessel;
                            if (vessel != null)
                            {
                                val = vessel.id;
                            }

                            foreach (ConfiguredContract otherContract in contractList)
                            {
                                if (val.Equals(otherContract.uniqueData[key]))
                                {
                                    throw new ContractRequirementException("Failed on unique value check for key '" + key + "'.");
                                }
                            }
                        }
                    }
                }

                // Check the captured requirements
                if (!ContractRequirement.RequirementsMet(contract, this, contract.requirements != null ? contract.requirements : requirements))
                {
                    throw new ContractRequirementException("Failed on contract requirement check.");
                }

                return(true);
            }
            catch (ContractRequirementException e)
            {
                LoggingUtil.LogLevel level = contract.ContractState == Contract.State.Active ? LoggingUtil.LogLevel.INFO : contract.contractType != null ? LoggingUtil.LogLevel.DEBUG : LoggingUtil.LogLevel.VERBOSE;
                string prefix = contract.contractType != null ? "Cancelling contract of type " + name + " (" + contract.Title + "): " :
                                "Didn't generate contract of type " + name + ": ";
                LoggingUtil.Log(level, this.GetType(), prefix + e.Message);
                return(false);
            }
            catch
            {
                LoggingUtil.LogError(this, "Exception while attempting to check requirements of contract type " + name);
                throw;
            }
            finally
            {
                LoggingUtil.logLevel = origLogLevel;
                loaded = true;
            }
        }
Exemplo n.º 2
0
        protected static T SelectUnique(List <T> input)
        {
            // Check if there's no values
            if (input == null || !input.Any())
            {
                return(default(T));
            }

            // Get details from the base parser
            ContractType contractType = BaseParser.currentParser.currentDataNode.Root.Factory as ContractType;
            string       key          = BaseParser.currentParser.currentKey;

            DataNode.UniquenessCheck uniquenessCheck = contractType.uniquenessChecks.ContainsKey(key) ? contractType.uniquenessChecks[key] : DataNode.UniquenessCheck.NONE;
            DataNode dataNode = BaseParser.currentParser.currentDataNode;

            // Provide warning of a better method
            if (dataNode != null && dataNode.IsDeterministic(key) && (uniquenessCheck == DataNode.UniquenessCheck.CONTRACT_ALL || uniquenessCheck == DataNode.UniquenessCheck.CONTRACT_ACTIVE))
            {
                IContractConfiguratorFactory factory = BaseParser.currentParser.currentDataNode.Factory;
                LoggingUtil.LogWarning(factory, factory.ErrorPrefix() + ": Consider using a DATA_EXPAND node instead of the SelectUnique function when the values are deterministic - this will cause the player to see the full set of values in mission control before the contract is offered.");
            }

            // Check for properly uniquness check
            if (uniquenessCheck == DataNode.UniquenessCheck.NONE)
            {
                throw new NotSupportedException("The SelectUnique method can only be used in DATA nodes with the uniquenessCheck attribute set.");
            }

            // Get the active/offered contract lists
            IEnumerable <ConfiguredContract> contractList = ConfiguredContract.CurrentContracts.
                                                            Where(c => c != null && c.contractType != null);

            // Add in finished contracts
            if (uniquenessCheck == DataNode.UniquenessCheck.CONTRACT_ALL || uniquenessCheck == DataNode.UniquenessCheck.GROUP_ALL)
            {
                contractList = contractList.Union(ConfiguredContract.CompletedContracts.
                                                  Where(c => c != null && c.contractType != null));
            }

            // Filter anything that doesn't have our key
            contractList = contractList.Where(c => c.uniqueData.ContainsKey(key));

            // Check for contracts of the same type
            if (uniquenessCheck == DataNode.UniquenessCheck.CONTRACT_ALL || uniquenessCheck == DataNode.UniquenessCheck.CONTRACT_ACTIVE)
            {
                contractList = contractList.Where(c => c.contractType.name == contractType.name);
            }
            // Check for a shared group
            else if (contractType.group != null)
            {
                contractList = contractList.Where(c => c.contractType.group != null && c.contractType.group.name == contractType.group.name);
            }
            // Shared lack of group
            else
            {
                contractList = contractList.Where(c => c.contractType.group == null);
            }

            // Get the valid values
            IEnumerable <T> values;

            // Special case for vessels
            if (typeof(T) == typeof(Vessel))
            {
                values = input.Where(t => !contractList.Any(c => c.uniqueData[key].Equals(((Vessel)(object)t).id)));
            }
            else
            {
                values = input.Where(t => !contractList.Any(c => c.uniqueData[key].Equals(t)));
            }

            // Make a random selection from what's left
            return(values.Skip(r.Next(values.Count())).FirstOrDefault());
        }