From 9100a6e619978efd859785a2b150bd71c33fe424 Mon Sep 17 00:00:00 2001 From: Wessel Tip Date: Tue, 11 Jun 2024 10:39:13 +0200 Subject: [PATCH 1/5] feat: Add routing to web interface and database --- .../src/sections/2 data serialisatie.tex | 11 ++ .../.idea/dataSources.local.xml | 1 + .../469f6bec-f113-4467-9d39-7ac38558045a.xml | 86 +++++++----- .../.idea/.idea.REST API/.idea/workspace.xml | 72 ++++++---- src/Server/Console/Program.cs | 8 ++ src/Server/Console/Routes/RouteMap.cs | 126 ++++++++++++++++++ src/Server/Console/bin/Debug/net8.0/Console | Bin 77288 -> 77312 bytes .../Console/bin/Debug/net8.0/Console.dll | Bin 14336 -> 16384 bytes .../Console/bin/Debug/net8.0/Console.pdb | Bin 14764 -> 15616 bytes .../Console/bin/Debug/net8.0/LibParse.dll | Bin 14336 -> 14336 bytes .../Console/bin/Debug/net8.0/LibParse.pdb | Bin 16624 -> 16624 bytes .../Console/bin/Debug/net8.0/LibServer.dll | Bin 15360 -> 15360 bytes .../Console/bin/Debug/net8.0/LibServer.pdb | Bin 15768 -> 15768 bytes .../LibParse/bin/Debug/net8.0/LibParse.dll | Bin 14336 -> 14336 bytes .../LibParse/bin/Debug/net8.0/LibParse.pdb | Bin 16624 -> 16624 bytes src/Server/LibServer/Http/Request.cs | 1 - .../LibServer/bin/Debug/net8.0/LibServer.dll | Bin 15360 -> 15360 bytes .../LibServer/bin/Debug/net8.0/LibServer.pdb | Bin 15768 -> 15768 bytes src/Server/REST API.sln.DotSettings.user | 4 +- src/Web/src/components/mapCanvas.jsx | 27 ++++ 20 files changed, 270 insertions(+), 66 deletions(-) create mode 100644 media/Server/eindverslag persoonlijke bijdrage/src/sections/2 data serialisatie.tex create mode 100644 src/Server/Console/Routes/RouteMap.cs 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/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..7f75353 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,17 +44,7 @@ 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 @@ -70,26 +60,54 @@ 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 diff --git a/src/Server/.idea/.idea.REST API/.idea/workspace.xml b/src/Server/.idea/.idea.REST API/.idea/workspace.xml index 900ce2f..d7f9255 100755 --- a/src/Server/.idea/.idea.REST API/.idea/workspace.xml +++ b/src/Server/.idea/.idea.REST API/.idea/workspace.xml @@ -9,12 +9,22 @@ + - - - - - + + + + + + + + + + + + + + - { + "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/Program.cs b/src/Server/Console/Program.cs index 3d2e120..ab867a4 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/route", new RouteMap(cassandraSession) }, { "roomba/control", new RouteControl() } }; @@ -44,5 +45,12 @@ internal static class Program { Date timestamp, PRIMARY KEY (Id,Version,Date) )"); + + session.Execute(@" + CREATE TABLE IF NOT EXISTS Roommapper.Routes( + Id uuid, + Path text, + PRIMARY KEY (Id) + )"); } } diff --git a/src/Server/Console/Routes/RouteMap.cs b/src/Server/Console/Routes/RouteMap.cs new file mode 100644 index 0000000..98c8407 --- /dev/null +++ b/src/Server/Console/Routes/RouteMap.cs @@ -0,0 +1,126 @@ +using Cassandra; +using LibParse.Json; +using LibServer.Http; +using LibServer.Router; +using Console.JsonClasses; + +namespace Console.Routes; + +public class RouteMap(ISession cassandraSession): IRoute { + /// + /// GET request for the database/mapped route, return 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)), + }; + + 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)."); + + + // 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 route, insert a new map containing + /// object 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"); + } + + // 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 4b14b116ca2d635954acf11a4c897db70d93a3fc..d433124f6e2b5e05fc6321ce98d1f985fafb6086 100755 GIT binary patch delta 235 zcmaEHo2B6n%LEO^hK-u#%p&u?ZC00j-yHkj{pY#dGgD&hIi5Cd-omV%#b~zqL2gMY zkP3bL+os;k$VAV`%-qma!NEB{H#f7yO2IhEBFVtOAkiSz(9qP}z#z%c!pO`t#UeG? zBH7H?z}&#pEG5~}B!vM495j?Q!%~ZiGxPHlEc6WYNHmWJ*}(0$6&M3qrVFYvN-!B2 fZP!+1tYX~0LXGhO8>9F1PF+TG#+c~`bs5zG4VXwD delta 227 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 DJrHNF delta 5114 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 diff --git a/src/Server/Console/bin/Debug/net8.0/Console.pdb b/src/Server/Console/bin/Debug/net8.0/Console.pdb index 1b1190c63365af6eea1105294f57ec39003f9500..b4ce5246890a0c0af723930f6aac4c4be214dbf4 100755 GIT binary patch delta 8389 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 C;cFcL delta 7663 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 F{(s)aKoI}{ diff --git a/src/Server/Console/bin/Debug/net8.0/LibServer.dll b/src/Server/Console/bin/Debug/net8.0/LibServer.dll index 33acde8abfc20dd4fcaa6ccefd518c32e7eb2894..904f36295e92a67ab1b704fad950544eb9c7bfbd 100755 GIT binary patch delta 235 zcmZpuXsDRb!Sc1@_=$}@7J340YNZETD$P9_zPksr9yQ#x`HG$dtA>G@nVCVNQCgy5 zqDhibiiw%Id7`;RYHEs!Wm>YOQIeT?lBKbkdFo^l69blF_PCzO9wq?-TYm@bsM|i* ze~EBYlxops(a9@J5*46=_9;+7km}!4cY1wYy58a3q)Uf3YnpCn_BUWK149FbL< zG$3gR#3l?$Kwb)vHe)ac!bBjpU`Pc*keDSm8eankX03u3B AvH$=8 delta 235 zcmZpuXsDRb!E!zL``?W{7J33ETbhJ?45B@z&RHC=+xklP<|}#vU%<_3voK$eN6nW;sJ(PR-50~W=9B`+p>m;?yi&S`(>alFHA zj?{8)socYtCa*9_RDcRji-8J)R3|Rx%(wipcIlUsw~uVrG~LeZpUhy+V98*{kj!Ap zkOagQK%NDI2}24{ED=biFr+f10maRL&={x+q~4st04N6%0g0J_^@DV#Fc@vtx4g&% E02#$gQ2+n{ diff --git a/src/Server/Console/bin/Debug/net8.0/LibServer.pdb b/src/Server/Console/bin/Debug/net8.0/LibServer.pdb index 743d6280b854b68ddc247d1e27e47e0e4e6176f3..ef3ff029c42cb464db1c9fad6f209e3d2a7a021a 100755 GIT binary patch delta 6299 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 p_%a+s$2G0W(UFIIpqR!6m3$r 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 diff --git a/src/Server/LibParse/bin/Debug/net8.0/LibParse.dll b/src/Server/LibParse/bin/Debug/net8.0/LibParse.dll index 1a7535f3e6625c439ffe3af5e9d5c0302893d087..f44c188560dbea1ea74500b5fdb9096931bba8d4 100755 GIT binary patch delta 235 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 F{(s)aKoI}{ 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 33acde8abfc20dd4fcaa6ccefd518c32e7eb2894..904f36295e92a67ab1b704fad950544eb9c7bfbd 100755 GIT binary patch delta 235 zcmZpuXsDRb!Sc1@_=$}@7J340YNZETD$P9_zPksr9yQ#x`HG$dtA>G@nVCVNQCgy5 zqDhibiiw%Id7`;RYHEs!Wm>YOQIeT?lBKbkdFo^l69blF_PCzO9wq?-TYm@bsM|i* ze~EBYlxops(a9@J5*46=_9;+7km}!4cY1wYy58a3q)Uf3YnpCn_BUWK149FbL< zG$3gR#3l?$Kwb)vHe)ac!bBjpU`Pc*keDSm8eankX03u3B AvH$=8 delta 235 zcmZpuXsDRb!E!zL``?W{7J33ETbhJ?45B@z&RHC=+xklP<|}#vU%<_3voK$eN6nW;sJ(PR-50~W=9B`+p>m;?yi&S`(>alFHA zj?{8)socYtCa*9_RDcRji-8J)R3|Rx%(wipcIlUsw~uVrG~LeZpUhy+V98*{kj!Ap zkOagQK%NDI2}24{ED=biFr+f10maRL&={x+q~4st04N6%0g0J_^@DV#Fc@vtx4g&% E02#$gQ2+n{ diff --git a/src/Server/LibServer/bin/Debug/net8.0/LibServer.pdb b/src/Server/LibServer/bin/Debug/net8.0/LibServer.pdb index 743d6280b854b68ddc247d1e27e47e0e4e6176f3..ef3ff029c42cb464db1c9fad6f209e3d2a7a021a 100755 GIT binary patch delta 6299 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 p_%a+s$2G0W(UFIIpqR!6m3$r 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 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..add36e6 100644 --- a/src/Web/src/components/mapCanvas.jsx +++ b/src/Web/src/components/mapCanvas.jsx @@ -51,11 +51,30 @@ export default class MapCanvas extends React.Component { } } + async getRoutePoints() { + try { + const { searchOption, inputValue } = this.state; + const url = `${API_ENDPOINT}/database/route?id=${inputValue}`; + const data = await (await fetch(url)).json(); + + // Combine all found sets into a singular array. + const map = []; + if (!Array.isArray(data) || data.length < 1) return map; + data.forEach((set) => set.Objects.forEach((coord) => map.push(coord))); + + return map; + } catch (ex) { + return; + // this.props.onError(ex); + } + } + async draw() { // 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.getRoutePoints(); // Set the font for the text we will draw on the canvas ctx.font = "24px Comic Sans MS"; @@ -71,11 +90,19 @@ 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 => { ctx.beginPath(); ctx.arc(point[1], point[0], 1, 0, 2 * Math.PI); ctx.fill(); }); + + ctx.fillStyle = "#800000"; + route.forEach(point => { + ctx.beginPath(); + ctx.arc(point[1], point[0], 1, 0, 2 * Math.PI); + ctx.fill(); + }); } render() { From 9e77f4996ef4cc7b9df0605036e59c270f7da60b Mon Sep 17 00:00:00 2001 From: Wessel Tip Date: Tue, 11 Jun 2024 10:59:15 +0200 Subject: [PATCH 2/5] feat: Improve database/path route --- .../.idea/.idea.REST API/.idea/workspace.xml | 17 +++--------- src/Server/Console/Program.cs | 2 +- .../Routes/{RouteMap.cs => RoutePath.cs} | 25 ++++++++++++++---- .../Console/bin/Debug/net8.0/Console.dll | Bin 16384 -> 16384 bytes .../Console/bin/Debug/net8.0/Console.pdb | Bin 15616 -> 15692 bytes src/Web/src/components/mapCanvas.jsx | 25 +++--------------- 6 files changed, 28 insertions(+), 41 deletions(-) rename src/Server/Console/Routes/{RouteMap.cs => RoutePath.cs} (83%) diff --git a/src/Server/.idea/.idea.REST API/.idea/workspace.xml b/src/Server/.idea/.idea.REST API/.idea/workspace.xml index d7f9255..1fe2d9e 100755 --- a/src/Server/.idea/.idea.REST API/.idea/workspace.xml +++ b/src/Server/.idea/.idea.REST API/.idea/workspace.xml @@ -8,23 +8,12 @@ - - - + - - - - - - - - - - + diff --git a/src/Server/Console/Program.cs b/src/Server/Console/Program.cs index ab867a4..9b5aea9 100755 --- a/src/Server/Console/Program.cs +++ b/src/Server/Console/Program.cs @@ -19,7 +19,7 @@ internal static class Program { { "", new Root() }, { "database", new RouteDatabase(cassandraSession) }, { "database/metadata", new RouteMetadata(cassandraSession) }, - { "database/route", new RouteMap(cassandraSession) }, + { "database/path", new RoutePath(cassandraSession) }, { "roomba/control", new RouteControl() } }; diff --git a/src/Server/Console/Routes/RouteMap.cs b/src/Server/Console/Routes/RoutePath.cs similarity index 83% rename from src/Server/Console/Routes/RouteMap.cs rename to src/Server/Console/Routes/RoutePath.cs index 98c8407..e68c0e3 100644 --- a/src/Server/Console/Routes/RouteMap.cs +++ b/src/Server/Console/Routes/RoutePath.cs @@ -6,9 +6,9 @@ using Console.JsonClasses; namespace Console.Routes; -public class RouteMap(ISession cassandraSession): IRoute { +public class RoutePath(ISession cassandraSession): IRoute { /// - /// GET request for the database/mapped route, return a map based on given criteria. + /// GET request for the database/path route, return a path of a map based on given criteria. /// public HttpResponse Get(HttpRequest request) { try { @@ -27,7 +27,6 @@ public class RouteMap(ISession cassandraSession): IRoute { if (selectStatement == null) 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); @@ -43,8 +42,8 @@ public class RouteMap(ISession cassandraSession): IRoute { } /// - /// POST request for the database route, insert a new map containing - /// object data into the database. + /// POST request for the database/path route, insert a new path containing + /// routing data into the database. /// public HttpResponse Post(HttpRequest request) { try { @@ -55,6 +54,22 @@ public class RouteMap(ISession cassandraSession): IRoute { 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. diff --git a/src/Server/Console/bin/Debug/net8.0/Console.dll b/src/Server/Console/bin/Debug/net8.0/Console.dll index 5aa069c8705dc1c6088e5759dba1b5e494029864..ee6bf232a9112c13270c37452557164fc89d165e 100755 GIT binary patch delta 4584 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 XIlSeA3om*_(@s|mdTURy{u1kd!X#{i delta 4343 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 diff --git a/src/Server/Console/bin/Debug/net8.0/Console.pdb b/src/Server/Console/bin/Debug/net8.0/Console.pdb index b4ce5246890a0c0af723930f6aac4c4be214dbf4..74b6ef266c391bcbdf957cfade23355dc1404207 100755 GIT binary patch delta 2116 zcmah~dr(wm6hG&?ckeE{%Zdr|P;q$^0{dWLK~@DJA0Ul@s8|Wet{|aKK`7$73vBo( zpErCU8D(RZwqj&&5_*i`BVSFWqe%@@SdRYTSeBrjOW16VGwsapobx;9cg}bB?)QD` zTy=8Q7Sod!0U&G*fUg{&A1KbRes;;SvMLH;fO5Q)E64{>0JKT*^n#h0k-H&3|Fpng@i()fj6xE}K z``6Mk_qnvDZS(M}Jcm@GFgblQpqv+>ArIZMupyg-95k^s z2YS)C3`!l9&81W!S4`4ILoq6$#ZW_;O5RDC0Ye+vB4Za>7g;5&HTDkm0+SZdGHFg4 z#i0plObICo#T0iZILYcwZDd`>Hpb&L8RoiBlRF}t>R(b0H z1#kb*$T;VX`fJ)5k6Qa$WqtBl6PNBfb|n2o)r;eDU%q|x+U5os^?koTPlUi4@>_B&Wuow@ej zV9BfXxu-aQxASwdIfGBdyNGPO0%{U_k8-nxh|{lbi6AgEjpv?W?W$N z?XYX>OxIr;%z3Z-nUBh@uP^i7A&Y%FWBw`4<9Ag*f7aaH+*b5|efajl=y@7|Xi@Xp9huU)OSbX#_-FHg31h6gpxOxkpA&6H#5%g-#hRe0d! zzUrwX=C$&BeC{p(rRBrb-`^X53Z}%}i1iQrWXa^J~uP;fmB^gpu%*nRJ*5pL;i6zEGhD7}$tJzSRkg(WhGMYO2HFeRW7NXmRZYR1o zpnE&I_o4fJvBqpx_M!VGx(D%)Mtt8~KK3CpJhT)K)saR_OG@ibPjFa~@#zKCIyy&|^M-Y&H$W67jFpqM(uVI?%Z`9=RB%qdxkHOz z(m-}2!q41mFW;sl!t%CIq9`8>H8l|erw9do=(!XHb14Gp=w&Pd zdKLviYyvTC3Ro~YkOf)=8{!l=FmS-E;6SR91Nn$51f}AF9U=%(j}WQ3kfr9qX2cEz zOTz;L;-rQTKO^`!PngAw^`D0e?o0u=Ak%WeAE7~nAi@z*!!@SPgV^Di2MJmpEJmbT zSX4GKi9ia3QNSw*d-#`MuyPNqJ7HX62kXZ$X7moI z_qFO>QRHB?JhPxvlgL2ZVZ%ow_q5^Tk;`m&405>*XI|)S!`s5&)4_DMc3E+`hit!xHRJ2Dl2DC+L1Lk`)1r+m^ zYRuqNm}gr2_(@ZOl9P=VciwB1)cLDAucoH%8;z9}4ZevN>*M#f4IaDSOMgAI#k;$C z&JKF3T}!BN?y5I)GG?c&4ou4y<6hv3M|n;ND7aVnsr2b!RP7i^Qv2JI#8#KOZkO*@ zYbC|MHuYrtSf*_`b>|s9OW;m!(aQxM^l5>PCol3VQWXW!9ATF=er&lY6cN*Kp+qX} zFCN$+7;!u7JD{$D5ncu#!pA30zUHlI_!wTcNSpbLQXV2`IYTt5ezG$+~ z`I^JBBMBw0b$RwDoF|uU`Z0aGzcDu>%>U_=l?MX?X4o}aYV$P@GjIN8bbJ*1Mz~{} zIOI^jEc*OXpVk#edUiVLx7C^U7)rTEHyXs!#E+-(!@0 za~x)w%YJ`Qb9#c8v)s7GMSj^Sug7<7<>ZJC*%w9cpME~SIae_*_j%-($745#cFvHj z+Px@dQ1{KmofD&lmG_-GqI(>%avE(i9kx9gyM$8+Dxr~@Ah`ENCKc`Fddck#Ken8C6NWF+YsbA{$ z5*evqPU_d8hK>$;NA^-dKWPyEBO?ti^pl`A&zCAiwld45;Dto)WhaSZj;=&V-aih*^Y?!a=Gif+|d) zV(>yBYI=UiI6IjrU&NZuhCtdBGR`@V6n@Ld3Jw9b6=%iatwG}H(n-mS?D5Qzb%BKC zODWVq`1u?z0k6N#EDyZ-5)WejpT#)gokZ+#_Mw#DD6pq+!i37_3hALqim_ZFux76J Uz-2(P(`d%|y0|dT&(#(F1Q;Ia%K!iX diff --git a/src/Web/src/components/mapCanvas.jsx b/src/Web/src/components/mapCanvas.jsx index add36e6..25102b1 100644 --- a/src/Web/src/components/mapCanvas.jsx +++ b/src/Web/src/components/mapCanvas.jsx @@ -33,28 +33,10 @@ export default class MapCanvas extends React.Component { this.draw(); } - async getLinePoints() { + async getLinePoints(endpoint = '') { try { const { searchOption, inputValue } = this.state; - const url = `${API_ENDPOINT}/database?${searchOption}=${inputValue}`; - const data = await (await fetch(url)).json(); - - // Combine all found sets into a singular array. - const map = []; - if (!Array.isArray(data) || data.length < 1) return map; - data.forEach((set) => set.Objects.forEach((coord) => map.push(coord))); - - return map; - } catch (ex) { - return; - // this.props.onError(ex); - } - } - - async getRoutePoints() { - try { - const { searchOption, inputValue } = this.state; - const url = `${API_ENDPOINT}/database/route?id=${inputValue}`; + const url = `${API_ENDPOINT}/database/${endpoint}?${searchOption}=${inputValue}`; const data = await (await fetch(url)).json(); // Combine all found sets into a singular array. @@ -74,7 +56,8 @@ export default class MapCanvas extends React.Component { const ctx = this.canvasRef.current.getContext('2d'); // Get the points to draw from the server const points = await this.getLinePoints(); - const route = await this.getRoutePoints(); + const route = await this.getLinePoints("path"); + // const route = await this.getRoutePoints(); // Set the font for the text we will draw on the canvas ctx.font = "24px Comic Sans MS"; From 1326ab92babd2fdc780a5054d632cf9714c58d67 Mon Sep 17 00:00:00 2001 From: Wessel Tip Date: Tue, 11 Jun 2024 11:32:11 +0200 Subject: [PATCH 3/5] feat: Voeg map name support toe --- .../469f6bec-f113-4467-9d39-7ac38558045a.xml | 66 ------------------ .../.idea/.idea.REST API/.idea/workspace.xml | 7 +- src/Server/Console/JsonClasses/Database.cs | 2 + src/Server/Console/Program.cs | 5 +- src/Server/Console/Routes/RouteDatabase.cs | 13 ++-- src/Server/Console/Routes/RoutePath.cs | 3 +- .../Console/bin/Debug/net8.0/Console.dll | Bin 16384 -> 16896 bytes .../Console/bin/Debug/net8.0/Console.pdb | Bin 15692 -> 15744 bytes src/Web/src/components/mapCanvas.jsx | 28 ++++---- 9 files changed, 33 insertions(+), 91 deletions(-) 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 ee6bf232a9112c13270c37452557164fc89d165e..36d31f872da0f20c377d65dd1e1fc1aa13a718a2 100755 GIT binary patch delta 4935 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%0AEZLDn0x{tIm! Bni>EA delta 4609 zcmb7I3v^V)8UE)!=I(AbkIiHAes9xK;9w2gqKe3uoveW<4|lD&gO#v)G0yy~NldbWyqDoYUKilj$fT3! z5Iy4~V&J&B7+h2?TC~r#e`w+oJ(ze*r*2-VCzo&@$Rl#udEzd;IUGx5Bu}vzE9kZ7 z8PuIOg3jKa0$8}~)1{+6X_91kj990=5f%Xiag`Q0?e1xErPJPgnk?9k1nLjVth7G# zH|$%X3KhwavU_NrY^4x&+am_Wb=$jTPfQLcd%x&1vPx#`WrVr*-S)8=^Am>nk&)Io zV=t39(>`cUyRStv??q%59bZY3Jx`csHM7M6)5jhW>r5~IJ&f#kM4#zTc5~|XhUO#R z7;brYTdBM41Tk(_7bQaxKv`XsXvP@<%)D&bX|u$3xrpZ}=Qhn2EuBS-Pz8DgbfOa3 zb+%og3L3jftmB)ia~YiO(@z59 z6&}`P`#pu7O0q|_%T(WSK5n>Zmw6n^olj zTEV2e4{}bu2+ZkGCFwvyoNA46BZJz^1T%xS1H*~5AK^J&g{(QPg;P!+>miHNcZ?U% z;U09(q1#y_Y%YL17yS#tT;xE2I9j6u3|Zr-8qq-s_>f^VfYX1Ev6s~-#!!Z0E0;^A z<4&M&8WCoO6@86Ks==*PeoT_-6tCEM%G4l_Vt=C;=uGk|_Mu`!}RlDb$*BRxNX zOw_doDW;Q-WMq+R;5%!UE|CgRf@x(k&4XDPZ_*jPLKn_KPD6a9&gmuNQedhk+ZQp3 zK81a}742u0Hc@Ls`*LHYUQ3VBI^Bz8H$bw8-w0e|*-HM6h&-$mo1==BJUM|o>1ksa z;j3^m5bdC&Yzx>`ioL@Q^Ipu<0mW`hn?PA~dLpX3*6IaI!wE$cu{5Y9%C12_leQ^# z8=Y@$N6hDaVQCt1<03!Kya?N=yQp5Vh?^Md#`{S+l_A`;1+OB>s^ZD&4jWc%N7}RIFeZFtj&2Va;tx?SJpg5LnG6weno8M<4bcXASWl(qC>sGw zqy8w{4VF%iM%ja48T6|ttHw!^Nq>&ACVE!SA~!xdQBajkHl;}xjt0yopHfDW$)?SU zMUu&(p{PzKlS5-sCPU=X;V6?K^5But``C;O3+;=s19FY-2I|ztFn)t3b!qz6S-QP} zZ_>Hi|85ypfiGgRS1QhIhFv4^Pb#^Gl{SK~lshwG8dZqT(^A6|*t{N+Ydan2!f`!e zCQyaK28Bx$E?0Po!YdTE0~zfDrqGWSz6r!(4a}gMsKczH3idtT04%eX09UdLAb*}W zV_8c}H~GV?4cl(QTu-}zUjyD|%0)O~4nzKRb_bA*owSKw(Ra}(-EQrtB`n8$gqAbE z`4ly<$N2;ufc}&7T5sX-dC>SP`4k?Y5Z9QG{D^fZYBR~xSvzxU;R1FD8To;C z8>Q@3s4IbWII3QywMGKmH5>IxvJkl3+)rKXC$x-pv0C2DZek0xRlr6Z<(nAO@ZL}X zdXP_+ly%WQ9$Esc_=`5)LIJI0-wlgSdu5oe;^#r7kKcIMMO zY#CdkZK4<0GHn-YWfw!@)^5-k{`BqDE{gj3s7ZW$8ZpzLl>#SJN@wuUFHpA~W-7&OUY>UM3H)9=hK+g!V1^bE5y#}?;~T5O%TCUBK_{2Yf^@FTETa(Jh)OM`cIq9wBydC*b-@BQDB6NIi?@T9X#*dLb4yo?@0MOZ z_GxLRHa1*-iisnY?*^0JE|+Ig-#y~J>%Mw%s(x){RQOMCR0vnAKN@vCl63vzA9R}c+uPAL$5u5ysc9!_#ypEZWIM{Oe*@8VPY?hA diff --git a/src/Server/Console/bin/Debug/net8.0/Console.pdb b/src/Server/Console/bin/Debug/net8.0/Console.pdb index 74b6ef266c391bcbdf957cfade23355dc1404207..5dfc8b33d4aa03c31143ac6b09f47e8b384f78e2 100755 GIT binary patch delta 1880 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 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 })} > + - - Date: Tue, 11 Jun 2024 21:56:08 +0200 Subject: [PATCH 4/5] Update Cell class to include related functions --- .../CoveragePathPlanner.cs | 213 +++++++++--------- 1 file changed, 106 insertions(+), 107 deletions(-) diff --git a/src/CoveragePathPlanner/CoveragePathPlanner.cs b/src/CoveragePathPlanner/CoveragePathPlanner.cs index dbeff63..8bdf026 100644 --- a/src/CoveragePathPlanner/CoveragePathPlanner.cs +++ b/src/CoveragePathPlanner/CoveragePathPlanner.cs @@ -1,136 +1,135 @@ -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)); + } } From e637ec901f5e0dec8043d72bcdeb0a7480001f0e Mon Sep 17 00:00:00 2001 From: zwarenelle Date: Tue, 11 Jun 2024 23:16:25 +0200 Subject: [PATCH 5/5] Fix --- src/CoveragePathPlanner/CoveragePathPlanner.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CoveragePathPlanner/CoveragePathPlanner.cs b/src/CoveragePathPlanner/CoveragePathPlanner.cs index 8bdf026..2a5b3e2 100644 --- a/src/CoveragePathPlanner/CoveragePathPlanner.cs +++ b/src/CoveragePathPlanner/CoveragePathPlanner.cs @@ -1,3 +1,4 @@ +using System; using System.Drawing; public class CoveragePathPlanner