Exile Linq to DEBUG only. exp
Exile Linq to DEBUG only.

// VOID_CareerTracker // VOID_CareerTracker
// //
// VCT_Master.cs // VCT_Master.cs
// //
// Copyright © 2015, toadicus // Copyright © 2015, toadicus
// All rights reserved. // All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, // Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met: // are permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, // 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer. // this list of conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, // 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation and/or other // this list of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution. // materials provided with the distribution.
// //
// 3. Neither the name of the copyright holder nor the names of its contributors may be used // 3. Neither the name of the copyright holder nor the names of its contributors may be used
// to endorse or promote products derived from this software without specific prior written permission. // to endorse or promote products derived from this software without specific prior written permission.
// //
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   
using KSP; using KSP;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using ToadicusTools.Extensions; using ToadicusTools.Extensions;
using UnityEngine; using UnityEngine;
using VOID; using VOID;
  #if DEBUG
  using System.Linq;
  #endif
   
namespace VOID.VOID_CareerTracker namespace VOID.VOID_CareerTracker
{ {
[KSPScenario( [KSPScenario(
ScenarioCreationOptions.AddToNewCareerGames | ScenarioCreationOptions.AddToExistingCareerGames, ScenarioCreationOptions.AddToNewCareerGames | ScenarioCreationOptions.AddToExistingCareerGames,
GameScenes.SPACECENTER, GameScenes.EDITOR, GameScenes.FLIGHT, GameScenes.TRACKSTATION GameScenes.SPACECENTER, GameScenes.EDITOR, GameScenes.FLIGHT, GameScenes.TRACKSTATION
)] )]
public class VCTScenario : ScenarioModule public class VCTScenario : ScenarioModule
{ {
#region Static Members #region Static Members
private const string TRANSACTION_KEY = "CURRENCY_TRANSACTION"; private const string TRANSACTION_KEY = "CURRENCY_TRANSACTION";
private const string NEWGAME_KEY = "NewGame"; private const string NEWGAME_KEY = "NewGame";
   
public static VCTScenario Instance public static VCTScenario Instance
{ {
get; get;
private set; private set;
} }
   
public static IList<CurrencyTransaction> GetTransactionList public static IList<CurrencyTransaction> GetTransactionList
{ {
get get
{ {
if (VCTScenario.Instance != null) if (VCTScenario.Instance != null)
{ {
return VCTScenario.Instance.TransactionList; return VCTScenario.Instance.TransactionList;
} }
else else
{ {
return new List<CurrencyTransaction>().AsReadOnly(); return new List<CurrencyTransaction>().AsReadOnly();
} }
} }
} }
#endregion #endregion
   
private bool isNewGame; private bool isNewGame;
   
private List<CurrencyTransaction> transactionDatabase; private List<CurrencyTransaction> transactionDatabase;
private List<CurrencyTransaction> fundingTransactions; private List<CurrencyTransaction> fundingTransactions;
private List<CurrencyTransaction> scienceTransactions; private List<CurrencyTransaction> scienceTransactions;
private List<CurrencyTransaction> reputationTransactions; private List<CurrencyTransaction> reputationTransactions;
   
public IList<CurrencyTransaction> TransactionList public IList<CurrencyTransaction> TransactionList
{ {
get get
{ {
return this.transactionDatabase.AsReadOnly(); return this.transactionDatabase.AsReadOnly();
} }
} }
   
public IList<CurrencyTransaction> FundingTranscations public IList<CurrencyTransaction> FundingTranscations
{ {
get get
{ {
return this.fundingTransactions.AsReadOnly(); return this.fundingTransactions.AsReadOnly();
} }
} }
   
public IList<CurrencyTransaction> ScienceTransactions public IList<CurrencyTransaction> ScienceTransactions
{ {
get get
{ {
return this.scienceTransactions.AsReadOnly(); return this.scienceTransactions.AsReadOnly();
} }
} }
   
public IList<CurrencyTransaction> ReputationTransations public IList<CurrencyTransaction> ReputationTransations
{ {
get get
{ {
return this.reputationTransactions.AsReadOnly(); return this.reputationTransactions.AsReadOnly();
} }
} }
   
public double CurrentFunds public double CurrentFunds
{ {
get; get;
private set; private set;
} }
   
public float CurrentScience public float CurrentScience
{ {
get; get;
private set; private set;
} }
   
public float CurrentReputation public float CurrentReputation
{ {
get; get;
private set; private set;
} }
   
#region ScenarioModule Overrides #region ScenarioModule Overrides
public override void OnAwake() public override void OnAwake()
{ {
VCTScenario.Instance = this; VCTScenario.Instance = this;
   
this.isNewGame = true; this.isNewGame = true;
   
base.OnAwake(); base.OnAwake();
   
this.transactionDatabase = new List<CurrencyTransaction>(); this.transactionDatabase = new List<CurrencyTransaction>();
this.fundingTransactions = new List<CurrencyTransaction>(); this.fundingTransactions = new List<CurrencyTransaction>();
this.scienceTransactions = new List<CurrencyTransaction>(); this.scienceTransactions = new List<CurrencyTransaction>();
this.reputationTransactions = new List<CurrencyTransaction>(); this.reputationTransactions = new List<CurrencyTransaction>();
   
GameEvents.Modifiers.OnCurrencyModified.Add(this.OnCurrencyModifiedHandler); GameEvents.Modifiers.OnCurrencyModified.Add(this.OnCurrencyModifiedHandler);
GameEvents.OnFundsChanged.Add(this.OnFundsChangedHandler); GameEvents.OnFundsChanged.Add(this.OnFundsChangedHandler);
GameEvents.OnScienceChanged.Add(this.OnScienceChangedHandler); GameEvents.OnScienceChanged.Add(this.OnScienceChangedHandler);
GameEvents.OnReputationChanged.Add(this.OnReputationChangedHandler); GameEvents.OnReputationChanged.Add(this.OnReputationChangedHandler);
} }
   
public override void OnLoad(ConfigNode node) public override void OnLoad(ConfigNode node)
{ {
base.OnLoad(node); base.OnLoad(node);
   
ConfigNode[] transNodes = node.GetNodes(TRANSACTION_KEY); ConfigNode[] transNodes = node.GetNodes(TRANSACTION_KEY);
ConfigNode transNode; ConfigNode transNode;
for (int idx = 0; idx < transNodes.Length; idx++) for (int idx = 0; idx < transNodes.Length; idx++)
{ {
transNode = transNodes[idx]; transNode = transNodes[idx];
   
CurrencyTransaction trans = new CurrencyTransaction(); CurrencyTransaction trans = new CurrencyTransaction();
   
trans.Load(transNode); trans.Load(transNode);
   
this.AddTransaction(trans); this.AddTransaction(trans);
} }
   
CurrencyTransaction.TransactionSorter sorter = new CurrencyTransaction.TransactionSorter( CurrencyTransaction.TransactionSorter sorter = new CurrencyTransaction.TransactionSorter(
CurrencyTransaction.TransactionSorter.SortType.Time, CurrencyTransaction.TransactionSorter.SortType.Time,
CurrencyTransaction.TransactionSorter.SortOrder.Ascending CurrencyTransaction.TransactionSorter.SortOrder.Ascending
); );
   
this.transactionDatabase.Sort(sorter); this.transactionDatabase.Sort(sorter);
this.fundingTransactions.Sort(sorter); this.fundingTransactions.Sort(sorter);
this.scienceTransactions.Sort(sorter); this.scienceTransactions.Sort(sorter);
this.reputationTransactions.Sort(sorter); this.reputationTransactions.Sort(sorter);
   
this.isNewGame = node.GetValue(NEWGAME_KEY, this.isNewGame); this.isNewGame = node.GetValue(NEWGAME_KEY, this.isNewGame);
   
if (this.isNewGame) if (this.isNewGame)
{ {
this.RebalanceDatabase(); this.RebalanceDatabase();
} }
   
this.Log("Loaded.\n{0}", this.ToString()); this.Log("Loaded.\n{0}", this.ToString());
} }
   
public override void OnSave(ConfigNode node) public override void OnSave(ConfigNode node)
{ {
base.OnSave(node); base.OnSave(node);
   
node.ClearNodes(); node.ClearNodes();
   
CurrencyTransaction trans; CurrencyTransaction trans;
for (int idx = 0; idx < this.transactionDatabase.Count; idx++) for (int idx = 0; idx < this.transactionDatabase.Count; idx++)
{ {
trans = this.transactionDatabase[idx]; trans = this.transactionDatabase[idx];
   
ConfigNode transNode = new ConfigNode(TRANSACTION_KEY); ConfigNode transNode = new ConfigNode(TRANSACTION_KEY);
   
trans.Save(transNode); trans.Save(transNode);
   
node.AddNode(transNode); node.AddNode(transNode);
} }
   
if (node.HasValue(NEWGAME_KEY)) if (node.HasValue(NEWGAME_KEY))
{ {
node.SetValue(NEWGAME_KEY, bool.FalseString); node.SetValue(NEWGAME_KEY, bool.FalseString);
} }
else else
{ {
node.AddValue(NEWGAME_KEY, bool.FalseString); node.AddValue(NEWGAME_KEY, bool.FalseString);
} }
   
this.Log("Saved."); this.Log("Saved.");
} }
   
public override string ToString() public override string ToString()
{ {
return string.Format( return string.Format(
"[VCT_Master]: CurrentFunds={1}, CurrentScience={2}, CurrentReputation={3}, transctionDatabase {0}", "[VCT_Master]: CurrentFunds={1}, CurrentScience={2}, CurrentReputation={3}, transctionDatabase {0}",
#if DEBUG #if DEBUG
string.Format("\n\t{0}", string.Format("\n\t{0}",
string.Join("\n\t", this.transactionDatabase.Select(t => t.ToString()).ToArray())), string.Join("\n\t", this.transactionDatabase.Select(t => t.ToString()).ToArray())),
#else #else
string.Format("contains {0} Transactions", this.transactionDatabase.Count), string.Format("contains {0} Transactions", this.transactionDatabase.Count),
#endif #endif
CurrentFunds, CurrentFunds,
CurrentScience, CurrentScience,
CurrentReputation CurrentReputation
); );
} }
#endregion #endregion
   
#region MonoBehaviour LifeCycle Methods #region MonoBehaviour LifeCycle Methods
public void OnDestroy() public void OnDestroy()
{ {
GameEvents.Modifiers.OnCurrencyModified.Remove(this.OnCurrencyModifiedHandler); GameEvents.Modifiers.OnCurrencyModified.Remove(this.OnCurrencyModifiedHandler);
GameEvents.OnFundsChanged.Remove(this.OnFundsChangedHandler); GameEvents.OnFundsChanged.Remove(this.OnFundsChangedHandler);
GameEvents.OnScienceChanged.Remove(this.OnScienceChangedHandler); GameEvents.OnScienceChanged.Remove(this.OnScienceChangedHandler);
GameEvents.OnReputationChanged.Remove(this.OnReputationChangedHandler); GameEvents.OnReputationChanged.Remove(this.OnReputationChangedHandler);
   
VCTScenario.Instance = null; VCTScenario.Instance = null;
} }
#endregion #endregion
   
#region Event Handlers #region Event Handlers
public void OnCurrencyModifiedHandler(CurrencyModifierQuery query) public void OnCurrencyModifiedHandler(CurrencyModifierQuery query)
{ {
this.AddTransaction(query); this.AddTransaction(query);
} }
   
public void OnFundsChangedHandler(double funds, TransactionReasons reason) public void OnFundsChangedHandler(double funds, TransactionReasons reason)
{ {
if (funds != this.CurrentFunds) if (funds != this.CurrentFunds)
{ {
if (Math.Abs(funds - this.CurrentFunds) < 0.01) if (Math.Abs(funds - this.CurrentFunds) < 0.01)
{ {
this.CurrentFunds = funds; this.CurrentFunds = funds;
return; return;
} }
   
CurrencyTransaction correction = new CurrencyTransaction( CurrencyTransaction correction = new CurrencyTransaction(
Planetarium.GetUniversalTime(), Planetarium.GetUniversalTime(),
TransactionReasons.None, TransactionReasons.None,
(float)(funds - this.CurrentFunds), (float)(funds - this.CurrentFunds),
0f, 0f,
0f 0f
); );
   
this.AddTransaction(correction); this.AddTransaction(correction);
   
this.Log("Detected discrepancy in funds totals: admin shows {0}, VCT shows {1}; correcting with {2}.", this.Log("Detected discrepancy in funds totals: admin shows {0}, VCT shows {1}; correcting with {2}.",
funds, funds,
this.CurrentFunds, this.CurrentFunds,
correction correction
); );
} }
} }
   
public void OnScienceChangedHandler(float science, TransactionReasons reason) public void OnScienceChangedHandler(float science, TransactionReasons reason)
{ {
if (science != this.CurrentScience) if (science != this.CurrentScience)
{ {
if (Mathf.Abs(science - this.CurrentScience) < 0.01) if (Mathf.Abs(science - this.CurrentScience) < 0.01)
{ {
this.CurrentScience = science; this.CurrentScience = science;
return; return;
} }
   
CurrencyTransaction correction = new CurrencyTransaction( CurrencyTransaction correction = new CurrencyTransaction(
Planetarium.GetUniversalTime(), Planetarium.GetUniversalTime(),
TransactionReasons.None, TransactionReasons.None,
0f, 0f,
science - this.CurrentScience, science - this.CurrentScience,
0f 0f
); );
   
this.AddTransaction(correction); this.AddTransaction(correction);
   
this.Log("Detected discrepancy in science totals: R&D shows {0}, VCT shows {1}; correcting with {2}.", this.Log("Detected discrepancy in science totals: R&D shows {0}, VCT shows {1}; correcting with {2}.",
science, science,
this.CurrentScience, this.CurrentScience,
correction correction
); );
} }
} }
   
public void OnReputationChangedHandler(float reputation, TransactionReasons reason) public void OnReputationChangedHandler(float reputation, TransactionReasons reason)
{ {
if (reputation != this.CurrentReputation) if (reputation != this.CurrentReputation)
{ {
if (Mathf.Abs(reputation - this.CurrentReputation) < 0.01) if (Mathf.Abs(reputation - this.CurrentReputation) < 0.01)
{ {
this.CurrentReputation = reputation; this.CurrentReputation = reputation;
return; return;
} }
   
CurrencyTransaction correction = new CurrencyTransaction( CurrencyTransaction correction = new CurrencyTransaction(
Planetarium.GetUniversalTime(), Planetarium.GetUniversalTime(),
TransactionReasons.None, TransactionReasons.None,
0f, 0f,
0f, 0f,
reputation - this.CurrentReputation reputation - this.CurrentReputation
); );
   
this.AddTransaction(correction); this.AddTransaction(correction);
   
this.Log("Detected discrepancy in rep totals: admin shows {0}, VCT shows {1}; correcting with {2}.", this.Log("Detected discrepancy in rep totals: admin shows {0}, VCT shows {1}; correcting with {2}.",
reputation, reputation,
this.CurrentReputation, this.CurrentReputation,
correction correction
); );
} }
} }
#endregion #endregion
   
#region Utility Methods #region Utility Methods
internal void AddTransaction(CurrencyTransaction transaction) internal void AddTransaction(CurrencyTransaction transaction)
{ {
if (transaction.FundsDelta == 0 && transaction.ScienceDelta == 0 && transaction.ReputationDelta == 0) if (transaction.FundsDelta == 0 && transaction.ScienceDelta == 0 && transaction.ReputationDelta == 0)
{ {
return; return;
} }
   
this.transactionDatabase.Add(transaction); this.transactionDatabase.Add(transaction);
   
if (transaction.FundsDelta != 0f) if (transaction.FundsDelta != 0f)
{ {
this.fundingTransactions.Add(transaction); this.fundingTransactions.Add(transaction);
} }
   
if (transaction.ScienceDelta != 0f) if (transaction.ScienceDelta != 0f)
{ {
this.scienceTransactions.Add(transaction); this.scienceTransactions.Add(transaction);
} }
   
if (transaction.ReputationDelta != 0f) if (transaction.ReputationDelta != 0f)
{ {
this.reputationTransactions.Add(transaction); this.reputationTransactions.Add(transaction);
} }
   
this.CurrentFunds += (double)transaction.FundsDelta; this.CurrentFunds += (double)transaction.FundsDelta;
this.CurrentScience += transaction.ScienceDelta; this.CurrentScience += transaction.ScienceDelta;
this.CurrentReputation += transaction.ReputationDelta; this.CurrentReputation += transaction.ReputationDelta;
   
this.LogDebug("Added transaction: {0}", transaction); this.LogDebug("Added transaction: {0}", transaction);
} }
   
internal void AddTransaction(CurrencyModifierQuery query) internal void AddTransaction(CurrencyModifierQuery query)
{ {
CurrencyTransaction transaction = new CurrencyTransaction(Planetarium.GetUniversalTime(), query); CurrencyTransaction transaction = new CurrencyTransaction(Planetarium.GetUniversalTime(), query);
   
this.AddTransaction(transaction); this.AddTransaction(transaction);
} }
   
internal void RebalanceDatabase() internal void RebalanceDatabase()
{ {
this.CurrentFunds = 0f; this.CurrentFunds = 0f;
   
CurrencyTransaction trans; CurrencyTransaction trans;
for (int idx = 0; idx < this.transactionDatabase.Count; idx++) for (int idx = 0; idx < this.transactionDatabase.Count; idx++)
{ {
trans = this.transactionDatabase[idx]; trans = this.transactionDatabase[idx];
this.CurrentFunds += trans.FundsDelta; this.CurrentFunds += trans.FundsDelta;
} }
   
this.OnFundsChangedHandler(Funding.Instance.Funds, TransactionReasons.None); this.OnFundsChangedHandler(Funding.Instance.Funds, TransactionReasons.None);
   
this.CurrentScience = 0f; this.CurrentScience = 0f;
   
for (int idx = 0; idx < this.transactionDatabase.Count; idx++) for (int idx = 0; idx < this.transactionDatabase.Count; idx++)
{ {
trans = this.transactionDatabase[idx]; trans = this.transactionDatabase[idx];
this.CurrentScience += trans.ScienceDelta; this.CurrentScience += trans.ScienceDelta;
} }
   
this.OnScienceChangedHandler(ResearchAndDevelopment.Instance.Science, TransactionReasons.None); this.OnScienceChangedHandler(ResearchAndDevelopment.Instance.Science, TransactionReasons.None);
   
this.CurrentReputation = 0f; this.CurrentReputation = 0f;
   
for (int idx = 0; idx < this.transactionDatabase.Count; idx++) for (int idx = 0; idx < this.transactionDatabase.Count; idx++)
{ {
trans = this.transactionDatabase[idx]; trans = this.transactionDatabase[idx];
this.CurrentReputation += trans.ReputationDelta; this.CurrentReputation += trans.ReputationDelta;
} }
   
this.OnReputationChangedHandler(Reputation.Instance.reputation, TransactionReasons.None); this.OnReputationChangedHandler(Reputation.Instance.reputation, TransactionReasons.None);
} }
#endregion #endregion
} }
} }