the-best-sort 1.0.2 ā 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +135 -41
- package/dist/index.d.ts +64 -64
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +146 -127
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
# The Best Sort
|
|
2
2
|
|
|
3
|
-
A comprehensive AI-friendly TypeScript library for array
|
|
3
|
+
A comprehensive AI-friendly TypeScript library for array sorting and asynchronous processing using powerful strategy with advanced object-oriented programming patterns and design principles.
|
|
4
4
|
|
|
5
5
|
## Overview
|
|
6
6
|
|
|
7
|
-
The Best Sort is a production
|
|
7
|
+
The Best Sort is a production-ready TypeScript framework designed to handle efficient sorting operations at scale. At its core, it implements a powerful asynchronous sleep sort strategy, enabling you to sort large datasets with concurrent processing capabilities. The framework leverages event-driven architecture to provide real-time observability into sorting progress, making it practical for production environments where monitoring and performance insights matter.
|
|
8
|
+
|
|
9
|
+
Whether you're sorting massive collections, processing data streams, or integrating sorting into AI agent workflows, The Best Sort delivers type-safe, extensible sorting solutions. Built with modern software engineering practices, it provides both a reliable tool for practical sorting tasks and a learning resource for developers seeking to understand how sophisticated sorting systems are implemented in contemporary applications.
|
|
8
10
|
|
|
9
11
|
## Installation
|
|
10
12
|
|
|
@@ -35,40 +37,51 @@ npx tsc src/index.ts --experimentalDecorators --emitDecoratorMetadata
|
|
|
35
37
|
node the-best-sort.js
|
|
36
38
|
```
|
|
37
39
|
|
|
38
|
-
##
|
|
40
|
+
## Advanced Sorting Strategies
|
|
39
41
|
|
|
40
|
-
The Best Sort implements multiple design patterns to create a robust and extensible framework, including singleton, factory, builder, facade, decorators, strategy, observer, command invoker and runner.
|
|
42
|
+
The Best Sort implements multiple design patterns to create a robust and extensible framework, including singleton, factory, builder, facade, decorators, strategy, observer, command invoker and runner so you can implement flexible, adaptive sorting solutions for any dataset.
|
|
41
43
|
|
|
42
44
|
|
|
43
45
|
## Core Components
|
|
44
46
|
|
|
45
|
-
###
|
|
47
|
+
### SortableNumber
|
|
46
48
|
|
|
47
|
-
A comparable number wrapper implementing the `
|
|
49
|
+
A comparable number wrapper implementing the `SortableNumber` interface:
|
|
48
50
|
|
|
49
51
|
```typescript
|
|
50
|
-
const nums
|
|
52
|
+
const nums = [1, 2, 3].map(n => new SortableNumber(n));
|
|
51
53
|
```
|
|
52
54
|
|
|
53
55
|
|
|
54
|
-
###
|
|
56
|
+
### SortingContext
|
|
55
57
|
|
|
56
58
|
Manages state and event notifications during visualization:
|
|
57
59
|
|
|
58
60
|
```typescript
|
|
59
|
-
const context = new
|
|
61
|
+
const context = new SortingContext<SortableNumber>("Strategy Name");
|
|
60
62
|
context.attach(observer);
|
|
61
63
|
context.emitElementDisplayed(element, index, delay);
|
|
62
64
|
```
|
|
63
65
|
|
|
66
|
+
## StrategyFactory
|
|
67
|
+
|
|
68
|
+
Create sorting strategies through the factory:
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
const factory = new ConcreteSortingStrategyFactory<SortableNumber>();
|
|
72
|
+
const strategy = factory.createStrategy(StrategyType.DEFAULT);
|
|
73
|
+
```
|
|
74
|
+
|
|
64
75
|
|
|
65
76
|
### Observers
|
|
66
77
|
|
|
67
78
|
Track visualization events and collect metrics:
|
|
68
79
|
|
|
69
80
|
```typescript
|
|
70
|
-
const statsObserver = new StatisticsObserver<
|
|
71
|
-
|
|
81
|
+
const statsObserver = new StatisticsObserver<SortableNumber>();
|
|
82
|
+
const historyObserver = new HistoryObserver<SortableNumber>();
|
|
83
|
+
sorter.addObserver(statsObserver);
|
|
84
|
+
sorter.addObserver(historyObserver);
|
|
72
85
|
```
|
|
73
86
|
|
|
74
87
|
|
|
@@ -88,21 +101,21 @@ ConfigurationManager.getInstance().updateConfig({
|
|
|
88
101
|
|
|
89
102
|
## Event Types
|
|
90
103
|
|
|
91
|
-
The library emits the following event types during
|
|
104
|
+
The library emits the following event types during sorting:
|
|
92
105
|
|
|
93
|
-
- `STARTED` -
|
|
94
|
-
- `
|
|
95
|
-
- `COMPLETED` -
|
|
96
|
-
- `ERROR` - An error occurred during
|
|
106
|
+
- `STARTED` - Sorting has started
|
|
107
|
+
- `ELEMENT_SORTED` - An array element was processed and added to result
|
|
108
|
+
- `COMPLETED` - Sorting has completed
|
|
109
|
+
- `ERROR` - An error occurred during sorting
|
|
97
110
|
|
|
98
111
|
## Performance Metrics
|
|
99
112
|
|
|
100
113
|
`StatisticsObserver` collects the following metrics:
|
|
101
114
|
|
|
102
115
|
```typescript
|
|
103
|
-
interface
|
|
116
|
+
interface SortingStatistics {
|
|
104
117
|
duration: number; // Total duration in milliseconds
|
|
105
|
-
|
|
118
|
+
sortedElements: number; // Number of elements sorted
|
|
106
119
|
totalDelay: number; // Sum of all delays
|
|
107
120
|
averageDelay: number; // Average delay per element
|
|
108
121
|
eventCounts: Map<EventType, number>; // Event counts by type
|
|
@@ -114,11 +127,11 @@ interface VisualizationStatistics {
|
|
|
114
127
|
|
|
115
128
|
The library follows a layered architecture:
|
|
116
129
|
|
|
117
|
-
1. **Core Domain** - `
|
|
130
|
+
1. **Core Domain** - `SortableNumber`, event types, configuration
|
|
118
131
|
2. **Patterns Layer** - Decorators, strategies, factory implementations
|
|
119
|
-
3. **Context Layer** - `
|
|
120
|
-
4. **Observer Layer** - Multiple observer implementations
|
|
121
|
-
5. **Application Layer** - `
|
|
132
|
+
3. **Context Layer** - `SortingContext` managing state and notifications
|
|
133
|
+
4. **Observer Layer** - Multiple observer implementations (Console, Statistics, History)
|
|
134
|
+
5. **Application Layer** - `ArraySorter`, `CommandInvoker`, runners
|
|
122
135
|
6. **Factory Layer** - Strategy and builder creation
|
|
123
136
|
|
|
124
137
|
## TypeScript Features Used
|
|
@@ -131,55 +144,138 @@ The library follows a layered architecture:
|
|
|
131
144
|
- Readonly types for immutability
|
|
132
145
|
- Object destructuring and spreading
|
|
133
146
|
|
|
147
|
+
## Usage
|
|
148
|
+
|
|
149
|
+
Basic usage:
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
const numbers = [1, 100, 10];ā
|
|
153
|
+
const sortableArray = numbers.map(n => new SortableNumber(n));
|
|
154
|
+
|
|
155
|
+
const factory = new ConcreteSortingStrategyFactory<SortableNumber>();
|
|
156
|
+
const strategy = factory.createStrategy(StrategyType.DEFAULT);
|
|
157
|
+
|
|
158
|
+
const sorter = new SorterBuilder<SortableNumber>()
|
|
159
|
+
.setArray(sortableArray)
|
|
160
|
+
.setStrategy(strategy)
|
|
161
|
+
.build();
|
|
162
|
+
|
|
163
|
+
const sortedArray = await sorter.execute();
|
|
164
|
+
console.log(sortedArray)
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### With custom observers
|
|
168
|
+
|
|
169
|
+
```typescript
|
|
170
|
+
const statisticsObserver = new StatisticsObserver<SortableNumber>();
|
|
171
|
+
const historyObserver = new HistoryObserver<SortableNumber>();
|
|
172
|
+
|
|
173
|
+
const sorter = new SorterBuilder<SortableNumber>()
|
|
174
|
+
.setArray(sortableArray)
|
|
175
|
+
.setStrategy(strategy)
|
|
176
|
+
.addObserver(statisticsObserver)
|
|
177
|
+
.addObserver(historyObserver)
|
|
178
|
+
.build();
|
|
179
|
+
|
|
180
|
+
await sorter.execute();
|
|
181
|
+
statisticsObserver.printStatistics();
|
|
182
|
+
historyObserver.printHistory();
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### Using command pattern
|
|
186
|
+
|
|
187
|
+
```typescript
|
|
188
|
+
const invoker = new CommandInvoker();
|
|
189
|
+
const sortingCommand = new ExecuteSortingCommand(sorter);
|
|
190
|
+
|
|
191
|
+
invoker.enqueueCommand(sortingCommand);
|
|
192
|
+
const results = await invoker.executeAll();
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### Using template method pattern
|
|
196
|
+
|
|
197
|
+
```typescript
|
|
198
|
+
const runner = new LoggingSortingRunner<SortableNumber>();
|
|
199
|
+
const sortedArray = await runner.run(sortableArray, StrategyType.DEFAULT);
|
|
200
|
+
```
|
|
201
|
+
|
|
134
202
|
## Extending the Library
|
|
135
203
|
|
|
136
204
|
### Creating Custom Observers
|
|
137
205
|
|
|
138
206
|
```typescript
|
|
139
|
-
class
|
|
140
|
-
update(event:
|
|
141
|
-
|
|
207
|
+
class MetricsObserver<T extends ISortable> implements IObserver<T> {
|
|
208
|
+
update(event: SortingEvent<T>): void {
|
|
209
|
+
if (event.type === EventType.ELEMENT_SORTED) {
|
|
210
|
+
// Custom logic here
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
sorter.addObserver(new MetricsObserver());
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### Creating custom strategies
|
|
219
|
+
|
|
220
|
+
```typescript
|
|
221
|
+
class BubbleSortStrategy<T extends ISortable>
|
|
222
|
+
extends AbstractSortingStrategy<T> {
|
|
223
|
+
|
|
224
|
+
sort(array: T[], context: SortingContext<T>): Promise<T[]> {
|
|
225
|
+
context.emitStarted();
|
|
226
|
+
// Implementation
|
|
227
|
+
context.emitCompleted();
|
|
228
|
+
return Promise.resolve(result);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
getName(): string {
|
|
232
|
+
return 'Bubble Sort Strategy';
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
getDescription(): string {
|
|
236
|
+
return 'Classic bubble sort implementation';
|
|
142
237
|
}
|
|
143
238
|
}
|
|
144
239
|
|
|
145
|
-
|
|
240
|
+
// Register strategy
|
|
241
|
+
factory.registerStrategy(StrategyType.BUBBLE, new BubbleSortStrategy());
|
|
146
242
|
```
|
|
147
243
|
|
|
148
244
|
|
|
149
245
|
### Creating Custom Commands
|
|
150
246
|
|
|
151
247
|
```typescript
|
|
152
|
-
class
|
|
153
|
-
execute(): void {
|
|
154
|
-
|
|
248
|
+
class ResetCommand implements ICommand {
|
|
249
|
+
async execute(): Promise<void> {
|
|
250
|
+
ConfigurationManager.getInstance().resetToDefaults();
|
|
155
251
|
}
|
|
156
252
|
|
|
157
253
|
getDescription(): string {
|
|
158
|
-
return
|
|
254
|
+
return 'Reset configuration to defaults';
|
|
159
255
|
}
|
|
160
256
|
}
|
|
161
257
|
|
|
162
|
-
invoker.enqueueCommand(new
|
|
258
|
+
invoker.enqueueCommand(new ResetCommand());
|
|
163
259
|
```
|
|
164
260
|
|
|
165
261
|
|
|
166
262
|
### Creating Custom Runners
|
|
167
263
|
|
|
168
264
|
```typescript
|
|
169
|
-
class
|
|
170
|
-
extends
|
|
171
|
-
|
|
265
|
+
class MetricsSortingRunner<T extends ISortable>
|
|
266
|
+
extends AbstractSortingRunner<T> {
|
|
267
|
+
|
|
172
268
|
protected beforeRun(): void {
|
|
173
|
-
console.log(
|
|
269
|
+
console.log('Initializing sorting with metrics...');
|
|
174
270
|
}
|
|
175
|
-
|
|
271
|
+
|
|
176
272
|
protected afterRun(): void {
|
|
177
|
-
console.log(
|
|
273
|
+
console.log('Sorting completed with full metrics');
|
|
178
274
|
}
|
|
179
275
|
}
|
|
180
276
|
|
|
181
|
-
const runner = new
|
|
182
|
-
runner.run(
|
|
277
|
+
const runner = new MetricsSortingRunner<SortableNumber>();
|
|
278
|
+
const result = await runner.run(sortableArray, StrategyType.DEFAULT);
|
|
183
279
|
```
|
|
184
280
|
|
|
185
281
|
## Requirements
|
|
@@ -190,9 +286,7 @@ runner.run(array, StrategyType.TIMEOUT_FOREACH);
|
|
|
190
286
|
|
|
191
287
|
## Limitations
|
|
192
288
|
|
|
193
|
-
- All timing is based on setTimeout, which may be affected by event loop congestion
|
|
194
289
|
- Very large arrays (10,000+) may cause performance degradation
|
|
195
|
-
- setTimeout precision is not guaranteed to be exact at sub-millisecond scales
|
|
196
290
|
|
|
197
291
|
## Contributing
|
|
198
292
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
interface
|
|
1
|
+
interface ISortable {
|
|
2
2
|
getValue(): number;
|
|
3
3
|
toString(): string;
|
|
4
4
|
}
|
|
5
5
|
interface IObserver<T> {
|
|
6
|
-
update(event:
|
|
6
|
+
update(event: SortingEvent<T>): void;
|
|
7
7
|
}
|
|
8
8
|
interface ISubject<T> {
|
|
9
9
|
attach(observer: IObserver<T>): void;
|
|
10
10
|
detach(observer: IObserver<T>): void;
|
|
11
|
-
notify(event:
|
|
11
|
+
notify(event: SortingEvent<T>): void;
|
|
12
12
|
}
|
|
13
13
|
declare enum EventType {
|
|
14
14
|
STARTED = "STARTED",
|
|
15
|
-
|
|
15
|
+
ELEMENT_SORTED = "ELEMENT_SORTED",
|
|
16
16
|
COMPLETED = "COMPLETED",
|
|
17
17
|
ERROR = "ERROR"
|
|
18
18
|
}
|
|
19
|
-
interface
|
|
19
|
+
interface SortingEvent<T> {
|
|
20
20
|
type: EventType;
|
|
21
21
|
element?: T;
|
|
22
22
|
index?: number;
|
|
@@ -24,27 +24,27 @@ interface VisualizationEvent<T> {
|
|
|
24
24
|
delay?: number;
|
|
25
25
|
metadata?: Record<string, any>;
|
|
26
26
|
}
|
|
27
|
-
interface
|
|
28
|
-
|
|
27
|
+
interface ISortingStrategy<T extends ISortable> {
|
|
28
|
+
sort(array: T[], context: SortingContext<T>): Promise<T[]>;
|
|
29
29
|
getName(): string;
|
|
30
30
|
getDescription(): string;
|
|
31
31
|
}
|
|
32
|
-
interface
|
|
33
|
-
createStrategy(type: StrategyType):
|
|
34
|
-
registerStrategy(type: StrategyType, strategy:
|
|
32
|
+
interface ISortingStrategyFactory<T extends ISortable> {
|
|
33
|
+
createStrategy(type: StrategyType): ISortingStrategy<T>;
|
|
34
|
+
registerStrategy(type: StrategyType, strategy: ISortingStrategy<T>): void;
|
|
35
35
|
listAvailableStrategies(): string[];
|
|
36
36
|
}
|
|
37
37
|
declare enum StrategyType {
|
|
38
|
-
|
|
38
|
+
DEFAULT = "DEFAULT"
|
|
39
39
|
}
|
|
40
|
-
interface
|
|
40
|
+
interface SortingConfig {
|
|
41
41
|
baseDelayMs: number;
|
|
42
42
|
enableLogging: boolean;
|
|
43
43
|
logPrefix: string;
|
|
44
44
|
showTimestamps: boolean;
|
|
45
45
|
colorize: boolean;
|
|
46
46
|
}
|
|
47
|
-
declare class
|
|
47
|
+
declare class SortableNumber implements ISortable {
|
|
48
48
|
private readonly value;
|
|
49
49
|
constructor(value: number);
|
|
50
50
|
getValue(): number;
|
|
@@ -56,14 +56,14 @@ declare class ConfigurationManager {
|
|
|
56
56
|
private config;
|
|
57
57
|
private constructor();
|
|
58
58
|
static getInstance(): ConfigurationManager;
|
|
59
|
-
getConfig(): Readonly<
|
|
60
|
-
updateConfig(partial: Partial<
|
|
59
|
+
getConfig(): Readonly<SortingConfig>;
|
|
60
|
+
updateConfig(partial: Partial<SortingConfig>): void;
|
|
61
61
|
resetToDefaults(): void;
|
|
62
62
|
}
|
|
63
63
|
declare function Measure(target: any, propertyKey: string, descriptor: PropertyDescriptor): PropertyDescriptor;
|
|
64
64
|
declare function Log(target: any, propertyKey: string, descriptor: PropertyDescriptor): PropertyDescriptor;
|
|
65
65
|
declare function ValidateArray(target: any, propertyKey: string, descriptor: PropertyDescriptor): PropertyDescriptor;
|
|
66
|
-
declare class
|
|
66
|
+
declare class SortingContext<T extends ISortable> implements ISubject<T> {
|
|
67
67
|
private strategyName;
|
|
68
68
|
private observers;
|
|
69
69
|
private eventHistory;
|
|
@@ -71,129 +71,129 @@ declare class VisualizationContext<T extends IVisualizable> implements ISubject<
|
|
|
71
71
|
constructor(strategyName: string);
|
|
72
72
|
attach(observer: IObserver<T>): void;
|
|
73
73
|
detach(observer: IObserver<T>): void;
|
|
74
|
-
notify(event:
|
|
74
|
+
notify(event: SortingEvent<T>): void;
|
|
75
75
|
emitStarted(): void;
|
|
76
|
-
|
|
76
|
+
emitElementSorted(element: T, index: number, delay: number): void;
|
|
77
77
|
emitCompleted(): void;
|
|
78
78
|
emitError(error: Error): void;
|
|
79
|
-
getEventHistory():
|
|
79
|
+
getEventHistory(): SortingEvent<T>[];
|
|
80
80
|
getElementCount(): number;
|
|
81
81
|
getStrategyName(): string;
|
|
82
82
|
}
|
|
83
|
-
declare class ConsoleLoggingObserver<T extends
|
|
83
|
+
declare class ConsoleLoggingObserver<T extends ISortable> implements IObserver<T> {
|
|
84
84
|
private config;
|
|
85
|
-
update(event:
|
|
85
|
+
update(event: SortingEvent<T>): void;
|
|
86
86
|
}
|
|
87
|
-
declare class StatisticsObserver<T extends
|
|
87
|
+
declare class StatisticsObserver<T extends ISortable> implements IObserver<T> {
|
|
88
88
|
private startTime;
|
|
89
89
|
private endTime;
|
|
90
|
-
private
|
|
90
|
+
private sortedElements;
|
|
91
91
|
private totalDelay;
|
|
92
92
|
private events;
|
|
93
|
-
update(event:
|
|
94
|
-
getStatistics():
|
|
93
|
+
update(event: SortingEvent<T>): void;
|
|
94
|
+
getStatistics(): SortingStatistics;
|
|
95
95
|
printStatistics(): void;
|
|
96
96
|
reset(): void;
|
|
97
97
|
}
|
|
98
|
-
interface
|
|
98
|
+
interface SortingStatistics {
|
|
99
99
|
duration: number;
|
|
100
|
-
|
|
100
|
+
sortedElements: number;
|
|
101
101
|
totalDelay: number;
|
|
102
102
|
averageDelay: number;
|
|
103
103
|
eventCounts: Map<EventType, number>;
|
|
104
104
|
}
|
|
105
|
-
declare class HistoryObserver<T extends
|
|
105
|
+
declare class HistoryObserver<T extends ISortable> implements IObserver<T> {
|
|
106
106
|
private history;
|
|
107
|
-
update(event:
|
|
107
|
+
update(event: SortingEvent<T>): void;
|
|
108
108
|
getHistory(): Array<{
|
|
109
|
-
event:
|
|
109
|
+
event: SortingEvent<T>;
|
|
110
110
|
formattedTime: string;
|
|
111
111
|
}>;
|
|
112
112
|
printHistory(): void;
|
|
113
113
|
clear(): void;
|
|
114
114
|
}
|
|
115
|
-
declare abstract class
|
|
116
|
-
abstract
|
|
115
|
+
declare abstract class AbstractSortingStrategy<T extends ISortable> implements ISortingStrategy<T> {
|
|
116
|
+
abstract sort(array: T[], context: SortingContext<T>): Promise<T[]>;
|
|
117
117
|
abstract getName(): string;
|
|
118
118
|
abstract getDescription(): string;
|
|
119
|
-
protected getConfig(): Readonly<
|
|
119
|
+
protected getConfig(): Readonly<SortingConfig>;
|
|
120
120
|
}
|
|
121
|
-
declare class
|
|
122
|
-
|
|
121
|
+
declare class DefaultStrategy<T extends ISortable> extends AbstractSortingStrategy<T> {
|
|
122
|
+
sort(array: T[], context: SortingContext<T>): Promise<T[]>;
|
|
123
123
|
getName(): string;
|
|
124
124
|
getDescription(): string;
|
|
125
125
|
}
|
|
126
|
-
declare class
|
|
126
|
+
declare class ConcreteSortingStrategyFactory<T extends ISortable> implements ISortingStrategyFactory<T> {
|
|
127
127
|
private strategies;
|
|
128
128
|
constructor();
|
|
129
|
-
createStrategy(type: StrategyType):
|
|
130
|
-
registerStrategy(type: StrategyType, strategy:
|
|
129
|
+
createStrategy(type: StrategyType): ISortingStrategy<T>;
|
|
130
|
+
registerStrategy(type: StrategyType, strategy: ISortingStrategy<T>): void;
|
|
131
131
|
listAvailableStrategies(): string[];
|
|
132
132
|
hasStrategy(type: StrategyType): boolean;
|
|
133
133
|
}
|
|
134
|
-
declare class
|
|
134
|
+
declare class SorterBuilder<T extends ISortable> {
|
|
135
135
|
private array?;
|
|
136
136
|
private strategy?;
|
|
137
137
|
private observers;
|
|
138
138
|
private config?;
|
|
139
139
|
private enableDefaultObservers;
|
|
140
140
|
setArray(array: T[]): this;
|
|
141
|
-
setStrategy(strategy:
|
|
141
|
+
setStrategy(strategy: ISortingStrategy<T>): this;
|
|
142
142
|
addObserver(observer: IObserver<T>): this;
|
|
143
|
-
setConfig(config: Partial<
|
|
143
|
+
setConfig(config: Partial<SortingConfig>): this;
|
|
144
144
|
disableDefaultObservers(): this;
|
|
145
|
-
build():
|
|
145
|
+
build(): ArraySorter<T>;
|
|
146
146
|
reset(): this;
|
|
147
147
|
}
|
|
148
|
-
declare class
|
|
148
|
+
declare class ArraySorter<T extends ISortable> {
|
|
149
149
|
private array;
|
|
150
150
|
private strategy;
|
|
151
151
|
private context;
|
|
152
|
-
constructor(array: T[], strategy:
|
|
152
|
+
constructor(array: T[], strategy: ISortingStrategy<T>);
|
|
153
153
|
addObserver(observer: IObserver<T>): void;
|
|
154
154
|
removeObserver(observer: IObserver<T>): void;
|
|
155
|
-
execute():
|
|
156
|
-
getContext():
|
|
157
|
-
getEventHistory():
|
|
155
|
+
execute(): Promise<T[]>;
|
|
156
|
+
getContext(): SortingContext<T>;
|
|
157
|
+
getEventHistory(): SortingEvent<T>[];
|
|
158
158
|
}
|
|
159
159
|
interface ICommand {
|
|
160
|
-
execute():
|
|
160
|
+
execute(): Promise<any>;
|
|
161
161
|
getDescription(): string;
|
|
162
162
|
}
|
|
163
|
-
declare class
|
|
164
|
-
private
|
|
165
|
-
constructor(
|
|
166
|
-
execute():
|
|
163
|
+
declare class ExecuteSortingCommand<T extends ISortable> implements ICommand {
|
|
164
|
+
private sorter;
|
|
165
|
+
constructor(sorter: ArraySorter<T>);
|
|
166
|
+
execute(): Promise<T[]>;
|
|
167
167
|
getDescription(): string;
|
|
168
168
|
}
|
|
169
169
|
declare class UpdateConfigCommand implements ICommand {
|
|
170
170
|
private config;
|
|
171
|
-
constructor(config: Partial<
|
|
172
|
-
execute(): void
|
|
171
|
+
constructor(config: Partial<SortingConfig>);
|
|
172
|
+
execute(): Promise<void>;
|
|
173
173
|
getDescription(): string;
|
|
174
174
|
}
|
|
175
175
|
declare class CommandInvoker {
|
|
176
176
|
private commandQueue;
|
|
177
177
|
private executedCommands;
|
|
178
178
|
enqueueCommand(command: ICommand): void;
|
|
179
|
-
executeNext():
|
|
180
|
-
executeAll():
|
|
179
|
+
executeNext(): Promise<any>;
|
|
180
|
+
executeAll(): Promise<any[]>;
|
|
181
181
|
getQueueSize(): number;
|
|
182
182
|
clearQueue(): void;
|
|
183
183
|
getExecutedCommands(): ICommand[];
|
|
184
184
|
}
|
|
185
|
-
declare abstract class
|
|
186
|
-
run(array: T[], strategyType: StrategyType):
|
|
185
|
+
declare abstract class AbstractSortingRunner<T extends ISortable> {
|
|
186
|
+
run(array: T[], strategyType: StrategyType): Promise<T[]>;
|
|
187
187
|
protected abstract beforeRun(): void;
|
|
188
188
|
protected abstract afterRun(): void;
|
|
189
|
-
protected
|
|
190
|
-
protected
|
|
189
|
+
protected buildSorter(builder: SorterBuilder<T>, array: T[], strategy: ISortingStrategy<T>): ArraySorter<T>;
|
|
190
|
+
protected executeSorting(sorter: ArraySorter<T>): Promise<T[]>;
|
|
191
191
|
}
|
|
192
|
-
declare class
|
|
192
|
+
declare class LoggingSortingRunner<T extends ISortable> extends AbstractSortingRunner<T> {
|
|
193
193
|
protected beforeRun(): void;
|
|
194
194
|
protected afterRun(): void;
|
|
195
195
|
}
|
|
196
|
-
declare function
|
|
197
|
-
declare function demonstrateWithTemplateMethod(): void
|
|
198
|
-
declare function demonstrateWithCustomConfig(): void
|
|
196
|
+
declare function demonstrateSorting(): Promise<void>;
|
|
197
|
+
declare function demonstrateWithTemplateMethod(): Promise<void>;
|
|
198
|
+
declare function demonstrateWithCustomConfig(): Promise<void>;
|
|
199
199
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,UAAU,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,UAAU,SAAS;IACjB,QAAQ,IAAI,MAAM,CAAC;IACnB,QAAQ,IAAI,MAAM,CAAC;CACpB;AAKD,UAAU,SAAS,CAAC,CAAC;IACnB,MAAM,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;CACtC;AAKD,UAAU,QAAQ,CAAC,CAAC;IAClB,MAAM,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IACrC,MAAM,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IACrC,MAAM,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;CACtC;AAKD,aAAK,SAAS;IACZ,OAAO,YAAY;IACnB,cAAc,mBAAmB;IACjC,SAAS,cAAc;IACvB,KAAK,UAAU;CAChB;AAKD,UAAU,YAAY,CAAC,CAAC;IACtB,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,CAAC,EAAE,CAAC,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAChC;AAKD,UAAU,gBAAgB,CAAC,CAAC,SAAS,SAAS;IAC5C,IAAI,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;IAC3D,OAAO,IAAI,MAAM,CAAC;IAClB,cAAc,IAAI,MAAM,CAAC;CAC1B;AAKD,UAAU,uBAAuB,CAAC,CAAC,SAAS,SAAS;IACnD,cAAc,CAAC,IAAI,EAAE,YAAY,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAAC;IACxD,gBAAgB,CAAC,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAC1E,uBAAuB,IAAI,MAAM,EAAE,CAAC;CACrC;AAKD,aAAK,YAAY;IACf,OAAO,YAAY;CACpB;AAKD,UAAU,aAAa;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,OAAO,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,OAAO,CAAC;IACxB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAKD,cAAM,cAAe,YAAW,SAAS;IAC3B,OAAO,CAAC,QAAQ,CAAC,KAAK;gBAAL,KAAK,EAAE,MAAM;IAE1C,QAAQ,IAAI,MAAM;IAIlB,QAAQ,IAAI,MAAM;IAIlB,gBAAgB,IAAI,MAAM;CAG3B;AAKD,cAAM,oBAAoB;IACxB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAuB;IAC9C,OAAO,CAAC,MAAM,CAAgB;IAE9B,OAAO;IAUP,MAAM,CAAC,WAAW,IAAI,oBAAoB;IAO1C,SAAS,IAAI,QAAQ,CAAC,aAAa,CAAC;IAIpC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,GAAG,IAAI;IAInD,eAAe,IAAI,IAAI;CASxB;AAKD,iBAAS,OAAO,CAAC,MAAM,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,kBAAkB,sBAqBhF;AAKD,iBAAS,GAAG,CAAC,MAAM,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,kBAAkB,sBAY5E;AAKD,iBAAS,aAAa,CAAC,MAAM,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,kBAAkB,sBAetF;AAKD,cAAM,cAAc,CAAC,CAAC,SAAS,SAAS,CAAE,YAAW,QAAQ,CAAC,CAAC,CAAC;IAKlD,OAAO,CAAC,YAAY;IAJhC,OAAO,CAAC,SAAS,CAAgC;IACjD,OAAO,CAAC,YAAY,CAAyB;IAC7C,OAAO,CAAC,YAAY,CAAa;gBAEb,YAAY,EAAE,MAAM;IAExC,MAAM,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,IAAI;IAIpC,MAAM,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,IAAI;IAIpC,MAAM,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI;IAKpC,WAAW,IAAI,IAAI;IASnB,iBAAiB,CAAC,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAajE,aAAa,IAAI,IAAI;IAYrB,SAAS,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAS7B,eAAe,IAAI,YAAY,CAAC,CAAC,CAAC,EAAE;IAIpC,eAAe,IAAI,MAAM;IAIzB,eAAe,IAAI,MAAM;CAG1B;AAKD,cAAM,sBAAsB,CAAC,CAAC,SAAS,SAAS,CAAE,YAAW,SAAS,CAAC,CAAC,CAAC;IACvE,OAAO,CAAC,MAAM,CAAkD;IAEhE,MAAM,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI;CA0BrC;AAKD,cAAM,kBAAkB,CAAC,CAAC,SAAS,SAAS,CAAE,YAAW,SAAS,CAAC,CAAC,CAAC;IACnE,OAAO,CAAC,SAAS,CAAa;IAC9B,OAAO,CAAC,OAAO,CAAa;IAC5B,OAAO,CAAC,cAAc,CAAa;IACnC,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,MAAM,CAAqC;IAEnD,MAAM,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI;IAsBpC,aAAa,IAAI,iBAAiB;IAUlC,eAAe,IAAI,IAAI;IAavB,KAAK,IAAI,IAAI;CAOd;AAED,UAAU,iBAAiB;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;CACrC;AAKD,cAAM,eAAe,CAAC,CAAC,SAAS,SAAS,CAAE,YAAW,SAAS,CAAC,CAAC,CAAC;IAChE,OAAO,CAAC,OAAO,CAGP;IAER,MAAM,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI;IAOpC,UAAU,IAAI,KAAK,CAAC;QAAE,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,CAAC;IAItE,YAAY,IAAI,IAAI;IAOpB,KAAK,IAAI,IAAI;CAGd;AAKD,uBAAe,uBAAuB,CAAC,CAAC,SAAS,SAAS,CACxD,YAAW,gBAAgB,CAAC,CAAC,CAAC;IAE9B,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IACnE,QAAQ,CAAC,OAAO,IAAI,MAAM;IAC1B,QAAQ,CAAC,cAAc,IAAI,MAAM;IAEjC,SAAS,CAAC,SAAS,IAAI,QAAQ,CAAC,aAAa,CAAC;CAG/C;AAKD,cAAM,eAAe,CAAC,CAAC,SAAS,SAAS,CACvC,SAAQ,uBAAuB,CAAC,CAAC,CAAC;IAKlC,IAAI,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IAsC1D,OAAO,IAAI,MAAM;IAIjB,cAAc,IAAI,MAAM;CAGzB;AAKD,cAAM,8BAA8B,CAAC,CAAC,SAAS,SAAS,CACtD,YAAW,uBAAuB,CAAC,CAAC,CAAC;IAErC,OAAO,CAAC,UAAU,CAAqD;;IASvE,cAAc,CAAC,IAAI,EAAE,YAAY,GAAG,gBAAgB,CAAC,CAAC,CAAC;IAYvD,gBAAgB,CAAC,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,IAAI;IAIzE,uBAAuB,IAAI,MAAM,EAAE;IAInC,WAAW,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO;CAGzC;AAKD,cAAM,aAAa,CAAC,CAAC,SAAS,SAAS;IACrC,OAAO,CAAC,KAAK,CAAC,CAAM;IACpB,OAAO,CAAC,QAAQ,CAAC,CAAsB;IACvC,OAAO,CAAC,SAAS,CAAsB;IACvC,OAAO,CAAC,MAAM,CAAC,CAAyB;IACxC,OAAO,CAAC,sBAAsB,CAAiB;IAE/C,QAAQ,CAAC,KAAK,EAAE,CAAC,EAAE,GAAG,IAAI;IAK1B,WAAW,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,IAAI;IAKhD,WAAW,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,IAAI;IAKzC,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,aAAa,CAAC,GAAG,IAAI;IAK/C,uBAAuB,IAAI,IAAI;IAK/B,KAAK,IAAI,WAAW,CAAC,CAAC,CAAC;IA0BvB,KAAK,IAAI,IAAI;CAQd;AAMD,cAAM,WAAW,CAAC,CAAC,SAAS,SAAS;IAIjC,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,QAAQ;IAJlB,OAAO,CAAC,OAAO,CAAoB;gBAGzB,KAAK,EAAE,CAAC,EAAE,EACV,QAAQ,EAAE,gBAAgB,CAAC,CAAC,CAAC;IAKvC,WAAW,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,IAAI;IAIzC,cAAc,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,IAAI;IAKtC,OAAO,IAAI,OAAO,CAAC,CAAC,EAAE,CAAC;IAiB7B,UAAU,IAAI,cAAc,CAAC,CAAC,CAAC;IAI/B,eAAe,IAAI,YAAY,CAAC,CAAC,CAAC,EAAE;CAGrC;AAKD,UAAU,QAAQ;IAChB,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC;IACxB,cAAc,IAAI,MAAM,CAAC;CAC1B;AAKD,cAAM,qBAAqB,CAAC,CAAC,SAAS,SAAS,CAAE,YAAW,QAAQ;IACtD,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC;IAEpC,OAAO,IAAI,OAAO,CAAC,CAAC,EAAE,CAAC;IAI7B,cAAc,IAAI,MAAM;CAGzB;AAKD,cAAM,mBAAoB,YAAW,QAAQ;IAC/B,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,OAAO,CAAC,aAAa,CAAC;IAE5C,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAK9B,cAAc,IAAI,MAAM;CAGzB;AAKD,cAAM,cAAc;IAClB,OAAO,CAAC,YAAY,CAAkB;IACtC,OAAO,CAAC,gBAAgB,CAAkB;IAE1C,cAAc,CAAC,OAAO,EAAE,QAAQ,GAAG,IAAI;IAIjC,WAAW,IAAI,OAAO,CAAC,GAAG,CAAC;IAU3B,UAAU,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IASlC,YAAY,IAAI,MAAM;IAItB,UAAU,IAAI,IAAI;IAIlB,mBAAmB,IAAI,QAAQ,EAAE;CAGlC;AAKD,uBAAe,qBAAqB,CAAC,CAAC,SAAS,SAAS;IAChD,GAAG,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,YAAY,EAAE,YAAY,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IAgB/D,SAAS,CAAC,QAAQ,CAAC,SAAS,IAAI,IAAI;IACpC,SAAS,CAAC,QAAQ,CAAC,QAAQ,IAAI,IAAI;IAEnC,SAAS,CAAC,WAAW,CACnB,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,EACzB,KAAK,EAAE,CAAC,EAAE,EACV,QAAQ,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAC5B,WAAW,CAAC,CAAC,CAAC;cAOD,cAAc,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;CAGrE;AAKD,cAAM,oBAAoB,CAAC,CAAC,SAAS,SAAS,CAC5C,SAAQ,qBAAqB,CAAC,CAAC,CAAC;IAEhC,SAAS,CAAC,SAAS,IAAI,IAAI;IAI3B,SAAS,CAAC,QAAQ,IAAI,IAAI;CAG3B;AAGD,iBAAe,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC,CAuDjD;AAKD,iBAAe,6BAA6B,IAAI,OAAO,CAAC,IAAI,CAAC,CAQ5D;AAKD,iBAAe,2BAA2B,IAAI,OAAO,CAAC,IAAI,CAAC,CA4B1D"}
|
package/dist/index.js
CHANGED
|
@@ -11,15 +11,15 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
11
11
|
var EventType;
|
|
12
12
|
(function (EventType) {
|
|
13
13
|
EventType["STARTED"] = "STARTED";
|
|
14
|
-
EventType["
|
|
14
|
+
EventType["ELEMENT_SORTED"] = "ELEMENT_SORTED";
|
|
15
15
|
EventType["COMPLETED"] = "COMPLETED";
|
|
16
16
|
EventType["ERROR"] = "ERROR";
|
|
17
17
|
})(EventType || (EventType = {}));
|
|
18
18
|
var StrategyType;
|
|
19
19
|
(function (StrategyType) {
|
|
20
|
-
StrategyType["
|
|
20
|
+
StrategyType["DEFAULT"] = "DEFAULT";
|
|
21
21
|
})(StrategyType || (StrategyType = {}));
|
|
22
|
-
class
|
|
22
|
+
class SortableNumber {
|
|
23
23
|
constructor(value) {
|
|
24
24
|
this.value = value;
|
|
25
25
|
}
|
|
@@ -30,7 +30,7 @@ class VisualizableNumber {
|
|
|
30
30
|
return `${this.value}`;
|
|
31
31
|
}
|
|
32
32
|
toDetailedString() {
|
|
33
|
-
return `
|
|
33
|
+
return `SortableNumber(${this.value})`;
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
36
|
class ConfigurationManager {
|
|
@@ -38,7 +38,7 @@ class ConfigurationManager {
|
|
|
38
38
|
this.config = {
|
|
39
39
|
baseDelayMs: 1000,
|
|
40
40
|
enableLogging: true,
|
|
41
|
-
logPrefix: '',
|
|
41
|
+
logPrefix: 'šÆ',
|
|
42
42
|
showTimestamps: false,
|
|
43
43
|
colorize: true
|
|
44
44
|
};
|
|
@@ -108,7 +108,7 @@ function ValidateArray(target, propertyKey, descriptor) {
|
|
|
108
108
|
};
|
|
109
109
|
return descriptor;
|
|
110
110
|
}
|
|
111
|
-
class
|
|
111
|
+
class SortingContext {
|
|
112
112
|
constructor(strategyName) {
|
|
113
113
|
this.strategyName = strategyName;
|
|
114
114
|
this.observers = new Set();
|
|
@@ -133,15 +133,15 @@ class VisualizationContext {
|
|
|
133
133
|
};
|
|
134
134
|
this.notify(event);
|
|
135
135
|
}
|
|
136
|
-
|
|
136
|
+
emitElementSorted(element, index, delay) {
|
|
137
137
|
this.elementCount++;
|
|
138
138
|
const event = {
|
|
139
|
-
type: EventType.
|
|
139
|
+
type: EventType.ELEMENT_SORTED,
|
|
140
140
|
element,
|
|
141
141
|
index,
|
|
142
142
|
timestamp: Date.now(),
|
|
143
143
|
delay,
|
|
144
|
-
metadata: {
|
|
144
|
+
metadata: { totalSorted: this.elementCount }
|
|
145
145
|
};
|
|
146
146
|
this.notify(event);
|
|
147
147
|
}
|
|
@@ -186,14 +186,14 @@ class ConsoleLoggingObserver {
|
|
|
186
186
|
: '';
|
|
187
187
|
switch (event.type) {
|
|
188
188
|
case EventType.STARTED:
|
|
189
|
-
console.log(`\n${this.config.logPrefix} ${timestamp}
|
|
189
|
+
console.log(`\n${this.config.logPrefix} ${timestamp}Sorting started: ${event.metadata?.strategy}`);
|
|
190
190
|
break;
|
|
191
|
-
case EventType.
|
|
191
|
+
case EventType.ELEMENT_SORTED:
|
|
192
192
|
const delayInfo = event.delay ? ` (delay: ${event.delay}ms)` : '';
|
|
193
|
-
console.log(`${this.config.logPrefix} ${timestamp}Element ${event.element?.getValue()}
|
|
193
|
+
console.log(`${this.config.logPrefix} ${timestamp}Element ${event.element?.getValue()} added to result${delayInfo}`);
|
|
194
194
|
break;
|
|
195
195
|
case EventType.COMPLETED:
|
|
196
|
-
console.log(`${this.config.logPrefix} ${timestamp}
|
|
196
|
+
console.log(`${this.config.logPrefix} ${timestamp}Sorting completed: ${event.metadata?.totalElements} elements\n`);
|
|
197
197
|
break;
|
|
198
198
|
case EventType.ERROR:
|
|
199
199
|
console.error(`${this.config.logPrefix} ${timestamp}Error: ${event.metadata?.error}`);
|
|
@@ -205,7 +205,7 @@ class StatisticsObserver {
|
|
|
205
205
|
constructor() {
|
|
206
206
|
this.startTime = 0;
|
|
207
207
|
this.endTime = 0;
|
|
208
|
-
this.
|
|
208
|
+
this.sortedElements = 0;
|
|
209
209
|
this.totalDelay = 0;
|
|
210
210
|
this.events = new Map();
|
|
211
211
|
}
|
|
@@ -216,8 +216,8 @@ class StatisticsObserver {
|
|
|
216
216
|
case EventType.STARTED:
|
|
217
217
|
this.startTime = event.timestamp;
|
|
218
218
|
break;
|
|
219
|
-
case EventType.
|
|
220
|
-
this.
|
|
219
|
+
case EventType.ELEMENT_SORTED:
|
|
220
|
+
this.sortedElements++;
|
|
221
221
|
if (event.delay) {
|
|
222
222
|
this.totalDelay += event.delay;
|
|
223
223
|
}
|
|
@@ -230,17 +230,17 @@ class StatisticsObserver {
|
|
|
230
230
|
getStatistics() {
|
|
231
231
|
return {
|
|
232
232
|
duration: this.endTime - this.startTime,
|
|
233
|
-
|
|
233
|
+
sortedElements: this.sortedElements,
|
|
234
234
|
totalDelay: this.totalDelay,
|
|
235
|
-
averageDelay: this.
|
|
235
|
+
averageDelay: this.sortedElements > 0 ? this.totalDelay / this.sortedElements : 0,
|
|
236
236
|
eventCounts: new Map(this.events)
|
|
237
237
|
};
|
|
238
238
|
}
|
|
239
239
|
printStatistics() {
|
|
240
240
|
const stats = this.getStatistics();
|
|
241
|
-
console.log('\n
|
|
241
|
+
console.log('\nš Sorting Statistics:');
|
|
242
242
|
console.log(` Duration: ${stats.duration.toFixed(2)}ms`);
|
|
243
|
-
console.log(` Elements
|
|
243
|
+
console.log(` Elements Sorted: ${stats.sortedElements}`);
|
|
244
244
|
console.log(` Total Delay: ${stats.totalDelay}ms`);
|
|
245
245
|
console.log(` Average Delay: ${stats.averageDelay.toFixed(2)}ms`);
|
|
246
246
|
console.log(' Event Counts:');
|
|
@@ -251,7 +251,7 @@ class StatisticsObserver {
|
|
|
251
251
|
reset() {
|
|
252
252
|
this.startTime = 0;
|
|
253
253
|
this.endTime = 0;
|
|
254
|
-
this.
|
|
254
|
+
this.sortedElements = 0;
|
|
255
255
|
this.totalDelay = 0;
|
|
256
256
|
this.events.clear();
|
|
257
257
|
}
|
|
@@ -270,7 +270,7 @@ class HistoryObserver {
|
|
|
270
270
|
return [...this.history];
|
|
271
271
|
}
|
|
272
272
|
printHistory() {
|
|
273
|
-
console.log('\n
|
|
273
|
+
console.log('\nš Sorting History:');
|
|
274
274
|
this.history.forEach(({ event, formattedTime }, index) => {
|
|
275
275
|
console.log(` ${index + 1}. [${formattedTime}] ${event.type}${event.element ? ` - ${event.element.getValue()}` : ''}`);
|
|
276
276
|
});
|
|
@@ -279,38 +279,44 @@ class HistoryObserver {
|
|
|
279
279
|
this.history = [];
|
|
280
280
|
}
|
|
281
281
|
}
|
|
282
|
-
class
|
|
282
|
+
class AbstractSortingStrategy {
|
|
283
283
|
getConfig() {
|
|
284
284
|
return ConfigurationManager.getInstance().getConfig();
|
|
285
285
|
}
|
|
286
286
|
}
|
|
287
|
-
class
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
287
|
+
class DefaultStrategy extends AbstractSortingStrategy {
|
|
288
|
+
sort(array, context) {
|
|
289
|
+
return new Promise((resolve, reject) => {
|
|
290
|
+
context.emitStarted();
|
|
291
|
+
const result = [];
|
|
292
|
+
let completedCount = 0;
|
|
293
|
+
const totalElements = array.length;
|
|
294
|
+
try {
|
|
295
|
+
array.forEach((element, index) => {
|
|
296
|
+
const delayMs = element.getValue();
|
|
297
|
+
setTimeout(() => {
|
|
298
|
+
result.push(element);
|
|
299
|
+
console.log(`Added to result array: ${element.getValue()}`);
|
|
300
|
+
context.emitElementSorted(element, index, delayMs);
|
|
301
|
+
completedCount++;
|
|
302
|
+
if (completedCount === totalElements) {
|
|
298
303
|
context.emitCompleted();
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
304
|
+
resolve(result);
|
|
305
|
+
}
|
|
306
|
+
}, delayMs);
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
catch (error) {
|
|
310
|
+
context.emitError(error);
|
|
311
|
+
reject(error);
|
|
312
|
+
}
|
|
313
|
+
});
|
|
308
314
|
}
|
|
309
315
|
getName() {
|
|
310
|
-
return '
|
|
316
|
+
return 'Default Fast Strategy (Sleep Sort)';
|
|
311
317
|
}
|
|
312
318
|
getDescription() {
|
|
313
|
-
return '
|
|
319
|
+
return 'Sorts array using blazing fast algorithm. Elements are added to result array in order of completion.';
|
|
314
320
|
}
|
|
315
321
|
}
|
|
316
322
|
__decorate([
|
|
@@ -318,13 +324,13 @@ __decorate([
|
|
|
318
324
|
ValidateArray,
|
|
319
325
|
Measure,
|
|
320
326
|
__metadata("design:type", Function),
|
|
321
|
-
__metadata("design:paramtypes", [Array,
|
|
322
|
-
__metadata("design:returntype",
|
|
323
|
-
],
|
|
324
|
-
class
|
|
327
|
+
__metadata("design:paramtypes", [Array, SortingContext]),
|
|
328
|
+
__metadata("design:returntype", Promise)
|
|
329
|
+
], DefaultStrategy.prototype, "sort", null);
|
|
330
|
+
class ConcreteSortingStrategyFactory {
|
|
325
331
|
constructor() {
|
|
326
332
|
this.strategies = new Map();
|
|
327
|
-
this.registerStrategy(StrategyType.
|
|
333
|
+
this.registerStrategy(StrategyType.DEFAULT, new DefaultStrategy());
|
|
328
334
|
}
|
|
329
335
|
createStrategy(type) {
|
|
330
336
|
const strategy = this.strategies.get(type);
|
|
@@ -343,7 +349,7 @@ class ConcreteVisualizationStrategyFactory {
|
|
|
343
349
|
return this.strategies.has(type);
|
|
344
350
|
}
|
|
345
351
|
}
|
|
346
|
-
class
|
|
352
|
+
class SorterBuilder {
|
|
347
353
|
constructor() {
|
|
348
354
|
this.observers = [];
|
|
349
355
|
this.enableDefaultObservers = true;
|
|
@@ -370,20 +376,20 @@ class VisualizerBuilder {
|
|
|
370
376
|
}
|
|
371
377
|
build() {
|
|
372
378
|
if (!this.array) {
|
|
373
|
-
throw new Error('Array is required to build
|
|
379
|
+
throw new Error('Array is required to build sorter');
|
|
374
380
|
}
|
|
375
381
|
if (!this.strategy) {
|
|
376
|
-
throw new Error('Strategy is required to build
|
|
382
|
+
throw new Error('Strategy is required to build sorter');
|
|
377
383
|
}
|
|
378
384
|
if (this.config) {
|
|
379
385
|
ConfigurationManager.getInstance().updateConfig(this.config);
|
|
380
386
|
}
|
|
381
|
-
const
|
|
387
|
+
const sorter = new ArraySorter(this.array, this.strategy);
|
|
382
388
|
if (this.enableDefaultObservers) {
|
|
383
|
-
|
|
389
|
+
sorter.addObserver(new ConsoleLoggingObserver());
|
|
384
390
|
}
|
|
385
|
-
this.observers.forEach(observer =>
|
|
386
|
-
return
|
|
391
|
+
this.observers.forEach(observer => sorter.addObserver(observer));
|
|
392
|
+
return sorter;
|
|
387
393
|
}
|
|
388
394
|
reset() {
|
|
389
395
|
this.array = undefined;
|
|
@@ -394,11 +400,11 @@ class VisualizerBuilder {
|
|
|
394
400
|
return this;
|
|
395
401
|
}
|
|
396
402
|
}
|
|
397
|
-
class
|
|
403
|
+
class ArraySorter {
|
|
398
404
|
constructor(array, strategy) {
|
|
399
405
|
this.array = array;
|
|
400
406
|
this.strategy = strategy;
|
|
401
|
-
this.context = new
|
|
407
|
+
this.context = new SortingContext(strategy.getName());
|
|
402
408
|
}
|
|
403
409
|
addObserver(observer) {
|
|
404
410
|
this.context.attach(observer);
|
|
@@ -406,14 +412,18 @@ class ArrayVisualizer {
|
|
|
406
412
|
removeObserver(observer) {
|
|
407
413
|
this.context.detach(observer);
|
|
408
414
|
}
|
|
409
|
-
execute() {
|
|
415
|
+
async execute() {
|
|
410
416
|
console.log('\n' + '='.repeat(70));
|
|
411
|
-
console.log(
|
|
417
|
+
console.log(`š ${this.strategy.getName()}`);
|
|
418
|
+
console.log('='.repeat(70));
|
|
419
|
+
console.log(`š ${this.strategy.getDescription()}`);
|
|
420
|
+
console.log(`š„ Input array: [${this.array.map(x => x.getValue()).join(', ')}]`);
|
|
412
421
|
console.log('='.repeat(70));
|
|
413
|
-
|
|
414
|
-
console.log(
|
|
422
|
+
const result = await this.strategy.sort([...this.array], this.context);
|
|
423
|
+
console.log('\n' + '='.repeat(70));
|
|
424
|
+
console.log(`ā
Sorted result: [${result.map(x => x.getValue()).join(', ')}]`);
|
|
415
425
|
console.log('='.repeat(70));
|
|
416
|
-
|
|
426
|
+
return result;
|
|
417
427
|
}
|
|
418
428
|
getContext() {
|
|
419
429
|
return this.context;
|
|
@@ -426,29 +436,29 @@ __decorate([
|
|
|
426
436
|
Measure,
|
|
427
437
|
__metadata("design:type", Function),
|
|
428
438
|
__metadata("design:paramtypes", []),
|
|
429
|
-
__metadata("design:returntype",
|
|
430
|
-
],
|
|
431
|
-
class
|
|
432
|
-
constructor(
|
|
433
|
-
this.
|
|
439
|
+
__metadata("design:returntype", Promise)
|
|
440
|
+
], ArraySorter.prototype, "execute", null);
|
|
441
|
+
class ExecuteSortingCommand {
|
|
442
|
+
constructor(sorter) {
|
|
443
|
+
this.sorter = sorter;
|
|
434
444
|
}
|
|
435
|
-
execute() {
|
|
436
|
-
this.
|
|
445
|
+
async execute() {
|
|
446
|
+
return await this.sorter.execute();
|
|
437
447
|
}
|
|
438
448
|
getDescription() {
|
|
439
|
-
return 'Execute array
|
|
449
|
+
return 'Execute array sorting';
|
|
440
450
|
}
|
|
441
451
|
}
|
|
442
452
|
class UpdateConfigCommand {
|
|
443
453
|
constructor(config) {
|
|
444
454
|
this.config = config;
|
|
445
455
|
}
|
|
446
|
-
execute() {
|
|
456
|
+
async execute() {
|
|
447
457
|
ConfigurationManager.getInstance().updateConfig(this.config);
|
|
448
|
-
console.log('Configuration updated');
|
|
458
|
+
console.log('ā
Configuration updated');
|
|
449
459
|
}
|
|
450
460
|
getDescription() {
|
|
451
|
-
return 'Update
|
|
461
|
+
return 'Update sorting configuration';
|
|
452
462
|
}
|
|
453
463
|
}
|
|
454
464
|
class CommandInvoker {
|
|
@@ -459,18 +469,22 @@ class CommandInvoker {
|
|
|
459
469
|
enqueueCommand(command) {
|
|
460
470
|
this.commandQueue.push(command);
|
|
461
471
|
}
|
|
462
|
-
executeNext() {
|
|
472
|
+
async executeNext() {
|
|
463
473
|
const command = this.commandQueue.shift();
|
|
464
474
|
if (command) {
|
|
465
475
|
console.log(`\nš§ Executing: ${command.getDescription()}`);
|
|
466
|
-
command.execute();
|
|
476
|
+
const result = await command.execute();
|
|
467
477
|
this.executedCommands.push(command);
|
|
478
|
+
return result;
|
|
468
479
|
}
|
|
469
480
|
}
|
|
470
|
-
executeAll() {
|
|
481
|
+
async executeAll() {
|
|
482
|
+
const results = [];
|
|
471
483
|
while (this.commandQueue.length > 0) {
|
|
472
|
-
this.executeNext();
|
|
484
|
+
const result = await this.executeNext();
|
|
485
|
+
results.push(result);
|
|
473
486
|
}
|
|
487
|
+
return results;
|
|
474
488
|
}
|
|
475
489
|
getQueueSize() {
|
|
476
490
|
return this.commandQueue.length;
|
|
@@ -482,96 +496,101 @@ class CommandInvoker {
|
|
|
482
496
|
return [...this.executedCommands];
|
|
483
497
|
}
|
|
484
498
|
}
|
|
485
|
-
class
|
|
486
|
-
run(array, strategyType) {
|
|
499
|
+
class AbstractSortingRunner {
|
|
500
|
+
async run(array, strategyType) {
|
|
487
501
|
this.beforeRun();
|
|
488
|
-
const factory = new
|
|
502
|
+
const factory = new ConcreteSortingStrategyFactory();
|
|
489
503
|
const strategy = factory.createStrategy(strategyType);
|
|
490
|
-
const builder = new
|
|
491
|
-
const
|
|
492
|
-
this.
|
|
504
|
+
const builder = new SorterBuilder();
|
|
505
|
+
const sorter = this.buildSorter(builder, array, strategy);
|
|
506
|
+
const result = await this.executeSorting(sorter);
|
|
493
507
|
this.afterRun();
|
|
508
|
+
return result;
|
|
494
509
|
}
|
|
495
|
-
|
|
510
|
+
buildSorter(builder, array, strategy) {
|
|
496
511
|
return builder
|
|
497
512
|
.setArray(array)
|
|
498
513
|
.setStrategy(strategy)
|
|
499
514
|
.build();
|
|
500
515
|
}
|
|
501
|
-
|
|
502
|
-
|
|
516
|
+
async executeSorting(sorter) {
|
|
517
|
+
return await sorter.execute();
|
|
503
518
|
}
|
|
504
519
|
}
|
|
505
|
-
class
|
|
520
|
+
class LoggingSortingRunner extends AbstractSortingRunner {
|
|
506
521
|
beforeRun() {
|
|
507
|
-
console.log('\n Starting
|
|
522
|
+
console.log('\nš Starting sorting process...');
|
|
508
523
|
}
|
|
509
524
|
afterRun() {
|
|
510
|
-
console.log('\n
|
|
525
|
+
console.log('\nā
Sorting process completed.');
|
|
511
526
|
}
|
|
512
527
|
}
|
|
513
|
-
function
|
|
528
|
+
async function demonstrateSorting() {
|
|
514
529
|
ConfigurationManager.getInstance().updateConfig({
|
|
515
530
|
enableLogging: true,
|
|
516
|
-
logPrefix: '>',
|
|
531
|
+
logPrefix: '> ',
|
|
517
532
|
showTimestamps: false
|
|
518
533
|
});
|
|
519
534
|
console.log('\n' + '='.repeat(70));
|
|
520
|
-
console.log('ARRAY
|
|
521
|
-
console.log(' Using setTimeout + forEach Strategy');
|
|
535
|
+
console.log('šØ ARRAY SORTING USING');
|
|
522
536
|
console.log('='.repeat(70));
|
|
523
|
-
const numbers = [1, 2,
|
|
524
|
-
const
|
|
525
|
-
console.log(`\n Input array: [${numbers.join(', ')}]`);
|
|
526
|
-
|
|
527
|
-
const
|
|
528
|
-
const strategy = factory.createStrategy(StrategyType.TIMEOUT_FOREACH);
|
|
537
|
+
const numbers = [3, 1, 4, 1, 5, 9, 2, 6];
|
|
538
|
+
const sortableArray = numbers.map(n => new SortableNumber(n));
|
|
539
|
+
console.log(`\nš„ Input array: [${numbers.join(', ')}]`);
|
|
540
|
+
const factory = new ConcreteSortingStrategyFactory();
|
|
541
|
+
const strategy = factory.createStrategy(StrategyType.DEFAULT);
|
|
529
542
|
const statisticsObserver = new StatisticsObserver();
|
|
530
543
|
const historyObserver = new HistoryObserver();
|
|
531
|
-
const builder = new
|
|
532
|
-
const
|
|
533
|
-
.setArray(
|
|
544
|
+
const builder = new SorterBuilder();
|
|
545
|
+
const sorter = builder
|
|
546
|
+
.setArray(sortableArray)
|
|
534
547
|
.setStrategy(strategy)
|
|
535
548
|
.addObserver(statisticsObserver)
|
|
536
549
|
.addObserver(historyObserver)
|
|
537
550
|
.build();
|
|
538
551
|
const invoker = new CommandInvoker();
|
|
539
|
-
const
|
|
540
|
-
invoker.enqueueCommand(
|
|
541
|
-
invoker.executeAll();
|
|
552
|
+
const sortingCommand = new ExecuteSortingCommand(sorter);
|
|
553
|
+
invoker.enqueueCommand(sortingCommand);
|
|
554
|
+
const results = await invoker.executeAll();
|
|
555
|
+
const sortedArray = results[0];
|
|
556
|
+
console.log('\n' + 'ā'.repeat(70));
|
|
557
|
+
console.log(`\nš Final sorted array: [${sortedArray.map(x => x.getValue()).join(', ')}]`);
|
|
542
558
|
setTimeout(() => {
|
|
543
559
|
console.log('\n' + 'ā'.repeat(70));
|
|
544
560
|
statisticsObserver.printStatistics();
|
|
545
561
|
historyObserver.printHistory();
|
|
546
562
|
console.log('\n' + '='.repeat(70));
|
|
547
|
-
console.log('DEMONSTRATION COMPLETED');
|
|
563
|
+
console.log('ā
DEMONSTRATION COMPLETED');
|
|
548
564
|
console.log('='.repeat(70) + '\n');
|
|
549
|
-
},
|
|
565
|
+
}, 100);
|
|
550
566
|
}
|
|
551
|
-
function demonstrateWithTemplateMethod() {
|
|
552
|
-
const numbers = [
|
|
553
|
-
const
|
|
554
|
-
const runner = new
|
|
555
|
-
runner.run(
|
|
567
|
+
async function demonstrateWithTemplateMethod() {
|
|
568
|
+
const numbers = [5, 2, 8, 1, 9];
|
|
569
|
+
const sortableArray = numbers.map(n => new SortableNumber(n));
|
|
570
|
+
const runner = new LoggingSortingRunner();
|
|
571
|
+
const sortedArray = await runner.run(sortableArray, StrategyType.DEFAULT);
|
|
572
|
+
console.log(`\nā
Template Method result: [${sortedArray.map(x => x.getValue()).join(', ')}]`);
|
|
556
573
|
}
|
|
557
|
-
function demonstrateWithCustomConfig() {
|
|
558
|
-
const numbers = [
|
|
559
|
-
const
|
|
574
|
+
async function demonstrateWithCustomConfig() {
|
|
575
|
+
const numbers = [10, 5, 15, 3, 20];
|
|
576
|
+
const sortableArray = numbers.map(n => new SortableNumber(n));
|
|
560
577
|
const invoker = new CommandInvoker();
|
|
561
578
|
const configCommand = new UpdateConfigCommand({
|
|
562
|
-
logPrefix: '[
|
|
579
|
+
logPrefix: '[SLEEP SORT] ',
|
|
563
580
|
showTimestamps: true
|
|
564
581
|
});
|
|
565
582
|
invoker.enqueueCommand(configCommand);
|
|
566
|
-
const factory = new
|
|
567
|
-
const strategy = factory.createStrategy(StrategyType.
|
|
568
|
-
const
|
|
569
|
-
.setArray(
|
|
583
|
+
const factory = new ConcreteSortingStrategyFactory();
|
|
584
|
+
const strategy = factory.createStrategy(StrategyType.DEFAULT);
|
|
585
|
+
const sorter = new SorterBuilder()
|
|
586
|
+
.setArray(sortableArray)
|
|
570
587
|
.setStrategy(strategy)
|
|
571
588
|
.build();
|
|
572
|
-
const
|
|
573
|
-
invoker.enqueueCommand(
|
|
574
|
-
invoker.executeAll();
|
|
589
|
+
const sortingCommand = new ExecuteSortingCommand(sorter);
|
|
590
|
+
invoker.enqueueCommand(sortingCommand);
|
|
591
|
+
const results = await invoker.executeAll();
|
|
592
|
+
const sortedArray = results[1];
|
|
593
|
+
console.log(`\nā
Custom config result: [${sortedArray.map(x => x.getValue()).join(', ')}]`);
|
|
575
594
|
}
|
|
576
|
-
console.log('\n Starting demonstration...\n');
|
|
577
|
-
|
|
595
|
+
console.log('\nš¬ Starting demonstration...\n');
|
|
596
|
+
demonstrateSorting();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "the-best-sort",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Sorting framework basid on best design patterns with the most powerful sort strategies in TypeScript",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -39,13 +39,13 @@
|
|
|
39
39
|
"bugs": {
|
|
40
40
|
"url": "https://github.com/danilasar/the-best-sort/issues"
|
|
41
41
|
},
|
|
42
|
-
"homepage": "https://
|
|
42
|
+
"homepage": "https://sort.danilasar.ru",
|
|
43
43
|
"engines": {
|
|
44
44
|
"node": ">=18.0.0"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@types/node": "^20.10.0",
|
|
48
|
-
"
|
|
49
|
-
"
|
|
48
|
+
"tsx": "^4.20.6",
|
|
49
|
+
"typescript": "^5.3.0"
|
|
50
50
|
}
|
|
51
51
|
}
|