<commit_before>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OfficeOpenXml;
using OfficeOpenXml.Drawing;
using DamageMeter.TeraDpsApi;
using Data;
using Tera.Game;
using System.IO;
using System.Drawing;
using OfficeOpenXml.Style;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Xml;
using System.Xml.Serialization;
using OfficeOpenXml.Drawing.Chart;

namespace DamageMeter
{
    static class EPPExstension
    {
        public static void InvisibleSerie(this ExcelBarChart chart, ExcelChartSerie series)
        {
            var i = 0;
            var found = false;
            foreach (var s in chart.Series)
            {
                if (s == series)
                {
                    found = true;
                    break;
                }
                ++i;
            }
            if (!found) throw new InvalidOperationException("series not found.");

            var nsm = chart.WorkSheet.Drawings.NameSpaceManager;
            var nschart = nsm.LookupNamespace("c");
            var nsa = nsm.LookupNamespace("a");
            var node = chart.ChartXml.SelectSingleNode(@"c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser[c:idx[@val='" + i.ToString(CultureInfo.InvariantCulture) + "']]", nsm);
            var doc = chart.ChartXml;

            var spPr = doc.CreateElement("c:spPr", nschart);
            spPr.AppendChild(doc.CreateElement("a:noFill", nsa));
            var ln = spPr.AppendChild(doc.CreateElement("a:ln", nsa));
            ln.Attributes.Append(doc.CreateAttribute("w")).Value = "25400";
            ln.AppendChild(doc.CreateElement("a:noFill", nsa));

            node.AppendChild(spPr);
        }
        public static void FirstAxisDate(this ExcelBarChart chart, int maxVal)
        {
            var nsm = chart.WorkSheet.Drawings.NameSpaceManager;
            var nschart = nsm.LookupNamespace("c");
            var node = chart.ChartXml.SelectSingleNode(@"c:chartSpace/c:chart/c:plotArea/c:catAx[c:axId[@val='1']]", nsm);
            var doc = chart.ChartXml;
            node = RenameNode(node, nschart, "c:dateAx");
            node.SelectSingleNode("c:auto/@val", nsm).Value = "0";
            node.SelectSingleNode("c:tickLblPos/@val", nsm).Value = "none";
            node.SelectSingleNode("c:crosses/@val", nsm).Value = "max";
            var scale = node.SelectSingleNode("c:scaling", nsm);
            var max = doc.CreateElement("c:max", nschart);
            max.Attributes.Append(doc.CreateAttribute("val")).Value = maxVal.ToString();
            scale.AppendChild(max);

            var layout = doc.CreateElement("c:manualLayout", nschart);
            var child = doc.CreateElement("c:layoutTarget", nschart);
            child.Attributes.Append(doc.CreateAttribute("val")).Value = "inner";
            layout.AppendChild(child);
            child = doc.CreateElement("c:xMode", nschart);
            child.Attributes.Append(doc.CreateAttribute("val")).Value = "edge";
            layout.AppendChild(child);
            child = doc.CreateElement("c:yMode", nschart);
            child.Attributes.Append(doc.CreateAttribute("val")).Value = "edge";
            layout.AppendChild(child);
            child = doc.CreateElement("c:x", nschart);
            child.Attributes.Append(doc.CreateAttribute("val")).Value = "0.005";
            layout.AppendChild(child);
            child = doc.CreateElement("c:h", nschart);
            child.Attributes.Append(doc.CreateAttribute("val")).Value = (1F-1.6F/(maxVal+2)).ToString(CultureInfo.InvariantCulture);
            layout.AppendChild(child);
            node = doc.SelectSingleNode(@"c:chartSpace/c:chart/c:plotArea/c:layout", nsm);
            node.AppendChild(layout);
        }
        public static XmlNode RenameNode(XmlNode node, string namespaceUri, string qualifiedName)
        {
            if (node.NodeType == XmlNodeType.Element)
            {
                XmlElement oldElement = (XmlElement)node;
                XmlElement newElement =
                node.OwnerDocument.CreateElement(qualifiedName, namespaceUri);
                while (oldElement.HasAttributes)
                {
                    newElement.SetAttributeNode(oldElement.RemoveAttributeNode(oldElement.Attributes[0]));
                }
                while (oldElement.HasChildNodes)
                {
                    newElement.AppendChild(oldElement.FirstChild);
                }
                oldElement.ParentNode?.ReplaceChild(newElement, oldElement);
                return newElement;
            }
            return null;
        }
        public static void FixEppPlusBug(this ExcelChart chart) //epplus do not renumber series in the chart correctly if inserted not in sequence.
        {
            var xml = chart.ChartXml;
            var nsm = chart.WorkSheet.Drawings.NameSpaceManager;
            var badattr = xml.SelectNodes("//c:idx", nsm);
            int idx = 0;
            foreach (XmlNode attr in badattr)
            {
                attr.Attributes["val"].Value = idx.ToString();
                idx++;
            }
            badattr = xml.SelectNodes("//c:order", nsm);
            idx = 0;
            foreach (XmlNode attr in badattr)
            {
                attr.Attributes["val"].Value = idx.ToString();
                idx++;
            }
        }

    }

    class ExcelExport
    {
        private static BasicTeraData BTD = BasicTeraData.Instance;
        private static object savelock = new object();
        public static void ExcelSave(ExtendedStats exdata)
        {
            lock (savelock) //can't save 2 excel files at one time
            {
                if (!BTD.WindowData.Excel) return;
                var data = exdata.BaseStats;
                NpcInfo Boss = exdata.Entity.Info;
                var dir = Path.Combine(BTD.ResourceDirectory, $"logs/{Boss.Area.Replace(":", "-")}");
                Directory.CreateDirectory(dir);
                var fname = Path.Combine(dir, $"{Boss.Name.Replace(":", "-")} {DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss", CultureInfo.InvariantCulture)}.xlsx");
                FileInfo file = new FileInfo(fname);
                if (file.Exists) return; //the only case this can happen is BAM mobtraining, that's not so interesting statistic to deal with more complex file names.
                using (ExcelPackage package = new ExcelPackage(file))
                {
                    ExcelWorksheet details = CreateDetailsSheet(package, exdata);
                    ExcelWorksheet ws = package.Workbook.Worksheets.Add("Boss");
                    var linkStyle = package.Workbook.Styles.CreateNamedStyle("HyperLink");   //This one is language dependent
                    linkStyle.Style.Font.UnderLine = true;
                    linkStyle.Style.Font.Color.SetColor(Color.Blue);
                    ws.DefaultRowHeight = 30;
                    ws.Cells.Style.Font.Size = 14;
                    ws.Cells.Style.Font.Name = "Arial";
                    ws.Cells[1, 1].Value = $"{Boss.Area}: {Boss.Name} {TimeSpan.FromSeconds(double.Parse(data.fightDuration)).ToString(@"mm\:ss")}";
                    ws.Cells[1, 1, 1, 6].Merge = true;
                    ws.Cells[1, 1, 1, 8].Style.Font.Bold = true;
                    ws.Cells[1, 7].Value = long.Parse(data.partyDps);
                    ws.Cells[1, 7].Style.Numberformat.Format = @"#,#00,\k\/\s";<commit_msg>Move Excel logs to My Documents\ShinraMeter folder<commit_after>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OfficeOpenXml;
using OfficeOpenXml.Drawing;
using DamageMeter.TeraDpsApi;
using Data;
using Tera.Game;
using System.IO;
using System.Drawing;
using OfficeOpenXml.Style;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Xml;
using System.Xml.Serialization;
using OfficeOpenXml.Drawing.Chart;

namespace DamageMeter
{
    static class EPPExstension
    {
        public static void InvisibleSerie(this ExcelBarChart chart, ExcelChartSerie series)
        {
            var i = 0;
            var found = false;
            foreach (var s in chart.Series)
            {
                if (s == series)
                {
                    found = true;
                    break;
                }
                ++i;
            }
            if (!found) throw new InvalidOperationException("series not found.");

            var nsm = chart.WorkSheet.Drawings.NameSpaceManager;
            var nschart = nsm.LookupNamespace("c");
            var nsa = nsm.LookupNamespace("a");
            var node = chart.ChartXml.SelectSingleNode(@"c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser[c:idx[@val='" + i.ToString(CultureInfo.InvariantCulture) + "']]", nsm);
            var doc = chart.ChartXml;

            var spPr = doc.CreateElement("c:spPr", nschart);
            spPr.AppendChild(doc.CreateElement("a:noFill", nsa));
            var ln = spPr.AppendChild(doc.CreateElement("a:ln", nsa));
            ln.Attributes.Append(doc.CreateAttribute("w")).Value = "25400";
            ln.AppendChild(doc.CreateElement("a:noFill", nsa));

            node.AppendChild(spPr);
        }
        public static void FirstAxisDate(this ExcelBarChart chart, int maxVal)
        {
            var nsm = chart.WorkSheet.Drawings.NameSpaceManager;
            var nschart = nsm.LookupNamespace("c");
            var node = chart.ChartXml.SelectSingleNode(@"c:chartSpace/c:chart/c:plotArea/c:catAx[c:axId[@val='1']]", nsm);
            var doc = chart.ChartXml;
            node = RenameNode(node, nschart, "c:dateAx");
            node.SelectSingleNode("c:auto/@val", nsm).Value = "0";
            node.SelectSingleNode("c:tickLblPos/@val", nsm).Value = "none";
            node.SelectSingleNode("c:crosses/@val", nsm).Value = "max";
            var scale = node.SelectSingleNode("c:scaling", nsm);
            var max = doc.CreateElement("c:max", nschart);
            max.Attributes.Append(doc.CreateAttribute("val")).Value = maxVal.ToString();
            scale.AppendChild(max);

            var layout = doc.CreateElement("c:manualLayout", nschart);
            var child = doc.CreateElement("c:layoutTarget", nschart);
            child.Attributes.Append(doc.CreateAttribute("val")).Value = "inner";
            layout.AppendChild(child);
            child = doc.CreateElement("c:xMode", nschart);
            child.Attributes.Append(doc.CreateAttribute("val")).Value = "edge";
            layout.AppendChild(child);
            child = doc.CreateElement("c:yMode", nschart);
            child.Attributes.Append(doc.CreateAttribute("val")).Value = "edge";
            layout.AppendChild(child);
            child = doc.CreateElement("c:x", nschart);
            child.Attributes.Append(doc.CreateAttribute("val")).Value = "0.005";
            layout.AppendChild(child);
            child = doc.CreateElement("c:h", nschart);
            child.Attributes.Append(doc.CreateAttribute("val")).Value = (1F-1.6F/(maxVal+2)).ToString(CultureInfo.InvariantCulture);
            layout.AppendChild(child);
            node = doc.SelectSingleNode(@"c:chartSpace/c:chart/c:plotArea/c:layout", nsm);
            node.AppendChild(layout);
        }
        public static XmlNode RenameNode(XmlNode node, string namespaceUri, string qualifiedName)
        {
            if (node.NodeType == XmlNodeType.Element)
            {
                XmlElement oldElement = (XmlElement)node;
                XmlElement newElement =
                node.OwnerDocument.CreateElement(qualifiedName, namespaceUri);
                while (oldElement.HasAttributes)
                {
                    newElement.SetAttributeNode(oldElement.RemoveAttributeNode(oldElement.Attributes[0]));
                }
                while (oldElement.HasChildNodes)
                {
                    newElement.AppendChild(oldElement.FirstChild);
                }
                oldElement.ParentNode?.ReplaceChild(newElement, oldElement);
                return newElement;
            }
            return null;
        }
        public static void FixEppPlusBug(this ExcelChart chart) //epplus do not renumber series in the chart correctly if inserted not in sequence.
        {
            var xml = chart.ChartXml;
            var nsm = chart.WorkSheet.Drawings.NameSpaceManager;
            var badattr = xml.SelectNodes("//c:idx", nsm);
            int idx = 0;
            foreach (XmlNode attr in badattr)
            {
                attr.Attributes["val"].Value = idx.ToString();
                idx++;
            }
            badattr = xml.SelectNodes("//c:order", nsm);
            idx = 0;
            foreach (XmlNode attr in badattr)
            {
                attr.Attributes["val"].Value = idx.ToString();
                idx++;
            }
        }

    }

    class ExcelExport
    {
        private static BasicTeraData BTD = BasicTeraData.Instance;
        private static object savelock = new object();
        public static void ExcelSave(ExtendedStats exdata)
        {
            lock (savelock) //can't save 2 excel files at one time
            {
                if (!BTD.WindowData.Excel) return;
                var data = exdata.BaseStats;
                NpcInfo Boss = exdata.Entity.Info;
                var dir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), $"ShinraMeter/{Boss.Area.Replace(":", "-")}");
                Directory.CreateDirectory(dir);
                var fname = Path.Combine(dir, $"{Boss.Name.Replace(":", "-")} {DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss", CultureInfo.InvariantCulture)}.xlsx");
                FileInfo file = new FileInfo(fname);
                if (file.Exists) return; //the only case this can happen is BAM mobtraining, that's not so interesting statistic to deal with more complex file names.
                using (ExcelPackage package = new ExcelPackage(file))
                {
                    ExcelWorksheet details = CreateDetailsSheet(package, exdata);
                    ExcelWorksheet ws = package.Workbook.Worksheets.Add("Boss");
                    var linkStyle = package.Workbook.Styles.CreateNamedStyle("HyperLink");   //This one is language dependent
                    linkStyle.Style.Font.UnderLine = true;
                    linkStyle.Style.Font.Color.SetColor(Color.Blue);
                    ws.DefaultRowHeight = 30;
                    ws.Cells.Style.Font.Size = 14;
                    ws.Cells.Style.Font.Name = "Arial";
                    ws.Cells[1, 1].Value = $"{Boss.Area}: {Boss.Name} {TimeSpan.FromSeconds(double.Parse(data.fightDuration)).ToString(@"mm\:ss")}";
                    ws.Cells[1, 1, 1, 6].Merge = true;
                    ws.Cells[1, 1, 1, 8].Style.Font.Bold = true;
                    ws.Cells[1, 7].Value = long.Parse(data.partyDps);
                    ws.Cells[1, 7].Style.Numberformat.Format = @"#,#00,\k\/\s";
{'fraction_non_alphanumeric': 0.11962803055463302, 'fraction_numerical': 0.005313849219528396, 'mean_word_length': 2.036708350141186, 'pattern_counts': {'":': 4, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 6}, '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': '2951695', 'n_tokens_mistral': 4342, 'n_tokens_neox': 4078, 'n_words': 809}