Reworked LinkedList and Queue
- Reworked LinkedList and Queue - Written tests for LinkedList and Queue
This commit is contained in:
parent
a2f0b4584f
commit
4f8670c657
@ -12,14 +12,13 @@ export class ApplicationContext
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Called like:
|
* Called like:
|
||||||
*
|
* ```
|
||||||
* const registerPlayerInfo = this.applicationContext.getLatestValue(ContextVariableType.REGISTER_PLAYER_REQUEST).getValue<IRegisterPlayerRequestData>();
|
* const registerPlayerInfo = this.applicationContext.getLatestValue(ContextVariableType.REGISTER_PLAYER_REQUEST).getValue<IRegisterPlayerRequestData>();
|
||||||
*
|
*
|
||||||
* const activePlayerSessionId = this.applicationContext.getLatestValue(ContextVariableType.SESSION_ID).getValue<string>();
|
* const activePlayerSessionId = this.applicationContext.getLatestValue(ContextVariableType.SESSION_ID).getValue<string>();
|
||||||
*
|
*
|
||||||
* const matchInfo = this.applicationContext.getLatestValue(ContextVariableType.RAID_CONFIGURATION).getValue<IGetRaidConfigurationRequestData>();
|
* const matchInfo = this.applicationContext.getLatestValue(ContextVariableType.RAID_CONFIGURATION).getValue<IGetRaidConfigurationRequestData>();
|
||||||
* @param type
|
* ```
|
||||||
* @returns
|
|
||||||
*/
|
*/
|
||||||
public getLatestValue(type: ContextVariableType): ContextVariable
|
public getLatestValue(type: ContextVariableType): ContextVariable
|
||||||
{
|
{
|
||||||
@ -27,18 +26,21 @@ export class ApplicationContext
|
|||||||
{
|
{
|
||||||
return this.variables.get(type)?.getTail()?.getValue();
|
return this.variables.get(type)?.getTail()?.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
return undefined;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public getValues(type: ContextVariableType): ContextVariable[]
|
public getValues(type: ContextVariableType): ContextVariable[]
|
||||||
{
|
{
|
||||||
if (this.variables.has(type))
|
if (this.variables.has(type))
|
||||||
{
|
{
|
||||||
return this.variables.get(type).toList();
|
const res: ContextVariable[] = [];
|
||||||
|
|
||||||
|
for (const value of this.variables.get(type).values())
|
||||||
|
{
|
||||||
|
res.push(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return undefined;
|
return res;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public addValue(type: ContextVariableType, value: any): void
|
public addValue(type: ContextVariableType, value: any): void
|
||||||
@ -53,12 +55,12 @@ export class ApplicationContext
|
|||||||
list = new LinkedList<ContextVariable>();
|
list = new LinkedList<ContextVariable>();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (list.getSize() >= ApplicationContext.holderMaxSize)
|
if (list.length >= ApplicationContext.holderMaxSize)
|
||||||
{
|
{
|
||||||
list.removeFirst();
|
list.shift();
|
||||||
}
|
}
|
||||||
|
|
||||||
list.add(new ContextVariable(value, type));
|
list.append(new ContextVariable(value, type));
|
||||||
this.variables.set(type, list);
|
this.variables.set(type, list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,14 +127,14 @@ export class ImporterUtil
|
|||||||
directoriesToRead.enqueueAll(directories.map((d) => `${filepath}${d}`));
|
directoriesToRead.enqueueAll(directories.map((d) => `${filepath}${d}`));
|
||||||
filesToProcess.enqueueAll(files.map((f) => new VisitNode(filepath, f)));
|
filesToProcess.enqueueAll(files.map((f) => new VisitNode(filepath, f)));
|
||||||
|
|
||||||
while (!directoriesToRead.isEmpty())
|
while (directoriesToRead.length !== 0)
|
||||||
{
|
{
|
||||||
const directory = directoriesToRead.dequeue();
|
const directory = directoriesToRead.dequeue();
|
||||||
filesToProcess.enqueueAll(this.vfs.getFiles(directory).map((f) => new VisitNode(`${directory}/`, f)));
|
filesToProcess.enqueueAll(this.vfs.getFiles(directory).map((f) => new VisitNode(`${directory}/`, f)));
|
||||||
directoriesToRead.enqueueAll(this.vfs.getDirs(directory).map((d) => `${directory}/${d}`));
|
directoriesToRead.enqueueAll(this.vfs.getDirs(directory).map((d) => `${directory}/${d}`));
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!filesToProcess.isEmpty())
|
while (filesToProcess.length !== 0)
|
||||||
{
|
{
|
||||||
const fileNode = filesToProcess.dequeue();
|
const fileNode = filesToProcess.dequeue();
|
||||||
if (this.vfs.getFileExtension(fileNode.fileName) === "json")
|
if (this.vfs.getFileExtension(fileNode.fileName) === "json")
|
||||||
|
@ -1,231 +1,317 @@
|
|||||||
|
import { LinkedListNode } from "./Nodes";
|
||||||
|
|
||||||
export class LinkedList<T>
|
export class LinkedList<T>
|
||||||
{
|
{
|
||||||
private head: LinkedListNode<T>;
|
private head?: LinkedListNode<T>;
|
||||||
private tail: LinkedListNode<T>;
|
private tail?: LinkedListNode<T>;
|
||||||
|
private _length: number;
|
||||||
|
|
||||||
public add(t: T): void
|
public get length(): number
|
||||||
{
|
{
|
||||||
|
return this._length;
|
||||||
|
}
|
||||||
|
|
||||||
|
private set length(value: number)
|
||||||
|
{
|
||||||
|
this._length = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor()
|
||||||
|
{
|
||||||
|
this.length = 0;
|
||||||
|
this.head = this.tail = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds an element to the start of the list.
|
||||||
|
*/
|
||||||
|
public prepend(value: T): void
|
||||||
|
{
|
||||||
|
const node = new LinkedListNode(value);
|
||||||
|
this.length++;
|
||||||
|
|
||||||
if (!this.head)
|
if (!this.head)
|
||||||
{
|
{
|
||||||
const node = new LinkedListNode(t);
|
this.head = this.tail = node;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
node.next = this.head;
|
||||||
|
this.head.prev = node;
|
||||||
this.head = node;
|
this.head = node;
|
||||||
this.tail = node;
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
/**
|
||||||
|
* Adds an element at the given index to the list.
|
||||||
|
*/
|
||||||
|
public insertAt(value: T, idx: number): void
|
||||||
{
|
{
|
||||||
|
if (idx < 0 || idx > this.length)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (idx === 0)
|
||||||
|
{
|
||||||
|
this.prepend(value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (idx === this.length)
|
||||||
|
{
|
||||||
|
this.append(value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let ref = this.head;
|
let ref = this.head;
|
||||||
let next = this.head.getNextNode();
|
for (let i = 0; i <= idx; ++i)
|
||||||
while (next)
|
|
||||||
{
|
{
|
||||||
ref = next;
|
ref = ref.next;
|
||||||
next = ref.getNextNode();
|
|
||||||
}
|
}
|
||||||
const node = new LinkedListNode(t, ref);
|
|
||||||
ref.setNextNode(node);
|
const node = new LinkedListNode(value);
|
||||||
this.tail = node;
|
this.length++;
|
||||||
|
|
||||||
|
node.next = ref;
|
||||||
|
node.prev = ref.prev;
|
||||||
|
ref.prev = node;
|
||||||
|
|
||||||
|
if (node.prev)
|
||||||
|
{
|
||||||
|
node.prev.next = node;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public addRange(list: T[]): void
|
/**
|
||||||
|
* Adds an element to the end of the list.
|
||||||
|
*/
|
||||||
|
public append(value: T): void
|
||||||
{
|
{
|
||||||
for (const item of list)
|
const node = new LinkedListNode(value);
|
||||||
{
|
this.length++;
|
||||||
this.add(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public getHead(): LinkedListNode<T>
|
|
||||||
{
|
|
||||||
return this.head;
|
|
||||||
}
|
|
||||||
|
|
||||||
public getTail(): LinkedListNode<T>
|
|
||||||
{
|
|
||||||
return this.tail;
|
|
||||||
}
|
|
||||||
|
|
||||||
public isEmpty(): boolean
|
|
||||||
{
|
|
||||||
return this.head === undefined || this.head === null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public getSize(): number
|
|
||||||
{
|
|
||||||
let size = 0;
|
|
||||||
let next = this.head;
|
|
||||||
while (next)
|
|
||||||
{
|
|
||||||
size++;
|
|
||||||
next = next.getNextNode();
|
|
||||||
}
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
public removeFirst(): LinkedListNode<T>
|
|
||||||
{
|
|
||||||
if (!this.head)
|
|
||||||
{
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
const node = this.head;
|
|
||||||
if (this.head.getNextNode())
|
|
||||||
{
|
|
||||||
this.head = this.head.getNextNode();
|
|
||||||
this.head.setPreviousNode(undefined);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this.head = undefined;
|
|
||||||
}
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
public removeLast(): LinkedListNode<T>
|
|
||||||
{
|
|
||||||
if (!this.tail)
|
if (!this.tail)
|
||||||
{
|
{
|
||||||
return undefined;
|
this.head = this.tail = node;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const node = this.tail;
|
node.prev = this.tail;
|
||||||
if (this.tail.getPreviousNode())
|
this.tail.next = node;
|
||||||
{
|
this.tail = this.tail.next;
|
||||||
this.tail = this.tail.getPreviousNode();
|
|
||||||
this.tail.setNextNode(undefined);
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
/**
|
||||||
|
* Returns the first element's value.
|
||||||
|
*/
|
||||||
|
public getHead(): T
|
||||||
|
{
|
||||||
|
return this.head?.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the element from the list at the given index and returns it's value.
|
||||||
|
*/
|
||||||
|
public get(idx: number): T
|
||||||
|
{
|
||||||
|
if (idx < 0 || idx >= this.length)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (idx === 0)
|
||||||
|
{
|
||||||
|
return this.getHead();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (idx === this.length - 1)
|
||||||
|
{
|
||||||
|
return this.getTail();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const [index, value] of this.entries())
|
||||||
|
{
|
||||||
|
if (idx === index)
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the last element's value.
|
||||||
|
*/
|
||||||
|
public getTail(): T
|
||||||
|
{
|
||||||
|
return this.tail?.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds and removes the first element from a list that has a value equal to the given value, returns it's value if it successfully removed it.
|
||||||
|
*/
|
||||||
|
public remove(value: T): T
|
||||||
|
{
|
||||||
|
let ref = this.head;
|
||||||
|
for (let i = 0; ref && i < this.length; ++i)
|
||||||
|
{
|
||||||
|
if (ref.value === value)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ref = ref.next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ref)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.length--;
|
||||||
|
|
||||||
|
if (this.length === 0)
|
||||||
|
{
|
||||||
|
const out = this.head.value;
|
||||||
|
this.head = this.tail = undefined;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ref.prev)
|
||||||
|
{
|
||||||
|
ref.prev.next = ref.next;
|
||||||
|
}
|
||||||
|
if (ref.next)
|
||||||
|
{
|
||||||
|
ref.next.prev = ref.prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ref === this.head)
|
||||||
|
{
|
||||||
|
this.head = ref.next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ref === this.tail)
|
||||||
|
{
|
||||||
|
this.tail = ref.prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
ref.prev = ref.next = undefined;
|
||||||
|
|
||||||
|
return ref.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the first element from the list and returns it's value. If the list is empty, undefined is returned and the list is not modified.
|
||||||
|
*/
|
||||||
|
public shift(): T
|
||||||
|
{
|
||||||
|
if (!this.head)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.length--;
|
||||||
|
|
||||||
|
const ref = this.head;
|
||||||
|
this.head = this.head.next;
|
||||||
|
|
||||||
|
ref.next = undefined;
|
||||||
|
|
||||||
|
if (this.length === 0)
|
||||||
{
|
{
|
||||||
this.tail = undefined;
|
this.tail = undefined;
|
||||||
}
|
}
|
||||||
return node;
|
|
||||||
|
return ref.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public indexOf(func: (t: T) => boolean): number
|
/**
|
||||||
|
* Removes the element from the list at the given index and returns it's value.
|
||||||
|
*/
|
||||||
|
public removeAt(idx: number): T
|
||||||
{
|
{
|
||||||
const node = this.head;
|
if (idx < 0 || idx >= this.length)
|
||||||
let index = 0;
|
|
||||||
while (node)
|
|
||||||
{
|
{
|
||||||
if (func(node.getValue()))
|
return;
|
||||||
{
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
return undefined;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public contains(func: (t: T) => boolean): boolean
|
if (idx === 0)
|
||||||
|
{
|
||||||
|
return this.shift();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (idx === this.length - 1)
|
||||||
|
{
|
||||||
|
return this.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
let ref = this.head;
|
||||||
|
this.length--;
|
||||||
|
|
||||||
|
for (let i = 0; i < idx; ++i)
|
||||||
|
{
|
||||||
|
ref = ref.next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ref.prev)
|
||||||
|
{
|
||||||
|
ref.prev.next = ref.next;
|
||||||
|
}
|
||||||
|
if (ref.next)
|
||||||
|
{
|
||||||
|
ref.next.prev = ref.prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ref.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the last element from the list and returns it's value. If the list is empty, undefined is returned and the list is not modified.
|
||||||
|
*/
|
||||||
|
public pop(): T
|
||||||
|
{
|
||||||
|
if (!this.tail)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.length--;
|
||||||
|
|
||||||
|
const ref = this.tail;
|
||||||
|
this.tail = this.tail.prev;
|
||||||
|
|
||||||
|
ref.prev = undefined;
|
||||||
|
|
||||||
|
if (this.length === 0)
|
||||||
|
{
|
||||||
|
this.head = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ref.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an iterable of index, value pairs for every entry in the list.
|
||||||
|
*/
|
||||||
|
public *entries(): IterableIterator<[number, T]>
|
||||||
|
{
|
||||||
|
let node = this.head;
|
||||||
|
for (let i = 0; i < this.length; ++i)
|
||||||
|
{
|
||||||
|
yield [i, node.value];
|
||||||
|
node = node.next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an iterable of values in the list.
|
||||||
|
*/
|
||||||
|
public *values(): IterableIterator<T>
|
||||||
{
|
{
|
||||||
let node = this.head;
|
let node = this.head;
|
||||||
while (node)
|
while (node)
|
||||||
{
|
{
|
||||||
if (func(node.getValue()))
|
yield node.value;
|
||||||
{
|
node = node.next;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
node = node.getNextNode();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public forEachNode(func: (t: LinkedListNode<T>) => void): void
|
|
||||||
{
|
|
||||||
let node = this.head;
|
|
||||||
while (node)
|
|
||||||
{
|
|
||||||
func(node);
|
|
||||||
node = node.getNextNode();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public forEachValue(func: (t: T) => void): void
|
|
||||||
{
|
|
||||||
let node = this.head;
|
|
||||||
while (node)
|
|
||||||
{
|
|
||||||
func(node.getValue());
|
|
||||||
node = node.getNextNode();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public findFirstNode(func: (t: LinkedListNode<T>) => boolean): LinkedListNode<T>
|
|
||||||
{
|
|
||||||
let node = this.head;
|
|
||||||
while (node)
|
|
||||||
{
|
|
||||||
if (func(node))
|
|
||||||
{
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
node = node.getNextNode();
|
|
||||||
}
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
public findFirstValue(func: (t: T) => boolean): T
|
|
||||||
{
|
|
||||||
let node = this.head;
|
|
||||||
while (node)
|
|
||||||
{
|
|
||||||
if (func(node.getValue()))
|
|
||||||
{
|
|
||||||
return node.getValue();
|
|
||||||
}
|
|
||||||
node = node.getNextNode();
|
|
||||||
}
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
public toList(): T[]
|
|
||||||
{
|
|
||||||
const elements: T[] = [];
|
|
||||||
let node = this.head;
|
|
||||||
while (node)
|
|
||||||
{
|
|
||||||
elements.push(node.getValue());
|
|
||||||
node = node.getNextNode();
|
|
||||||
}
|
|
||||||
return elements;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class LinkedListNode<T>
|
|
||||||
{
|
|
||||||
private previous: LinkedListNode<T>;
|
|
||||||
private value: T;
|
|
||||||
private next: LinkedListNode<T>;
|
|
||||||
|
|
||||||
constructor(value: T, previous: LinkedListNode<T> = undefined, next: LinkedListNode<T> = undefined)
|
|
||||||
{
|
|
||||||
this.value = value;
|
|
||||||
this.previous = previous;
|
|
||||||
this.next = next;
|
|
||||||
}
|
|
||||||
|
|
||||||
public getValue(): T
|
|
||||||
{
|
|
||||||
return this.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public getNextNode(): LinkedListNode<T>
|
|
||||||
{
|
|
||||||
return this.next;
|
|
||||||
}
|
|
||||||
|
|
||||||
public setNextNode(node: LinkedListNode<T>): void
|
|
||||||
{
|
|
||||||
this.next = node;
|
|
||||||
}
|
|
||||||
|
|
||||||
public getPreviousNode(): LinkedListNode<T>
|
|
||||||
{
|
|
||||||
return this.previous;
|
|
||||||
}
|
|
||||||
|
|
||||||
public setPreviousNode(node: LinkedListNode<T>): void
|
|
||||||
{
|
|
||||||
this.previous = node;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
5
project/src/utils/collections/lists/Nodes.ts
Normal file
5
project/src/utils/collections/lists/Nodes.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export class LinkedListNode<T>
|
||||||
|
{
|
||||||
|
constructor(public value: T, public prev?: LinkedListNode<T>, public next?: LinkedListNode<T>)
|
||||||
|
{}
|
||||||
|
}
|
@ -1,21 +1,30 @@
|
|||||||
|
import { LinkedList } from "../lists/LinkedList";
|
||||||
|
|
||||||
export class Queue<T>
|
export class Queue<T>
|
||||||
{
|
{
|
||||||
private elements: Record<number, T>;
|
private list: LinkedList<T>;
|
||||||
private head: number;
|
|
||||||
private tail: number;
|
public get length(): number
|
||||||
|
{
|
||||||
|
return this.list.length;
|
||||||
|
}
|
||||||
|
|
||||||
constructor()
|
constructor()
|
||||||
{
|
{
|
||||||
this.elements = {};
|
this.list = new LinkedList<T>();
|
||||||
this.head = 0;
|
|
||||||
this.tail = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds an element to the end of the queue.
|
||||||
|
*/
|
||||||
public enqueue(element: T): void
|
public enqueue(element: T): void
|
||||||
{
|
{
|
||||||
this.elements[this.tail] = element;
|
this.list.append(element);
|
||||||
this.tail++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterates over the elements received and adds each one to the end of the queue.
|
||||||
|
*/
|
||||||
public enqueueAll(elements: T[]): void
|
public enqueueAll(elements: T[]): void
|
||||||
{
|
{
|
||||||
for (const element of elements)
|
for (const element of elements)
|
||||||
@ -24,25 +33,19 @@ export class Queue<T>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the first element from the queue and returns it's value. If the queue is empty, undefined is returned and the queue is not modified.
|
||||||
|
*/
|
||||||
public dequeue(): T
|
public dequeue(): T
|
||||||
{
|
{
|
||||||
const item = this.elements[this.head];
|
return this.list.shift();
|
||||||
delete this.elements[this.head];
|
|
||||||
this.head++;
|
|
||||||
return item;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the first element's value.
|
||||||
|
*/
|
||||||
public peek(): T
|
public peek(): T
|
||||||
{
|
{
|
||||||
return this.elements[this.head];
|
return this.list.getHead();
|
||||||
}
|
|
||||||
public getLength(): number
|
|
||||||
{
|
|
||||||
return this.tail - this.head;
|
|
||||||
}
|
|
||||||
|
|
||||||
public isEmpty(): boolean
|
|
||||||
{
|
|
||||||
return this.getLength() === 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
263
project/tests/utils/collections/lists/LinkedList.test.ts
Normal file
263
project/tests/utils/collections/lists/LinkedList.test.ts
Normal file
@ -0,0 +1,263 @@
|
|||||||
|
import "reflect-metadata";
|
||||||
|
import { describe, expect, it } from "vitest";
|
||||||
|
|
||||||
|
import { LinkedList } from "@spt-aki/utils/collections/lists/LinkedList";
|
||||||
|
|
||||||
|
describe("LinkedList", () =>
|
||||||
|
{
|
||||||
|
describe("prepend", () =>
|
||||||
|
{
|
||||||
|
const list = new LinkedList<number>();
|
||||||
|
list.prepend(420);
|
||||||
|
list.prepend(69);
|
||||||
|
list.prepend(8008135);
|
||||||
|
list.prepend(1337);
|
||||||
|
|
||||||
|
it("adds elements to the begining of the list", () =>
|
||||||
|
{
|
||||||
|
expect(list.getHead()).toEqual(1337);
|
||||||
|
expect(list.length).toEqual(4);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("append", () =>
|
||||||
|
{
|
||||||
|
const list = new LinkedList<number>();
|
||||||
|
list.append(420);
|
||||||
|
list.append(69);
|
||||||
|
list.append(8008135);
|
||||||
|
list.append(1337);
|
||||||
|
|
||||||
|
it("adds elements to the end of the list", () =>
|
||||||
|
{
|
||||||
|
expect(list.getHead()).toEqual(420);
|
||||||
|
expect(list.length).toEqual(4);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("insertAt", () =>
|
||||||
|
{
|
||||||
|
describe("empty list", () =>
|
||||||
|
{
|
||||||
|
const list = new LinkedList<number>();
|
||||||
|
|
||||||
|
it("should allow insertions at index 0 only", () =>
|
||||||
|
{
|
||||||
|
list.insertAt(420, 1);
|
||||||
|
expect(list.length).toEqual(0);
|
||||||
|
|
||||||
|
list.insertAt(420, 0);
|
||||||
|
expect(list.length).toEqual(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("filled list", () =>
|
||||||
|
{
|
||||||
|
const list = new LinkedList<number>();
|
||||||
|
list.append(420);
|
||||||
|
list.append(69);
|
||||||
|
list.append(8008135);
|
||||||
|
list.append(1337);
|
||||||
|
|
||||||
|
it("shouldn't insert if index is < 0 and > length", () =>
|
||||||
|
{
|
||||||
|
list.insertAt(10100111001, -1);
|
||||||
|
expect(list.length).toEqual(4);
|
||||||
|
|
||||||
|
list.insertAt(123, 5); // index 4 would work even though it's out of bounds because it's the next index, it's the same as doing an append
|
||||||
|
expect(list.length).toEqual(4);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should insert if index is between 0 and length", () =>
|
||||||
|
{
|
||||||
|
list.insertAt(10100111001, 0);
|
||||||
|
expect(list.length).toEqual(5);
|
||||||
|
|
||||||
|
list.insertAt(69420, 3);
|
||||||
|
expect(list.length).toEqual(6);
|
||||||
|
|
||||||
|
list.insertAt(123, 6);
|
||||||
|
expect(list.length).toEqual(7);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("getHead/getTail", () =>
|
||||||
|
{
|
||||||
|
it("should return undefined if the list is empty", () =>
|
||||||
|
{
|
||||||
|
const list = new LinkedList<number>();
|
||||||
|
expect(list.getHead()).toEqual(undefined);
|
||||||
|
expect(list.getTail()).toEqual(undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return the head and the tail values if the list has 1 or more elements", () =>
|
||||||
|
{
|
||||||
|
const list = new LinkedList<number>();
|
||||||
|
list.append(420);
|
||||||
|
list.append(69);
|
||||||
|
list.append(8008135);
|
||||||
|
|
||||||
|
expect(list.getHead()).toEqual(420);
|
||||||
|
expect(list.getTail()).toEqual(8008135);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("get", () =>
|
||||||
|
{
|
||||||
|
describe("empty list", () =>
|
||||||
|
{
|
||||||
|
const list = new LinkedList<number>();
|
||||||
|
|
||||||
|
it("should return undefined", () =>
|
||||||
|
{
|
||||||
|
expect(list.get(0)).toEqual(undefined);
|
||||||
|
expect(list.get(1)).toEqual(undefined);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("filled list", () =>
|
||||||
|
{
|
||||||
|
const list = new LinkedList<number>();
|
||||||
|
list.append(420);
|
||||||
|
list.append(69);
|
||||||
|
list.append(8008135);
|
||||||
|
list.append(1337);
|
||||||
|
|
||||||
|
it("should return undefined if index is < 0 or >= length", () =>
|
||||||
|
{
|
||||||
|
expect(list.get(-1)).toEqual(undefined);
|
||||||
|
expect(list.get(list.length)).toEqual(undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return the value if the index is between 0 and length - 1", () =>
|
||||||
|
{
|
||||||
|
expect(list.get(0)).toEqual(420);
|
||||||
|
expect(list.get(1)).toEqual(69);
|
||||||
|
expect(list.get(list.length - 1)).toEqual(1337);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("remove", () =>
|
||||||
|
{
|
||||||
|
const list = new LinkedList<number>();
|
||||||
|
list.append(420);
|
||||||
|
list.append(69);
|
||||||
|
list.append(8008135);
|
||||||
|
list.append(1337);
|
||||||
|
|
||||||
|
it("should return undefined if it doesn't find any element with the same value", () =>
|
||||||
|
{
|
||||||
|
expect(list.remove(10100111001)).toEqual(undefined);
|
||||||
|
expect(list.length).toEqual(4);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should remove an element and return it's value if one is found with the same value", () =>
|
||||||
|
{
|
||||||
|
expect(list.remove(420)).toEqual(420);
|
||||||
|
expect(list.length).toEqual(3);
|
||||||
|
|
||||||
|
expect(list.remove(8008135)).toEqual(8008135);
|
||||||
|
expect(list.length).toEqual(2);
|
||||||
|
|
||||||
|
expect(list.remove(1337)).toEqual(1337);
|
||||||
|
expect(list.length).toEqual(1);
|
||||||
|
|
||||||
|
expect(list.remove(69)).toEqual(69);
|
||||||
|
expect(list.length).toEqual(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("shift", () =>
|
||||||
|
{
|
||||||
|
describe("empty list", () =>
|
||||||
|
{
|
||||||
|
const list = new LinkedList<number>();
|
||||||
|
|
||||||
|
it("shouldn't change the list and should return undefined if list is empty", () =>
|
||||||
|
{
|
||||||
|
expect(list.shift()).toEqual(undefined);
|
||||||
|
expect(list.length).toEqual(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("filled list", () =>
|
||||||
|
{
|
||||||
|
const list = new LinkedList<number>();
|
||||||
|
list.append(420);
|
||||||
|
list.append(1337);
|
||||||
|
|
||||||
|
it("should remove the first element and return it's value", () =>
|
||||||
|
{
|
||||||
|
expect(list.shift()).toEqual(420);
|
||||||
|
expect(list.length).toEqual(1);
|
||||||
|
|
||||||
|
expect(list.shift()).toEqual(1337);
|
||||||
|
expect(list.length).toEqual(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("pop", () =>
|
||||||
|
{
|
||||||
|
describe("empty list", () =>
|
||||||
|
{
|
||||||
|
const list = new LinkedList<number>();
|
||||||
|
|
||||||
|
it("shouldn't change the list and should return undefined if list is empty", () =>
|
||||||
|
{
|
||||||
|
expect(list.pop()).toEqual(undefined);
|
||||||
|
expect(list.length).toEqual(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("filled list", () =>
|
||||||
|
{
|
||||||
|
const list = new LinkedList<number>();
|
||||||
|
list.append(420);
|
||||||
|
list.append(1337);
|
||||||
|
|
||||||
|
it("should remove the first element and return it's value", () =>
|
||||||
|
{
|
||||||
|
expect(list.pop()).toEqual(1337);
|
||||||
|
expect(list.length).toEqual(1);
|
||||||
|
|
||||||
|
expect(list.pop()).toEqual(420);
|
||||||
|
expect(list.length).toEqual(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("removeAt", () =>
|
||||||
|
{
|
||||||
|
const list = new LinkedList<number>();
|
||||||
|
list.append(420);
|
||||||
|
list.append(69);
|
||||||
|
list.append(8008135);
|
||||||
|
list.append(1337);
|
||||||
|
list.append(10100111001);
|
||||||
|
|
||||||
|
it("should return undefined if index is < 0 or >= length", () =>
|
||||||
|
{
|
||||||
|
expect(list.removeAt(-1)).toEqual(undefined);
|
||||||
|
expect(list.removeAt(list.length)).toEqual(undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should remove an element and return it's value if index is between 0 and length - 1", () =>
|
||||||
|
{
|
||||||
|
expect(list.removeAt(0)).toEqual(420);
|
||||||
|
expect(list.length).toEqual(4);
|
||||||
|
|
||||||
|
expect(list.removeAt(2)).toEqual(1337);
|
||||||
|
expect(list.length).toEqual(3);
|
||||||
|
|
||||||
|
expect(list.removeAt(list.length - 1)).toEqual(10100111001);
|
||||||
|
expect(list.length).toEqual(2);
|
||||||
|
|
||||||
|
expect(list.removeAt(1)).toEqual(8008135);
|
||||||
|
expect(list.removeAt(0)).toEqual(69);
|
||||||
|
expect(list.length).toEqual(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
63
project/tests/utils/collections/queue/Queue.test.ts
Normal file
63
project/tests/utils/collections/queue/Queue.test.ts
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
import "reflect-metadata";
|
||||||
|
import { describe, expect, it } from "vitest";
|
||||||
|
|
||||||
|
import { Queue } from "@spt-aki/utils/collections/queue/Queue";
|
||||||
|
|
||||||
|
describe("LinkedList", () =>
|
||||||
|
{
|
||||||
|
describe("enqueue", () =>
|
||||||
|
{
|
||||||
|
const queue = new Queue<number>();
|
||||||
|
queue.enqueue(420);
|
||||||
|
queue.enqueue(69);
|
||||||
|
queue.enqueue(8008135);
|
||||||
|
queue.enqueue(1337);
|
||||||
|
|
||||||
|
it("adds elements to the end of the queue", () =>
|
||||||
|
{
|
||||||
|
expect(queue.peek()).toEqual(420);
|
||||||
|
expect(queue.length).toEqual(4);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("enqueueAll", () =>
|
||||||
|
{
|
||||||
|
const queue = new Queue<number>();
|
||||||
|
queue.enqueueAll([420, 69, 8008135, 1337]);
|
||||||
|
|
||||||
|
it("iterates the array and adds each element to the end of the queue", () =>
|
||||||
|
{
|
||||||
|
expect(queue.peek()).toEqual(420);
|
||||||
|
expect(queue.length).toEqual(4);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("dequeue", () =>
|
||||||
|
{
|
||||||
|
const queue = new Queue<number>();
|
||||||
|
queue.enqueueAll([420, 69, 8008135, 1337]);
|
||||||
|
|
||||||
|
it("removes the first element and return it's value", () =>
|
||||||
|
{
|
||||||
|
expect(queue.dequeue()).toEqual(420);
|
||||||
|
expect(queue.peek()).toEqual(69);
|
||||||
|
expect(queue.length).toEqual(3);
|
||||||
|
|
||||||
|
expect(queue.dequeue()).toEqual(69);
|
||||||
|
expect(queue.peek()).toEqual(8008135);
|
||||||
|
expect(queue.length).toEqual(2);
|
||||||
|
|
||||||
|
expect(queue.dequeue()).toEqual(8008135);
|
||||||
|
expect(queue.peek()).toEqual(1337);
|
||||||
|
expect(queue.length).toEqual(1);
|
||||||
|
|
||||||
|
expect(queue.dequeue()).toEqual(1337);
|
||||||
|
expect(queue.peek()).toEqual(undefined);
|
||||||
|
expect(queue.length).toEqual(0);
|
||||||
|
|
||||||
|
expect(queue.dequeue()).toEqual(undefined);
|
||||||
|
expect(queue.peek()).toEqual(undefined);
|
||||||
|
expect(queue.length).toEqual(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user