diff --git a/src/Server/.idea/.idea.REST API/.idea/dataSources/469f6bec-f113-4467-9d39-7ac38558045a.xml b/src/Server/.idea/.idea.REST API/.idea/dataSources/469f6bec-f113-4467-9d39-7ac38558045a.xml index 7f75353..60d559b 100644 --- a/src/Server/.idea/.idea.REST API/.idea/dataSources/469f6bec-f113-4467-9d39-7ac38558045a.xml +++ b/src/Server/.idea/.idea.REST API/.idea/dataSources/469f6bec-f113-4467-9d39-7ac38558045a.xml @@ -44,71 +44,5 @@ replication:{'class': 'org.apache.cassandra.locator.LocalStrategy replication:{'class': 'org.apache.cassandra.locator.SimpleStrategy', 'replication_factor': '2'} - - caching:{'keys': 'ALL', 'rows_per_partition': 'ALL'} -compression:{'sstable_compression': 'org.apache.cassandra.io.compress.LZ4Compressor'} -bloom_filter_fp_chance:0.01 -default_time_to_live:0 -speculative_retry:99.0PERCENTILE -gc_grace_seconds:864000 -max_index_interval:2048 -memtable_flush_period_in_ms:0 -min_index_interval:128 -read_repair_chance:0 -crc_check_chance:1 -dclocal_read_repair_chance:0 -compaction:{'class': 'SizeTieredCompactionStrategy'} - -
- - caching:{'keys': 'ALL', 'rows_per_partition': 'ALL'} -compression:{'sstable_compression': 'org.apache.cassandra.io.compress.LZ4Compressor'} -bloom_filter_fp_chance:0.01 -default_time_to_live:0 -speculative_retry:99.0PERCENTILE -gc_grace_seconds:864000 -max_index_interval:2048 -memtable_flush_period_in_ms:0 -min_index_interval:128 -read_repair_chance:0 -crc_check_chance:1 -dclocal_read_repair_chance:0 -compaction:{'class': 'SizeTieredCompactionStrategy'} - -
- - uuid|0s - 1 - - - int|0s - 2 - - - timestamp|0s - 3 - - - text|0s - 4 - - - id -version|ASC -date|ASC - - - - uuid|0s - 1 - - - text|0s - 2 - - - id - - \ No newline at end of file diff --git a/src/Server/.idea/.idea.REST API/.idea/workspace.xml b/src/Server/.idea/.idea.REST API/.idea/workspace.xml index 1fe2d9e..231935c 100755 --- a/src/Server/.idea/.idea.REST API/.idea/workspace.xml +++ b/src/Server/.idea/.idea.REST API/.idea/workspace.xml @@ -8,9 +8,12 @@ + + - + + @@ -120,7 +123,7 @@ - + diff --git a/src/Server/Console/JsonClasses/Database.cs b/src/Server/Console/JsonClasses/Database.cs index 8fd661f..473b6bc 100755 --- a/src/Server/Console/JsonClasses/Database.cs +++ b/src/Server/Console/JsonClasses/Database.cs @@ -6,11 +6,13 @@ public class Data { public int version; public string date; public string id; + public string name; } public class RowData { public string Id; public int[][] Objects; public int Version; + public string Name; public DateTime Date; } diff --git a/src/Server/Console/Program.cs b/src/Server/Console/Program.cs index 9b5aea9..5ea247b 100755 --- a/src/Server/Console/Program.cs +++ b/src/Server/Console/Program.cs @@ -40,10 +40,11 @@ internal static class Program { session.Execute(@" CREATE TABLE IF NOT EXISTS Roommapper.Maps( Id uuid, - Objects text, Version int, + Name text, + Objects text, Date timestamp, - PRIMARY KEY (Id,Version,Date) + PRIMARY KEY (Id,Name) )"); session.Execute(@" diff --git a/src/Server/Console/Routes/RouteDatabase.cs b/src/Server/Console/Routes/RouteDatabase.cs index 2ce06f2..c0679d7 100755 --- a/src/Server/Console/Routes/RouteDatabase.cs +++ b/src/Server/Console/Routes/RouteDatabase.cs @@ -12,13 +12,13 @@ public class RouteDatabase(ISession cassandraSession): IRoute { /// public HttpResponse Get(HttpRequest request) { try { - // Prepare the select statement based on the given criteria // If no criteria is given, throw an exception. // Using a prepare due to the potential of SQL injection when accepting // any form of user data. var queries = new Dictionary> { ["id"] = id => cassandraSession.Prepare(@"SELECT * FROM Roommapper.Maps WHERE Id = ?;").Bind(Guid.Parse(id)), + ["name"] = name => cassandraSession.Prepare(@"SELECT * FROM Roommapper.Maps WHERE Name = ?;").Bind(name), ["date"] = date => cassandraSession.Prepare(@"SELECT * FROM roommapper.maps WHERE Date = ?;").Bind(DateTime.Parse(date)), ["version"] = version => cassandraSession.Prepare(@"SELECT * FROM roommapper.maps WHERE Version = ?;").Bind(int.Parse(version)), ["all"] = _ => cassandraSession.Prepare(@"SELECT * FROM roommapper.maps;").Bind() @@ -29,7 +29,7 @@ public class RouteDatabase(ISession cassandraSession): IRoute { .Select(query => query.Value(request.QueryString[query.Key])) .FirstOrDefault(); - if (selectStatement == null) throw new Exception("No valid search criteria given, give one of (id, date, version)."); + if (selectStatement == null) throw new Exception("No valid search criteria given, give one of (id, date, version, name)."); // Execute the query and return all rows in an array @@ -65,9 +65,9 @@ public class RouteDatabase(ISession cassandraSession): IRoute { var uuid = Guid.NewGuid(); var insertStatement = cassandraSession.Prepare(@" - INSERT INTO Roommapper.Maps(Id, Date, Version, Objects) - VALUES (?, toTimeStamp(now()), ?, ?); - ").Bind(uuid, 1, parsedBody.objects); + INSERT INTO Roommapper.Maps(Id, Name, Date, Version, Objects) + VALUES (?, ?, toTimeStamp(now()), ?, ?); + ").Bind(uuid, parsedBody.name, 1, parsedBody.objects); cassandraSession.Execute(insertStatement); @@ -126,7 +126,8 @@ public class RouteDatabase(ISession cassandraSession): IRoute { Id = row.GetValue("id").ToString(), Objects = $"[{row.GetValue("objects")}]".FromJson(), Version = row.GetValue("version"), - Date = row.GetValue("date") + Date = row.GetValue("date"), + Name = row.GetValue("name") }).ToList().ToJson(); } } diff --git a/src/Server/Console/Routes/RoutePath.cs b/src/Server/Console/Routes/RoutePath.cs index e68c0e3..1664a6a 100644 --- a/src/Server/Console/Routes/RoutePath.cs +++ b/src/Server/Console/Routes/RoutePath.cs @@ -18,6 +18,7 @@ public class RoutePath(ISession cassandraSession): IRoute { // any form of user data. var queries = new Dictionary> { ["id"] = id => cassandraSession.Prepare(@"SELECT * FROM Roommapper.Routes WHERE Id = ?;").Bind(Guid.Parse(id)), + ["name"] = name => cassandraSession.Prepare(@"SELECT * FROM Roommapper.Routes WHERE Id = ?;").Bind(name) }; var selectStatement = queries @@ -25,7 +26,7 @@ public class RoutePath(ISession cassandraSession): IRoute { .Select(query => query.Value(request.QueryString[query.Key])) .FirstOrDefault(); - if (selectStatement == null) throw new Exception("No valid search criteria given, give one of (id)."); + if (selectStatement == null) throw new Exception("No valid search criteria given, give one of (id, name)."); // Execute the query and return all rows in an array var rowSet = cassandraSession.Execute(selectStatement); diff --git a/src/Server/Console/bin/Debug/net8.0/Console.dll b/src/Server/Console/bin/Debug/net8.0/Console.dll index ee6bf23..36d31f8 100755 Binary files a/src/Server/Console/bin/Debug/net8.0/Console.dll and b/src/Server/Console/bin/Debug/net8.0/Console.dll differ diff --git a/src/Server/Console/bin/Debug/net8.0/Console.pdb b/src/Server/Console/bin/Debug/net8.0/Console.pdb index 74b6ef2..5dfc8b3 100755 Binary files a/src/Server/Console/bin/Debug/net8.0/Console.pdb and b/src/Server/Console/bin/Debug/net8.0/Console.pdb differ diff --git a/src/Web/src/components/mapCanvas.jsx b/src/Web/src/components/mapCanvas.jsx index 25102b1..daaae70 100644 --- a/src/Web/src/components/mapCanvas.jsx +++ b/src/Web/src/components/mapCanvas.jsx @@ -15,8 +15,8 @@ export default class MapCanvas extends React.Component { // Get a reference to the canvas element so we can draw on it this.canvasRef = React.createRef(); this.state = { - inputValue: '8a97354d-d4ac-43c6-8b32-528cc24e3ede', - searchOption: 'id', + inputValue: '', + searchOption: 'name', canvasWidth: props.width || this.defaultWidth, canvasHeight: props.height || this.defaultHeight, }; @@ -33,16 +33,18 @@ export default class MapCanvas extends React.Component { this.draw(); } - async getLinePoints(endpoint = '') { + async getLinePoints(endpoint = '', altKey, altVal) { try { const { searchOption, inputValue } = this.state; - const url = `${API_ENDPOINT}/database/${endpoint}?${searchOption}=${inputValue}`; + const key = altKey || this.state.searchOption; + const val = altVal || this.state.inputValue; + const url = `${API_ENDPOINT}/database/${endpoint}?${key}=${val}`; const data = await (await fetch(url)).json(); // Combine all found sets into a singular array. - const map = []; + const map = { 'id': data.length < 2 ? data[0].Id : undefined, 'points': [] }; if (!Array.isArray(data) || data.length < 1) return map; - data.forEach((set) => set.Objects.forEach((coord) => map.push(coord))); + data.forEach((set) => set.Objects.forEach((coord) => map.points.push(coord))); return map; } catch (ex) { @@ -55,9 +57,8 @@ export default class MapCanvas extends React.Component { // Get the 2D context from the canvas element const ctx = this.canvasRef.current.getContext('2d'); // Get the points to draw from the server - const points = await this.getLinePoints(); - const route = await this.getLinePoints("path"); - // const route = await this.getRoutePoints(); + const map = await this.getLinePoints(); + const route = await this.getLinePoints('path', 'id', map ? map.id : ''); // Set the font for the text we will draw on the canvas ctx.font = "24px Comic Sans MS"; @@ -66,7 +67,7 @@ export default class MapCanvas extends React.Component { ctx.clearRect(0, 0, this.state.canvasWidth, this.state.canvasHeight); // If there are no points, display a message and return - if (!points || points.length < 1) { + if (!map || map.points.length < 1) { ctx.fillText("No valid entry found.", 10, this.state.canvasHeight / 2); return; } @@ -74,14 +75,14 @@ export default class MapCanvas extends React.Component { // Loop trough all coordinates, draw a dot at each point to form a top-down // view of the objects. ctx.fillStyle = "#000"; - points.forEach(point => { + map.points.forEach(point => { ctx.beginPath(); ctx.arc(point[1], point[0], 1, 0, 2 * Math.PI); ctx.fill(); }); ctx.fillStyle = "#800000"; - route.forEach(point => { + route.points.forEach(point => { ctx.beginPath(); ctx.arc(point[1], point[0], 1, 0, 2 * Math.PI); ctx.fill(); @@ -99,9 +100,8 @@ export default class MapCanvas extends React.Component { value={searchOption} onChange={(val) => this.setState({ searchOption: val })} > + - -