public static List <VesselModel> FromCsv(string csv)
        {
            List <VesselModel> results = new List <VesselModel>();

            string[] lines = csv.Split('\n');
            if (lines.Length > 0)
            {
                for (var k = 1; k < lines.Length; k++)
                {
                    //                    Debug.Log(string.Format("[BDArmory.BDAScoreModels]: VesselModel.FromCsv line {0}", lines[k]));
                    if (!lines[k].Contains(","))
                    {
                        continue;
                    }
                    try
                    {
                        string[] values = lines[k].Split(',');
                        if (values.Length > 0)
                        {
                            VesselModel model = new VesselModel();
                            model.id        = int.Parse(values[0]);
                            model.player_id = int.Parse(values[1]);
                            model.craft_url = values[2];
                            model.name      = values[3];
                            results.Add(model);
                        }
                    }
                    catch (Exception e)
                    {
                        Debug.Log("[BDArmory.BDAScoreModels]: VesselModel.FromCsv error: " + e);
                    }
                }
            }
            return(results);
        }
        private void ReceiveVessels(string response)
        {
            if (response == null || "".Equals(response))
            {
                Debug.Log(string.Format("[BDAScoreClient] Received empty vessel collection response"));
                return;
            }
            List <VesselModel> collection = VesselModel.FromCsv(response);

            vessels.Clear();
            if (collection == null)
            {
                Debug.Log(string.Format("[BDAScoreClient] Failed to parse vessel collection: {0}", response));
                return;
            }
            foreach (VesselModel vesselModel in collection)
            {
                if (!vessels.ContainsKey(vesselModel.id)) // Skip duplicates.
                {
                    Debug.Log(string.Format("[BDAScoreClient] Vessel {0}", vesselModel.ToString()));
                    vessels.Add(vesselModel.id, vesselModel);
                }
                else
                {
                    Debug.Log("[BDAScoreClient]: Vessel " + vesselModel.ToString() + " is already in the vessel list, skipping.");
                }
            }
            Debug.Log(string.Format("[BDAScoreClient] Vessels: {0}", vessels.Count));
        }
        private void SaveCraftFile(VesselModel vessel, byte[] bytes)
        {
            PlayerModel p = players[vessel.player_id];

            if (p == null)
            {
                Debug.Log(string.Format("[BDAScoreClient] Failed to save craft for vessel {0}, player {1}", vessel.id, vessel.player_id));
                return;
            }

            string vesselName = string.Format("{0}_{1}", p.name, vessel.name);
            string filename   = string.Format("{0}/{1}.craft", vesselPath, vesselName);

            System.IO.File.WriteAllBytes(filename, bytes);

            // load the file and modify its vessel name to match the player
            string[] lines   = File.ReadAllLines(filename);
            string   pattern = ".*ship = (.+)";

            string[] modifiedLines = lines
                                     .Select(e => Regex.Replace(e, pattern, "ship = " + vesselName))
                                     .Where(e => !e.Contains("VESSELNAMING"))
                                     .ToArray();
            File.WriteAllLines(filename, modifiedLines);
            Debug.Log(string.Format("[BDAScoreClient] Saved craft for player {0}", vesselName));
        }
        private List <RecordModel> BuildRecords(string hash, HeatModel heat)
        {
            List <RecordModel> results = new List <RecordModel>();
            var playerNames            = activePlayers;

            Debug.Log(string.Format("[BDAScoreService] Building records for {0} players", playerNames.Count));
            foreach (string playerName in playerNames)
            {
                var separatorIndex = playerName.IndexOf('_');
                if (separatorIndex < 0)
                {
                    Debug.Log(string.Format("[BDAScoreService] Unmatched player {0}", playerName));
                    Debug.Log("DEBUG players were " + string.Join(", ", client.players.Values));
                    continue;
                }

                var         playerNamePart = playerName.Substring(0, separatorIndex);
                PlayerModel player         = client.players.Values.FirstOrDefault(e => e.name == playerNamePart);
                if (player == null)
                {
                    Debug.Log(string.Format("[BDAScoreService] Unmatched player {0}", playerNamePart));
                    Debug.Log("DEBUG players were " + string.Join(", ", client.players.Values));
                    continue;
                }

                var         vesselNamePart = playerName.Substring(separatorIndex + 1);
                VesselModel vessel         = client.vessels.Values.FirstOrDefault(e => e.player_id == player.id && e.name == vesselNamePart);
                if (vessel == null)
                {
                    Debug.Log(string.Format("[BDAScoreService] Unmatched vessel for playerId {0}", player.id));
                    Debug.Log("DEBUG vessels were " + string.Join(", ", client.vessels.Values.Select(p => p.id)));
                    continue;
                }

                RecordModel record = new RecordModel();
                record.vessel_id      = vessel.id;
                record.competition_id = int.Parse(hash);
                record.heat_id        = heat.id;
                record.hits_out       = ComputeTotalHitsOut(playerName);
                record.hits_in        = ComputeTotalHitsIn(playerName);
                record.dmg_out        = ComputeTotalDamageOut(playerName);
                record.dmg_in         = ComputeTotalDamageIn(playerName);
                record.ram_parts_out  = ComputeTotalRammedPartsOut(playerName);
                record.ram_parts_in   = ComputeTotalRammedPartsIn(playerName);
                record.mis_parts_out  = ComputeTotalMissilePartsOut(playerName);
                record.mis_parts_in   = ComputeTotalMissilePartsIn(playerName);
                record.mis_dmg_out    = ComputeTotalMissileDamageOut(playerName);
                record.mis_dmg_in     = ComputeTotalMissileDamageIn(playerName);
                record.wins           = ComputeWins(playerName);
                record.kills          = ComputeTotalKills(playerName);
                record.deaths         = ComputeTotalDeaths(playerName);
                record.assists        = ComputeTotalAssists(playerName);
                record.death_order    = ComputeDeathOrder(playerName);
                record.death_time     = ComputeDeathTime(playerName);
                if (longestHitDistance.ContainsKey(playerName) && longestHitWeapon.ContainsKey(playerName))
                {
                    record.distance = (float)longestHitDistance[playerName];
                    record.weapon   = longestHitWeapon[playerName];
                }
                results.Add(record);
            }
            Debug.Log(string.Format("[BDAScoreService] Built records for {0} players", results.Count));
            return(results);
        }