WIP
This commit is contained in:
parent
91d0a55d5e
commit
b61ffde4c9
@ -1,8 +1,7 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using Xunit;
|
using Xunit;
|
||||||
using Aurora;
|
using Aurora;
|
||||||
using Aurora.Services.Signal;
|
using Aurora.Services.Signal;
|
||||||
|
using Aurora.Cursor;
|
||||||
|
|
||||||
|
|
||||||
namespace AuroraSignal.test
|
namespace AuroraSignal.test
|
||||||
@ -14,57 +13,30 @@ namespace AuroraSignal.test
|
|||||||
[InlineData(SortDirection.Desc)]
|
[InlineData(SortDirection.Desc)]
|
||||||
public void CursorListSortOnStringValue(SortDirection direction)
|
public void CursorListSortOnStringValue(SortDirection direction)
|
||||||
{
|
{
|
||||||
CursorList<Party> cursor = new CursorList<Party>();
|
CursorList<Party> list = new CursorList<Party>();
|
||||||
cursor.Add(new Party(){Name = "asdf", PartyId = "1111"});
|
list.Add(new Party() { Name = "asdf", Id = "1111" });
|
||||||
cursor.Add(new Party(){Name = "bsdf", PartyId = "2222"});
|
list.Add(new Party() { Name = "bsdf", Id = "2222" });
|
||||||
cursor.Add(new Party(){Name = "csdf", PartyId = "3333"});
|
list.Add(new Party() { Name = "csdf", Id = "3333" });
|
||||||
|
|
||||||
List<Party> result = cursor.WithSort("Name", direction).Get();
|
CursorResult<Party> result = new Cursor<Party>(ref list)
|
||||||
|
.WithSort(item => item.Value.Name, direction)
|
||||||
|
.GetNextPage();
|
||||||
|
|
||||||
if(direction == SortDirection.Desc)
|
if (direction == SortDirection.Desc)
|
||||||
{
|
{
|
||||||
Assert.Collection<Party>(cursor,
|
Assert.Collection<Party>(result.Result,
|
||||||
item => item.Name.Equals("asdf"),
|
item => item.Name.Equals("asdf"),
|
||||||
item => item.Name.Equals("bsdf"),
|
item => item.Name.Equals("bsdf"),
|
||||||
item => item.Name.Equals("csdf"));
|
item => item.Name.Equals("csdf"));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Assert.Collection<Party>(cursor,
|
Assert.Collection<Party>(result.Result,
|
||||||
item => item.Name.Equals("csdf"),
|
item => item.Name.Equals("csdf"),
|
||||||
item => item.Name.Equals("bsdf"),
|
item => item.Name.Equals("bsdf"),
|
||||||
item => item.Name.Equals("asdf"));
|
item => item.Name.Equals("asdf"));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory()]
|
|
||||||
[InlineData(SortDirection.Asc)]
|
|
||||||
[InlineData(SortDirection.Desc)]
|
|
||||||
public void CursorListSortOnIntValue(SortDirection direction)
|
|
||||||
{
|
|
||||||
CursorList<object> cursor = new CursorList<object>();
|
|
||||||
cursor.Add(new {Name = "asdf", PartyId = 1111});
|
|
||||||
cursor.Add(new {Name = "bsdf", PartyId = 2222});
|
|
||||||
cursor.Add(new {Name = "csdf", PartyId = 3333});
|
|
||||||
|
|
||||||
List<object> result = cursor.WithSort("PartyId", direction).Get();
|
|
||||||
|
|
||||||
if(direction == SortDirection.Desc)
|
|
||||||
{
|
|
||||||
Assert.Collection<object>(cursor,
|
|
||||||
item => item.Equals(new {Name = "asdf", PartyId = 1111}),
|
|
||||||
item => item.Equals(new {Name = "bsdf", PartyId = 2222}),
|
|
||||||
item => item.Equals(new {Name = "csdf", PartyId = 3333}));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Assert.Collection<object>(cursor,
|
|
||||||
item => item.Equals(new {Name = "csdf", PartyId = 3333}),
|
|
||||||
item => item.Equals(new {Name = "bsdf", PartyId = 2222}),
|
|
||||||
item => item.Equals(new {Name = "asdf", PartyId = 1111}));
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
9
AuroraSignal/Src/Augments/Party.cs
Normal file
9
AuroraSignal/Src/Augments/Party.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
using Aurora.Cursor;
|
||||||
|
|
||||||
|
namespace Aurora.Services.Signal
|
||||||
|
{
|
||||||
|
public partial class Party : ICursorObject
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
112
AuroraSignal/Src/Cursor/Cursor.cs
Normal file
112
AuroraSignal/Src/Cursor/Cursor.cs
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
namespace Aurora.Cursor
|
||||||
|
{
|
||||||
|
public enum SortDirection
|
||||||
|
{
|
||||||
|
Asc,
|
||||||
|
Desc,
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Cursor<T> where T : ICursorObject
|
||||||
|
{
|
||||||
|
private CursorList<T> _list;
|
||||||
|
|
||||||
|
private string? _previousPageToken;
|
||||||
|
private string? _nextPageToken;
|
||||||
|
private int _pageSize;
|
||||||
|
private Func<KeyValuePair<string, T>, string> _sortDelgate;
|
||||||
|
private SortDirection _direction;
|
||||||
|
public Cursor(ref CursorList<T> list)
|
||||||
|
{
|
||||||
|
this._list = list;
|
||||||
|
this._previousPageToken = string.Empty;
|
||||||
|
this._nextPageToken = string.Empty;
|
||||||
|
this._pageSize = 10;
|
||||||
|
this._sortDelgate = delegate (KeyValuePair<string, T> item)
|
||||||
|
{
|
||||||
|
return item.Value.Id;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public CursorResult<T> GetNextPage()
|
||||||
|
{
|
||||||
|
List<KeyValuePair<string, T>> tmpList;
|
||||||
|
|
||||||
|
// Sort reference list
|
||||||
|
if (this._direction == SortDirection.Desc)
|
||||||
|
{
|
||||||
|
tmpList = this._list.OrderByDescending(this._sortDelgate).ToList();
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tmpList = this._list.OrderBy(this._sortDelgate).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tmpList == null)
|
||||||
|
{
|
||||||
|
throw new System.NullReferenceException();
|
||||||
|
}
|
||||||
|
|
||||||
|
int startIdx = 0;
|
||||||
|
if (!string.IsNullOrEmpty(this._nextPageToken))
|
||||||
|
{
|
||||||
|
// TODO find another way to index into the list that's not a regular array search
|
||||||
|
startIdx = tmpList.FindIndex(item => item.Key == this._nextPageToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
int endIdx = startIdx + this._pageSize;
|
||||||
|
|
||||||
|
List<T> selection = new List<T>();
|
||||||
|
|
||||||
|
// Get page
|
||||||
|
for (int i = startIdx; i < tmpList.Count && i < endIdx; i++)
|
||||||
|
{
|
||||||
|
selection.Add(tmpList.ElementAt(i).Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new CursorResult<T>
|
||||||
|
{
|
||||||
|
NextPageToken = selection[selection.Count - 1].Id,
|
||||||
|
PrevPageToken = selection[0].Id,
|
||||||
|
Count = this._list.Count,
|
||||||
|
Result = selection
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public CursorResult<T> GetPreviousPage()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Cursor<T> WithNextPage(string nextPageToken)
|
||||||
|
{
|
||||||
|
this._nextPageToken = nextPageToken;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Cursor<T> WithPreviousPage(string prevPageToken)
|
||||||
|
{
|
||||||
|
this._previousPageToken = prevPageToken;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Cursor<T> WithSort(Func<KeyValuePair<string, T>, string> sortDelegate, SortDirection direction)
|
||||||
|
{
|
||||||
|
this._sortDelgate = sortDelegate;
|
||||||
|
this._direction = direction;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Cursor<T> WithSize(int size)
|
||||||
|
{
|
||||||
|
this._pageSize = size;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
32
AuroraSignal/Src/Cursor/CursorList.cs
Normal file
32
AuroraSignal/Src/Cursor/CursorList.cs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using Aurora.Utils;
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
namespace Aurora.Cursor
|
||||||
|
{
|
||||||
|
|
||||||
|
public class CursorList<T> : SortedList<string, T> where T : ICursorObject
|
||||||
|
{
|
||||||
|
|
||||||
|
public CursorList()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public CursorList<T> Add(T item)
|
||||||
|
{
|
||||||
|
string itemHashId = HashUtil.GetHash(new string[] { item.Id, item.GetHashCode().ToString() }).ToString();
|
||||||
|
bool res = this.TryAdd(itemHashId, item);
|
||||||
|
|
||||||
|
if (res == false)
|
||||||
|
{
|
||||||
|
throw new System.Exception("Failed to add item to cursor list");
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
9
AuroraSignal/Src/Cursor/CursorObject.cs
Normal file
9
AuroraSignal/Src/Cursor/CursorObject.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Aurora.Cursor
|
||||||
|
{
|
||||||
|
public interface ICursorObject
|
||||||
|
{
|
||||||
|
string Id { get; set; }
|
||||||
|
}
|
||||||
|
}
|
25
AuroraSignal/Src/Cursor/CursorResult.cs
Normal file
25
AuroraSignal/Src/Cursor/CursorResult.cs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Aurora.Cursor
|
||||||
|
{
|
||||||
|
public class CursorResult<T>
|
||||||
|
{
|
||||||
|
public CursorResult()
|
||||||
|
{
|
||||||
|
Result = new List<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public CursorResult(CursorResult<T> cpy)
|
||||||
|
{
|
||||||
|
NextPageToken = cpy.NextPageToken;
|
||||||
|
PrevPageToken = cpy.PrevPageToken;
|
||||||
|
Result = cpy.Result;
|
||||||
|
Count = cpy.Count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string NextPageToken { get; set; }
|
||||||
|
public string PrevPageToken { get; set; }
|
||||||
|
public List<T> Result { get; set; }
|
||||||
|
public int Count { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -1,94 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Aurora
|
|
||||||
{
|
|
||||||
public enum SortDirection {
|
|
||||||
Asc,
|
|
||||||
Desc,
|
|
||||||
}
|
|
||||||
|
|
||||||
public class CursorList<T> : List<T>
|
|
||||||
{
|
|
||||||
private string _orderBy;
|
|
||||||
private SortDirection _direction;
|
|
||||||
private string _previousPageToken;
|
|
||||||
private string _nextPageToken;
|
|
||||||
private int _pageSize;
|
|
||||||
|
|
||||||
public CursorList(){
|
|
||||||
this._direction = SortDirection.Desc;
|
|
||||||
this._orderBy = string.Empty;
|
|
||||||
this._previousPageToken = string.Empty;
|
|
||||||
this._nextPageToken = string.Empty;
|
|
||||||
this._pageSize = 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CursorList<T> WithNextPage(string nextPageToken){
|
|
||||||
this._nextPageToken = nextPageToken;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CursorList<T> WithPreviousPage(string prevPageToken){
|
|
||||||
this._previousPageToken = prevPageToken;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CursorList<T> WithSort(string orderBy, SortDirection direction ) {
|
|
||||||
this._orderBy = orderBy;
|
|
||||||
this._direction = direction;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CursorList<T> WithSize(int size){
|
|
||||||
this._pageSize = size;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<T> Get(){
|
|
||||||
if(this._nextPageToken != string.Empty && this._previousPageToken != string.Empty){
|
|
||||||
throw new System.InvalidOperationException("Cannot specify both next and previous page tokens");
|
|
||||||
}
|
|
||||||
|
|
||||||
List<T> tmpList = new List<T>(this);
|
|
||||||
|
|
||||||
|
|
||||||
tmpList.Sort(delegate(T first, T second){
|
|
||||||
object firstVal = first.GetType().GetProperty(this._orderBy).GetValue(first, null);
|
|
||||||
object secondVal = first.GetType().GetProperty(this._orderBy).GetValue(second, null);
|
|
||||||
int compare = 0;
|
|
||||||
|
|
||||||
if(firstVal == null && secondVal == null)
|
|
||||||
{
|
|
||||||
compare = 0;
|
|
||||||
}
|
|
||||||
else if(firstVal == null)
|
|
||||||
{
|
|
||||||
compare = 1;
|
|
||||||
}
|
|
||||||
else if(secondVal == null)
|
|
||||||
{
|
|
||||||
compare = -1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
|
|
||||||
// Determine number or string types
|
|
||||||
if(firstVal is string)
|
|
||||||
{
|
|
||||||
string firstStr = firstVal as string;
|
|
||||||
string secondStr = secondVal as string;
|
|
||||||
compare = firstStr.CompareTo(secondStr);
|
|
||||||
} else if(firstVal is int)
|
|
||||||
{
|
|
||||||
int? firstInt = firstVal as int?;
|
|
||||||
int? secondInt = secondVal as int?;
|
|
||||||
compare = firstInt > secondInt ? 1 : -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return this._direction == SortDirection.Asc ? compare : compare * -1;
|
|
||||||
});
|
|
||||||
|
|
||||||
return tmpList.GetRange(0, this._pageSize > tmpList.Count ? tmpList.Count : this._pageSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -54,7 +54,7 @@ service Signal {
|
|||||||
message Party {
|
message Party {
|
||||||
//The resource name of the party
|
//The resource name of the party
|
||||||
string name = 1;
|
string name = 1;
|
||||||
string party_id = 2;
|
string id = 2;
|
||||||
string display_name = 3;
|
string display_name = 3;
|
||||||
string description = 4;
|
string description = 4;
|
||||||
string host_ip = 5;
|
string host_ip = 5;
|
||||||
@ -63,7 +63,7 @@ message Party {
|
|||||||
|
|
||||||
message PartyListItem {
|
message PartyListItem {
|
||||||
string name = 1;
|
string name = 1;
|
||||||
string party_id = 2;
|
string id = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ListPartiesRequest {
|
message ListPartiesRequest {
|
||||||
|
@ -4,6 +4,7 @@ using System.Linq;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Grpc.Core;
|
using Grpc.Core;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Aurora.Cursor;
|
||||||
|
|
||||||
namespace Aurora.Services.Signal
|
namespace Aurora.Services.Signal
|
||||||
{
|
{
|
||||||
|
25
AuroraSignal/Src/Utils/HashUtil.cs
Normal file
25
AuroraSignal/Src/Utils/HashUtil.cs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Text;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Aurora.Utils
|
||||||
|
{
|
||||||
|
public class HashUtil
|
||||||
|
{
|
||||||
|
public static Guid GetHash(string[] inputs)
|
||||||
|
{
|
||||||
|
string input = "";
|
||||||
|
foreach (string str in inputs)
|
||||||
|
{
|
||||||
|
input += str;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] stringbytes = Encoding.UTF8.GetBytes(input);
|
||||||
|
byte[] hashedBytes = new System.Security.Cryptography
|
||||||
|
.SHA1CryptoServiceProvider()
|
||||||
|
.ComputeHash(stringbytes);
|
||||||
|
Array.Resize(ref hashedBytes, 16);
|
||||||
|
return new Guid(hashedBytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -7,6 +7,9 @@
|
|||||||
"settings": {
|
"settings": {
|
||||||
"files.exclude": {
|
"files.exclude": {
|
||||||
"**/obj": true
|
"**/obj": true
|
||||||
}
|
},
|
||||||
|
"dotnet-test-explorer.testProjectPath": "./AuroraSignal.test",
|
||||||
|
"editor.formatOnSave": true,
|
||||||
|
"editor.defaultFormatter": "ms-dotnettools.csharp"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user