WIP
This commit is contained in:
parent
91d0a55d5e
commit
b61ffde4c9
@ -1,8 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Xunit;
|
||||
using Aurora;
|
||||
using Aurora.Services.Signal;
|
||||
using Aurora.Cursor;
|
||||
|
||||
|
||||
namespace AuroraSignal.test
|
||||
@ -14,57 +13,30 @@ namespace AuroraSignal.test
|
||||
[InlineData(SortDirection.Desc)]
|
||||
public void CursorListSortOnStringValue(SortDirection direction)
|
||||
{
|
||||
CursorList<Party> cursor = new CursorList<Party>();
|
||||
cursor.Add(new Party(){Name = "asdf", PartyId = "1111"});
|
||||
cursor.Add(new Party(){Name = "bsdf", PartyId = "2222"});
|
||||
cursor.Add(new Party(){Name = "csdf", PartyId = "3333"});
|
||||
CursorList<Party> list = new CursorList<Party>();
|
||||
list.Add(new Party() { Name = "asdf", Id = "1111" });
|
||||
list.Add(new Party() { Name = "bsdf", Id = "2222" });
|
||||
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,
|
||||
item => item.Name.Equals("asdf"),
|
||||
item => item.Name.Equals("bsdf"),
|
||||
Assert.Collection<Party>(result.Result,
|
||||
item => item.Name.Equals("asdf"),
|
||||
item => item.Name.Equals("bsdf"),
|
||||
item => item.Name.Equals("csdf"));
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.Collection<Party>(cursor,
|
||||
item => item.Name.Equals("csdf"),
|
||||
item => item.Name.Equals("bsdf"),
|
||||
Assert.Collection<Party>(result.Result,
|
||||
item => item.Name.Equals("csdf"),
|
||||
item => item.Name.Equals("bsdf"),
|
||||
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 {
|
||||
//The resource name of the party
|
||||
string name = 1;
|
||||
string party_id = 2;
|
||||
string id = 2;
|
||||
string display_name = 3;
|
||||
string description = 4;
|
||||
string host_ip = 5;
|
||||
@ -63,7 +63,7 @@ message Party {
|
||||
|
||||
message PartyListItem {
|
||||
string name = 1;
|
||||
string party_id = 2;
|
||||
string id = 2;
|
||||
}
|
||||
|
||||
message ListPartiesRequest {
|
||||
|
@ -4,6 +4,7 @@ using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Grpc.Core;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Aurora.Cursor;
|
||||
|
||||
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": {
|
||||
"files.exclude": {
|
||||
"**/obj": true
|
||||
}
|
||||
},
|
||||
"dotnet-test-explorer.testProjectPath": "./AuroraSignal.test",
|
||||
"editor.formatOnSave": true,
|
||||
"editor.defaultFormatter": "ms-dotnettools.csharp"
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user