using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.Linq;
using System.Data.Linq.Mapping;
using System.Data.SQLite;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Text;
using System.Dynamic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using System.Text.RegularExpressions;
using System.Threading;
using System.Web;
using System.Windows.Forms;
using System.Xml.Linq;
using System.Xml.XPath;
using cardvisa.Properties;
using NLua;

namespace cardvisa
{
    public partial class Form1 : Form
    {
        static System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
        {
            string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"bin\");
            path = Path.Combine(path, args.Name.Split(',')[0]);
            path = string.Format(@"{0}.dll", path);
            path = string.Format(@"{0}.xml", path);
            return System.Reflection.Assembly.LoadFrom(path);
        }
        public Form1()
        {
            InitializeComponent();
            AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
            SettingPath();
        }
        public SettingData settings;
        public CDBTableHelper cdbh = new CDBTableHelper();    
        public PicViewer picViewer = new PicViewer();
        public MyListBox myListBox = new MyListBox();
        Brush myBrush = Brushes.Black;
        SolidBrush mySBrush = new SolidBrush(Color.White);
        Rectangle myRect = new Rectangle(0,0,0,0);
        int lockobj = 0;
        List<string> filelist = new List<string> { "0禁止.jpg", "1限制.jpg", "2准限.jpg", "3通过.png", "4回退.jpg" };
        public List<string> zipcdblist { get; set; } = new List<string>();
        public int cardindex = 0;
        public int cardcounts { get; set; } = 0;
        private PrivateFontCollection myPfc = new PrivateFontCollection();
        public void SettingPath()
        {
            string configpath = Application.StartupPath + "\\setting.json";
            if (!File.Exists(configpath))
            {
                settings = new SettingData(); ;
                string jsonString = JsonSerializer.Serialize(settings);
                File.WriteAllText(configpath, jsonString);
            }
            if (File.Exists(configpath))
            {                
                string json = File.ReadAllText(configpath);
                settings = JsonSerializer.Deserialize<SettingData>(json);
                if (File.Exists(settings.ygopath))
                {
                    settings.pathcheck = true;
                }
                else
                {
                    OpenFileDialog dialog = new OpenFileDialog();
                    if (dialog.ShowDialog() == DialogResult.OK)
                    {
                        settings.ygopath = dialog.FileName;
                        string jsonString = JsonSerializer.Serialize(settings);
                        File.WriteAllText(configpath, jsonString);
                    }
                }
                refreshlist();
            }
            if (File.Exists(Application.StartupPath+ "\\res\\AdobeHeitiStd-Regular.otf"))
            {
                myPfc.AddFontFile(Application.StartupPath + "\\res\\AdobeHeitiStd-Regular.otf");
                Font mft = new Font(myPfc.Families[0],12);
                listBox1.Font = mft;
                richTextBox1.Font = mft;
            }
        }
        private void button1_Click(object sender, EventArgs e)
        {
            //将卡片签出
            if (button3.Text == "关闭库")
            {
                //下一页
                PageFillList(-1);
            }
            else
            {
                checkDirectory();
                string targetfile = Application.StartupPath + "\\checkout\\package.cdb";
                string dir = Application.StartupPath + "\\checkin";
                Director(dir, "cdb");
                cdbh.Execute(targetfile);
                if (cdbh.cardlistex.Count > 0)
                {
                    cdbh.Execute(Application.StartupPath + "\\checkout\\NotAllowedFiles\\TypeErrorCards.cdb", false);
                }
                Director(dir, "ascdb");
                DeckPackOut("#default");
                foreach (var item in zipcdblist) { File.Delete(item); }       
                refreshlist();
                MessageBox.Show("“快速”打包完成");
            }
        }
        private void button2_Click(object sender, EventArgs e)
        {
            //将卡片签入到服务器
            if (button3.Text == "关闭库")
            {
                //下一页
                PageFillList(1);
            }
            else
            {
                checkDirectory();
                string dir = Application.StartupPath + "\\checkin";
                Director(dir,"excdb");
                MessageBox.Show("压缩处理完成");
            }
        }
        private void button3_Click(object sender, EventArgs e)
        {
            if (button3.Text == "关闭库")
            {
                button1.Text = "签出打包";
                button2.Text = "压缩处理";
                button3.Text = "打开库";
                button4.Text = "导出卡表";
                button5.Text = "MD5校验";
                refreshlist();
                picViewer.Hide();
            }
            else
            {                
                button1.Text = "上一页";
                button2.Text = "下一页";
                button3.Text = "关闭库";
                button4.Text = "判决通知";
                button5.Text = "删除卡";
                var id = listBox1.SelectedIndex;
                string txtFilePath = "";
                if (id > 0)
                {
                    txtFilePath = Application.StartupPath + "\\checkout\\" + listBox1.Items[id].ToString();
                }
                else
                {
                    using (OpenFileDialog ofd = new OpenFileDialog())
                    {
                        ofd.Filter = "文本文件|*.cdb";
                        if (ofd.ShowDialog() == DialogResult.OK)
                        {
                            txtFilePath = ofd.FileName;
                        }
                    }
                }
                FillListBoxFromCDB((txtFilePath == "" ? Application.StartupPath + "\\checkout\\package.cdb" : txtFilePath));
                if (picViewer.IsDisposed) { picViewer = new PicViewer(); }
                picViewer.Show();
                picViewer.Location = new Point(Location.X + Size.Width, Location.Y);
                
                /*
                if (myListBox.IsDisposed) { myListBox = new MyListBox(); }
                myListBox.Show();
                myListBox.Location = new Point(Location.X - myListBox.Size.Width , Location.Y);
                */
            }
        }
        private void button4_Click(object sender, EventArgs e)
        {
            string txtFilePath = "";
            var id = listBox1.SelectedIndex;
            if (id > 0)
            {
                txtFilePath = Application.StartupPath + "\\checkout\\" + listBox1.Items[id].ToString();                
            }
            else
            {
                if (button3.Text != "关闭库")
                {
                    using (OpenFileDialog ofd = new OpenFileDialog())
                    {
                        ofd.Filter = "文本文件|*.cdb";
                        if (ofd.ShowDialog() == DialogResult.OK) txtFilePath = ofd.FileName;                        
                    }
                }
            }
            if (button3.Text == "关闭库")
            {
                LflistPackOut(Application.StartupPath + "\\checkout");
            }
            else
            {
                if (txtFilePath != "") DeckPackOut(txtFilePath);
            }
        }
        private void button5_Click(object sender, EventArgs e)
        {
            if (button3.Text == "关闭库")
            {
                var id = listBox1.SelectedIndex;
                if (id > 0 && id <= 20)
                {
                    sqldata sqd = cdbh.cmds[GetCardFromListID()];
                    string code = sqd.code.ToString();
                    string temp = Application.StartupPath + "\\checkout\\";
                    string srcl = temp + "script\\c" + code + ".lua";
                    string srcp = temp + "pics\\" + code + ".jpg";
                    string tgpath = temp + "NotAllowedFiles\\";
                    if (File.Exists(srcl))
                    {
                        File.Move(srcl, tgpath + "c" + code + ".lua");
                    }
                    if (File.Exists(srcp))
                    {
                        File.Move(srcp, tgpath + code + ".jpg");
                        string srcpf = srcp.Replace("\\pics\\", "\\pics\\field\\");
                        if (File.Exists(srcpf))
                        {
                            File.Move(srcpf, tgpath + code + ".jpg");
                        }
                    }
                    if (!File.Exists(tgpath + "deleted.cdb"))
                    {
                        CommonHandler.CreateCDBFiles(tgpath + "deleted.cdb");
                    }
                    if (File.Exists(tgpath + "deleted.cdb"))
                    {
                        cdbh.Remove(sqd);
                        SqliteDataContext db = new SqliteDataContext("Data Source=" + tgpath + "deleted.cdb" + ";");
                        db.ExecuteCommand(sqd.cmdd.getInsertcmd());
                        db.ExecuteCommand(sqd.cmdt.getInsertcmd());
                        db.Dispose();
                    }
                    cardcounts -= 1;
                    PageFillList(cardindex);
                }
            }
            else
            {
                List<string> cardlist = new List<string>();    
                Dictionary<long,string> cardict = new Dictionary<long, string>();
                string path = Application.StartupPath + "\\checkout\\lflist.conf";
                if (!File.Exists(path))
                {
                    using (StreamWriter sw = new StreamWriter(path, false, (new UTF8Encoding(false)))) { sw.Write(""); }
                }
                else
                {
                    string[] strsets = File.ReadAllLines(path);
                    string reg = "(?<id>\\d{1,10})\\s(?<lf>\\d).*(?<=[-]{2})(?<name>.*)";
                    List<long> templist = new List<long>();
                    foreach (var str in strsets)
                    {
                        Match mt = Regex.Match(str, reg);
                        if (mt.Success)
                        {
                            long cid = long.Parse(mt.Groups["id"].Value);
                            if (!templist.Contains(cid)) { 
                                templist.Add(cid);
                            }
                            if (cardict.ContainsKey(cid)) {
                                cardict[cid] = str;
                            }
                            else
                            {
                                cardict.Add(cid, str);
                            }
                        }
                        else
                        {
                            templist.Sort();
                            for (int i = 0; i < templist.Count; i++)
                            {
                                long code = templist[i];
                                cardlist.Add(cardict[code]);
                            } 
                            cardlist.Add(str);
                            templist.Clear();
                        }
                    }
                }
                //output
                string content = "";
                for (int i = 0; i < cardlist.Count; i++)
                {
                    content += cardlist[i].ToString() + "\n";
                }
                using (StreamWriter sw = new StreamWriter(Application.StartupPath + "\\checkout\\" + "\\lflist.txt", false, (new UTF8Encoding(false))))
                {
                    sw.Write(content.Replace("\r\n", "\n"));
                }
            }
        }        
        private void button6_Click(object sender, EventArgs e)
        {
            if (pictureBox1.Visible)
            {
                button6.Text = "△";
                pictureBox1.Visible = false;
            }
            else
            {
                button6.Text = "×";
                pictureBox1.Visible = true;
            }
        }
        private void button7_Click(object sender, EventArgs e)
        {
            List<Control> objc = new List<Control>()
            {
                button1,button2, button3, button4, button5, button6,button7
            };
            if (button7.Text == "关灯")
            {
                Color bgc = ColorTranslator.FromHtml("#121212");
                Color ftc = ColorTranslator.FromHtml("#eeeeee");
                button7.Text = "开灯";
                foreach (var item in objc)
                {
                    item.BackColor = bgc;
                    item.ForeColor = ftc;
                }
                richTextBox1.BackColor = bgc;
                richTextBox1.ForeColor = ftc;
                listBox1.BackColor = bgc;
                listBox1.ForeColor = ftc;
                BackColor = ColorTranslator.FromHtml("#333333");
            }
            else
            {
                button7.Text = "关灯";
                foreach (var item in objc)
                {
                    item.BackColor = DefaultBackColor;
                    item.ForeColor = Color.Black;                     
                }
                richTextBox1.BackColor = Color.White;
                richTextBox1.ForeColor = Color.Black;
                listBox1.BackColor = Color.White;
                listBox1.ForeColor = Color.Black;
                BackColor = DefaultBackColor;
            }
            /*
            string tpath = Application.StartupPath + "\\checkout\\test.txt";
            LuaDebug debug = new LuaDebug();
            debug.Show();
            TaskFile tskf = new TaskFile();
            Lua rua = new Lua();
            rua.State.Encoding = Encoding.UTF8;
            rua.RegisterFunction("ReadText", tskf, tskf.GetType().GetMethod("ReadText"));
            rua.RegisterFunction("AppendText", tskf, tskf.GetType().GetMethod("AppendText"));
            rua.DoString(@"
                function main(path) 
                    AppendText(path,'你好，世界')
                    return 0
                end
            ").ToString();
            var ruaFunc = rua["main"] as LuaFunction;

            debug.Print(ruaFunc.Call(tpath).First().ToString());
            //
            */
        }
        private void button8_Click(object sender, EventArgs e)
        {
            PuzzleGame pzg = new PuzzleGame();
            pzg.ShowDialog();            
        }
        public void refreshlist()
        {
            listBox1.Items.Clear();
            listBox1.Items.Add("选择文件");
            DIRForEachFilesThenCallback(Application.StartupPath + "\\checkout", (Action<dynamic>)((fsinfo) => {
                if (!(fsinfo is DirectoryInfo))
                {
                    if (fsinfo.Name.Contains(".cdb")) listBox1.Items.Add(fsinfo.Name);
                }
            }));
        }
        public void checkDirectory()
        {
            string dir = Application.StartupPath + "\\";
            if (!Directory.Exists(dir+ "checkin")) Directory.CreateDirectory(dir + "checkin");
            if (!Directory.Exists(dir+ "checkout")) Directory.CreateDirectory(dir + "checkout");
            List<string> dirs = new List<string> { "temp", "pics", "pics\\field", "script", "text", "deck", "NotAllowedFiles" };
            string targetfile = Application.StartupPath + "\\" + "checkout" + "\\package.cdb";
            CommonHandler.CreateCDBFiles(targetfile);
            foreach (var item in dirs)
            {
                string temp = dir + "\\checkout\\" + item;
                if (!string.IsNullOrEmpty(temp))
                {
                    if (!Directory.Exists(temp)) Directory.CreateDirectory(temp);
                }
            }
        }
        public void FillListBoxFromCDB(string pathName)
        {
            if (File.Exists(pathName))
            {
                string lostedFiles = "缺少文件：";
                string constr = "Data Source=" + pathName + ";";
                SqliteDataContext db = new SqliteDataContext(constr);
                var datassets = (from q1 in db.Datarows select q1).ToList();
                var textssets = (from q2 in db.Textrows select q2).ToList();
                cardindex = 0;
                cardcounts = datassets.Count() > textssets.Count() ? datassets.Count() : textssets.Count();
                cdbh.Dispose();
                cdbh.openedfile = pathName;
                for (int i = 0; i < cardcounts; i++)
                {
                    var cardd = datassets[i];
                    var code = cardd.id;
                    var cti = new CardTypeInfo(cardd.type);
                    bool otbug = settings.packDIY ? (cardd.ot != 4) : false;
                    bool lostcheck = (cardd.alias == 0 && cti.IsNeedScript());
                    if (lostcheck || otbug)//非同名卡
                    {  
                        string parentpath = Path.GetDirectoryName(pathName);
                        bool lualost = lostcheck && !File.Exists(parentpath + "\\script\\c" + code + ".lua");   
                        bool piclost = lostcheck && !File.Exists(parentpath + "\\pics\\" + code + ".jpg");
                        if (lualost || piclost) {
                            lostedFiles += "\r\n"                               
                                +"【" + code.ToString() + "】"
                                + textssets[i].name + "："
                                + (lualost ? "脚本丢失" : "")
                                + (lualost && piclost ? "，" : "")
                                + (piclost ? "图片丢失" : "")
                                + ((lualost || piclost) && otbug ? "，" : "")
                                + (otbug ? "规则错误" : "")
                                + "。";
                        }                        
                    }
                    cdbh.Add(new sqldata(cardd.id, DateTime.Now, textssets[i], cardd, false));
                }
                PageFillList();
                LflistReader();
                richTextBox1.Text = lostedFiles;
            }
        }
        public void PageFillList(int page = 0)
        {
            int maxp = (int)Math.Ceiling((double)cardcounts / 20);
            int fromindex = cardindex;
            cardindex = (page > 1 ? page - 1 : cardindex + page);
            if (cardindex < 0)
            {
                cardindex = 0;
            }
            else if (cardindex >= maxp)
            {
                cardindex = maxp - 1;
            }
            if ((cardindex != fromindex) || cardindex == 0)
            {
                listBox1.Items.Clear();
                listBox1.Items.Add("选择文件");
                int ii = 0;
                int cardid = cardindex * 20;
                int maxlg = cardid + 20 > cardcounts ? cardcounts : cardid + 20;
                for (; (cardid + ii < maxlg); ii++)
                {
                    long cardcode = cdbh.cardlist[cardid + ii];
                    string cardname = cdbh.cmds[cardcode].cmdt.name;
                    listBox1.Items.Add((ii + 1) + "||" + cardcode + "||" + cardname);
                }
                listBox1.Items.Add("第" + (cardindex + 1) + "页/共" + Math.Ceiling((double)cardcounts / 20) + "页");
            }
        }
        public void StreamCopy(string sourcePath, string targetPath, string text) {
            bool allowedfile = true;
            string legaltype = "";
            if (Regex.IsMatch(text, "xpcall"))
            {
                allowedfile = false;
                legaltype = "usexpcall_";
            }
            if (Regex.IsMatch(text, "goto"))
            {
                allowedfile = false;
                legaltype = "usegoto_";
            }
            text = text.Replace("\r\n", "\n");
            if (allowedfile)
            {
                using (StreamWriter sw = new StreamWriter(targetPath, false, (new UTF8Encoding(false)))) { sw.Write(text); }
            }
            else
            {
                if (sourcePath != "fromzip")
                {
                    File.Copy(sourcePath, Application.StartupPath + "\\checkout\\NotAllowedFiles\\" + legaltype + Path.GetFileName(sourcePath), true);
                }
                else
                {
                    using (StreamWriter sw = new StreamWriter(Application.StartupPath + "\\checkout\\NotAllowedFiles\\" + legaltype + Path.GetFileName(targetPath), false, (new UTF8Encoding(false)))) { sw.Write(text); }
                }
            }
        }
        public void StreamCopy(string sourcePath, string targetPath)
        {
            using (StreamReader sr = new StreamReader(sourcePath))
            {
                string text = sr.ReadToEnd();
                StreamCopy(sourcePath,targetPath,text);
            }
        }
        public bool CompressImage(Image imgSource, string targetPath, int quality = 75, int maxsize = 120, bool sfsc = true, int rar4x = 2) {
            ImageFormat tFormat = imgSource.RawFormat;
            int dHeight = imgSource.Height / rar4x;
            int dWidth = imgSource.Width / rar4x;
            int sW = 0, sH = 0;
            //按比例缩放
            Size tem_size = new Size(imgSource.Width, imgSource.Height);
            if (tem_size.Width > dHeight || tem_size.Width > dWidth)
            {
                if ((tem_size.Width * dHeight) > (tem_size.Width * dWidth))
                {
                    sW = dWidth;
                    sH = (dWidth * tem_size.Height) / tem_size.Width;
                }
                else
                {
                    sH = dHeight;
                    sW = (tem_size.Width * dHeight) / tem_size.Height;
                }
            }
            else
            {
                sW = tem_size.Width;
                sH = tem_size.Height;
            }

            Bitmap ob = new Bitmap(dWidth, dHeight);
            Graphics g = Graphics.FromImage(ob);

            g.Clear(Color.White);
            g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
            g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;

            g.DrawImage(imgSource, new Rectangle((dWidth - sW) / 2, (dHeight - sH) / 2, sW, sH), 0, 0, imgSource.Width, imgSource.Height, GraphicsUnit.Pixel);
            g.Dispose();

            //保存图片并压缩
            EncoderParameters ep = new EncoderParameters();
            long[] qy = new long[1];
            qy[0] = quality;
            EncoderParameter eParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, qy);
            ep.Param[0] = eParam;

            try
            {
                ImageCodecInfo[] arrayICI = ImageCodecInfo.GetImageEncoders();
                ImageCodecInfo jpegICIinfo = null;
                for (int x = 0; x < arrayICI.Length; x++)
                {
                    if (arrayICI[x].FormatDescription.Equals("JPEG"))
                    {
                        jpegICIinfo = arrayICI[x];
                        break;
                    }
                }
                if (jpegICIinfo != null)
                {
                    ob.Save(targetPath, jpegICIinfo, ep);
                    FileInfo fi = new FileInfo(targetPath);
                    if (fi.Length > 1024 * maxsize)
                    {
                        quality = quality - 10;
                        CompressImage(imgSource, targetPath, quality, maxsize, false, sfsc ? 2 : 4);
                    }
                }
                else
                {
                    ob.Save(targetPath, tFormat);
                }
                return true;
            }
            catch { return false; }
            finally
            {
                imgSource.Dispose();
                ob.Dispose();
            }
        }

        public bool CompressImage(string sourcePath, string targetPath, int quality = 75, int maxsize = 120, bool sfsc = true, int rar4x = 2)
        {            
            FileInfo firstFileInfo = new FileInfo(sourcePath);
            if (sfsc == true && firstFileInfo.Length < maxsize * 1024)
            {
                firstFileInfo.CopyTo(targetPath, true);
                return true;
            }
            Image imgSource = Image.FromFile(sourcePath);
            return CompressImage(imgSource, targetPath, quality, maxsize, sfsc, rar4x);
        }
        public void DIRForEachFilesThenCallback(string dir, dynamic cbk)
        {
            DirectoryInfo d = new DirectoryInfo(dir);
            FileSystemInfo[] fsinfos = d.GetFileSystemInfos();
            foreach (FileSystemInfo fsinfo in fsinfos)
            {
                if (cbk is Action<dynamic>) cbk(fsinfo);
            }
        }
        public void DeckPackOut(string txtFilePath)
        {
            string folderpath = txtFilePath == "#default" ? Application.StartupPath + "\\checkout\\deck" : "";
            txtFilePath = txtFilePath == "#default" ? Application.StartupPath + "\\checkout\\package.cdb" : txtFilePath;
            if (File.Exists(txtFilePath))
            {
                string constr = "Data Source=" + txtFilePath + ";";
                SqliteDataContext db = new SqliteDataContext(constr);
                var idsets = (from q1 in db.Idrows select q1);
                var excodelist = new List<string>();
                var maincodelist = new List<string>();
                foreach (var card in idsets)
                {
                    var code = card.id;
                    var type = card.type;
                    var dexA = Convert.ToString(type, 16);
                    var excard = false;
                    /*
                    融合=0x40,
                    同调=0x2000
                    超量=0x800000
                    连接=0x4000000
                    */
                    if (!excard && dexA.Length >= 2)
                    {
                        string a = dexA.Substring(dexA.Length - 2, 1);
                        excard = excard ? excard : CommonHandler.dexf(a, 4);
                    }
                    if (!excard && dexA.Length >= 4)
                    {
                        string a = dexA.Substring(dexA.Length - 4, 1);
                        excard = excard ? excard : CommonHandler.dexf(a, 2);
                    }
                    if (!excard && dexA.Length >= 6)
                    {
                        string a = dexA.Substring(dexA.Length - 6, 1);
                        excard = excard ? excard : CommonHandler.dexf(a, 8);
                    }
                    if (!excard && dexA.Length >= 7)
                    {
                        string a = dexA.Substring(dexA.Length - 7, 1);
                        excard = excard ? excard : CommonHandler.dexf(a, 4);
                    }
                    if (excard)
                    {
                        excodelist.Add(code.ToString());
                    }
                    else
                    {
                        maincodelist.Add(code.ToString());
                    }
                }
                //准备输出文件
                Func<int, string> c2o = (n) => {
                    switch (n)
                    {
                        case 11:
                        case 12:
                        case 13:
                            return $"{n}th";
                        default:
                            string n2t = n.ToString();
                            char lastd = n2t[n2t.Length - 1];
                            string suffix = "";
                            switch (lastd)
                            {
                                case '1':
                                    suffix = "st";
                                    break;
                                case '2':
                                    suffix = "nd";
                                    break;
                                case '3':
                                    suffix = "rd";
                                    break;
                                default:
                                    suffix = "th";
                                    break;
                            }
                            return $"{n}{suffix}";
                    }
                };
                if (folderpath == "")
                {
                    FolderBrowserDialog dialog = new FolderBrowserDialog();
                    dialog.Description = "请选择卡组文件要保存到的目录文件夹";
                    if (dialog.ShowDialog() == DialogResult.OK)
                    {
                        folderpath = dialog.SelectedPath;
                    }
                }
                double mc = Math.Ceiling((double)(((double)maincodelist.Count) / 40));
                double ec = Math.Ceiling((double)(((double)excodelist.Count) / 15));
                int page = (int)(mc > ec ? (int)mc : (int)ec);
                for (int i = 0; i < page; i++)
                {
                    string content = "#created by hakune";
                    content += "\r\n#main";
                    for (int mj = 0; (i * 40 + mj) < maincodelist.Count && (i * 40 + mj) < (i + 1) * 40; mj++)
                    {
                        content += "\r\n" + maincodelist[i * 40 + mj];
                    }
                    content += "\r\n#extra";
                    for (int ej = 0; (i * 15 + ej) < excodelist.Count && (i * 15 + ej) < (i + 1) * 15; ej++)
                    {
                        content += "\r\n" + excodelist[i * 15 + ej];
                    }
                    string filename = DateTime.Now.ToString("yyyy-MM-dd") + " " + c2o(i + 1) + ".ydk";
                    string path = folderpath + "\\" + filename;
                    using (StreamWriter sw = new StreamWriter(path, false, (new UTF8Encoding(false))))
                    {
                        sw.Write(content.Replace("\r\n", "\n"));
                    }
                }
                Process.Start("explorer.exe", folderpath);
            }
        }
        public void LflistReader(string path = "")
        {
            if(path == "") path = Application.StartupPath + "\\checkout\\lflist.txt";
            if (!File.Exists(path))
            {
                using (StreamWriter sw = new StreamWriter(path, false, (new UTF8Encoding(false)))) { sw.Write(""); }
            }
            else
            {
                string[] strsets = File.ReadAllLines(path);
                string reg = "(?<id>\\d{1,10})\\s(?<lf>\\d).*(?<=[-]{2})(?<name>.*)";
                foreach (var str in strsets)
                {
                    Match mt = Regex.Match(str,reg);
                    if (mt.Success)
                    {
                        long cid = long.Parse(mt.Groups["id"].Value);
                        if (cdbh.cmds.ContainsKey(cid)) { 
                            cdbh.cmds[cid].LFState = (LFStates)Enum.Parse(typeof(LFStates), mt.Groups["lf"].Value);
                        }
                    }
                }
            }
        }
        public void LflistPackOut(string txtFilePath)
        {
            List<string> list = new List<string> { "#forbidden", "#limit", "#semi limit", "#Passed", "#Returned" };
            foreach (long cid in cdbh.cardlist)
            {
                sqldata sqd = cdbh.cmds[cid];                
                list[(int)sqd.LFState] += "\n" + sqd.cmdd.id.ToString().PadLeft(8, '0') + " " + (int)sqd.LFState + " --" + sqd.cmdt.name;
            }
            string content = list[0] + "\n" + list[1] + "\n" + list[2] + "\n" + list[4] + "\n" + list[3];
            using (StreamWriter sw = new StreamWriter(txtFilePath + "\\lflist.txt", false, (new UTF8Encoding(false))))
            {
                sw.Write(content.Replace("\r\n", "\n"));
            }
            Process.Start("explorer.exe", txtFilePath);
        }
        public void Director(string dir)
        {
            Director(dir, "#default");
        }
        public void Director(string dir, string mode)
        {
            DirectoryInfo d = new DirectoryInfo(dir);
            FileSystemInfo[] fsinfos = d.GetFileSystemInfos();
            foreach (FileSystemInfo fsinfo in fsinfos)
            {
                if (fsinfo is DirectoryInfo)
                {
                    Director(fsinfo.FullName, mode);
                }
                else
                {
                    string flag = "";
                    if (mode == "#default" || mode == "excdb" || mode == "ascdb")
                    {
                        if (fsinfo.FullName.Contains(".cdb") && mode != "excdb" && mode != "ascdb")
                        {
                            flag = "cdb";
                        }
                        else
                        {
                            if (fsinfo.FullName.Contains(".lua") && (mode == "ascdb" || mode=="excdb")) flag = "script";
                            if (((fsinfo.FullName.Contains(".jpg") || fsinfo.FullName.Contains(".png")) && fsinfo.FullName.Contains("thumbnail") != true)) flag = "pics";
                            if (fsinfo.FullName.Contains(".txt")) flag = "text";
                            if (fsinfo.FullName.Contains(".zip")) flag = "zip";
                        }
                    }
                    else
                    {
                        if (fsinfo.FullName.Contains("." + mode)) flag = mode;//cdb入口
                        if (fsinfo.FullName.Contains(".cdb")) flag = "cdb";
                        if (fsinfo.FullName.Contains(".zip")) flag = "cdb";
                    }
                    swtodo(fsinfo, flag, mode == "excdb" ? true : false);
                }
            }
        }
        public void swtodo(FileSystemInfo fsinfo, string flag,bool allowedfile = false)
        {
            int icd = 0;
            if (int.TryParse(fsinfo.Name.Replace(fsinfo.Extension, "").Replace("c", ""), out icd)) { 
                allowedfile = (allowedfile || cdbh.cardlist.Contains(icd)) ? true : false; 
            }       
            switch (flag)
            {
                case "text":
                case "script":
                case "pics":
                    //需要直接复制过去                       
                    string pathtemp = Application.StartupPath + "\\checkout\\" + (allowedfile ? (fsinfo.FullName.Contains("field") ? "pics\\field\\" : flag + "\\") : fsinfo.FullName.Contains(".txt") ? "text\\" : "NotAllowedFiles\\") + fsinfo.Name;
                    pathtemp = pathtemp.Replace(".png", ".jpg");
                    DateTime dt = File.GetLastWriteTime(pathtemp);
                    if (!File.Exists(pathtemp) || (fsinfo.LastWriteTime > dt))
                    {
                        if (flag == "pics")
                        {
                            CompressImage(fsinfo.FullName, pathtemp);
                        }
                        else
                        {
                            if (flag == "text")
                            {
                                StreamCopy(fsinfo.FullName, pathtemp.Replace(".txt"," new.txt"));
                            }
                            else
                            {
                                StreamCopy(fsinfo.FullName, pathtemp);
                            }
                        }
                    }
                    break;
                case "cdb":
                case "zip":
                    if (File.Exists(fsinfo.FullName))
                    {
                        if (fsinfo.FullName.Contains(".cdb"))
                        {
                            cdbh.AddFromCDB(fsinfo.FullName);
                        }
                        else
                        {
                            using (var zip = ZipFile.OpenRead(fsinfo.FullName))
                            {
                                foreach (var entry in zip.Entries)
                                {
                                    string flag2 = "";
                                    if (flag == "cdb")
                                    {
                                        if (entry.Name.Contains(".cdb")) flag2 = "cdb";
                                    }
                                    else
                                    {
                                        if (entry.Name.Contains(".lua")) flag2 = "script";
                                        if (entry.Name.Contains(".jpg") && entry.Name.Contains("thumbnail") != true) flag2 = "pics";
                                        if (entry.Name.Contains(".txt")) flag2 = "text";
                                    }
                                    switch (flag2)
                                    {
                                        case "text":
                                        case "script":
                                        case "pics":
                                            icd = 0;
                                            int.TryParse(entry.Name.Replace(Path.GetExtension(entry.Name), "").Replace("c", ""), out icd);
                                            allowedfile = cdbh.cardlist.Contains(icd) ? true : false;
                                            string tgpath = Application.StartupPath + "\\checkout\\" + (allowedfile ? (entry.FullName.Contains("field") ? "pics\\field\\" : flag2 + "\\") : entry.FullName.Contains(".txt") ? "text\\" : "NotAllowedFiles\\") + entry.Name;
                                            tgpath = tgpath.Replace(".png",".jpg");
                                            DateTime dtt = File.GetLastWriteTime(tgpath);
                                            if (!File.Exists(tgpath) || (entry.LastWriteTime.DateTime > dtt))
                                            {
                                                using (var stream = entry.Open())
                                                {
                                                    if (flag2 == "pics")
                                                    {
                                                        if (stream.Length > 120 * 1024)
                                                        {
                                                            Image img = Image.FromStream(stream);
                                                            CompressImage(img, tgpath);
                                                        }
                                                        else
                                                        {
                                                            entry.ExtractToFile(tgpath);
                                                        }
                                                    }
                                                    else
                                                    {
                                                        using (var sr = new StreamReader(stream))
                                                        {
                                                            var str = sr.ReadToEnd();
                                                            if (entry.Name != "")
                                                            {
                                                                StreamCopy("fromzip", tgpath, str);
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                            break;
                                        case "cdb":
                                            if (entry.Name.Contains("cdb"))
                                            {
                                                tgpath = Application.StartupPath + "\\checkout\\temp\\" + fsinfo.Name.Replace(".zip", "--") + entry.Name;
                                                if (File.Exists(tgpath))
                                                {
                                                    File.Delete(tgpath);
                                                }
                                                entry.ExtractToFile(tgpath);
                                                cdbh.AddFromCDB(tgpath);
                                                zipcdblist.Add(tgpath);
                                            }
                                            break;
                                        default:
                                            break;
                                    }
                                }
                            }
                        }
                    }                    
                    break;
                default:
                    break;
            }
        }        
        public long GetCardFromListID(int index = -1) {
            var id = index > 0 ? index : listBox1.SelectedIndex;
            if(id>0 &&id <= 20)
            {
                int cid = cardindex * 20 + id - 1;
                cid = cid >= cardcounts ? cardcounts - 1 : cid;
                long cidd = cdbh.cardlist[cid];
                return cidd;
            }
            return 0;
        }
        private void listBox1_MeasureItem(object sender, MeasureItemEventArgs e)
        {
            e.ItemHeight = 20;
        }
        //该代码会不断重复循环DrawItem
        private void listBox1_DrawItem(object sender, DrawItemEventArgs e)
        {
            if (e.Index < 0) return;
            if (lockobj == 1) return;            
            if (button7.Text == "开灯")
            {
                myBrush = Brushes.White;
                mySBrush.Color = Color.Black;
            }            
            myRect.X = e.Bounds.X;
            myRect.Y = e.Bounds.Y;
            myRect.Width = e.Bounds.Width;
            myRect.Height = e.Bounds.Height;
            e.Graphics.FillRectangle(mySBrush,myRect);//罪魁祸首
            /*
            if (cdbh.cmds.Count > 0)
            {
                var id = e.Index > 0 ? (e.Index < 20 ? e.Index : 19) : 2;
                sqldata sqd = cdbh.cmds[GetCardFromListID(id)];
                switch (sqd.LFState)
                {
                    case LFStates.死刑:
                        myBrush = Brushes.Red;
                        break;
                    case LFStates.Limited:
                        myBrush = Brushes.Orange;
                        break;
                    case LFStates.SubLimited:
                        myBrush = Brushes.Blue;
                        break;
                    default:
                        myBrush = button7.Text == "关灯" ? Brushes.Black : Brushes.White;
                        break;
                }
            }*/
            if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
            {                
                e.Graphics.FillRectangle(new SolidBrush(Color.LightBlue),myRect);//罪魁祸首
            }
            e.Graphics.DrawString(listBox1.Items[e.Index].ToString(), listBox1.Font, myBrush,myRect, StringFormat.GenericDefault);
            e.DrawFocusRectangle();
        }
        private void listBox1_SelectedValueChanged(object sender, EventArgs e)
        {
            if (button3.Text == "关闭库")
            {
                
                var id = listBox1.SelectedIndex;
                if (id > 0 && id <= 20)
                {
                    sqldata sqd = cdbh.cmds[GetCardFromListID()];
                    string ctp = Convert.ToString(sqd.cmdd.type, 16);
                    CardTypeInfo ctpinfo = new CardTypeInfo(ctp);
                    ctpinfo.cdinit(sqd.cmdd.race, "race");
                    ctpinfo.cdinit(sqd.cmdd.attribute, "attr");
                    var lv = ctpinfo.GetLevel(sqd.cmdd.level);
                    richTextBox1.Text = "";
                    try
                    {                        
                        string imgpath = Application.StartupPath + "\\res\\" + filelist[(int)sqd.LFState];
                        if (File.Exists(imgpath))
                        {
                            using (Image img = Image.FromFile(imgpath))
                            {
                                pictureBox1.Image = new Bitmap(img);
                            }                            
                            button6.Text = "×";
                            pictureBox1.Visible = true;                            
                        }
                    }
                    catch (Exception exc)
                    {
                        richTextBox1.Text += exc.ToString();
                    }
                    richTextBox1.Text =
                        sqd.cmdt.name + "[" + sqd.cmdd.id + "]" + "\r\n" +
                        (ctpinfo.IsCardType("怪兽") ? "[怪兽|" +
                            ctpinfo.CardTypeFormat("怪兽") +
                        "] " + ctpinfo.CardTypeFormat("", "|", "race") + "/" + ctpinfo.CardTypeFormat("", "|", "attr")
                        + "\r\n"
                        + "[" + (ctpinfo.IsCardType("超量") ? "☆" : (ctpinfo.IsCardType("连接") ? "LINK-" : "★")) + lv + "] "
                        + "攻击力：" + sqd.cmdd.atk +
                        (ctpinfo.IsCardType("连接") ? "" : " / 守备力：" + sqd.cmdd.def) :
                            (ctpinfo.IsCardType("魔法") ? "[魔法" +
                                ctpinfo.CardTypeFormat("魔法", "|", "type", "|") +
                            "]" :
                                (ctpinfo.IsCardType("陷阱") ? "[陷阱" +
                                    ctpinfo.CardTypeFormat("陷阱", "|", "type", "|") +
                                "]" : "[卡种错误]"))) + "\r\n" +
                        sqd.cmdt.desc;
                    string path = Path.GetDirectoryName(cdbh.openedfile);
                    string pathtemp = path + "\\pics\\" + sqd.code + ".jpg";
                    picViewer.FillPic(pathtemp);
                }
                if (id > 20 || cardindex * 20 + id - 1 == cardcounts)
                {
                    Form fm1 = new Form();
                    fm1.Size = new Size(160, 100);
                    fm1.StartPosition = FormStartPosition.CenterParent;
                    System.Windows.Forms.Label lb = new System.Windows.Forms.Label();
                    lb.Location = new Point(15, 12);
                    lb.Size = new Size(60, 20);
                    lb.Font = new Font("宋体", 12F);
                    lb.Text = "转跳到";
                    TextBox tbx = new TextBox();
                    tbx.Location = new Point(75, 10);
                    tbx.Size = new Size(60, 23);                    
                    Button btnyes = new Button();
                    btnyes.Location = new Point(10, 33);
                    btnyes.Size = new Size(60, 23);
                    btnyes.Text = "确定";                    
                    Button btnno = new Button();
                    btnno.Location = new Point(75, 33);
                    btnno.Size = new Size(60, 23);
                    btnno.Text = "取消";
                    Action<bool> act = (bool flag) =>
                    {
                        if (flag)
                        {
                            int pageid = cardindex;
                            int.TryParse(tbx.Text, out pageid);
                            PageFillList(pageid);
                        }
                        fm1.Close();
                        fm1.Dispose();
                    };
                    tbx.KeyDown += (object obj, KeyEventArgs args) => {
                        string inputValue = tbx.Text;
                        if (args.KeyCode == Keys.Enter) act(true);
                    };
                    btnyes.Click += (object obj, EventArgs args) => { act(true); };
                    btnno.Click += (object obj, EventArgs args) => { act(false); };
                    fm1.Controls.Add(lb);
                    fm1.Controls.Add(tbx);
                    fm1.Controls.Add(btnyes);
                    fm1.Controls.Add(btnno);
                    fm1.ShowDialog();
                }
            }
        }
        private void pictureBox1_Click(object sender, EventArgs e)
        {
            Form fm1 = new Form();
            string path = Application.StartupPath + "\\res\\";
            fm1.Size = new Size(365,280);
            fm1.StartPosition = FormStartPosition.CenterParent;
            List<string> list = new List<string> {
                "0禁止.jpg","1限制.jpg","2准限.jpg","3通过.jpg","4回退.jpg"
            };
            List<string> emname = new List<string> { "Forbidden", "Limited", "SubLimited", "UnLimited", "死刑" };
            List<PictureBox> pblist = new List<PictureBox> {
                new PictureBox(),new PictureBox(),new PictureBox(),new PictureBox(),new PictureBox()
            };
            int id = 0;
            foreach (var pb in pblist)
            {
                pb.Visible = true;
                pb.SizeMode = PictureBoxSizeMode.Zoom;
                pb.Size = new Size(120, 120);
                pb.Location = new Point((id - 3 >= 0 ? (id - 3) * 120 : id * 120), (id - 3 >= 0 ? 120 : 0));
                pb.Image = Image.FromFile(path + list[id]);
                pb.Name = emname[id];
                pb.Click += (object sder,EventArgs args) => {
                    PictureBox pbn = sder as PictureBox;
                    pictureBox1.Image = pbn.Image;                    
                    if (button3.Text == "关闭库")
                    {
                        var cid = listBox1.SelectedIndex;
                        if (cid > 0 && cid < 20)
                        {
                            sqldata sqd = cdbh.cmds[GetCardFromListID()];                           
                            sqd.LFState = (LFStates)Enum.Parse(typeof(LFStates), pbn.Name);
                        }
                    }
                    fm1.Close();
                    fm1.Dispose();
                };
                fm1.Controls.Add(pb);
                id++;
            }
            fm1.ShowDialog();
        }
        private void listBox1_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right && button3.Text == "关闭库")
            {
                var id = listBox1.SelectedIndex;
                if (id > 0 && id <= 20)
                {
                    sqldata sqd = cdbh.cmds[GetCardFromListID()];
                    bool flag = (button7.Text == "开灯");
                    ContextMenuStrip cms = new ContextMenuStrip();
                    cms.RenderMode = ToolStripRenderMode.Professional;
                    cms.Renderer = new ToolStripProfessionalRenderer(new MqxsColorTable(flag));
                    if (flag)
                    {
                        cms.BackColor = ColorTranslator.FromHtml("#121212");
                        cms.ForeColor = ColorTranslator.FromHtml("#eeeeee");
                    }
                    cms.Items.Add("打开脚本");
                    cms.Items.Add("查看卡图");
                    string path = Path.GetDirectoryName(cdbh.openedfile);                    
                    cms.Items[0].Click += (object sder, EventArgs args) => {   
                        string pathtemp = path + "\\script\\c" + sqd.code + ".lua";
                        if (File.Exists(pathtemp)) Process.Start("explorer.exe", pathtemp);                        
                    };
                    cms.Items[1].Click += (object sder, EventArgs args) => {
                        string pathtemp = path + "\\pics\\" + sqd.code + ".jpg";
                        if (File.Exists(pathtemp)) Process.Start("explorer.exe", pathtemp);
                    };
                    listBox1.ContextMenuStrip = cms;
                    cms.Show(listBox1, new Point(e.X, e.Y));
                }                
            }
        }
        private void listBox1_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (button3.Text == "关闭库")
            {
                int index = this.listBox1.IndexFromPoint(e.Location);
                if (index != ListBox.NoMatches && index != 0)
                {
                    sqldata sqd = cdbh.cmds[GetCardFromListID()];
                    string path = Path.GetDirectoryName(cdbh.openedfile);
                    string pathtemp = path + "\\pics\\" + sqd.code + ".jpg";
                    if (File.Exists(pathtemp))
                    {
                        PicViewer pv = new PicViewer();
                        pv.Text = sqd.cmdt.id.ToString();
                        pv.FillPic(pathtemp);
                        pv.Show();
                    }
                }
            }
        }
        private void Form1_Move(object sender, EventArgs e)
        {
            picViewer.Location = new Point(Location.X + Size.Width, Location.Y);
            myListBox.Location = new Point(Location.X - myListBox.Width, Location.Y);
        }

        
    }
    [Table(Name = "main.datas")]
    public class datas
    {
        [Column(Name = "id", IsPrimaryKey = true)]
        public UInt32 id { get; set; }
        [Column(Name = "ot")]
        public Int64 ot { get; set; }
        [Column(Name = "alias")]
        public Int64 alias { get; set; }
        [Column(Name = "setcode")]
        public Int64 setcode { get; set; }
        [Column(Name = "type")]
        public Int64 type { get; set; }
        [Column(Name = "atk")]
        public Int64 atk { get; set; }
        [Column(Name = "def")]
        public Int64 def { get; set; }
        [Column(Name = "level")]
        public Int64 level { get; set; }
        [Column(Name = "race")]
        public Int64 race { get; set; }
        [Column(Name = "attribute")]
        public Int64 attribute { get; set; }
        [Column(Name = "category")]
        public Int64 category { get; set; }

        public string getInsertcmd()
        {
            return "INSERT OR REPLACE INTO datas VALUES ("
                + id.ToString() + ","
                + ot.ToString() + ","
                + alias.ToString() + ","
                + setcode.ToString() + ","
                + type.ToString() + ","
                + atk.ToString() + ","
                + def.ToString() + ","
                + level.ToString() + ","
                + race.ToString() + ","
                + attribute.ToString() + ","
                + category.ToString() + ");"
                ;
        }
    }
    [Table(Name = "main.texts")]
    public class texts
    {
        [Column(Name = "id", IsPrimaryKey = true)]
        public Int64 id { get; set; }
        [Column(Name = "name", DbType = "text")]
        public string name { get; set; }
        [Column(Name = "desc", DbType = "text")]
        public string desc { get; set; }
        [Column(Name = "str1", DbType = "text")]
        public string str1 { get; set; }
        [Column(Name = "str2", DbType = "text")]
        public string str2 { get; set; }
        [Column(Name = "str3", DbType = "text")]
        public string str3 { get; set; }
        [Column(Name = "str4", DbType = "text")]
        public string str4 { get; set; }
        [Column(Name = "str5", DbType = "text")]
        public string str5 { get; set; }
        [Column(Name = "str6", DbType = "text")]
        public string str6 { get; set; }
        [Column(Name = "str7", DbType = "text")]
        public string str7 { get; set; }
        [Column(Name = "str8", DbType = "text")]
        public string str8 { get; set; }
        [Column(Name = "str9", DbType = "text")]
        public string str9 { get; set; }
        [Column(Name = "str10", DbType = "text")]
        public string str10 { get; set; }
        [Column(Name = "str11", DbType = "text")]
        public string str11 { get; set; }
        [Column(Name = "str12", DbType = "text")]
        public string str12 { get; set; }
        [Column(Name = "str13", DbType = "text")]
        public string str13 { get; set; }
        [Column(Name = "str14", DbType = "text")]
        public string str14 { get; set; }
        [Column(Name = "str15", DbType = "text")]
        public string str15 { get; set; }
        [Column(Name = "str16", DbType = "text")]
        public string str16 { get; set; }
        public string getInsertcmd()
        {
            return "INSERT OR REPLACE INTO texts VALUES ("
                + id.ToString() + ",'"
                + name.Replace("'", "''") + "','"
                + desc.Replace("'", "''") + "','"
                + str1.Replace("'", "''") + "','"
                + str2.Replace("'", "''") + "','"
                + str3.Replace("'", "''") + "','"
                + str4.Replace("'", "''") + "','"
                + str5.Replace("'", "''") + "','"
                + str6.Replace("'", "''") + "','"
                + str7.Replace("'", "''") + "','"
                + str8.Replace("'", "''") + "','"
                + str9.Replace("'", "''") + "','"
                + str10.Replace("'", "''") + "','"
                + str11.Replace("'", "''") + "','"
                + str12.Replace("'", "''") + "','"
                + str13.Replace("'", "''") + "','"
                + str14.Replace("'", "''") + "','"
                + str15.Replace("'", "''") + "','"
                + str16.Replace("'", "''") + "');";
        }
    }
    [Table(Name = "main.datas")]
    public class ids
    {
        [Column(Name = "id", IsPrimaryKey = true)]
        public Int64 id { get; set; }
        [Column(Name = "type")]
        public Int64 type { get; set; }

    }
    public class LittleGame:Form
    {
        PictureBox pb = new PictureBox();
        PictureBox foxpb = new PictureBox();
        System.Windows.Forms.Label lb = new System.Windows.Forms.Label();
        System.Windows.Forms.Label lb2 = new System.Windows.Forms.Label();
        int score = 100;
        int shoot = 0;
        int combo = 0;
        DateTime LastClickTime = DateTime.MinValue;        
        public LittleGame()
        {
            Text = "抓住大猩猩";
            Size = new System.Drawing.Size(800, 500);
            StartPosition = FormStartPosition.CenterParent;
            lb.Size = new Size(600, 20);
            lb.Location = new System.Drawing.Point(0,440);            
            lb.Font = new Font("宋体", 12F);
            lb.Text = "得分：" + score + "分";
            pb.Size = new Size(100,100);
            pb.SizeMode = PictureBoxSizeMode.Zoom;
            pb.BackColor = Color.Transparent;
            pb.Image = Image.FromFile(Application.StartupPath + "\\res\\3通过.png");              
            pb.Click += (object sender, EventArgs e) => {
                TimeSpan sec = new TimeSpan(DateTime.Now.Ticks - LastClickTime.Ticks);
                LastClickTime = DateTime.Now;
                int d = (int)Math.Floor((sec.TotalMilliseconds / 50));
                MouseEventArgs mea = e as MouseEventArgs;
                int a = (int)Math.Floor((double)(Math.Abs(mea.X - 50) / 5));
                int b = (int)Math.Floor((double)(Math.Abs(mea.Y - 50) / 5));
                combo = d > 20 ? 0 : combo + 1;
                int c = 100 - a * a - b * b - (d > 30 ? 60 : d) + (combo > 10 ? 10 : 0) + (combo > 30 ? 10 : 0) + (combo > 60 ? 10 : 0) + (combo > 100 ? 10 : 0);
                score += c > 0 ? c : 0;
                shoot++;                
                GamePlay(); 
            };
            lb2.Size = new Size(600, 20);
            lb2.Location = new System.Drawing.Point(600, 330);
            lb2.Font = new Font("宋体", 14F);
            lb2.Text = "好厉害！要加油哦！";
            lb2.Visible = false;
            foxpb.Size = new Size(100, 100);
            foxpb.SizeMode = PictureBoxSizeMode.Zoom;
            foxpb.BackColor = Color.Transparent;
            foxpb.Image = Image.FromFile(Application.StartupPath + "\\res\\hakunewakuwaku.png");            
            foxpb.Location = new Point(680,350);
            foxpb.Visible = false;
            Controls.Add(pb);
            Controls.Add(lb);
            Controls.Add(lb2);
            Controls.Add(foxpb);
        }
        public void GamePlay()
        {
            Random rd = new Random();            
            pb.Location = new System.Drawing.Point(rd.Next(0,70)*10, rd.Next(0, 38)*10);
            lb.Text = "得分：" + score + "分/平均：" + Math.Floor((double)(score / shoot)) + "分" + (combo > 10 ? "连击：" + combo + "combos" : "");
            if(combo > 10) { 
                foxpb.Visible=true;
                lb2.Visible = true;
                List<string> list = new List<string>() {
                    "好厉害！要加油哦！",
                    "得分越来越高了呢。",
                    "还能坚持的住吗？",
                    "白音还在看着哦？",
                    "目标是多少连击呢？",
                    "现在是"+combo+"连击",
                    "不断磨砺自己吧！",
                    "要好好瞄准哦？",
                    "反应太慢会断连的。",
                    "重要的可是气势哦！",
                    "不足的部分用勇气！",
                    "我也是加把劲骑士！",
                    "只要不停下鼠标……",
                    "化作闪耀的道路吧！",
                    "还不能停下来哦？",
                    "不，不要，不要停……",
                    "不会出现的哦？"
                };
                lb2.Text = list[rd.Next(0,15)];
            } else { 
                foxpb.Visible=false;
                lb2.Visible=false;
            }
        }
    }
    public class MqxsColorTable: ProfessionalColorTable
    {
        Color bgc = ColorTranslator.FromHtml("#121212");
        public bool flag { get; set; } = false;
        public MqxsColorTable() { }
        public MqxsColorTable(bool a) { flag = a; }
        public override Color MenuItemSelected => ColorTranslator.FromHtml("#0071d7");
        public override Color ImageMarginGradientBegin => flag ? bgc : Color.White;
        public override Color ImageMarginGradientMiddle => flag ? bgc : Color.White;
        public override Color ImageMarginGradientEnd => flag ? bgc : Color.White;
    }
    public enum LFStates:int
    {
        Forbidden = 0,
        Limited = 1,
        SubLimited = 2,
        UnLimited = 3,
        死刑 = 4
    }    
    public class CommonHandler
    {  
        public static string GetMD5(string path)
        {
            try
            {
                using (FileStream fStream = new FileStream(path,System.IO.FileMode.Open))
                {
                    MD5 md5 = new MD5CryptoServiceProvider();
                    byte[] retVal = md5.ComputeHash(fStream);
                    StringBuilder sb = new StringBuilder();
                    for (int i = 0; i < retVal.Length; i++)
                    {
                        sb.Append(retVal[i].ToString("X2"));
                    }
                    return sb.ToString();
                }
            }
            catch (Exception ex)
            {
                throw new Exception("md5 failed,error:" + ex.Message);
            }
        }
        public static bool dexf(string a, int b)
        {
            Dictionary<string, List<int>> list = new Dictionary<string, List<int>>
            {
                ["0"] = new List<int> { 0 },
                ["1"] = new List<int> { 1 },
                ["2"] = new List<int> { 2 },
                ["3"] = new List<int> { 1, 2 },
                ["4"] = new List<int> { 4 },
                ["5"] = new List<int> { 1, 4 },
                ["6"] = new List<int> { 2, 4 },
                ["7"] = new List<int> { 1, 2, 4 },
                ["8"] = new List<int> { 8 },
                ["9"] = new List<int> { 1, 8 },
                ["a"] = new List<int> { 2, 8 },
                ["b"] = new List<int> { 1, 2, 8 },
                ["c"] = new List<int> { 4, 8 },
                ["d"] = new List<int> { 1, 4, 8 },
                ["e"] = new List<int> { 2, 4, 8 },
                ["f"] = new List<int> { 1, 2, 4, 8 }
            };
            return list[a].Contains(b) ? true : false;
        }
        public static void CreateCDBFiles(string filePath)
        {
            if (!File.Exists(filePath))
            {
                SQLiteConnection.CreateFile(filePath);
                if (File.Exists(filePath))
                {
                    SQLiteConnection strconn = new SQLiteConnection("data source=" + filePath);
                    if (strconn.State != ConnectionState.Open)
                    {
                        strconn.Open();
                        SQLiteCommand cmd = strconn.CreateCommand();
                        cmd.Connection = strconn;
                        cmd.CommandText = "CREATE TABLE IF NOT EXISTS datas(id integer PRIMARY KEY NOT NULL,ot integer,alias integer,setcode integer,type integer,atk integer,def integer,level integer,race integer,attribute integer,category integer)";
                        cmd.ExecuteNonQuery();
                        cmd.CommandText = "CREATE TABLE IF NOT EXISTS texts(id integer PRIMARY KEY NOT NULL,name text,desc text,str1 text,str2 text,str3 text,str4 text,str5 text,str6 text,str7 text,str8 text,str9 text,str10 text,str11 text,str12 text,str13 text,str14 text,str15 text,str16 text)";
                        cmd.ExecuteNonQuery();
                    }
                    strconn.Close();
                }
            }
        }
    }
    public class SqliteDataContext : DataContext
    {
        public Table<ids> Idrows
        {
            get { return GetTable<ids>(); }
        }
        public Table<datas> Datarows
        {
            get { return GetTable<datas>(); }
        }
        public Table<texts> Textrows
        {
            get { return GetTable<texts>(); }
        }
        public SqliteDataContext(string connection, MappingSource mappingSource) : base(connection, mappingSource) { }
        public SqliteDataContext(IDbConnection connection, MappingSource mappingSource) : base(connection, mappingSource) { }
        public SqliteDataContext(string connectionString) : base(new SQLiteConnection(connectionString)) { }
        public SqliteDataContext(IDbConnection connection) : base(connection) { }
    }
    public class SettingData
    {
        public string ygopath { get; set; } = "";
        public bool pathcheck { get; set; } = false;
        public bool packDIY { get; set; } = true;
        public List<string> regs { get; set; }
    }
    public class sqldata
    {        
        public long code;
        public string name;
        public DateTime time;
        public texts cmdt { get; set; }
        public datas cmdd { get; set; }
        public LFStates LFState { get; set; }
        public sqldata(long c, DateTime dt, texts cdt, datas cdd, bool packDIY)
        {
            code = c; time = dt; cmdt = cdt; cmdd = packDIY ? cdd : CheckDatas(cdd, true); LFState = LFStates.UnLimited;
        }
        public sqldata(long code, LFStates lFState , string name)
        {
            this.code = code;
            LFState = lFState;
            this.name = name;            
        }
        public datas CheckDatas(datas cdd, bool packDIY)
        {
            if (packDIY) { cdd.ot = 4; }
            return cdd;
        }
        public string DataToString()
        {            
            return cmdd.getInsertcmd(); ;
        }
    }
    public class CDBTableHelper
    {
        public string openedfile = "";
        public List<long> cardlist = new List<long>();
        public List<long> cardlistex = new List<long>();
        public bool packDIY { get; set; } = true;
        public Dictionary<long, sqldata> cmds = new Dictionary<long, sqldata>();
        public void Dispose()
        {
            openedfile = "";
            cardlist.Clear();
            cardlistex.Clear();
            cmds.Clear();
        }
        public void Add(sqldata sqd, bool flag = true)
        {
            if (flag)
            {
                cardlist.Add(sqd.code);
            }
            else
            {
                cardlistex.Add(sqd.code);
            }
            cmds.Add(sqd.code, sqd);
        }
        public void AddFromCDB(string path)
        {
            FileInfo fsinfo = new FileInfo(path);            
            string constr = "Data Source=" + fsinfo.FullName + ";";
            SqliteDataContext db = new SqliteDataContext(constr);
            var datassets = (from q1 in db.Datarows select q1).ToList();
            var textssets = (from q2 in db.Textrows select q2).ToList();//.Skip(0).Take(30);    
            int maxlg = datassets.Count() > textssets.Count() ? datassets.Count() : textssets.Count();
            for (int i = 0; i < maxlg; i++)
            {
                var cardd = datassets[i];
                var cardt = textssets[i];
                var code = cardd.id;
                CardTypeInfo cti = new CardTypeInfo(cardd.type);
                var iflegaltype = cti.IsLegalType();
                if (cmds.ContainsKey(code))
                {
                    if ((fsinfo.LastWriteTime > cmds[code].time) && (!iflegaltype))//需要更新数据
                    {
                        cmds[code].time = fsinfo.LastWriteTime;
                        cmds[code].cmdd = cardd;
                        cmds[code].cmdt = cardt;
                    }
                }
                else//直接添加数据
                {
                    Add(new sqldata(code, fsinfo.LastWriteTime, cardt, cardd, packDIY), iflegaltype);
                }                
            }    
            db.Dispose();
        }
        public void EXEMission(SQLiteConnection cn, string tbn, List<string> lst, bool flag = true)
        {
            SQLiteTransaction ts = cn.BeginTransaction();
            string sql = "select " + lst.Aggregate("", (c, s) => c + (s + ",")).TrimEnd(',') + " from " + tbn;
            SQLiteDataAdapter dta = new SQLiteDataAdapter(sql, cn);
            SQLiteCommandBuilder scb = new SQLiteCommandBuilder(dta);
            dta.UpdateCommand = scb.GetUpdateCommand();
            DataSet DS = new DataSet();
            dta.FillSchema(DS, SchemaType.Source, "Temp");
            dta.Fill(DS, "Temp");
            DataTable DT = DS.Tables["Temp"];
            foreach (long codeid in (flag ? cardlist : cardlistex))
            {
                sqldata sqd = cmds[codeid];
                DataRow DR = DT.NewRow();
                var tpro = sqd.GetType().GetProperty(tbn == "datas" ? "cmdd" : "cmdt").GetValue(sqd, null);
                for (int i = 0; i < lst.Count; i++)
                {
                    DR[i] = tpro.GetType().GetProperty(lst[i]).GetValue(tpro, null);
                }
                if (!DT.Rows.Contains(DR[0])) DT.Rows.Add(DR);
            }
            dta.Update(DT);
            ts.Commit();
            DS.AcceptChanges();
            //释放资源
            dta.Dispose();
            DS.Clear();
        }
        public void Execute(string targetfile, bool flag = true)
        {
            List<string> datalist1 = new List<string> { "id", "ot", "alias", "setcode", "type", "atk", "def", "level", "race", "attribute", "category" };
            List<string> datalist2 = new List<string> { "id", "name", "desc", "str1", "str2", "str3", "str4", "str5", "str6", "str7", "str8", "str9", "str10", "str11", "str12", "str13", "str14", "str15", "str16" };
            if (flag) { cardlist.Sort(); } else { cardlistex.Sort(); }
            CommonHandler.CreateCDBFiles(targetfile);
            SQLiteConnection cn = new SQLiteConnection("Data Source=" + targetfile);
            cn.Open();
            EXEMission(cn, "datas", datalist1, flag);
            EXEMission(cn, "texts", datalist2, flag);
            cn.Close();
            cn.Dispose();
        }
        public void Remove(sqldata sqd)
        {            
            cardlist.Remove(sqd.code);
            cardlistex.Add(sqd.code);
            SqliteDataContext db = new SqliteDataContext("Data Source="+openedfile+";");            
            db.ExecuteCommand("delete from datas where id=" + sqd.code);
            db.ExecuteCommand("delete from texts where id=" + sqd.code);
            db.Dispose();
        }
    }
    public class CardTypeInfo
    {
        public CardTypeInfo(long cid)
        {
            string ctp = Convert.ToString(cid, 16);
            cdinit(ctp);
        }
        public CardTypeInfo(string ctp)
        {
            cdinit(ctp);
        }
        List<string> cardTypeList = new List<string> {
            "怪兽","魔法","陷阱","0x8",
            "通常","效果","融合","仪式",
            "陷阱怪兽","灵魂","同盟","二重",
            "调整","同调","衍生物","0x8000",
            "速攻","永续","装备","场地",
            "反击","反转","卡通","超量",
            "灵摆","特殊召唤","连接","0x8000000"
        };
        List<string> cardAttrList = new List<string>{
            "地","水","炎","风","光","暗","神"
        };
        List<string> cardRaceList = new List<string>{
            "战士族","魔法师族","天使族","恶魔族",
            "不死族","机械族","水族","炎族",
            "岩石族","鸟兽族","植物族","昆虫族",
            "雷族","龙族","兽族","兽战士族",
            "恐龙族","鱼族","海龙族","爬虫类族",
            "念动力族","幻神兽族","创造神族","幻龙族",
            "电子界族","幻想魔族"
        };
        List<string> cardTypeRules = new List<string>
        {
            "通常,效果,魔法,陷阱",
            "仪式,融合,同调,超量,连接,特殊召唤",
            "速攻,装备,永续,场地,仪式",
            "永续,反击"
        };
        Dictionary<string, bool> cardTypeDict = new Dictionary<string, bool>();
        public void cdinit(long cid, string name = "type")
        {
            cdinit(Convert.ToString(cid, 16), name);
        }
        public void cdinit(string ctp, string name = "type")
        {
            Dictionary<string, List<int>> list = new Dictionary<string, List<int>>
            {
                ["0"] = new List<int> { 0 },
                ["1"] = new List<int> { 1 },
                ["2"] = new List<int> { 2 },
                ["3"] = new List<int> { 1, 2 },
                ["4"] = new List<int> { 3 },
                ["5"] = new List<int> { 1, 3 },
                ["6"] = new List<int> { 2, 3 },
                ["7"] = new List<int> { 1, 2, 3 },
                ["8"] = new List<int> { 4 },
                ["9"] = new List<int> { 1, 4 },
                ["a"] = new List<int> { 2, 4 },
                ["b"] = new List<int> { 1, 2, 4 },
                ["c"] = new List<int> { 3, 4 },
                ["d"] = new List<int> { 1, 3, 4 },
                ["e"] = new List<int> { 2, 3, 4 },
                ["f"] = new List<int> { 1, 2, 3, 4 }
            };
            for (int i = 0; i < ctp.Length; i++)
            {
                if (list.ContainsKey(ctp[ctp.Length - 1 - i].ToString()))
                {
                    foreach (int item in list[ctp[ctp.Length - 1 - i].ToString()])
                    {
                        if (item > 0)
                        {
                            string temp = "";
                            switch (name)
                            {
                                case "type":
                                    temp = cardTypeList[i * 4 + item - 1];
                                    break;
                                case "attr":
                                    temp = cardAttrList[i * 4 + item - 1];
                                    break;
                                case "race":
                                    temp = cardRaceList[i * 4 + item - 1];
                                    break;
                                default:
                                    break;
                            }
                            cardTypeDict[temp] = true;
                        }
                    }
                }
            }
        }
        public int GetLevel(long lv)
        {
            string rt = Convert.ToString(lv, 16);
            rt = rt.Length >= 2 ? rt.Substring(rt.Length - 1, 1) : rt;
            return Convert.ToInt32(rt, 16);
        }
        public int GetRank(long lv)
        {
            string rt = Convert.ToString(lv, 16);
            rt = rt.Length >= 4 ? rt.Substring(rt.Length - 2, 1) : rt;
            return Convert.ToInt32(rt);
        }
        public bool IsCardType(string typeName)
        {
            return cardTypeDict.ContainsKey(typeName) ? cardTypeDict[typeName] : false;
        }
        public bool IsCardAttribute(string attrName)
        {
            return IsCardType(attrName);
        }
        public bool IsCardRace(string raceName)
        {
            return IsCardType(raceName + "族");
        }
        public bool IsLegalType()
        {
            //匹配性检查
            int ctpc = cardTypeDict.Keys.Count;
            int index = 1;
            foreach (var item in new List<string> { "怪兽", "魔法", "陷阱" })
            {
                if (cardTypeDict.ContainsKey(item))
                {
                    if (ctpc == 0 || (ctpc == 1 && item == "怪兽")) { return false; }//无种类或仅有怪兽时
                    if (ctpc == 1 && index > 1) { return true; }//仅有魔法、陷阱时
                    string mted = "";
                    foreach (var ctemp in cardTypeRules[index].Split(','))
                    {//2种类时必须满足魔法和陷阱条件
                        if (cardTypeDict.ContainsKey(ctemp))
                        {
                            if (ctpc <= 2) { return true; }
                            else if (mted == "") { mted = ctemp; }
                            else { return false; } //大于3时匹配到多个条件，进行唯一性检查
                        }
                    }
                }
                index++;
            }
            //多种类的冲突性检查
            foreach (var ctRule in cardTypeRules)
            {
                bool legaled1 = false; bool legaled2 = false;
                foreach (var item in ctRule.Split(','))
                {
                    if (legaled2) { return false; }
                    else
                    {
                        legaled2 = legaled1 ? (cardTypeDict.ContainsKey(item) ? cardTypeDict[item] : false) : legaled2;
                        legaled1 = legaled1 ? legaled1 : (cardTypeDict.ContainsKey(item) ? cardTypeDict[item] : false);
                    }
                }
            }
            return true;
        }
        public bool IsNeedScript()
        {
            if (cardTypeDict.ContainsKey("效果"))
            {
                return true;
            }
            else {
                if (cardTypeDict.ContainsKey("通常"))
                {
                    return false;
                }
                else
                {
                    if (cardTypeDict.ContainsKey("魔法") || cardTypeDict.ContainsKey("陷阱"))
                    {
                        return true;
                    }
                    else
                    {
                        //ex白板、衍生物
                        return false;
                    }
                }
            }
        }
        public string CardTypeFormat(string ex = "", string patt = "|", string name = "type", string prefix = "", string suffix = "")
        {
            string rt = "";
            var exName = ex.Split(',');
            foreach (var cardTypeName in cardTypeDict.Keys)
            {
                if (cardTypeDict[cardTypeName] && !exName.Contains(cardTypeName))
                {
                    switch (name)
                    {
                        case "type":
                            if (cardTypeList.Contains(cardTypeName)) { rt += cardTypeName + patt; }
                            break;
                        case "attr":
                            if (cardAttrList.Contains(cardTypeName)) { rt += cardTypeName + patt; }
                            break;
                        case "race":
                            if (cardRaceList.Contains(cardTypeName)) { rt += cardTypeName + patt; }
                            break;
                        default:
                            break;
                    }
                }
            }
            return (prefix + rt + suffix).TrimEnd('|');
        }
    }    
}