/// <summary> /// 返回所有的事件记录中含有比 rect 的日期还要早的记录。 /// </summary> /// <param name="entries">存储事件链的模型类</param> /// <param name="rect">用于日期比较的目标方块</param> /// <returns></returns> private static List<StatistTotalByDateTime> EarlierThanEarliestRectangle(List<StatistTotalByDateTime> entries, Rectangle rect) { List<StatistTotalByDateTime> earlierThanEarliestRectangleLik = new List<StatistTotalByDateTime>(); foreach (var item in entries) { if (item.DateTime < DatetimeParser.ParseExpressToDateTime(rect.Name, DateMode.DateWithSlash)) { earlierThanEarliestRectangleLik.Add(item); } } return earlierThanEarliestRectangleLik; }
/// <summary> /// 该构造器接收一个字符串序列,把它转换成StatistTotalByDateTime链表,同时接收一个 DateMode 指示日期字符串的分割方式 /// </summary> /// <param name="lines">文本序列</param> /// <param name="dateMode">指示日期字符串的分割方式</param> public StatistTotalByDateTimeModel(IEnumerable <string> lines, DateMode dateMode) { foreach (var line in lines) { if (line != "" && line != "\r") // 忽略空行 { StatistTotalByDateTime statist = DatetimeParser.ParseExpressToStatistTotalByDateTime(line, dateMode); this.Add(statist); } } }
/// <summary> /// 打开文件选取器 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private async void OpenFileButtonAsync_Click(object sender, RoutedEventArgs e) { FileOpenPicker openPicker = new FileOpenPicker { ViewMode = PickerViewMode.Thumbnail, SuggestedStartLocation = PickerLocationId.ComputerFolder }; openPicker.FileTypeFilter.Add(".txt"); openPicker.FileTypeFilter.Add(".mast"); _file = await openPicker.PickSingleFileAsync(); if (_file != null) { ProgressBoard progressBoard = new ProgressBoard(); ProgressBoard.SlideOn(CurrentRectanglesCanvas, progressBoard); ResetRectangle(); // 每次选择文件之后都要重置方块颜色 Windows.Storage.AccessCache.StorageApplicationPermissions.FutureAccessList.Add(_file); string text = await FileIO.ReadTextAsync(_file); try { IEnumerable <string> lines = DatetimeParser.SplitByLine(text); _model = new StatistTotalByDateTimeModel(lines); ExtendStackCanvasByFilterOldRecorders(EarlierThanEarliestRectangle(_model.ToStatistTotalByDateTimeArray().ToList(), _earliestRectangle), _earliestRectangle); ProgressBoard.CancelOn(CurrentRectanglesCanvas, progressBoard); foreach (Canvas canvas in StackCanvas.Children) { ProgressBoard.SlideOn(canvas, new ProgressBoard()); } TioSalamanca[] res = _model.GroupDateTimesByTotal(); #if DEBUG for (int level = 0; level < res.Length; level++) { Debug.WriteLine($"level: {level + 1}"); Debug.WriteLine($" List res[{level}]:"); foreach (var group in res[level]) { Debug.WriteLine($" Total: {group.Key}"); foreach (var item in group) { Debug.WriteLine($" {item}"); } } } #endif DrawRectangleColor(res, false); } catch (ArgumentException err) { PopErrorDialogAsync(err.Message); } _saveMode = SaveMode.OrginalFile; // 表示当前的操作基于磁盘上已有的文件 } }
/// <summary> /// 筛选出没有在当前 RectanglesCanvas 面板中显示的、日期更久远的记录, /// 然后根据这些记录在 StackCanvas 面板中生成新的方块面板,接着在这些 /// 新生成的面板中着色日期更久远的记录。 /// </summary> private void ExtendStackCanvasByFilterOldRecorders(List<StatistTotalByDateTime> oldRecorders, Rectangle earliestRectangle, int canvasOrdinal = 1) { Canvas oldRectanglesCanvas = new Canvas() { Name = $"OldRectanglesCanvas_{canvasOrdinal}" }; Rectangle oldRect = this.RectanglesLayout(oldRectanglesCanvas, DatetimeParser.ParseExpressToDateTime(earliestRectangle.Name, DateMode.DateWithSlash).AddDays(-1)); DateTag(oldRectanglesCanvas); this.StackCanvas.Children.Insert(0, oldRectanglesCanvas); List<StatistTotalByDateTime> newOldRecorders = EarlierThanEarliestRectangle(oldRecorders, oldRect); if (newOldRecorders.Count > 0) { ExtendStackCanvasByFilterOldRecorders(newOldRecorders, oldRect, canvasOrdinal + 1); } }
/// <summary> /// 添加一个条目 /// </summary> /// <param name="rectName">接收一个字符串表达式,格式为“mm dd yyyy x{Total}”或“mm/dd/yyyy”</param> public void AddEntry(string rectName) { this.AddEntry(DatetimeParser.ParseExpressToStatistTotalByDateTime(rectName, DateMode.DateWithSlash)); }
/// <summary> /// 给相应的 Rectangle 标记上日期和星期数 /// </summary> /// <param name="canvas"></param> private static void DateTag(Canvas canvas) { /* * 下面的查询语句用来提取画布中最左侧的一列方块(res1)和最上侧的一行方块(res2), * 然后将这些方块标记上星期数和月份 */ IEnumerable<IGrouping<double, UIElement>> leftGroup = from rect in canvas.Children group rect by Canvas.GetLeft(rect); IEnumerable<IGrouping<double, UIElement>> topGroup = from rect in canvas.Children group rect by Canvas.GetTop(rect); double minLeftGroupKey = leftGroup.Min(group => group.Key); double minTopGroupKey = topGroup.Min(group => group.Key); IGrouping<double, UIElement> res1 = (from g in leftGroup where g.Key == minLeftGroupKey select g).First(); IGrouping<double, UIElement> res2 = (from g in topGroup where g.Key == minTopGroupKey select g).First(); /* * 给周一、周三、周五的方块打上标记 Mon、Wed、Fri */ foreach (Rectangle rect in res1) { if (DatetimeParser.ParseExpressToDateTime((rect as Rectangle).Name, DateMode.DateWithSlash).DayOfWeek == DayOfWeek.Monday || DatetimeParser.ParseExpressToDateTime((rect as Rectangle).Name, DateMode.DateWithSlash).DayOfWeek == DayOfWeek.Wednesday || DatetimeParser.ParseExpressToDateTime((rect as Rectangle).Name, DateMode.DateWithSlash).DayOfWeek == DayOfWeek.Friday) { var tbx = new TextBlock() { Text = DatetimeParser.ParseExpressToDateTime((rect as Rectangle).Name, DateMode.DateWithSlash).DayOfWeek.ToString().Substring(0, 3), FontSize = 10, Foreground = new SolidColorBrush(Windows.UI.Colors.Gray) }; Canvas.SetLeft(tbx, Canvas.GetLeft(rect) - 30); Canvas.SetTop(tbx, Canvas.GetTop(rect)); canvas.Children.Add(tbx); } } /* * 给每个月份开头的方块打上标记,从 Jan 到 Dec */ Rectangle previous = null; foreach (Rectangle rect in res2.Reverse()) { void setTopTag(string text) { var tbx = new TextBlock() { Text = text, FontSize = 10, Foreground = new SolidColorBrush(Windows.UI.Colors.Gray) }; Canvas.SetLeft(tbx, Canvas.GetLeft(rect)); Canvas.SetTop(tbx, Canvas.GetTop(rect) - 15); canvas.Children.Add(tbx); } if (previous == null) { setTopTag(DatetimeParser.NumberToMonth(DatetimeParser.ParseExpressToDateTime(rect.Name, DateMode.DateWithSlash).Month)); } else { int monthOfPreviousRectangle = DatetimeParser.ParseExpressToDateTime(previous.Name, DateMode.DateWithSlash).Month; int monthOfCurrentRectangle = DatetimeParser.ParseExpressToDateTime(rect.Name, DateMode.DateWithSlash).Month; if (monthOfCurrentRectangle != monthOfPreviousRectangle) { setTopTag(DatetimeParser.NumberToMonth(DatetimeParser.ParseExpressToDateTime(rect.Name, DateMode.DateWithSlash).Month)); } } previous = rect; } }