public HexSectorSelector(ResourceManager resourceManager, Sector sector, Point coords, int jump) { if (resourceManager == null) throw new ArgumentNullException("resourceManager"); if (sector == null) throw new ArgumentNullException("sector"); m_sector = sector; m_resourceManager = resourceManager; m_coords = coords; m_jump = jump; }
public HexSectorSelector(ResourceManager resourceManager, Sector sector, Hex coords, int jump) { if (resourceManager == null) throw new ArgumentNullException("resourceManager"); if (sector == null) throw new ArgumentNullException("sector"); this.sector = sector; this.resourceManager = resourceManager; this.coords = coords; this.jump = jump; }
public HexSelector(SectorMap map, ResourceManager resourceManager, Location location, int jump) { if (map == null) throw new ArgumentNullException("map"); if (resourceManager == null) throw new ArgumentNullException("resourceManager"); if (jump < 0 || jump > 36) throw new ArgumentOutOfRangeException("jump", jump, "jump must be between 0 and 36 inclusive"); m_map = map; m_resourceManager = resourceManager; m_location = location; m_jump = jump; }
public SubsectorSelector(ResourceManager resourceManager, Sector sector, int index) { if (resourceManager == null) throw new ArgumentNullException("resourceManager"); if (sector == null) throw new ArgumentNullException("sector"); if (index < 0 || index >= 16) throw new ArgumentOutOfRangeException("index", "index must be 0...15"); m_sector = sector; m_index = index; m_resourceManager = resourceManager; }
public SectorSelector(ResourceManager resourceManager, Sector sector) { if (resourceManager == null) throw new ArgumentNullException("resourceManager"); if (sector == null) throw new ArgumentNullException("sector"); m_sector = sector; m_resourceManager = resourceManager; }
public RectSelector(SectorMap map, ResourceManager resourceManager, RectangleF rect) { if (map == null) throw new ArgumentNullException("map"); if (resourceManager == null) throw new ArgumentNullException("resourceManager"); m_map = map; m_resourceManager = resourceManager; m_rect = rect; }
public void Resolve(SectorMap sectorMap, ResourceManager resourceManager, out Sector sector, out World world) { if (sectorMap == null) throw new ArgumentNullException("sectorMap"); sector = null; world = null; sector = sectorMap.FromLocation(Sector.X, Sector.Y); if (sector == null) return; WorldCollection worlds = sector.GetWorlds(resourceManager, cacheResults: true); if (worlds != null) world = worlds[World.X, World.Y]; }
internal void Serialize(ResourceManager resourceManager, TextWriter writer, string mediaType, bool includeMetadata = true, bool includeHeader = true, bool sscoords = false, WorldFilter filter = null) { WorldCollection worlds = GetWorlds(resourceManager); // TODO: less hacky T5 support bool isT5 = (mediaType == "TabDelimited" || mediaType == "SecondSurvey"); if (mediaType == "TabDelimited") { if (worlds != null) worlds.Serialize(writer, mediaType, includeHeader: includeHeader, filter: filter); return; } if (includeMetadata) { // Header // writer.WriteLine("# Generated by http://travellermap.com"); writer.WriteLine("# " + DateTime.Now.ToString("yyyy-MM-ddTHH:mm:sszzz", DateTimeFormatInfo.InvariantInfo)); writer.WriteLine(); writer.WriteLine("# {0}", Names[0]); writer.WriteLine("# {0},{1}", X, Y); writer.WriteLine(); foreach (var name in Names) { if (name.Lang != null) writer.WriteLine("# Name: {0} ({1})", name.Text, name.Lang); else writer.WriteLine("# Name: {0}", name); } if (Credits != null) { string stripped = Regex.Replace(Credits, "<.*?>", ""); stripped = Regex.Replace(stripped, @"\s+", " "); stripped = stripped.Trim(); writer.WriteLine(); writer.WriteLine("# Credits: {0}", stripped); } if (DataFile != null) { writer.WriteLine(); if (DataFile.Era != null) { writer.WriteLine("# Era: {0}", DataFile.Era); } writer.WriteLine(); if (DataFile.Author != null) { writer.WriteLine("# Author: {0}", DataFile.Author); } if (DataFile.Publisher != null) { writer.WriteLine("# Publisher: {0}", DataFile.Publisher); } if (DataFile.Copyright != null) { writer.WriteLine("# Copyright: {0}", DataFile.Copyright); } if (DataFile.Source != null) { writer.WriteLine("# Source: {0}", DataFile.Source); } if (DataFile.Ref != null) { writer.WriteLine("# Ref: {0}", DataFile.Ref); } } writer.WriteLine(); for (int i = 0; i < 16; ++i) { char c = (char)('A' + i); Subsector ss = Subsector(c); writer.WriteLine("# Subsector {0}: {1}", c, ss?.Name ?? ""); } writer.WriteLine(); } if (worlds == null) { if (includeMetadata) writer.WriteLine("# No world data available"); return; } // Allegiances if (includeMetadata) { // Use codes as present in the data, to match the worlds foreach (string code in worlds.AllegianceCodes().OrderBy(s => s)) { var alleg = GetAllegianceFromCode(code); if (alleg != null) writer.WriteLine("# Alleg: {0}: \"{1}\"", isT5 ? code : SecondSurvey.T5AllegianceCodeToLegacyCode(code), alleg.Name); } writer.WriteLine(); } // Worlds worlds.Serialize(writer, mediaType, includeHeader: includeHeader, sscoords: sscoords, filter: filter); }
private SectorMap(List<SectorMetafileEntry> metafiles, ResourceManager resourceManager) { foreach (var metafile in metafiles) { SectorCollection collection = resourceManager.GetXmlFileObject(metafile.filename, typeof(SectorCollection), cache: false) as SectorCollection; foreach (var sector in collection.Sectors) sector.Tags.AddRange(metafile.tags); if (sectors == null) sectors = collection; else sectors.Merge(collection); } milieux.Clear(); foreach (var sector in sectors.Sectors) { if (sector.MetadataFile != null) { Sector metadata = resourceManager.GetXmlFileObject(@"~/res/Sectors/" + sector.MetadataFile, typeof(Sector), cache: false) as Sector; sector.Merge(metadata); } string milieu = sector.Era ?? sector.DataFile?.Era ?? DEFAULT_MILIEU; if (!milieux.ContainsKey(milieu)) milieux.Add(milieu, new MilieuMap()); MilieuMap m = milieux[milieu]; m.locationMap.Add(sector.Location, sector); foreach (var name in sector.Names) { if (!m.nameMap.ContainsKey(name.Text)) m.nameMap.Add(name.Text, sector); // Automatically alias "SpinwardMarches" string spaceless = name.Text.Replace(" ", ""); if (spaceless != name.Text && !m.nameMap.ContainsKey(spaceless)) m.nameMap.Add(spaceless, sector); } if (!string.IsNullOrEmpty(sector.Abbreviation) && !m.nameMap.ContainsKey(sector.Abbreviation)) m.nameMap.Add(sector.Abbreviation, sector); } }
public static IEnumerable<ItemLocation> PerformSearch(string query, ResourceManager resourceManager, SearchResultsType types, int numResults) { List<ItemLocation> results = new List<ItemLocation>(); using (var connection = DBUtil.MakeConnection()) { List<string> clauses = new List<string>(); List<string> terms = new List<string>(); foreach (string t in query.Split((char[])null, StringSplitOptions.RemoveEmptyEntries)) { string term = t; string clause; if (term.StartsWith("uwp:")) { term = term.Substring(term.IndexOf(':') + 1); clause = "uwp LIKE @term"; types = SearchResultsType.UWP; } else if (term.StartsWith("exact:")) { term = term.Substring(term.IndexOf(':') + 1); clause = "name LIKE @term"; } else if (term.StartsWith("like:")) { term = term.Substring(term.IndexOf(':') + 1); clause = "SOUNDEX(name) = SOUNDEX(@term)"; } else if (term.Contains("%") || term.Contains("_")) { clause = "name LIKE @term"; } else { clause = "name LIKE @term + '%' OR name LIKE '% ' + @term + '%'"; } clause = clause.Replace("@term", String.Format("@term{0}", terms.Count)); clauses.Add("(" + clause + ")"); terms.Add(term); } string where = String.Join(" AND ", clauses.ToArray()); // NOTE: DISTINCT is to filter out "Ley" and "Ley Sector" (different names, same result). // TODO: Include the searched-for name in the results, and show alternate names in the result set. // {0} is the list of distinct fields (i.e. coordinates), {1} is the table, {2} is the filter string query_format = "SELECT DISTINCT TOP " + numResults + " {0},name FROM {1} WHERE {2} ORDER BY name ASC"; // Sectors if (types.HasFlag(SearchResultsType.Sectors) && numResults > 0) { string sql = String.Format(query_format, "x, y", "sectors", where); using (var sqlCommand = new SqlCommand(sql, connection)) { for (int i = 0; i < terms.Count; ++i) { sqlCommand.Parameters.AddWithValue(String.Format("@term{0}", i), terms[i]); } using (var row = sqlCommand.ExecuteReader()) { while (row.Read()) { results.Add(new SectorLocation(row.GetInt32(0), row.GetInt32(1))); numResults -= 1; } } } } // Subsectors if (types.HasFlag(SearchResultsType.Subsectors) && numResults > 0) { string sql = String.Format(query_format, "sector_x, sector_y, subsector_index", "subsectors", where); using (var sqlCommand = new SqlCommand(sql, connection)) { for (int i = 0; i < terms.Count; ++i) { sqlCommand.Parameters.AddWithValue(String.Format("@term{0}", i), terms[i]); } using (var row = sqlCommand.ExecuteReader()) { while (row.Read()) { char[] chars = new char[1]; row.GetChars(2, 0, chars, 0, chars.Length); results.Add(new SubsectorLocation(row.GetInt32(0), row.GetInt32(1), chars[0])); } } } } // Worlds & UWPs if ((types.HasFlag(SearchResultsType.Worlds) || types.HasFlag(SearchResultsType.UWP)) && numResults > 0) { string sql = String.Format(query_format, "sector_x, sector_y, hex_x, hex_y", "worlds", where); using (var sqlCommand = new SqlCommand(sql, connection)) { for (int i = 0; i < terms.Count; ++i) { sqlCommand.Parameters.AddWithValue(String.Format("@term{0}", i), terms[i]); } using (var row = sqlCommand.ExecuteReader()) { while (row.Read()) { results.Add(new WorldLocation(row.GetInt32(0), row.GetInt32(1), row.GetInt32(2), row.GetInt32(3))); } } } } } return results; }
public static void PopulateDatabase(ResourceManager resourceManager, StatusCallback callback) { // Lock on this class rather than the cacheResults. Tile requests are not // blocked but we don't index twice. lock (typeof(SearchEngine)) { // NOTE: This (re)initializes a static data structure used for // resolving names into sector locations, so needs to be run // before any other objects (e.g. Worlds) are loaded. SectorMap map = SectorMap.FromName(SectorMap.DefaultSetting, resourceManager); using (var connection = DBUtil.MakeConnection()) { SqlCommand sqlCommand; // // Repopulate the tables - locally first // FUTURE: will need to batch this up rather than keep it in memory! // DataTable dt_sectors = new DataTable(); for (int i = 0; i < 3; ++i) dt_sectors.Columns.Add(new DataColumn()); DataTable dt_subsectors = new DataTable(); for (int i = 0; i < 4; ++i) dt_subsectors.Columns.Add(new DataColumn()); DataTable dt_worlds = new DataTable(); for (int i = 0; i < 6; ++i) dt_worlds.Columns.Add(new DataColumn()); callback("Parsing data..."); foreach (Sector sector in map.Sectors) { if (!sector.Tags.Contains("OTU")) continue; foreach (Name name in sector.Names) { DataRow row = dt_sectors.NewRow(); row.ItemArray = new object[] { sector.X, sector.Y, name.Text }; dt_sectors.Rows.Add(row); } foreach (Subsector subsector in sector.Subsectors) { DataRow row = dt_subsectors.NewRow(); row.ItemArray = new object[] { sector.X, sector.Y, subsector.Index, subsector.Name }; dt_subsectors.Rows.Add(row); } #if DEBUG if (!sector.Selected) continue; #endif // NOTE: May need to page this at some point WorldCollection worlds = sector.GetWorlds(resourceManager, cacheResults: false); if (worlds == null) continue; foreach (World world in worlds) { DataRow row = dt_worlds.NewRow(); row.ItemArray = new object[] { sector.X, sector.Y, world.X, world.Y, world.Name != null && world.Name.Length > 0 ? (object)world.Name : (object)DBNull.Value, world.UWP }; dt_worlds.Rows.Add(row); } } // // Rebuild the tables with fresh schema // string[] rebuild_schema = { "IF EXISTS(SELECT 1 FROM sys.objects WHERE OBJECT_ID = OBJECT_ID(N'sectors') AND type = (N'U')) DROP TABLE sectors", "CREATE TABLE sectors(x int NOT NULL,y int NOT NULL,name nvarchar(50) NULL)", "CREATE NONCLUSTERED INDEX sector_name ON sectors ( name ASC ) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)", "IF EXISTS(SELECT 1 FROM sys.objects WHERE OBJECT_ID = OBJECT_ID(N'subsectors') AND type = (N'U')) DROP TABLE subsectors", "CREATE TABLE subsectors (sector_x int NOT NULL, sector_y int NOT NULL, subsector_index char(1) NOT NULL, name nvarchar(50) NULL )", "CREATE NONCLUSTERED INDEX subsector_name ON subsectors ( name ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)", "IF EXISTS(SELECT 1 FROM sys.objects WHERE OBJECT_ID = OBJECT_ID(N'worlds') AND type = (N'U')) DROP TABLE worlds", "CREATE TABLE worlds( sector_x int NOT NULL, sector_y int NOT NULL, hex_x int NOT NULL, hex_y int NOT NULL, name nvarchar(50) NULL, uwp nchar(9) NULL )", "CREATE NONCLUSTERED INDEX world_name ON worlds ( name ASC ) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)", "CREATE NONCLUSTERED INDEX world_uwp ON worlds ( uwp ASC ) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)", }; callback("Rebuilding schema..."); foreach (string cmd in rebuild_schema) { sqlCommand = new SqlCommand(cmd, connection); sqlCommand.ExecuteNonQuery(); } // // And shovel the data into the database en masse // using (var bulk = new SqlBulkCopy(connection, SqlBulkCopyOptions.TableLock, null)) { callback(String.Format("Writing {0} sectors...", dt_sectors.Rows.Count)); bulk.BatchSize = dt_sectors.Rows.Count; bulk.DestinationTableName = "sectors"; bulk.WriteToServer(dt_sectors); bulk.Close(); } using (var bulk = new SqlBulkCopy(connection, SqlBulkCopyOptions.TableLock, null)) { callback(String.Format("Writing {0} subsectors...", dt_subsectors.Rows.Count)); bulk.BatchSize = dt_subsectors.Rows.Count; bulk.DestinationTableName = "subsectors"; bulk.WriteToServer(dt_subsectors); bulk.Close(); } using (var bulk = new SqlBulkCopy(connection, SqlBulkCopyOptions.TableLock, null)) { callback(String.Format("Writing {0} worlds...", dt_worlds.Rows.Count)); bulk.BatchSize = 4096; bulk.DestinationTableName = "worlds"; bulk.WriteToServer(dt_worlds); bulk.Close(); } } callback("Complete!"); } }
public static IEnumerable<ItemLocation> PerformSearch(string query, ResourceManager resourceManager, SearchResultsType types, int maxResultsPerType) { List<ItemLocation> results = new List<ItemLocation>(); List<string> clauses; List<string> terms; types = ParseQuery(query, types, out clauses, out terms); if (clauses.Count() == 0) return results; string where = String.Join(" AND ", clauses.ToArray()); // NOTE: DISTINCT is to filter out "Ley" and "Ley Sector" (different names, same result). // TODO: Include the searched-for name in the results, and show alternate names in the result set. // {0} is the list of distinct fields (i.e. coordinates), {1} is the list of fields in the subquery (same as {0} but with "name" added, {2} is the table, {3} is the filter // Since we need the distinct values from the term {0} but don't use the name for the results construction, we can ignore name in the resultset. // This allows us to get the top N results from the database, sort by name, and then toss out duplicates not based on name but on the other, used, columns // Here's a sample subquery that works for the sector table. // SELECT DISTINCT TOP 160 tt.x, tt.y FROM (SELECT TOP 160 x, y,name FROM sectors WHERE (name LIKE 'LEY%' OR name LIKE '%LEY%') ORDER BY name ASC) AS tt; string query_format = "SELECT DISTINCT TOP " + maxResultsPerType + " {0} FROM (SELECT TOP " + maxResultsPerType + " {1} FROM {2} WHERE {3}) AS TT"; using (var connection = DBUtil.MakeConnection()) { // Sectors if (types.HasFlag(SearchResultsType.Sectors)) { // Note duplicated field names so the results of both queries can come out right. string sql = String.Format(query_format, "TT.x, TT.y", "x, y", "sectors", where); using (var sqlCommand = new SqlCommand(sql, connection)) { for (int i = 0; i < terms.Count; ++i) sqlCommand.Parameters.AddWithValue(String.Format("@term{0}", i), terms[i]); using (var row = sqlCommand.ExecuteReader()) { while (row.Read()) { results.Add(new SectorLocation(row.GetInt32(0), row.GetInt32(1))); } } } } // Subsectors if (types.HasFlag(SearchResultsType.Subsectors)) { // Note duplicated field names so the results of both queries can come out right. string sql = String.Format(query_format, "TT.sector_x, TT.sector_y, TT.subsector_index", "sector_x, sector_y, subsector_index", "subsectors", where); using (var sqlCommand = new SqlCommand(sql, connection)) { for (int i = 0; i < terms.Count; ++i) sqlCommand.Parameters.AddWithValue(String.Format("@term{0}", i), terms[i]); using (var row = sqlCommand.ExecuteReader()) { while (row.Read()) { char[] chars = new char[1]; row.GetChars(2, 0, chars, 0, chars.Length); results.Add(new SubsectorLocation(row.GetInt32(0), row.GetInt32(1), chars[0])); } } } } // Worlds & UWPs, etc if (types.HasFlag(SearchResultsType.Worlds)) { // Note duplicated field names so the results of both queries can come out right. string sql = String.Format(query_format, "TT.sector_x, TT.sector_y, TT.hex_x, TT.hex_y", "sector_x, sector_y, hex_x, hex_y", "worlds", where); using (var sqlCommand = new SqlCommand(sql, connection)) { for (int i = 0; i < terms.Count; ++i) sqlCommand.Parameters.AddWithValue(String.Format("@term{0}", i), terms[i]); using (var row = sqlCommand.ExecuteReader()) { while (row.Read()) results.Add(new WorldLocation(row.GetInt32(0), row.GetInt32(1), row.GetInt32(2), row.GetInt32(3))); } } } } return results; }
public QuadrantSelector(ResourceManager resourceManager, Sector sector, int index) { if (resourceManager == null) throw new ArgumentNullException("resourceManager"); if (sector == null) throw new ArgumentNullException("sector"); if (index < 0 || index >= 4) throw new ArgumentOutOfRangeException("index", "index must be 0...3"); this.sector = sector; this.index = index; this.resourceManager = resourceManager; }
public static SectorMap GetInstance(ResourceManager resourceManager) { lock (SectorMap.s_lock) { if (s_instance == null) { List<SectorMetafileEntry> files = new List<SectorMetafileEntry> { // Meta new SectorMetafileEntry(@"~/res/legend.xml", new List<string> { "meta" } ), // OTU - Default Milieu new SectorMetafileEntry(@"~/res/sectors.xml", new List<string> { "OTU" } ), new SectorMetafileEntry(@"~/res/ZhodaniCoreRoute.xml", new List<string> { "ZCR" } ), // OTU - Other Milieu new SectorMetafileEntry(@"~/res/Sectors/M1000/m1000.xml", new List<string> {} ), // Non-OTU new SectorMetafileEntry(@"~/res/faraway.xml", new List<string> { "Faraway" } ), }; s_instance = new SectorMap(files, resourceManager); } } return s_instance; }
public static Milieu ForMilieu(ResourceManager resourceManager, string milieu) { return new Milieu(SectorMap.GetInstance(resourceManager), milieu); }
internal WorldCollection GetWorlds(ResourceManager resourceManager, bool cacheResults = true) { lock (this) { // Have it cached - just return it if (worlds != null) return worlds; // Can't look it up; failure case if (DataFile == null) return null; // Otherwise, look it up WorldCollection data = resourceManager.GetDeserializableFileObject(@"~/res/Sectors/" + DataFile, typeof(WorldCollection), cacheResults: false, mediaType: DataFile.Type) as WorldCollection; foreach (World world in data) world.Sector = this; if (cacheResults) worlds = data; return data; } }
public static void PopulateDatabase(ResourceManager resourceManager, StatusCallback callback) { // Lock to prevent indexing twice, without blocking tile requests. lock (SearchEngine.s_lock) { // NOTE: This (re)initializes a static data structure used for // resolving names into sector locations, so needs to be run // before any other objects (e.g. Worlds) are loaded. SectorMap map = SectorMap.GetInstance(resourceManager); using (var connection = DBUtil.MakeConnection()) { SqlCommand sqlCommand; // // Repopulate the tables - locally first // FUTURE: will need to batch this up rather than keep it in memory! // DataTable dt_sectors = new DataTable(); for (int i = 0; i < 3; ++i) dt_sectors.Columns.Add(new DataColumn()); DataTable dt_subsectors = new DataTable(); for (int i = 0; i < 4; ++i) dt_subsectors.Columns.Add(new DataColumn()); DataTable dt_worlds = new DataTable(); for (int i = 0; i < 13; ++i) dt_worlds.Columns.Add(new DataColumn()); DataTable dt_labels = new DataTable(); for (int i = 0; i < 4; ++i) dt_labels.Columns.Add(new DataColumn()); Dictionary<string, List<Point>> labels = new Dictionary<string, List<Point>>(); Action<string, Point> AddLabel = (string text, Point coords) => { if (text == null) return; text = SanifyLabel(text); if (!labels.ContainsKey(text)) labels.Add(text, new List<Point>()); labels[text].Add(coords); }; callback("Parsing data..."); foreach (Sector sector in map.Sectors) { if (!sector.Tags.Contains("OTU") && !sector.Tags.Contains("Faraway")) continue; foreach (Name name in sector.Names) { DataRow row = dt_sectors.NewRow(); row.ItemArray = new object[] { sector.X, sector.Y, name.Text }; dt_sectors.Rows.Add(row); } if (!string.IsNullOrEmpty(sector.Abbreviation)) { DataRow row = dt_sectors.NewRow(); row.ItemArray = new object[] { sector.X, sector.Y, sector.Abbreviation }; dt_sectors.Rows.Add(row); } foreach (Subsector subsector in sector.Subsectors) { DataRow row = dt_subsectors.NewRow(); row.ItemArray = new object[] { sector.X, sector.Y, subsector.Index, subsector.Name }; dt_subsectors.Rows.Add(row); } foreach (Border border in sector.Borders.Where(b => b.ShowLabel)) { AddLabel(border.GetLabel(sector), Astrometrics.LocationToCoordinates(new Location(sector.Location, border.LabelPosition))); } foreach (Label label in sector.Labels) { AddLabel(label.Text, Astrometrics.LocationToCoordinates(new Location(sector.Location, label.Hex))); } #if DEBUG if (!sector.Selected) continue; #endif // NOTE: May need to page this at some point WorldCollection worlds = sector.GetWorlds(resourceManager, cacheResults: false); if (worlds == null) continue; var world_query = from world in worlds where !world.IsPlaceholder select world; foreach (World world in world_query) { DataRow row = dt_worlds.NewRow(); row.ItemArray = new object[] { world.Coordinates.X, world.Coordinates.Y, sector.X, sector.Y, world.X, world.Y, string.IsNullOrEmpty(world.Name) ? (object)DBNull.Value : (object)world.Name, world.UWP, world.Remarks, world.PBG, string.IsNullOrEmpty(world.Zone) ? "G" : world.Zone, world.Allegiance, sector.Names.Count > 0 ? (object)sector.Names[0] : (object)DBNull.Value }; dt_worlds.Rows.Add(row); } } foreach (KeyValuePair<string, List<Point>> entry in labels) { string name = entry.Key; List<Point> points = entry.Value; Point avg = new Point( (int)Math.Round(points.Select(p => p.X).Average()), (int)Math.Round(points.Select(p => p.Y).Average())); Point min = new Point(points.Select(p => p.X).Min(), points.Select(p => p.Y).Min()); Point max = new Point(points.Select(p => p.X).Max(), points.Select(p => p.Y).Max()); Size size = new Size(max.X - min.X, max.Y - min.Y); int radius = Math.Max(size.Width, size.Height); DataRow row = dt_labels.NewRow(); row.ItemArray = new object[] { avg.X, avg.Y, radius, entry.Key }; dt_labels.Rows.Add(row); } // // Rebuild the tables with fresh schema // const string INDEX_OPTIONS = " WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)"; const string DROP_TABLE_IF_EXISTS = "IF EXISTS(SELECT 1 FROM sys.objects WHERE OBJECT_ID = OBJECT_ID(N'{0}') AND type = (N'U')) DROP TABLE {0}"; string[] rebuild_schema = { string.Format(DROP_TABLE_IF_EXISTS, "sectors"), "CREATE TABLE sectors (x int NOT NULL, y int NOT NULL, name nvarchar(50) NULL)", "CREATE NONCLUSTERED INDEX sector_name ON sectors ( name ASC )" + INDEX_OPTIONS, string.Format(DROP_TABLE_IF_EXISTS, "subsectors"), "CREATE TABLE subsectors (sector_x int NOT NULL, sector_y int NOT NULL, subsector_index char(1) NOT NULL, name nvarchar(50) NULL)", "CREATE NONCLUSTERED INDEX subsector_name ON subsectors ( name ASC )" + INDEX_OPTIONS, string.Format(DROP_TABLE_IF_EXISTS, "worlds"), "CREATE TABLE worlds (" + "x int NOT NULL, " + "y int NOT NULL, " + "sector_x int NOT NULL, " + "sector_y int NOT NULL, " + "hex_x int NOT NULL, " + "hex_y int NOT NULL, " + "name nvarchar(50) NULL, " + "uwp nchar(9) NULL, " + "remarks nvarchar(50) NULL, " + "pbg nchar(3) NULL, " + "zone nchar(1) NULL, " + "alleg nchar(4) NULL, " + "sector_name nvarchar(50) NULL)", "CREATE NONCLUSTERED INDEX world_name ON worlds ( name ASC )" + INDEX_OPTIONS, "CREATE NONCLUSTERED INDEX world_uwp ON worlds ( uwp ASC )" + INDEX_OPTIONS, "CREATE NONCLUSTERED INDEX world_pbg ON worlds ( pbg ASC )" + INDEX_OPTIONS, "CREATE NONCLUSTERED INDEX world_alleg ON worlds ( alleg ASC )" + INDEX_OPTIONS, "CREATE NONCLUSTERED INDEX world_sector_name ON worlds ( sector_name ASC )" + INDEX_OPTIONS, string.Format(DROP_TABLE_IF_EXISTS, "labels"), "CREATE TABLE labels (x int NOT NULL, y int NOT NULL, radius int NOT NULL, name nvarchar(50) NULL)", "CREATE NONCLUSTERED INDEX name ON labels ( name ASC )" + INDEX_OPTIONS, }; callback("Rebuilding schema..."); foreach (string cmd in rebuild_schema) { sqlCommand = new SqlCommand(cmd, connection); sqlCommand.ExecuteNonQuery(); } // // And shovel the data into the database en masse // Action<string, DataTable, int> BulkInsert = (string name, DataTable table, int batchSize) => { using (var bulk = new SqlBulkCopy(connection, SqlBulkCopyOptions.TableLock, null)) { callback(string.Format("Writing {0} {1}...", table.Rows.Count, name)); bulk.BatchSize = batchSize; bulk.DestinationTableName = name; bulk.WriteToServer(table); } }; BulkInsert("sectors", dt_sectors, dt_sectors.Rows.Count); BulkInsert("subsectors", dt_subsectors, dt_subsectors.Rows.Count); BulkInsert("worlds", dt_worlds, 4096); BulkInsert("labels", dt_labels, dt_labels.Rows.Count); } callback("Complete!"); } }
public RectSelector(SectorMap.Milieu map, ResourceManager resourceManager, RectangleF rect, bool slop = true) { if (map == null) throw new ArgumentNullException("map"); if (resourceManager == null) throw new ArgumentNullException("resourceManager"); this.map = map; this.resourceManager = resourceManager; this.rect = rect; Slop = slop; SlopFactor = 0.25f; }