diff --git a/media/Server/eindverslag persoonlijke bijdrage/src/sections/2 data serialisatie.tex b/media/Server/eindverslag persoonlijke bijdrage/src/sections/2 data serialisatie.tex new file mode 100644 index 0000000..be9e0b2 --- /dev/null +++ b/media/Server/eindverslag persoonlijke bijdrage/src/sections/2 data serialisatie.tex @@ -0,0 +1,11 @@ +Er zijn vele opties om data te verzenden tussen client en server. +Voor dit project is er voor gekozen om data te serialiseren naar JSON. +Dit is een veelgebruikte methode om data te verzenden tussen client en server. +Het voordeel van JSON is dat het een lichtgewicht formaat is en dat het makkelijk te lezen is. +Dit is handig voor debugging en het is makkelijk om te zetten naar een object in JavaScript. +Een nadeel van JSON is dat het niet binair is en dat het niet zo snel is als binair. +Dit is echter geen probleem voor dit project, omdat de hoeveelheid data die verstuurd wordt klein is. +\subsection{Serialisatie} +\label{sec:serialisatie} +% Path: 2 data serialisatie.tex + diff --git a/src/CoveragePathPlanner/CoveragePathPlanner.cs b/src/CoveragePathPlanner/CoveragePathPlanner.cs index dbeff63..2a5b3e2 100644 --- a/src/CoveragePathPlanner/CoveragePathPlanner.cs +++ b/src/CoveragePathPlanner/CoveragePathPlanner.cs @@ -1,136 +1,136 @@ using System; -using System.Collections.Generic; using System.Drawing; public class CoveragePathPlanner { - private int _width; - private int _height; - private List _cells; + private int _width; + private int _height; + private List _cells; - public CoveragePathPlanner(int width, int height) + public CoveragePathPlanner(int width, int height) + { + _width = width; + _height = height; + _cells = new List(); + + for (int x = 0; x < width; x++) { - _width = width; - _height = height; - _cells = new List(); + for (int y = 0; y < height; y++) + { + _cells.Add(new Cell { X = x, Y = y, IsObstacle = false, IsVisited = false, Cost = double.MaxValue }); + } + } + } - for (int x = 0; x < width; x++) + public List PlanPath(List obstacles) + { + // Add obstacles to the grid + foreach (Obstacle obstacle in obstacles) + { + foreach (Cell cell in _cells) + { + if (cell.IsWithinObstacle(obstacle)) { - for (int y = 0; y < height; y++) - { - _cells.Add(new Cell { X = x, Y = y, IsObstacle = false, IsVisited = false, Cost = double.MaxValue }); - } + cell.IsObstacle = true; } + } } - public List PlanPath(List obstacles) + // Initialize the start cell + Cell startCell = _cells[0]; + startCell.Cost = 0; + + // Create a priority queue to hold the cells to be processed + var queue = new PriorityQueue(); + queue.Enqueue(startCell, 0); + + while (queue.Count > 0) { - // Add obstacles to the grid - foreach (Obstacle obstacle in obstacles) + // Dequeue the cell with the lowest cost + Cell currentCell = queue.Dequeue(); + + // If the cell is the goal, construct the path + if (currentCell.X == _width - 1 && currentCell.Y == _height - 1) + { + List path = new List(); + while (currentCell != null) { - for (int x = obstacle.X; x < obstacle.X + obstacle.Width; x++) - { - for (int y = obstacle.Y; y < obstacle.Y + obstacle.Height; y++) - { - _cells[x + y * _width].IsObstacle = true; - } - } + path.Add(new Point(currentCell.X, currentCell.Y)); + currentCell = currentCell.Parent; } + return path; + } - // Initialize the start cell - Cell startCell = _cells[0]; - startCell.Cost = 0; + // Mark the cell as visited + currentCell.IsVisited = true; - // Create a priority queue to hold the cells to be processed - var queue = new PriorityQueue(); - queue.Enqueue(startCell, 0); - - while (queue.Count > 0) + // Explore the neighbors + foreach (Cell neighbor in currentCell.GetNeighbors(_cells)) + { + if (!neighbor.IsVisited && !neighbor.IsObstacle) { - // Dequeue the cell with the lowest cost - Cell currentCell = queue.Dequeue(); - - // If the cell is the goal, construct the path - if (currentCell.X == _width - 1 && currentCell.Y == _height - 1) - { - List path = new List(); - while (currentCell != null) - { - path.Add(new Point(currentCell.X, currentCell.Y)); - currentCell = currentCell.Parent; - } - return path; - } - - // Mark the cell as visited - currentCell.IsVisited = true; - - // Explore the neighbors - foreach (Cell neighbor in GetNeighbors(currentCell)) - { - if (!neighbor.IsVisited && !neighbor.IsObstacle) - { - // Calculate the cost of the neighbor - double cost = currentCell.Cost + 1; - if (cost < neighbor.Cost) - { - neighbor.Cost = cost; - neighbor.Parent = currentCell; - queue.Enqueue(neighbor, cost + Heuristic(neighbor)); - } - } - } + // Calculate the cost of the neighbor + double cost = currentCell.Cost + 1; + if (cost < neighbor.Cost) + { + neighbor.Cost = cost; + neighbor.Parent = currentCell; + queue.Enqueue(neighbor, cost + currentCell.Heuristic(_width, _height)); + } } - - // If no path is found, return an empty list - return new List(); - } - - private List GetNeighbors(Cell cell) - { - List neighbors = new List(); - - for (int x = -1; x <= 1; x++) - { - for (int y = -1; y <= 1; y++) - { - if (x == 0 && y == 0) continue; - - int neighborX = cell.X + x; - int neighborY = cell.Y + y; - - if (neighborX >= 0 && neighborX < _width && neighborY >= 0 && neighborY < _height) - { - neighbors.Add(_cells[neighborX + neighborY * _width]); - } - } - } - - return neighbors; - } - - private double Heuristic(Cell cell) - { - // Manhattan distance heuristic - return Math.Abs(cell.X - (_width - 1)) + Math.Abs(cell.Y - (_height - 1)); + } } + // If no path is found, return an empty list + return new List(); + } } public class Obstacle { - public int X { get; set; } - public int Y { get; set; } - public int Width { get; set; } - public int Height { get; set; } + public int X { get; set; } + public int Y { get; set; } + public int Width { get; set; } + public int Height { get; set; } } public class Cell { - public int X { get; set; } - public int Y { get; set; } - public bool IsObstacle { get; set; } - public bool IsVisited { get; set; } - public double Cost { get; set; } - public Cell Parent { get; set; } + public int X { get; set; } + public int Y { get; set; } + public bool IsObstacle { get; set; } + public bool IsVisited { get; set; } + public double Cost { get; set; } + public Cell Parent { get; set; } + + public bool IsWithinObstacle(Obstacle obstacle) + { + return X >= obstacle.X && X < obstacle.X + obstacle.Width && + Y >= obstacle.Y && Y < obstacle.Y + obstacle.Height; + } + + public IEnumerable GetNeighbors(List cells) + { + for (int x = -1; x <= 1; x++) + { + for (int y = -1; y <= 1; y++) + { + if (x == 0 && y == 0) continue; + + int neighborX = X + x; + int neighborY = Y + y; + + if (neighborX >= 0 && neighborX < cells.Count / cells[0].Y && neighborY >= 0 && neighborY < cells[0].Y) + { + yield return cells[neighborX + neighborY * cells.Count / cells[0].Y]; + } + } + } + } + + public double Heuristic(int width, int height) + { + // Manhattan distance heuristic + return Math.Abs(X - (width - 1)) + Math.Abs(Y - (height - 1)); + } } diff --git a/src/Server/.idea/.idea.REST API/.idea/dataSources.local.xml b/src/Server/.idea/.idea.REST API/.idea/dataSources.local.xml index 00a143e..2403de8 100755 --- a/src/Server/.idea/.idea.REST API/.idea/dataSources.local.xml +++ b/src/Server/.idea/.idea.REST API/.idea/dataSources.local.xml @@ -4,6 +4,7 @@ " + true master_key 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 4a1d21b..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 @@ -8,33 +8,33 @@ 1 1 - - durable_writes:true -replication:{'class': 'org.apache.cassandra.locator.SimpleStrategy', 'replication_factor': '1'} - - - - durable_writes:true -replication:{'class': 'org.apache.cassandra.locator.LocalStrategy'} - - - - durable_writes:true -replication:{'class': 'org.apache.cassandra.locator.SimpleStrategy', 'replication_factor': '1'} - - - + 1 durable_writes:true replication:{'class': 'org.apache.cassandra.locator.NetworkTopologyStrategy', 'datacenter1': '1'} - + + durable_writes:true +replication:{'class': 'org.apache.cassandra.locator.LocalStrategy'} + + + + durable_writes:true +replication:{'class': 'org.apache.cassandra.locator.SimpleStrategy', 'replication_factor': '1'} + + + durable_writes:true replication:{'class': 'org.apache.cassandra.locator.SimpleStrategy', 'replication_factor': '3'} - + + durable_writes:true +replication:{'class': 'org.apache.cassandra.locator.EverywhereStrategy'} + + + durable_writes:true replication:{'class': 'org.apache.cassandra.locator.LocalStrategy'} @@ -44,53 +44,5 @@ replication:{'class': 'org.apache.cassandra.locator.LocalStrategy replication:{'class': 'org.apache.cassandra.locator.SimpleStrategy', 'replication_factor': '2'} - - durable_writes:true -replication:{'class': 'org.apache.cassandra.locator.EverywhereStrategy'} - - - - durable_writes:true -replication:{'class': 'org.apache.cassandra.locator.SimpleStrategy', 'replication_factor': '1'} - - - - 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 - - \ 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 900ce2f..231935c 100755 --- a/src/Server/.idea/.idea.REST API/.idea/workspace.xml +++ b/src/Server/.idea/.idea.REST API/.idea/workspace.xml @@ -8,12 +8,14 @@ - + - - - - + + + + + + - { + "keyToString": { + ".NET Project.Console.executor": "Run", + "ASKED_ADD_EXTERNAL_FILES": "true", + "RunOnceActivity.OpenProjectViewOnStart": "true", + "RunOnceActivity.ShowReadmeOnStart": "true", + "d452b4e4-aa15-4fa9-847f-33d4d7fab23d.executor": "Run", + "git-widget-placeholder": "master", + "ignore.virus.scanning.warn.message": "true", + "node.js.detected.package.eslint": "true", + "node.js.detected.package.tslint": "true", + "node.js.selected.package.eslint": "(autodetect)", + "node.js.selected.package.tslint": "(autodetect)", + "nodejs_package_manager_path": "npm", + "settings.editor.selected.configurable": "HotReloadSettingsPage", + "vue.rearranger.settings.migration": "true" }, - "keyToStringList": { - "DatabaseDriversLRU": [ - "cassandra" + "keyToStringList": { + "DatabaseDriversLRU": [ + "cassandra" ], - "rider.external.source.directories": [ - "/home/wessel/.config/JetBrains/Rider2024.1/resharper-host/DecompilerCache", - "/home/wessel/.config/JetBrains/Rider2024.1/resharper-host/SourcesCache", - "/home/wessel/.local/share/Symbols/src" + "rider.external.source.directories": [ + "/home/wessel/.config/JetBrains/Rider2024.1/resharper-host/DecompilerCache", + "/home/wessel/.config/JetBrains/Rider2024.1/resharper-host/SourcesCache", + "/home/wessel/.local/share/Symbols/src" ] } -}]]> +} 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 3d2e120..5ea247b 100755 --- a/src/Server/Console/Program.cs +++ b/src/Server/Console/Program.cs @@ -19,6 +19,7 @@ internal static class Program { { "", new Root() }, { "database", new RouteDatabase(cassandraSession) }, { "database/metadata", new RouteMetadata(cassandraSession) }, + { "database/path", new RoutePath(cassandraSession) }, { "roomba/control", new RouteControl() } }; @@ -39,10 +40,18 @@ 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(@" + CREATE TABLE IF NOT EXISTS Roommapper.Routes( + Id uuid, + Path text, + PRIMARY KEY (Id) )"); } } 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 new file mode 100644 index 0000000..1664a6a --- /dev/null +++ b/src/Server/Console/Routes/RoutePath.cs @@ -0,0 +1,142 @@ +using Cassandra; +using LibParse.Json; +using LibServer.Http; +using LibServer.Router; +using Console.JsonClasses; + +namespace Console.Routes; + +public class RoutePath(ISession cassandraSession): IRoute { + /// + /// GET request for the database/path route, return a path of a map based on given criteria. + /// + 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.Routes WHERE Id = ?;").Bind(Guid.Parse(id)), + ["name"] = name => cassandraSession.Prepare(@"SELECT * FROM Roommapper.Routes WHERE Id = ?;").Bind(name) + }; + + var selectStatement = queries + .Where(query => request.QueryString.ContainsKey(query.Key)) + .Select(query => query.Value(request.QueryString[query.Key])) + .FirstOrDefault(); + + 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); + + // Create a list to hold the row data, convert it to a JSON string + var rows = RowsToString(rowSet); + + // Return the JSON string to the user + return new HttpResponse(rows); + } catch (Exception ex) { + // Return error message if failed for any reason + return new HttpResponse($"{{\"message\": \"{ex.Message.Replace("\"", "\\\"")}\"}}", 400); + } + } + + /// + /// POST request for the database/path route, insert a new path containing + /// routing data into the database. + /// + public HttpResponse Post(HttpRequest request) { + try { + // Parse request body to Data object, give error if non-nullable fields + // are null. + var parsedBody = request.Body?.FromJson(); + if (parsedBody?.objects == null) { + throw new Exception("objectData is null"); + } + + if (parsedBody?.id == null) { + throw new Exception("id is null"); + } + + var selectStatement = + parsedBody?.id != null ? cassandraSession.Prepare(@"SELECT * FROM Roommapper.Maps WHERE Id = ?;") + .Bind(Guid.Parse(parsedBody.id)) : + throw new Exception("No valid search criteria given, give one of (id)."); + + // Execute the query and return all rows in an array + var rowSet = cassandraSession.Execute(selectStatement); + + if (rowSet.IsExhausted()) { + throw new Exception("No matching map found with the given criteria."); + } + + // Prepare the insert statement, bind the values, and execute the query + // Using a prepare due to the potential of SQL injection when accepting + // any form of user data. + var uuid = Guid.Parse(parsedBody.id); + + var insertStatement = cassandraSession.Prepare(@" + INSERT INTO Roommapper.Routes(Id, path) + VALUES (?, ?); + ").Bind(uuid, parsedBody.objects); + + cassandraSession.Execute(insertStatement); + + // Return success message with the UUID of the inserted row + return new HttpResponse($"{{\"message\":\"success\",\"id\":\"{uuid}\"}}"); + } + catch (Exception ex) { + // Return error message if failed for any reason + return new HttpResponse($"{{\"message\": \"{ex.Message.Replace("\"", "\\\"")}\"}}", 400); + } + } + + /// + /// Deletes a given row + /// + public HttpResponse Delete(HttpRequest request) { + try { + var parsedBody = request.Body?.FromJson(); + + // 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 selectStatement = + parsedBody?.id != null ? cassandraSession.Prepare(@"SELECT * FROM Roommapper.Routes WHERE Id = ?;") + .Bind(Guid.Parse(parsedBody.id)) : + throw new Exception("No valid search criteria given, give one of (id)."); + + // Execute the query and return all rows in an array + var rowSet = cassandraSession.Execute(selectStatement); + + if (rowSet.IsExhausted()) { + throw new Exception("No rows found with the given criteria."); + } + + // Prepare and execute delete statement + var deleteStatement = cassandraSession.Prepare(@"DELETE FROM Roommapper.Routes WHERE Id = ?;") + .Bind(Guid.Parse(parsedBody.id)); + + cassandraSession.Execute(deleteStatement); + + return new HttpResponse($"{{\"message\":\"success\",\"entry\":{RowsToString(rowSet)}}}"); + + } catch (Exception ex) { + return new HttpResponse($"{{\"message\": \"{ex.Message.Replace("\"", "\\\"")}\"}}", 400); + } + } + + /// + /// Casts a set of `RowSet` into a valid JSON string. + /// + /// The `RowSet` to cast. + /// A valid JSON string formed from `rowSet`. + private string RowsToString(RowSet rowSet) { + return rowSet.Select(row => new RowData { + Id = row.GetValue("id").ToString(), + Objects = $"[{row.GetValue("path")}]".FromJson() + }).ToList().ToJson(); + } +} diff --git a/src/Server/Console/bin/Debug/net8.0/Console b/src/Server/Console/bin/Debug/net8.0/Console index 4b14b11..d433124 100755 Binary files a/src/Server/Console/bin/Debug/net8.0/Console and b/src/Server/Console/bin/Debug/net8.0/Console differ diff --git a/src/Server/Console/bin/Debug/net8.0/Console.dll b/src/Server/Console/bin/Debug/net8.0/Console.dll index 4ce4914..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 1b1190c..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/Server/Console/bin/Debug/net8.0/LibParse.dll b/src/Server/Console/bin/Debug/net8.0/LibParse.dll index 1a7535f..f44c188 100755 Binary files a/src/Server/Console/bin/Debug/net8.0/LibParse.dll and b/src/Server/Console/bin/Debug/net8.0/LibParse.dll differ diff --git a/src/Server/Console/bin/Debug/net8.0/LibParse.pdb b/src/Server/Console/bin/Debug/net8.0/LibParse.pdb index 9c184df..82875fa 100755 Binary files a/src/Server/Console/bin/Debug/net8.0/LibParse.pdb and b/src/Server/Console/bin/Debug/net8.0/LibParse.pdb differ diff --git a/src/Server/Console/bin/Debug/net8.0/LibServer.dll b/src/Server/Console/bin/Debug/net8.0/LibServer.dll index 33acde8..904f362 100755 Binary files a/src/Server/Console/bin/Debug/net8.0/LibServer.dll and b/src/Server/Console/bin/Debug/net8.0/LibServer.dll differ diff --git a/src/Server/Console/bin/Debug/net8.0/LibServer.pdb b/src/Server/Console/bin/Debug/net8.0/LibServer.pdb index 743d628..ef3ff02 100755 Binary files a/src/Server/Console/bin/Debug/net8.0/LibServer.pdb and b/src/Server/Console/bin/Debug/net8.0/LibServer.pdb differ diff --git a/src/Server/LibParse/bin/Debug/net8.0/LibParse.dll b/src/Server/LibParse/bin/Debug/net8.0/LibParse.dll index 1a7535f..f44c188 100755 Binary files a/src/Server/LibParse/bin/Debug/net8.0/LibParse.dll and b/src/Server/LibParse/bin/Debug/net8.0/LibParse.dll differ diff --git a/src/Server/LibParse/bin/Debug/net8.0/LibParse.pdb b/src/Server/LibParse/bin/Debug/net8.0/LibParse.pdb index 9c184df..82875fa 100755 Binary files a/src/Server/LibParse/bin/Debug/net8.0/LibParse.pdb and b/src/Server/LibParse/bin/Debug/net8.0/LibParse.pdb differ diff --git a/src/Server/LibServer/Http/Request.cs b/src/Server/LibServer/Http/Request.cs index b574b7b..c1a9c96 100755 --- a/src/Server/LibServer/Http/Request.cs +++ b/src/Server/LibServer/Http/Request.cs @@ -47,7 +47,6 @@ public class HttpRequest { catch { return -1; } } - var querySplit = Route.Split("?"); if (querySplit.Length == 1) return 0; diff --git a/src/Server/LibServer/bin/Debug/net8.0/LibServer.dll b/src/Server/LibServer/bin/Debug/net8.0/LibServer.dll index 33acde8..904f362 100755 Binary files a/src/Server/LibServer/bin/Debug/net8.0/LibServer.dll and b/src/Server/LibServer/bin/Debug/net8.0/LibServer.dll differ diff --git a/src/Server/LibServer/bin/Debug/net8.0/LibServer.pdb b/src/Server/LibServer/bin/Debug/net8.0/LibServer.pdb index 743d628..ef3ff02 100755 Binary files a/src/Server/LibServer/bin/Debug/net8.0/LibServer.pdb and b/src/Server/LibServer/bin/Debug/net8.0/LibServer.pdb differ diff --git a/src/Server/REST API.sln.DotSettings.user b/src/Server/REST API.sln.DotSettings.user index 4bc068e..879bd4b 100755 --- a/src/Server/REST API.sln.DotSettings.user +++ b/src/Server/REST API.sln.DotSettings.user @@ -1,5 +1,5 @@  INFO - <SessionState ContinuousTestingMode="0" IsActive="True" Name="ParseJsonToAnonymousObject" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"> - <Project Location="C:\Users\wesse\OneDrive - Hogeschool Inholland\roommapper\src\Server\Tests" Presentation="&lt;Tests&gt;" /> + <SessionState ContinuousTestingMode="0" IsActive="True" Name="ParseJsonToAnonymousObject" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"> + <Project Location="C:\Users\wesse\OneDrive - Hogeschool Inholland\roommapper\src\Server\Tests" Presentation="&lt;Tests&gt;" /> </SessionState> \ No newline at end of file diff --git a/src/Web/src/components/mapCanvas.jsx b/src/Web/src/components/mapCanvas.jsx index 1e4f4ba..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() { + async getLinePoints(endpoint = '', altKey, altVal) { try { const { searchOption, inputValue } = this.state; - const url = `${API_ENDPOINT}/database?${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,7 +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 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"; @@ -64,14 +67,22 @@ 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; } // Loop trough all coordinates, draw a dot at each point to form a top-down // view of the objects. - points.forEach(point => { + ctx.fillStyle = "#000"; + map.points.forEach(point => { + ctx.beginPath(); + ctx.arc(point[1], point[0], 1, 0, 2 * Math.PI); + ctx.fill(); + }); + + ctx.fillStyle = "#800000"; + route.points.forEach(point => { ctx.beginPath(); ctx.arc(point[1], point[0], 1, 0, 2 * Math.PI); ctx.fill(); @@ -89,9 +100,8 @@ export default class MapCanvas extends React.Component { value={searchOption} onChange={(val) => this.setState({ searchOption: val })} > + - -