private TileDay CreateOrGetDay(DateTime date, string fullPath, string relPath, out bool wasCreated) { wasCreated = false; var day = Days.FirstOrDefault((d) => d != null ? d.Date == date : false); if (day == null) { wasCreated = true; day = new TileDay() { FullPath = fullPath, RelativePath = relPath, Date = date/*, LastGroupZ = lastZ, LastGroupDeltaZ = lastDeltaZ*/ }; // Propagate with additional context. day.TileDataChanged += (s, e) => { if (e.Context.Day.Tile.HaveAcquisition) { double z; if (Double.IsNaN(e.Context.Day.Tile.Contents.DeltaZ)) { // Current tile DeltaZ has never been set - try to set. if (this.ZIndexZValueMap.TryGetValue(e.Context.Day.Tile.Contents.LatticePosition.Z - 1, out z)) { e.Context.Day.Tile.Contents.DeltaZ = e.Context.Day.Tile.Contents.Position.Z - z; } else { // If this tile is in the lowest Z index, make it zero. if (this.ZIndexZValueMap.Count == 0 || this.ZIndexZValueMap.Keys.OrderBy(x => x).FirstOrDefault() >= e.Context.Day.Tile.Contents.LatticePosition.Z) { e.Context.Day.Tile.Contents.DeltaZ = 0; } } } var shouldUpdateDeltaZ = false; // See if this is a new minimum for this lattice z index. if (this.ZIndexZValueMap.TryGetValue(e.Context.Day.Tile.Contents.LatticePosition.Z, out z)) { if (e.Context.Day.Tile.Contents.Position.Z < z) { z = e.Context.Day.Tile.Contents.Position.Z; ZIndexZValueMap[e.Context.Day.Tile.Contents.LatticePosition.Z] = z; shouldUpdateDeltaZ = true; } } else { // We don't have an entry yet, this is the new minimum for this ZIndex. z = e.Context.Day.Tile.Contents.Position.Z; ZIndexZValueMap[e.Context.Day.Tile.Contents.LatticePosition.Z] = z; shouldUpdateDeltaZ = true; } if (shouldUpdateDeltaZ) { // Update the delta Z for any tiles in the next layer that have not been set. Only needed when tiles are discovered out of order or there was something incomplete. var tiles = this.Days.Where((d) => { return (d != null) && (d.Index >= e.Context.Day.Index); }) .SelectMany(d => d.Groups) .SelectMany(g => g.Tiles) .Where(t => (t.Contents.LatticePosition.Z == e.Context.Day.Tile.Contents.LatticePosition.Z + 1)); tiles.All(t => { t.Contents.DeltaZ = t.Contents.Position.Z - z; return true; } ); // TODO also, if everything in the next layer is 0 (it thought it was the first Z index, then update to a real value. } if (e.Action == TileStateChangeAction.Add || e.Action == TileStateChangeAction.Changed || e.Action == TileStateChangeAction.Complete) { if (Lattice.AddTile(e.Context.Day.Tile)) { OnPropertyChanged("DuplicateGrids"); } } else if (e.Action == TileStateChangeAction.Remove) { // TODO Remove duplicate. } } e.SetMonitorId(Id); RaiseTileDataChanged(e); }; // Just propagate. day.IncompleteCollectionChanged += (s, e) => { OnPropertyChanged("IncompleteTiles"); OnCollectionChanged(IncompleteCollectionChanged, e); }; // Just propagate. day.TileCollectionChanged += (s, e) => OnCollectionChanged(TileCollectionChanged, e); // The first day a monitor sees must be the first day of the acquisition. At that point days can come in // any order. However, there is no support for shifting days if an earlier first day arrives. Deserialization // explicitly sorts by index and the initial scan explicitly scans and sorts day directories and submits to // the monitor before scanning group directories or tiles to enforce this. if (Days.Count == 0) { day.Index = 0; Days.Add(day); } else { int index = (int)Math.Round((date - Days[0].Date).TotalDays); day.Index = index; while (Days.Count <= index) { Days.Add(null); } Days[index] = day; } OnPropertyChanged("Days"); } return day; }
private void ScanForTileGroups(TileDay tileDay, bool isBeyondEmergingThreshold) { var groups = Directory.GetDirectories(tileDay.FullPath, "0?", SearchOption.TopDirectoryOnly).OrderBy(s => s); List<TileGroup> validGroups = new List<TileGroup>(); foreach (var groupFullPath in groups) { bool wasCreated; TileGroup tileGroup = tileDay.CreateOrGetTileGroup(groupFullPath, out wasCreated); if (tileGroup == null) { Trace.TraceError("\t\tFailed to create Tile Group object for {0} even though it matches the required naming pattern.", groupFullPath); continue; } validGroups.Add(tileGroup); if (wasCreated) { Trace.TraceInformation("\t\t{0} was an unrecognized Tile Group and has been added.", groupFullPath); } else { Trace.TraceInformation("\t\t{0} is an existing known Tile Group from earlier scans or deserialization.", groupFullPath); } } if (isBeyondEmergingThreshold) { // Do not monitor (or stop monitoring) for emerging files on days that are earlier than some threshold. UpdateHistorialTileGroupWorkers(validGroups); } else { UpdateTileGroupWorkers(validGroups); } }