<commit_before>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
//using System.Threading.Tasks;
using UnityEngine;
using System.IO;

namespace PersistentTrails
{
    public static class CraftLoader
    {
        public static List<PartValue> getParts(Vessel vessel, bool fetchModel)
        {
            List<PartValue> partList = new List<PartValue>();
            Vector3 rootPosition;
            Quaternion rootRotation;
            Transform referenceFrame = new GameObject().transform;
            Transform localTransform = new GameObject().transform;
            localTransform.parent = referenceFrame;
            if (vessel != null)
            {
                if (vessel.parts.Count > 0)
                {
                    //Debug.Log("vessel parts: " + vessel.parts.Count);
                    rootPosition = vessel.parts[0].transform.position;
                    rootRotation = vessel.parts[0].transform.rotation;
                    Quaternion worldUp = Quaternion.Euler((vessel.rigidbody.position - vessel.mainBody.position).normalized);
                    referenceFrame.position = vessel.transform.position;
                    referenceFrame.rotation = vessel.transform.rotation;
                    foreach (Part part in vessel.parts)
                    {
                        PartValue newPartValue = new PartValue();
                        newPartValue.scale = 1f / part.scaleFactor;
                        localTransform.rotation = part.transform.rotation;
                        localTransform.position = part.transform.position;
                        newPartValue.position = localTransform.localPosition;
                        newPartValue.rotation = localTransform.localRotation;
                        newPartValue.partName = part.name.Split(' ')[0];
                        if (fetchModel) newPartValue.model = findPartModel(newPartValue.partName);
                        partList.Add(newPartValue);
                    }
                    //Debug.Log("partList count: " + partList.Count);
                }
            }
            return partList;
        }        

        private static string serialize()
        {
            StringBuilder output = new StringBuilder();
            output.AppendLine(Utilities.craftFileFormat.ToString());
            foreach (PartValue value in getParts(FlightGlobals.ActiveVessel, false))
            {
                output.AppendLine(value.partName);
                output.AppendLine(Utilities.Vector3ToString(value.position));
                output.AppendLine(Utilities.QuaternionToString(value.rotation));
                output.AppendLine(value.scale.ToString());
            }
            output.Append("[EOF]");
            return output.ToString();
        }        

        public static void saveCraftToFile()
        {
            StreamWriter stream = new StreamWriter(Utilities.CraftPath + FlightGlobals.ActiveVessel.vesselName + ".crf");
            stream.WriteLine(serialize());
            stream.Close(); 
        }

        public static List<PartValue> loadCraftFromFile(string fileName)
        {
            List<PartValue> loadedList = new List<PartValue>();
            PartValue newValue = new PartValue();
            StreamReader stream = new StreamReader(fileName); // exceptions handled by assembleCraft
            string newLine = string.Empty;
            int craftFileFormat = 0;
            int.TryParse(stream.ReadLine(), out craftFileFormat);
            Debug.Log(String.Concat("Loading crf file, format ", craftFileFormat, ", ", fileName));
            try
            {
                while (!stream.EndOfStream && !(newLine == "[EOF]"))
                {
                    newLine = stream.ReadLine();
                    newValue.partName = newLine;                    
                    newValue.position = Utilities.parseVector3(stream.ReadLine());
                    newValue.rotation = Utilities.parseQuaternion(stream.ReadLine());
                    float.TryParse(stream.ReadLine(), out newValue.scale);
                    //Debug.Log("finding model " + newValue.partName);
                    newValue.model = findPartModel(newValue.partName);
                    //Debug.Log("model null? " + (newValue.model == null));
                    loadedList.Add(newValue.clone());
                }                
            }
            catch (Exception e)
            {
                Debug.Log("load craft file error: " + e.ToString());
            }
            return loadedList;
        }

        public static GameObject assembleCraft(string craftName, bool collidersOn) // --- craftName not actually used yet. This should take a saved craft file name as input ---
        {
            GameObject craft = new GameObject();
            Debug.Log("asembling craft " + craftName);
            List<PartValue> pvList;
            //List<PartValue> pvList = getParts(FlightGlobals.ActiveVessel, true); // load the craft file here into a partValue list
            try
            {
                pvList = loadCraftFromFile(craftName);
            }
            catch
            {
                throw new FileNotFoundException("error loading craft from file", craftName);
            }
            foreach (PartValue pv in pvList)
            {
                //Debug.Log("pv.name is " + pv.partName);
                pv.model.SetActive(true);
                //Debug.Log("pv.model exists");
                pv.model.transform.parent = craft.transform;
                pv.model.transform.localPosition = pv.position;
                pv.model.transform.localRotation = pv.rotation;
                if (pv.scale > 7f) pv.scale /= 10f;
                if (pv.scale > 7f) pv.scale /= 10f; // twice to catch both 0.01 scale parts, and 0.1 scales. Gotta find a better way. Need to read the part cfg scale
                pv.model.transform.localScale = new Vector3(pv.scale, pv.scale, pv.scale);
                //Debug.Log("Part: " + pv.partName + "Scale: " + pv.scale + "/" + pv.model.transform.localScale);
                //Debug.Log("Part: " + pv.position);
                //Debug.Log("Part: " + pv.rotation);
                //Debug.Log("Part: " + pv.scale);
            }
            setColliderStateInChildren(craft, collidersOn);
            return craft;
        }

        public static GameObject findPartModel(string partName)
        {
            UrlDir.UrlConfig[] cfg = GameDatabase.Instance.GetConfigs("PART");
            //Debug.Log("looping through " + cfg.Length);<commit_msg>exclude launch clamps and strutconnectors<commit_after>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
//using System.Threading.Tasks;
using UnityEngine;
using System.IO;

namespace PersistentTrails
{
    public static class CraftLoader
    {
        public static List<PartValue> getParts(Vessel vessel, bool fetchModel)
        {
            List<PartValue> partList = new List<PartValue>();
            Vector3 rootPosition;
            Quaternion rootRotation;
            Transform referenceFrame = new GameObject().transform;
            Transform localTransform = new GameObject().transform;
            localTransform.parent = referenceFrame;
            if (vessel != null)
            {
                if (vessel.parts.Count > 0)
                {
                    //Debug.Log("vessel parts: " + vessel.parts.Count);
                    rootPosition = vessel.parts[0].transform.position;
                    rootRotation = vessel.parts[0].transform.rotation;
                    Quaternion worldUp = Quaternion.Euler((vessel.rigidbody.position - vessel.mainBody.position).normalized);
                    referenceFrame.position = vessel.transform.position;
                    referenceFrame.rotation = vessel.transform.rotation;
                    foreach (Part part in vessel.parts)
                    {
                        if (part.name != "launchClamp1" && part.partName != "StrutConnector")
                        {
                            Debug.Log("getParts: part.partName " + part.partName);
                            PartValue newPartValue = new PartValue();
                            newPartValue.scale = 1f / part.scaleFactor;
                            localTransform.rotation = part.transform.rotation;
                            localTransform.position = part.transform.position;
                            newPartValue.position = localTransform.localPosition;
                            newPartValue.rotation = localTransform.localRotation;
                            newPartValue.partName = part.name.Split(' ')[0];
                            if (fetchModel) newPartValue.model = findPartModel(newPartValue.partName);
                            partList.Add(newPartValue);
                        }
                    }
                    //Debug.Log("partList count: " + partList.Count);
                }
            }
            return partList;
        }        

        private static string serialize()
        {
            StringBuilder output = new StringBuilder();
            output.AppendLine(Utilities.craftFileFormat.ToString());
            foreach (PartValue value in getParts(FlightGlobals.ActiveVessel, false))
            {
                output.AppendLine(value.partName);
                output.AppendLine(Utilities.Vector3ToString(value.position));
                output.AppendLine(Utilities.QuaternionToString(value.rotation));
                output.AppendLine(value.scale.ToString());
            }
            output.Append("[EOF]");
            return output.ToString();
        }        

        public static void saveCraftToFile()
        {
            StreamWriter stream = new StreamWriter(Utilities.CraftPath + FlightGlobals.ActiveVessel.vesselName + ".crf");
            stream.WriteLine(serialize());
            stream.Close(); 
        }

        public static List<PartValue> loadCraftFromFile(string fileName)
        {
            List<PartValue> loadedList = new List<PartValue>();
            PartValue newValue = new PartValue();
            StreamReader stream = new StreamReader(fileName); // exceptions handled by assembleCraft
            string newLine = string.Empty;
            int craftFileFormat = 0;
            int.TryParse(stream.ReadLine(), out craftFileFormat);
            Debug.Log(String.Concat("Loading crf file, format ", craftFileFormat, ", ", fileName));
            try
            {
                while (!stream.EndOfStream && !(newLine == "[EOF]"))
                {
                    newLine = stream.ReadLine();
                    newValue.partName = newLine;                    
                    newValue.position = Utilities.parseVector3(stream.ReadLine());
                    newValue.rotation = Utilities.parseQuaternion(stream.ReadLine());
                    float.TryParse(stream.ReadLine(), out newValue.scale);
                    //Debug.Log("finding model " + newValue.partName);
                    newValue.model = findPartModel(newValue.partName);
                    //Debug.Log("model null? " + (newValue.model == null));
                    loadedList.Add(newValue.clone());
                }                
            }
            catch (Exception e)
            {
                Debug.Log("load craft file error: " + e.ToString());
            }
            return loadedList;
        }

        public static GameObject assembleCraft(string craftName, bool collidersOn) // --- craftName not actually used yet. This should take a saved craft file name as input ---
        {
            GameObject craft = new GameObject();
            Debug.Log("asembling craft " + craftName);
            List<PartValue> pvList;
            //List<PartValue> pvList = getParts(FlightGlobals.ActiveVessel, true); // load the craft file here into a partValue list
            try
            {
                pvList = loadCraftFromFile(craftName);
            }
            catch
            {
                throw new FileNotFoundException("error loading craft from file", craftName);
            }
            foreach (PartValue pv in pvList)
            {
                //Debug.Log("pv.partName is " + pv.partName);
                pv.model.SetActive(true);
                //Debug.Log("pv.model exists");
                pv.model.transform.parent = craft.transform;
                pv.model.transform.localPosition = pv.position;
                pv.model.transform.localRotation = pv.rotation;
                if (pv.scale > 7f) pv.scale /= 10f;
                if (pv.scale > 7f) pv.scale /= 10f; // twice to catch both 0.01 scale parts, and 0.1 scales. Gotta find a better way. Need to read the part cfg scale
                pv.model.transform.localScale = new Vector3(pv.scale, pv.scale, pv.scale);
                //Debug.Log("Part: " + pv.partName + "Scale: " + pv.scale + "/" + pv.model.transform.localScale);
                //Debug.Log("Part: " + pv.position);
                //Debug.Log("Part: " + pv.rotation);
                //Debug.Log("Part: " + pv.scale);
            }
            setColliderStateInChildren(craft, collidersOn);
            return craft;
        }

        public static GameObject findPartModel(string partName)
        {
            UrlDir.UrlConfig[] cfg = GameDatabase.Instance.GetConfigs("PART");
            //Debug.Log("looping through " + cfg.Length);
{'fraction_non_alphanumeric': 0.09928025524968465, 'fraction_numerical': 0.0031906210580989833, 'mean_word_length': 1.6206494264048221, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2041925', 'n_tokens_mistral': 3401, 'n_tokens_neox': 3243, 'n_words': 695}