Checking for loops in foldertree, getting only unique children now.
Small Stability changes to VrmGrabber
This commit is contained in:
parent
731587ac77
commit
b727ef765a
|
@ -31,13 +31,22 @@ public static class FolderMethods
|
||||||
.NotNull();
|
.NotNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IEnumerable<Folder> ChildFolders(this Folder parent)
|
private static IEnumerable<Folder> ChildFolders(this Folder parent)
|
||||||
{
|
{
|
||||||
|
// Unsafe can give back loops
|
||||||
return Db
|
return Db
|
||||||
.Folders
|
.Folders
|
||||||
.Where(f => f.ParentId == parent.Id);
|
.Where(f => f.ParentId == parent.Id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<Folder> UniqueChildFolders(this Folder parent)
|
||||||
|
{
|
||||||
|
|
||||||
|
var set = new HashSet<Folder>(Db.Folders, EqualityComparer<Folder>.Default);
|
||||||
|
|
||||||
|
return ChildFolders(parent).Where(set.Add);
|
||||||
|
}
|
||||||
|
|
||||||
public static IEnumerable<Installation> ChildInstallations(this Folder parent)
|
public static IEnumerable<Installation> ChildInstallations(this Folder parent)
|
||||||
{
|
{
|
||||||
return Db
|
return Db
|
||||||
|
@ -48,14 +57,14 @@ public static class FolderMethods
|
||||||
public static IEnumerable<Folder> DescendantFolders(this Folder parent)
|
public static IEnumerable<Folder> DescendantFolders(this Folder parent)
|
||||||
{
|
{
|
||||||
return parent
|
return parent
|
||||||
.TraverseDepthFirstPreOrder(ChildFolders)
|
.TraverseDepthFirstPreOrder(UniqueChildFolders)
|
||||||
.Skip(1); // skip self
|
.Skip(1); // skip self
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IEnumerable<Folder> DescendantFoldersAndSelf(this Folder parent)
|
public static IEnumerable<Folder> DescendantFoldersAndSelf(this Folder parent)
|
||||||
{
|
{
|
||||||
return parent
|
return parent
|
||||||
.TraverseDepthFirstPreOrder(ChildFolders);
|
.TraverseDepthFirstPreOrder(UniqueChildFolders);
|
||||||
}
|
}
|
||||||
public static Boolean IsDescendantOf(this Folder folder, Folder ancestor)
|
public static Boolean IsDescendantOf(this Folder folder, Folder ancestor)
|
||||||
{
|
{
|
||||||
|
|
|
@ -138,7 +138,7 @@ public static class InstallationMethods
|
||||||
|
|
||||||
public static String GetOrderNumbers(this Installation installation)
|
public static String GetOrderNumbers(this Installation installation)
|
||||||
{
|
{
|
||||||
return string.Join(", ", Db.OrderNumber2Installation
|
return String.Join(", ", Db.OrderNumber2Installation
|
||||||
.Where(i => i.InstallationId == installation.Id)
|
.Where(i => i.InstallationId == installation.Id)
|
||||||
.Select(i => i.OrderNumber)
|
.Select(i => i.OrderNumber)
|
||||||
.ToReadOnlyList());
|
.ToReadOnlyList());
|
||||||
|
|
|
@ -13,10 +13,10 @@ public static class UserMethods
|
||||||
{
|
{
|
||||||
public static IEnumerable<Installation> AccessibleInstallations(this User user)
|
public static IEnumerable<Installation> AccessibleInstallations(this User user)
|
||||||
{
|
{
|
||||||
var direct = user.DirectlyAccessibleInstallations();
|
var direct = user.DirectlyAccessibleInstallations().ToList();
|
||||||
var fromFolders = user
|
var fromFolders = user
|
||||||
.AccessibleFolders()
|
.AccessibleFolders()
|
||||||
.SelectMany(u => u.ChildInstallations());
|
.SelectMany(u => u.ChildInstallations()).ToList();
|
||||||
|
|
||||||
return direct
|
return direct
|
||||||
.Concat(fromFolders)
|
.Concat(fromFolders)
|
||||||
|
@ -35,7 +35,7 @@ public static class UserMethods
|
||||||
{
|
{
|
||||||
var folders = user.AccessibleFolders() as IEnumerable<TreeNode>;
|
var folders = user.AccessibleFolders() as IEnumerable<TreeNode>;
|
||||||
|
|
||||||
// user.AccessibleInstallations().ForEach(i => i.FillOrderNumbers());
|
user.AccessibleInstallations().ForEach(i => i.FillOrderNumbers());
|
||||||
var installations = user.AccessibleInstallations();
|
var installations = user.AccessibleInstallations();
|
||||||
|
|
||||||
return folders.Concat(installations);
|
return folders.Concat(installations);
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
|
||||||
|
namespace InnovEnergy.App.Backend.DataTypes;
|
||||||
|
|
||||||
|
public abstract partial class TreeNode
|
||||||
|
{
|
||||||
|
private sealed class IdEqualityComparer : IEqualityComparer<TreeNode>
|
||||||
|
{
|
||||||
|
public Boolean Equals(TreeNode x, TreeNode y)
|
||||||
|
{
|
||||||
|
if (ReferenceEquals(x, y)) return true;
|
||||||
|
if (ReferenceEquals(x, null)) return false;
|
||||||
|
if (ReferenceEquals(y, null)) return false;
|
||||||
|
if (x.GetType() != y.GetType()) return false;
|
||||||
|
return x.Id == y.Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Int32 GetHashCode(TreeNode obj)
|
||||||
|
{
|
||||||
|
return obj.Id.GetHashCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEqualityComparer<TreeNode> IdComparer { get; } = new IdEqualityComparer();
|
||||||
|
}
|
|
@ -195,7 +195,7 @@ th { /* header cell */
|
||||||
for (var batteryId = 3; batteryId < Int64.Parse(numberOfBatteries) + 2; batteryId++)
|
for (var batteryId = 3; batteryId < Int64.Parse(numberOfBatteries) + 2; batteryId++)
|
||||||
{
|
{
|
||||||
localCommand = localCommand.Append(
|
localCommand = localCommand.Append(
|
||||||
$" && /opt/innovenergy/scripts/upload-bms-firmware {batteryTtyName} {batteryId} /opt/innovenergy/{FirmwareVersion}.bin");
|
$" && sleep 3m && /opt/innovenergy/scripts/upload-bms-firmware {batteryTtyName} {batteryId} /opt/innovenergy/{FirmwareVersion}.bin");
|
||||||
}
|
}
|
||||||
#pragma warning disable CS4014
|
#pragma warning disable CS4014
|
||||||
Db.ExecuteBufferedAsyncCommandOnIp(installationIp, localCommand)
|
Db.ExecuteBufferedAsyncCommandOnIp(installationIp, localCommand)
|
||||||
|
|
|
@ -153,7 +153,7 @@ public static partial class Db
|
||||||
var command = $"dbus-send --system --dest={pathToBattery.Split('"')[1]} --type=method_call --print-reply /FirmwareVersion com.victronenergy.BusItem.GetText";
|
var command = $"dbus-send --system --dest={pathToBattery.Split('"')[1]} --type=method_call --print-reply /FirmwareVersion com.victronenergy.BusItem.GetText";
|
||||||
var returnString = await ExecuteBufferedAsyncCommandOnIp(ip, command);
|
var returnString = await ExecuteBufferedAsyncCommandOnIp(ip, command);
|
||||||
var returnStringShortened = returnString.Split('"')[1];
|
var returnStringShortened = returnString.Split('"')[1];
|
||||||
return returnStringShortened.Length > 5 ? "Unknown" : returnStringShortened;
|
return returnStringShortened.Length > 10 ? "Unknown" : returnStringShortened;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task<String> NumberOfBatteries(String? ip, String? online)
|
private static async Task<String> NumberOfBatteries(String? ip, String? online)
|
||||||
|
|
|
@ -0,0 +1,116 @@
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
|
||||||
|
namespace InnovEnergy.Lib.Utils;
|
||||||
|
|
||||||
|
public static class GraphTraversal
|
||||||
|
{
|
||||||
|
public static IEnumerable<T> TraverseDepthFirstPreOrder<T>(T root,
|
||||||
|
Func<T, IEnumerable<T>> getChildren,
|
||||||
|
IEqualityComparer<T>? comparer = null)
|
||||||
|
{
|
||||||
|
return Traverse(root, TreeTraversal.TraverseDepthFirstPreOrder, getChildren, comparer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static IEnumerable<T> TraverseDepthFirstPostOrder<T>(T root,
|
||||||
|
Func<T, IEnumerable<T>> getChildren,
|
||||||
|
IEqualityComparer<T>? comparer = null)
|
||||||
|
{
|
||||||
|
return Traverse(root, TreeTraversal.TraverseDepthFirstPostOrder, getChildren, comparer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<T> TraverseBreadthFirst<T>(T root,
|
||||||
|
Func<T, IEnumerable<T>> getChildren,
|
||||||
|
IEqualityComparer<T>? comparer = null)
|
||||||
|
{
|
||||||
|
return Traverse(root, TreeTraversal.TraverseBreadthFirst, getChildren, comparer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<T> TraverseDepthFirstPreOrder<T>(IEnumerable<T> sources,
|
||||||
|
Func<T, IEnumerable<T>> getChildren,
|
||||||
|
IEqualityComparer<T>? comparer = null)
|
||||||
|
{
|
||||||
|
return Traverse(sources, TreeTraversal.TraverseDepthFirstPreOrder, getChildren, comparer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static IEnumerable<T> TraverseDepthFirstPostOrder<T>(IEnumerable<T> sources,
|
||||||
|
Func<T, IEnumerable<T>> getChildren,
|
||||||
|
IEqualityComparer<T>? comparer = null)
|
||||||
|
{
|
||||||
|
return Traverse(sources, TreeTraversal.TraverseDepthFirstPostOrder, getChildren, comparer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<T> TraverseBreadthFirst<T>(IEnumerable<T> sources,
|
||||||
|
Func<T, IEnumerable<T>> getChildren,
|
||||||
|
IEqualityComparer<T>? comparer = null)
|
||||||
|
{
|
||||||
|
return Traverse(sources, TreeTraversal.TraverseBreadthFirst, getChildren, comparer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static IEnumerable<T> Traverse<T>(T root,
|
||||||
|
Func<T , Func<T, IEnumerable<T>>,IEnumerable<T>> traversor,
|
||||||
|
Func<T, IEnumerable<T>> getChildren,
|
||||||
|
IEqualityComparer<T>? comparer = null)
|
||||||
|
{
|
||||||
|
var getUniqueChildren = GetUniqueChildren(getChildren, root, comparer);
|
||||||
|
return traversor(root, getUniqueChildren);
|
||||||
|
}
|
||||||
|
|
||||||
|
[SuppressMessage("ReSharper", "PossibleMultipleEnumeration")]
|
||||||
|
private static IEnumerable<T> Traverse<T>(IEnumerable<T> sources,
|
||||||
|
Func<T , Func<T, IEnumerable<T>>,IEnumerable<T>> traversor,
|
||||||
|
Func<T, IEnumerable<T>> getChildren,
|
||||||
|
IEqualityComparer<T>? comparer = null)
|
||||||
|
{
|
||||||
|
var set = new HashSet<T>(sources, comparer ?? EqualityComparer<T>.Default);
|
||||||
|
IEnumerable<T> GetUniqueChildren(T n) => getChildren(n).Where(set.Add);
|
||||||
|
|
||||||
|
return from s in sources
|
||||||
|
from e in traversor(s, GetUniqueChildren)
|
||||||
|
select e;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: IEqualityComparer
|
||||||
|
public static IEnumerable<(T source, T target)> Edges<T>(T node, Func<T, IEnumerable<T>> getChildren)
|
||||||
|
{
|
||||||
|
return Edges(node.AsSingleEnumerable(), getChildren);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: IEqualityComparer
|
||||||
|
public static IEnumerable<(T source, T target)> Edges<T>(IEnumerable<T> sources,
|
||||||
|
Func<T, IEnumerable<T>> getChildren)
|
||||||
|
{
|
||||||
|
var hs = new HashSet<(T source, T target)>();
|
||||||
|
|
||||||
|
IEnumerable<(T source, T target)> GetChildEdges((T source, T target) edge)
|
||||||
|
{
|
||||||
|
return getChildren(edge.target)
|
||||||
|
.Select(c => (edge.target, c))
|
||||||
|
.Where(hs!.Add);
|
||||||
|
}
|
||||||
|
|
||||||
|
return from src in sources.Select(s => (s, s))
|
||||||
|
from e in TreeTraversal.TraverseDepthFirstPreOrder(src, GetChildEdges).Skip(1)
|
||||||
|
select e;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Func<T, IEnumerable<T>> GetUniqueChildren<T>(Func<T, IEnumerable<T>> getChildren,
|
||||||
|
T root,
|
||||||
|
IEqualityComparer<T>? comparer)
|
||||||
|
{
|
||||||
|
return GetUniqueChildren(getChildren, root.AsSingleEnumerable(), comparer);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Func<T, IEnumerable<T>> GetUniqueChildren<T>(Func<T, IEnumerable<T>> getChildren,
|
||||||
|
IEnumerable<T> sources,
|
||||||
|
IEqualityComparer<T>? comparer)
|
||||||
|
{
|
||||||
|
var set = new HashSet<T>(sources, comparer ?? EqualityComparer<T>.Default);
|
||||||
|
return n => getChildren(n).Where(set.Add);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -1,3 +1,5 @@
|
||||||
|
using InnovEnergy.Lib.Utils.Reflection;
|
||||||
|
|
||||||
namespace InnovEnergy.Lib.Utils;
|
namespace InnovEnergy.Lib.Utils;
|
||||||
|
|
||||||
public static class TreeTraversal
|
public static class TreeTraversal
|
||||||
|
|
Loading…
Reference in New Issue