public void SetData(FFXIVLogDataSet dataset) { this.ffxivLogDataSet1 = dataset; string member = bindingSource1.DataMember; bindingSource1.DataSource = dataset; bindingSource1.DataMember = member; bindingSource2.DataSource = dataset; bindingSource2.DataMember = member; if (ffxivLogDataSet1.Anaylzed.Count > 0) { label1.Text = String.Format("{0} - {1}", ffxivLogDataSet1.Anaylzed[0].LocalTime, ffxivLogDataSet1.Anaylzed[ffxivLogDataSet1.Anaylzed.Count - 1].LocalTime.ToString("MM/dd HH:mm:ss")); } if (dataGridView1.Rows.Count > 0) { dataGridView1.Rows[0].Selected = true; } if (dataGridView2.Rows.Count > 0) { dataGridView2.Rows[dataGridView2.Rows.Count - 1].Selected = true; } UpdateFilter1(); UpdateFilter2(); }
public PivotA(FFXIVLogDataSet.AnaylzedRow[] rows) { foreach (FFXIVLogDataSet.AnaylzedRow row in rows) { DataRow newrow = ds.Anaylzed.NewRow(); newrow.ItemArray = row.ItemArray; ds.Anaylzed.AddAnaylzedRow((FFXIVLogDataSet.AnaylzedRow) newrow); } Tree = new TreeElementA(); Tree.ds = ds; RowLabels = new List<string>(); Filters = new List<string>(); Expressions = new List<string>(); RowLabels.Add("From"); RowLabels.Add("ActionName"); RowLabels.Add("To"); //Expressions.Add("Sum(Numeric)"); //Expressions.Add("Count(Numeric)"); //Expressions.Add("Avg(Numeric)"); //Expressions.Add("Max(Numeric)"); //Expressions.Add("Min(Numeric)"); //Expressions.Add("Min(TotalSeconds)"); //Expressions.Add("Max(TotalSeconds)"); //めちゃくちゃやねw Tree.RowLabels = RowLabels; Tree.Expressions = Expressions; }
private void EffectAnalyze(FFXIVLogDataSet.AnaylzedRow arow, FFXIVLog log) { string _logstring = log.LogBodyReplaceTabCode; Regex buffRegex = new Regex(@": ⇒ (?<to>.+)に「(?<buff>[^」]+)」の(?<on>効果)。|(?<to>[^:\s⇒].+)の「(?<buff>[^」]+)」が(?<off>切れた)。"); Match match = buffRegex.Match(_logstring); if (match.Groups["on"].Value != "") { arow.IsBuffOn = true; } else if (match.Groups["off"].Value != "") { arow.IsDebuffRemove = true; } arow.To = NameConvertTo(log,match.Groups["to"].Value); arow.From = NameConvertFrom(log,match.Groups["from"].Value); arow.BuffName = match.Groups["buff"].Value; if (arow.From == "") { SearchAction(arow, log); } if (arow.IsBuffOn && !arow.IsBuffNameNull()) { FFXIVLogDataSet.ActionRow action = null; if (arow.BuffName == "桜花狂咲") { action = ds.Action.FindByName("桜華狂咲"); } else { action = ds.Action.FindByName(arow.BuffName); } if (action != null) { SetDotSpace(arow); } } if (arow.IsBuffRemove && !arow.IsBuffNameNull()) { FFXIVLogDataSet.ActionRow action = ds.Action.FindByName(arow.BuffName); if (action ==null && arow.BuffName == "桜花狂咲") { action = ds.Action.FindByName("桜華狂咲"); } if (action != null) { CloseDot(arow.To, arow, false); } } }
private void CureAnalyze(FFXIVLogDataSet.AnaylzedRow arow, FFXIVLog log) { string _logstring = log.LogBodyReplaceTabCode; Regex actionStartRegex = new Regex(@":\s\s⇒\s(|(?<crit>クリティカル!)\s)(?<to>[^!]+)[は](|(?<dodge>[^\d\s]*)\s)(?<num>\d+)(|\((?<bonus>[+-]\d+)\%\))(?<hpmp>\w+)(回復|吸収)"); Match match = actionStartRegex.Match(_logstring); arow.IsCure = true; arow.To = NameConvertTo(log,match.Groups["to"].Value); arow.From = NameConvertFrom(log,match.Groups["from"].Value); arow.ActionName = match.Groups["action"].Value; if(match.Groups["num"].Value!="") { arow.Numeric = Convert.ToInt32(match.Groups["num"].Value, 10); } if (match.Groups["hpmp"].Value == "HP") { arow.IsHP = true; } else if (match.Groups["hpmp"].Value == "TP") { arow.IsTP = true; } else if (match.Groups["hpmp"].Value == "MP") { arow.IsMP = true; } if (match.Groups["crit"].Value != "") { arow.IsCritical = true; } if (arow.From == "") { if (!log.LogBodyReplaceTabCode.Contains("吸収")) { SearchAction(arow, log); } else { } } }
/// <summary> /// 倒した倒された力尽きた /// </summary> /// <param name="arow"></param> /// <param name="log"></param> private void KOAnaylyze(FFXIVLogDataSet.AnaylzedRow arow, FFXIVLog log) { string _logstring = log.LogBodyReplaceTabCode; Regex koRegex = new Regex(@":(?<to>.+)は、力尽きた。|:(?<to>.+)は、(?<from>.+)に倒された。|:(?<from>.+)は、(?<to>.+)を倒した。"); Match match = koRegex.Match(_logstring); if (match.Success) { arow.IsKO = true; arow.To = NameConvertTo(log, match.Groups["to"].Value); arow.From = NameConvertFrom(log, match.Groups["from"].Value); FFXIVLogDataSet.EnemyGroupRow eg = ds.EnemyGroup.FindByName(arow.To); if (eg != null && (arow.FLAG_WHO == (int)LOG_CATEGORY_WHO.MYSELF || arow.FLAG_WHO == (int)LOG_CATEGORY_WHO.PTMEMBER)) { eg.KOCount ++; if (eg.KOCount > eg.Count) { eg.Count = eg.KOCount; } } } }
/// <summary> /// コンテンツの開始終了 /// </summary> /// <param name="arow"></param> /// <param name="log"></param> private void ContentStartEnd(FFXIVLogDataSet.AnaylzedRow arow, FFXIVLog log) { string _logstring = log.LogBodyReplaceTabCode; Regex contentStartRegex = new Regex(@":「(?<content>.+)」の攻略を開始した。"); Match match = contentStartRegex.Match(_logstring); if (match.Success) { arow.IsContentStart = true; arow.ContentName = match.Groups["content"].Value; ds.ContentRegion.AddContentRegionRow(arow.ID, -1, arow.ContentName, true, false); } Regex contentEndRegex = new Regex(@":[^「]*?「(?<content>.+)」の攻略を終了した。"); match = contentEndRegex.Match(_logstring); if (match.Success) { arow.IsContentEnd = true; arow.ContentName = match.Groups["content"].Value; FFXIVLogDataSet.ContentRegionRow[]rows= (FFXIVLogDataSet.ContentRegionRow[]) ds.ContentRegion.Select(String.Format("ContentName = '{0}'",arow.ContentName.Replace("'","''"))); if (rows.Length > 0) { rows[rows.Length - 1].EndLogID = arow.ID; } } //:「(?<content>.+)」の攻略を開始した。 }
/// <summary> /// レベルシンクの開始と終了 /// </summary> /// <param name="arow"></param> /// <param name="log"></param> private void LevelSyncStartEnd(FFXIVLogDataSet.AnaylzedRow arow, FFXIVLog log) { string _logstring = log.LogBodyReplaceTabCode; Regex LevelSyncRegex = new Regex(@":レベル(?<level>\d+)にシンクされました。"); Match match = LevelSyncRegex.Match(_logstring); if (match.Success) { arow.SyncLevel = Convert.ToInt32(match.Groups["level"].Value, 10); arow.IsLevelSyncStart = true; } Regex LevelSyncEndRegex = new Regex(@":レベルシンクが解除されました。"); if (LevelSyncEndRegex.Match(_logstring).Success) { arow.IsLevelSyncEnd = true; } }
private void CloseDot(string to, FFXIVLogDataSet.AnaylzedRow arow, bool all) { FFXIVLogDataSet.EnemyGroupRow eg = ds.EnemyGroup.FindByName(to); if (eg != null) { FFXIVLogDataSet.AnaylzedRow[] effectrows = (FFXIVLogDataSet.AnaylzedRow[])ds.Anaylzed.Select(String.Format("ID >= {0} and IsEffecton = true and To = '{1}' and DotEndSeconds is null", eg.FirstID, to.Replace("'", "''")), "ID"); List<string> effects = new List<string>(); foreach (FFXIVLogDataSet.AnaylzedRow row in effectrows) {//DEBUG if (all) { row.DotEndSeconds = arow.TotalSeconds; } else if (!effects.Contains(row.EffectName)) { effects.Add(row.EffectName); } else { row.DotEndSeconds = arow.TotalSeconds; } } } }
public void SetData(FFXIVLogDataSet ds) { _dataset = ds; bindingSource1.DataSource = _dataset; bindingSource1.DataMember = "Anaylzed"; }
public FF14LogParser() { ds = new FFXIVLogDataSet(); ds.Anaylzed.TableCleared += new DataTableClearEventHandler(Anaylzed_TableCleared); SetAction(); }
/// <summary> /// ダメージ系のアナライズ /// </summary> /// <param name="arow"></param> /// <param name="log"></param> private void HitAnalyze(FFXIVLogDataSet.AnaylzedRow arow, FFXIVLog log) { //敵視UPの場合 if (log.LogBodyReplaceTabCode.Contains("敵視をアップ")) { Regex HateRegex = new Regex(@": ⇒ (?<to>.+)の敵視をアップ。"); Match match = HateRegex.Match(log.LogBodyReplaceTabCode.Replace("{022705CF01010103}", "").Replace("{0227050101010103}", ""));// System.Diagnostics.Debug.Write(log.LogBody); arow.To = NameConvertTo(log,match.Groups["to"].Value); arow.IsDamage = true; arow.IsHate = true; SearchAction(arow, log); return; } else { Regex HitRegex = new Regex(@":(\s|(?<from>.+)の(?<action>攻撃))\s⇒\s(|(?<crit>クリティカル!)\s)(?<to>[^!]+)[はに](|(?<dodge>[^\d\s]*)\s)(?<dmg>\d+)(|\((?<bonus>[+-]\d+)\%\))ダメージ"); arow.IsDamage = true;//ダメージタイプである arow.IsHP = true;//HPに影響する Match match = HitRegex.Match(log.LogBodyReplaceTabCode.Replace("{022705CF01010103}", "").Replace("{0227050101010103}", "")); //System.Diagnostics.Debug.Write(log.LogBody); arow.From = NameConvertFrom(log,match.Groups["from"].Value); arow.To = NameConvertTo(log,match.Groups["to"].Value); arow.ActionName = match.Groups["action"].Value; if (match.Groups["dmg"].Value != "") { arow.Numeric = Convert.ToInt32(match.Groups["dmg"].Value,10); } arow.IsCritical = match.Groups["crit"].Value != ""; if (match.Groups["bonus"].Value != "") { arow.BonusRate = Convert.ToInt32(match.Groups["bonus"].Value); } if (match.Groups["dodge"].Value.Contains("ブロック")) { arow.IsBlock = true; } if (match.Groups["dodge"].Value.Contains("受け流し")) { arow.IsParry = true; } } if (arow.From == "") { SearchAction(arow, log); } if (arow.IsFromNull()) arow.From = FF14LogParser.UnknownName; if (arow.IsActionNameNull()) arow.ActionName = FF14LogParser.UnknownName; //int damage = Convert.ToInt32(match.Groups["damage"].Value,10); //int bonus = Convert.ToInt32(match.Groups["bonus"].Value,10); //string to = match.Groups["to"].Value; }
/// <summary> /// 実行した中断したの分析 /// </summary> /// <param name="arow"></param> /// <param name="log"></param> private void ActionStartDoneAnalyze(FFXIVLogDataSet.AnaylzedRow arow, FFXIVLog log) { Regex ActionRegex = new Regex(@":(ターゲットが範囲外のため、|)(?<from>[^:\s⇒].+)[はの]「(?<action>[^」]+)」"); string _logstring = log.LogBodyReplaceTabCode; Match match = ActionRegex.Match(_logstring); arow.ActionName = match.Groups["action"].Value; if (log.LogBodyReplaceTabCode.Contains("中断した")) { arow.IsInterrupted = true; } else if (log.LogBodyReplaceTabCode.Contains("中断された")) { arow.IsInterrupted = true; } else if (log.LogBodyReplaceTabCode.Contains("の構え") || log.LogBodyReplaceTabCode.Contains("を唱えた")) { arow.IsStarted = true; } else { arow.IsDone = true; } arow.ActionName= match.Groups["action"].Value; arow.From = NameConvertFrom(log,match.Groups["from"].Value); }
/// <summary> /// ミス解析 /// </summary> /// <param name="arow"></param> /// <param name="log"></param> private void DodgeAnalyze(FFXIVLogDataSet.AnaylzedRow arow, FFXIVLog log) { Regex dodgeRegex = new Regex(@":(\s|(?<from>.+)の(?<action>攻撃))\s⇒\s(?<to>.+)にミス|: ⇒ (?<to>.+)は「(?<action>[^」]+)」をレジストした。|: ⇒ (?<to>.+)に効果なし。|: ⇒ (?<to>.+)はレジストした!"); arow.IsDodge = true; string _logstring = log.LogBodyReplaceTabCode; Match match = dodgeRegex.Match(_logstring); arow.ActionName = match.Groups["action"].Value; arow.To =NameConvertTo(log, match.Groups["to"].Value); //System.Diagnostics.Debug.Assert(arow.To != ""); arow.From =NameConvertFrom(log, match.Groups["from"].Value); if (arow.From == "") { SearchAction(arow, log); } }
/// <summary> /// データをリセットするか /// </summary> /// <param name="arow"></param> private void CheckReset(FFXIVLogDataSet.AnaylzedRow arow) { if (ResetID_Box.Checked) { //インスタンスダンジョン if (arow.IsContentStart) { button1_Click(this, null); SetStatus(String.Format("「{0}」が開始されました。DPSをリセットしました。", arow.ContentName)); } } if (FFXIVLog.GetLOG_TYPE(arow.ActionType) == LOG_CATEGORY_TYPE.GAME_EVENT) { if (arow.Body.Contains("封鎖まで") && ResetClose_Box.Checked) { button1_Click(this, null); SetStatus(String.Format("「{0}」 DPSをリセットしました。", arow.Body)); } if (arow.IsLevelSyncStart && ResetLevelSync_Box.Checked) button1_Click(this, null); if (arow.Body.Contains("チェンジした") && ResetClose_Box.Checked) { SetStatus(String.Format("「{0}」 DPSをリセットしました。", arow.Body)); button1_Click(this, null); } } }
private void SearchAction(FFXIVLogDataSet.AnaylzedRow arow, FFXIVLog log) { List<string> bodyList = new List<string>(); bodyList.Add(log.LogBodyReplaceTabCode); List<int> parentLogtypes = new List<int>(GetParentActionLogTypes(arow)); if (parentLogtypes.Count == 0) { return; } for (int i = ds.Anaylzed.Count - 2; i >= 0; i--) { FFXIVLogDataSet.AnaylzedRow ActionRow = ds.Anaylzed[i]; bodyList.Insert(0, ActionRow.Body); int minLogType = (int)log.LogType / 4 * 4; if(parentLogtypes.Contains(ActionRow.LogType) && (ActionRow.ActionType == 0xAB || ActionRow.ActionType == 0x2B)) { arow.ActionName = ds.Anaylzed[i].ActionName; arow.From = ds.Anaylzed[i].From; ActionRow.To = arow.To; break; } else if (ActionRow.TotalSeconds < log.TotalSeconds - 1)//2秒猶予 { arow.ActionName = FF14LogParser.UnknownName; arow.From = FF14LogParser.UnknownName; break; } } }
private void SetDotSpace(FFXIVLogDataSet.AnaylzedRow arow) { if (!arow.IsEffectOn) return ; FFXIVLogDataSet.ActionRow action = ds.Action.FindByName(arow.EffectName); if (action == null && arow.EffectName == "桜花狂咲") { action = ds.Action.FindByName("桜華狂咲"); } if (action == null || action.Dot威力 == 0) { return;//DOT以外は除外 } arow.IsDot = true; arow.Dot_Iryoku = action.Dot威力; arow.DotSecs = action.効果時間; DotRowList.Add(arow); if (arow.IsFromNull() || arow.From == "" || arow.From == FF14LogParser.UnknownName) return ; FFXIVLogDataSet.ActorRow actor = ds.Actor.FindByName(arow.From); ////DDダメージを取得 if (!actor.IsDamageBaseNull()) { arow.DamageBase = actor.DamageBase; } if (actor.IsNPC || actor.IsOther) { arow.DotSecs = action.効果時間;//NPC, OTHER はMAXのデフォルトの効果時間 return ; } //上書き、効果時間の判定 //効果時間内の同じアクション FFXIVLogDataSet.AnaylzedRow[] sames = (FFXIVLogDataSet.AnaylzedRow[])ds.Anaylzed.Select(String.Format("ID < {0} and IsEffecton = true and EffectName = '{1}' and To = '{2}' and TotalSeconds > {3} and From = '{4}'", arow.ID, action.Name, arow.To.Replace("'", "''"), arow.TotalSeconds - action.効果時間, arow.From.Replace("'", "''"))); if (sames.Length > 0) { FFXIVLogDataSet.AnaylzedRow[] rows = (FFXIVLogDataSet.AnaylzedRow[])ds.Anaylzed.Select(String.Format("IsKo = false and ToType = 3 and To = '{0}' and EnemyGroupID = {1} and ID >= {2}", arow.To, arow.EnemyGroupID,sames[0].ID), "ID"); FFXIVLogDataSet.AnaylzedRow[] ko_rows = (FFXIVLogDataSet.AnaylzedRow[])ds.Anaylzed.Select(String.Format("IsKo = true and To = '{0}' and EnemyGroupID = {1} and ID > {2}", arow.To, arow.EnemyGroupID, sames[0].ID), "ID"); arow.DotSpace = sames[0].DotSpace + rows.Length - ko_rows.Length - 1; if (arow.DotSpace < 0) { arow.DotSpace = 0; sames[sames.Length-1].IsOverride = true;//上書きされた sames[sames.Length-1].DotEndSeconds = arow.TotalSeconds; } } else { FFXIVLogDataSet.EnemyGroupRow eg = ds.EnemyGroup.FindByName(arow.To); if (eg == null) { arow.DotSpace = 0; return; } arow.DotSpace = eg.Count - eg.KOCount - 1; if (arow.DotSpace < 0) { arow.DotSpace = 0; } else if (arow.DotSpace > 0) { } } }
/// <summary> /// ログタイプから親となるログタイプを推定 /// </summary> /// <param name="logtype"></param> /// <returns></returns> private int[] GetParentActionLogTypes(FFXIVLogDataSet.AnaylzedRow row) { int actiontype = row.ActionType; int logtype = row.LogType; List<int> res = new List<int>(); //効果が切れたが処理できない if (row.IsBuffRemove || row.IsDebuffRemove) { return res.ToArray(); } if (actiontype == 0xA9 || actiontype == 0x29 || actiontype == 0xAA || actiontype == 0xAD || actiontype == 0x2D || actiontype == 0xAF || actiontype == 0x2F || actiontype == 0xAE || actiontype == 0x2E) {//攻撃 攻撃 ミス 回復 回復 if (logtype >= 0x04 && logtype <= 0x07) { res.Add(0x04);//自分の発動 } else if (logtype >= 0x08 && logtype <= 0x0B) { res.Add(0x08);//PTの発動 } else if (logtype >= 0x0C && logtype <= 0x0F) { res.Add(0x0C);//Allyの発動 } else if (logtype >= 0x10 && logtype <= 0x13) { res.Add(0x10);//other pcの発動 } else if (logtype >= 0x14 && logtype <= 0x17) { res.Add(0x14);//enemyの発動 } else if (logtype >= 0x18 && logtype <= 0x1B) { res.Add(0x18);//npcの発動 } } return res.ToArray(); }
/// <summary> /// ログからレポートを作成する /// </summary> /// <param name="log"></param> /// <returns></returns> private string CreateReport(FFXIVLogDataSet.AnaylzedRow log) { //ダメージ //if (log.ActionType == 0xA9 || log.ActionType == 0x29)//A9と29があるのはなぜだろう //{ // if (!log.IsNumericNull()) // { // int fromTotal = rep.GetTotalDamage(log.From,0); // int fromtoTotal = rep.GetTotalDamage(log.From,log.To,0); // int toTotal = rep.GetTakenDamage(log.To,0); // double rateFrom = 100.0 *(double)fromtoTotal/(double)fromTotal; // double rateTo = 100.0 *(double)fromtoTotal/(double)toTotal; // return String.Format("{0}[{1}/{3}({2:0.00}%)] ⇒ {4}[{5}/{7}({6:0.00}%)]", // log.From,// 0 // fromtoTotal,// 1 // rateFrom,// 2 // fromTotal,// 3 // log.To,// 4 // fromtoTotal,//5 // rateTo,//6 // toTotal); // } //} return ""; }