tracedsa 1.0.0__tar.gz

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.
Files changed (57) hide show
  1. tracedsa-1.0.0/.github/workflows/release.yml +66 -0
  2. tracedsa-1.0.0/.gitignore +7 -0
  3. tracedsa-1.0.0/.vscode/tasks.json +28 -0
  4. tracedsa-1.0.0/ArrayList/ArrayList.cpp +172 -0
  5. tracedsa-1.0.0/ArrayList/ArrayList.h +38 -0
  6. tracedsa-1.0.0/BST/BST.cpp +171 -0
  7. tracedsa-1.0.0/BST/BST.h +46 -0
  8. tracedsa-1.0.0/BST/BST_interactive.cpp +88 -0
  9. tracedsa-1.0.0/LICENSE +21 -0
  10. tracedsa-1.0.0/LinkedList/DoublyLinkedList.cpp +166 -0
  11. tracedsa-1.0.0/LinkedList/DoublyLinkedList.h +29 -0
  12. tracedsa-1.0.0/LinkedList/DoublyLinkedList_interactive.cpp +90 -0
  13. tracedsa-1.0.0/LinkedList/LinkedList.cpp +126 -0
  14. tracedsa-1.0.0/LinkedList/LinkedList.h +27 -0
  15. tracedsa-1.0.0/LinkedList/LinkedList_interactive.cpp +90 -0
  16. tracedsa-1.0.0/Makefile +24 -0
  17. tracedsa-1.0.0/PKG-INFO +81 -0
  18. tracedsa-1.0.0/PriorityQueue/Heap.cpp +184 -0
  19. tracedsa-1.0.0/PriorityQueue/Heap.h +36 -0
  20. tracedsa-1.0.0/PriorityQueue/Heap_interactive.cpp +111 -0
  21. tracedsa-1.0.0/Queue/CircularQueue.cpp +52 -0
  22. tracedsa-1.0.0/Queue/CircularQueue.h +17 -0
  23. tracedsa-1.0.0/Queue/CircularQueue_interactive.cpp +77 -0
  24. tracedsa-1.0.0/Queue/Queue.cpp +42 -0
  25. tracedsa-1.0.0/Queue/Queue.h +18 -0
  26. tracedsa-1.0.0/Queue/QueueAsLinkedList.cpp +72 -0
  27. tracedsa-1.0.0/Queue/QueueAsLinkedList.h +24 -0
  28. tracedsa-1.0.0/Queue/QueueAsLinkedList_interactive.cpp +75 -0
  29. tracedsa-1.0.0/Queue/Queue_interactive.cpp +78 -0
  30. tracedsa-1.0.0/README.md +70 -0
  31. tracedsa-1.0.0/Stack/Stack.cpp +57 -0
  32. tracedsa-1.0.0/Stack/Stack.h +22 -0
  33. tracedsa-1.0.0/Stack/StackAsLinkedList.cpp +83 -0
  34. tracedsa-1.0.0/Stack/StackAsLinkedList.h +25 -0
  35. tracedsa-1.0.0/Stack/StackAsLinkedList_interactive.cpp +68 -0
  36. tracedsa-1.0.0/Stack/stack_interactive.cpp +68 -0
  37. tracedsa-1.0.0/TestingModules.cpp +379 -0
  38. tracedsa-1.0.0/docs/Trace.png +0 -0
  39. tracedsa-1.0.0/makefile.inter +66 -0
  40. tracedsa-1.0.0/makefile.macos +40 -0
  41. tracedsa-1.0.0/makefile.windows +40 -0
  42. tracedsa-1.0.0/pyproject.toml +24 -0
  43. tracedsa-1.0.0/tracedsa/__init__.py +0 -0
  44. tracedsa-1.0.0/tracedsa/__main__.py +404 -0
  45. tracedsa-1.0.0/tracedsa/bridge.py +74 -0
  46. tracedsa-1.0.0/tracedsa/screens/__init__.py +0 -0
  47. tracedsa-1.0.0/tracedsa/screens/confirm_dialog.py +113 -0
  48. tracedsa-1.0.0/tracedsa/screens/help_screen.py +80 -0
  49. tracedsa-1.0.0/tracedsa/screens/info_screen.py +531 -0
  50. tracedsa-1.0.0/tracedsa/screens/menu.py +475 -0
  51. tracedsa-1.0.0/tracedsa/screens/splash.py +214 -0
  52. tracedsa-1.0.0/tracedsa/screens/trace_screen.py +518 -0
  53. tracedsa-1.0.0/tracedsa/widgets/__init__.py +0 -0
  54. tracedsa-1.0.0/tracedsa/widgets/ascii_array.py +103 -0
  55. tracedsa-1.0.0/tracedsa/widgets/ascii_heap.py +73 -0
  56. tracedsa-1.0.0/tracedsa/widgets/ascii_tree.py +75 -0
  57. tracedsa-1.0.0/tracedsa/widgets/ops_log.py +30 -0
@@ -0,0 +1,66 @@
1
+ name: Build and Publish
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ jobs:
9
+ build-linux:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+ - run: make -f makefile.inter all
14
+ - uses: actions/upload-artifact@v4
15
+ with:
16
+ name: bins-linux
17
+ path: tracedsa/bins/linux/
18
+
19
+ build-windows:
20
+ runs-on: windows-latest
21
+ steps:
22
+ - uses: actions/checkout@v4
23
+ - run: choco install mingw -y
24
+ - run: make -f makefile.windows all
25
+ - uses: actions/upload-artifact@v4
26
+ with:
27
+ name: bins-windows
28
+ path: tracedsa/bins/windows/
29
+
30
+ build-macos:
31
+ runs-on: macos-latest
32
+ steps:
33
+ - uses: actions/checkout@v4
34
+ - run: brew install gcc
35
+ - run: make -f makefile.macos CXX=g++-14 all
36
+ - uses: actions/upload-artifact@v4
37
+ with:
38
+ name: bins-macos
39
+ path: tracedsa/bins/macos/
40
+
41
+ publish:
42
+ needs: [build-linux, build-windows, build-macos]
43
+ runs-on: ubuntu-latest
44
+ steps:
45
+ - uses: actions/checkout@v4
46
+ - uses: actions/download-artifact@v4
47
+ with:
48
+ name: bins-linux
49
+ path: tracedsa/bins/linux
50
+ - uses: actions/download-artifact@v4
51
+ with:
52
+ name: bins-windows
53
+ path: tracedsa/bins/windows
54
+ - uses: actions/download-artifact@v4
55
+ with:
56
+ name: bins-macos
57
+ path: tracedsa/bins/macos
58
+ - uses: actions/setup-python@v5
59
+ with:
60
+ python-version: "3.12"
61
+ - run: pip install hatch twine
62
+ - run: hatch build
63
+ - run: twine upload dist/*
64
+ env:
65
+ TWINE_USERNAME: __token__
66
+ TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }}
@@ -0,0 +1,7 @@
1
+ CONTEXT.md
2
+ DESIGN.md
3
+ handoff.md
4
+ Main
5
+ bins
6
+ __pycache__
7
+ *.pyc
@@ -0,0 +1,28 @@
1
+ {
2
+ "tasks": [
3
+ {
4
+ "type": "cppbuild",
5
+ "label": "C/C++: g++ build active file",
6
+ "command": "/usr/bin/g++",
7
+ "args": [
8
+ "-fdiagnostics-color=always",
9
+ "-g",
10
+ "${file}",
11
+ "-o",
12
+ "${fileDirname}/${fileBasenameNoExtension}"
13
+ ],
14
+ "options": {
15
+ "cwd": "${fileDirname}"
16
+ },
17
+ "problemMatcher": [
18
+ "$gcc"
19
+ ],
20
+ "group": {
21
+ "kind": "build",
22
+ "isDefault": true
23
+ },
24
+ "detail": "Task generated by Debugger."
25
+ }
26
+ ],
27
+ "version": "2.0.0"
28
+ }
@@ -0,0 +1,172 @@
1
+ #include "ArrayList.h"
2
+
3
+ /*
4
+ MADE BY: HA
5
+ Array List implemention with dynamic resizing, the class got 10 methods:
6
+ 1. add(element): to add an element to the end of the list.
7
+ 2. add(index, element): to add an element at a specific index in the list.
8
+ 3. get(index): to retrieve the element at a specific index.
9
+ 4. set(index, element): to update the element at a specific index.
10
+ 5. remove(index): to remove the element at a specific index and return it.
11
+ 6. getSize(): to return the number of elements in the list.
12
+ 7. getCapacity(): to return the current capacity of the list.
13
+ 8. isEmpty(): to check if the list is empty.
14
+ 9. clear(): to remove all elements from the list.
15
+ 10. toString(): to return a string representation of the list (for TUI).
16
+ */
17
+
18
+ template <typename T>
19
+ ArrayList<T>::ArrayList() : data(nullptr), size(0), capacity(0){
20
+ resize(1); // Start with capacity of 1
21
+ }
22
+
23
+ // Check the initial capacity constructor for negative values and handle it
24
+ template <typename T>
25
+ ArrayList<T>::ArrayList(int initialCapacity) : data(nullptr), size(0), capacity(initialCapacity) {
26
+ if (initialCapacity < 0)
27
+ throw std::invalid_argument("Initial capacity cannot be negative");
28
+ if (initialCapacity > 0)
29
+ data = new T[initialCapacity];
30
+ else
31
+ data = nullptr;
32
+ }
33
+
34
+ template <typename T>
35
+ ArrayList<T>::~ArrayList(){
36
+ delete[] data;
37
+ }
38
+
39
+ template <typename T>
40
+ void ArrayList<T>::resize(int newCapacity){
41
+ if (newCapacity < 0)
42
+ throw std::invalid_argument("New capacity cannot be negative");
43
+
44
+ if (newCapacity == capacity)
45
+ return; // No change needed
46
+
47
+ T* newData = new T[newCapacity];
48
+
49
+ // Copy elements (only up to the minimum of old and new capacity)
50
+ int elementsToCopy = (size < newCapacity) ? size : newCapacity;
51
+ for (int i = 0; i < elementsToCopy; i++)
52
+ newData[i] = data[i];
53
+
54
+ delete[] data;
55
+ data = newData;
56
+ capacity = newCapacity;
57
+
58
+ // If we reduced capacity and size is now larger than capacity, adjust size
59
+ if (size > capacity)
60
+ size = capacity;
61
+ }
62
+
63
+ template <typename T>
64
+ void ArrayList<T>::add(const T& element) {
65
+ // Resize if needed (when size equals capacity)
66
+ if (size >= capacity){
67
+ int newCapacity = (capacity == 0) ? 1 : capacity * 2;
68
+ resize(newCapacity);
69
+ }
70
+
71
+ data[size] = element;
72
+ size++;
73
+ }
74
+
75
+ template <typename T>
76
+ void ArrayList<T>::add(int index, const T& element){
77
+ if (index < 0 || index > size)
78
+ throw std::out_of_range("Index out of range");
79
+
80
+ // Resize if needed
81
+ if (size >= capacity){
82
+ int newCapacity = (capacity == 0) ? 1 : capacity * 2;
83
+ resize(newCapacity);
84
+ }
85
+
86
+ // Shift elements to the right
87
+ for (int i = size; i > index;--i)
88
+ data[i] = data[i-1];
89
+
90
+ data[index] = element;
91
+ size++;
92
+ }
93
+
94
+ template <typename T>
95
+ T ArrayList<T>::get(int index) const {
96
+ if (index < 0 || index >= size)
97
+ throw std::out_of_range("Index out of range");
98
+ return data[index];
99
+ }
100
+
101
+ template <typename T>
102
+ void ArrayList<T>::set(int index, const T& element) {
103
+ if (index < 0 || index >= size)
104
+ throw std::out_of_range("Index out of range");
105
+ data[index] = element;
106
+ }
107
+
108
+ template <typename T>
109
+ T ArrayList<T>::remove(int index) {
110
+ if (index < 0 || index >= size)
111
+ throw std::out_of_range("Index out of range");
112
+
113
+ T removedElement = data[index];
114
+
115
+ // Shift elements to the left
116
+ for (int i = index; i < size - 1;++i)
117
+ data[i] = data[i+1];
118
+
119
+ size--;
120
+
121
+ // Optional: shrink capacity if it's too large (e.g., less than 25% full)
122
+ // For simplicity in this implementation, we won't shrink automatically
123
+ // but we could add: if (size > 0 && size <= capacity/4) resize(capacity/2);
124
+
125
+ return removedElement;
126
+ }
127
+
128
+ template <typename T>
129
+ int ArrayList<T>::getSize() const {
130
+ return size;
131
+ }
132
+
133
+ template <typename T>
134
+ int ArrayList<T>::getCapacity() const {
135
+ return capacity;
136
+ }
137
+
138
+ template <typename T>
139
+ bool ArrayList<T>::isEmpty() const {
140
+ return size == 0;
141
+ }
142
+
143
+ template <typename T>
144
+ void ArrayList<T>::clear(){
145
+ size = 0;
146
+ // Optional: reset to initial capacity or keep current capacity
147
+ // For simplicity, we keep the current capacity but reset size to 0
148
+ }
149
+
150
+ template <typename T>
151
+ std::string ArrayList<T>::toString() const {
152
+ if (size == 0){
153
+ return "[]";
154
+ }
155
+
156
+ std::string result = "[";
157
+ for (int i = 0; i < size; i++) {
158
+ std::ostringstream oss;
159
+ oss << data[i];
160
+ result += oss.str();
161
+ if (i < size - 1) {
162
+ result += ", ";
163
+ }
164
+ }
165
+ result += "]";
166
+ return result;
167
+ }
168
+
169
+ // Explicit instantiation for common types if needed
170
+ // template class ArrayList<int>;
171
+ // template class ArrayList<double>;
172
+ // template class ArrayList<std::string>;
@@ -0,0 +1,38 @@
1
+ #ifndef ARRAYLIST_H
2
+ #define ARRAYLIST_H
3
+
4
+ #include <stdexcept>
5
+ #include <string>
6
+ #include <sstream>
7
+
8
+ template <typename T>
9
+ class ArrayList {
10
+ private:
11
+ T* data;
12
+ int size;
13
+ int capacity;
14
+
15
+ void resize(int newCapacity);
16
+
17
+ public:
18
+ ArrayList();
19
+ ArrayList(int initialCapacity);
20
+ ~ArrayList();
21
+
22
+ // Core methods
23
+ void add(const T& element);
24
+ void add(int index, const T& element);
25
+ T get(int index) const;
26
+ void set(int index, const T& element);
27
+ T remove(int index);
28
+ int getSize() const;
29
+ int getCapacity() const;
30
+ bool isEmpty() const;
31
+ void clear();
32
+
33
+ // Utility methods
34
+ std::string toString() const;
35
+ };
36
+
37
+ #include "ArrayList.cpp"
38
+ #endif // ARRAYLIST_H
@@ -0,0 +1,171 @@
1
+ #include "BST.h"
2
+ using namespace std;
3
+
4
+ /*
5
+ MADE BY: HA
6
+ This module implements the Binary Search Tree (INT NUMBERS ONLY) DS with the following functionality:
7
+ 1. Insert: inserting a node in the tree
8
+ 2. Delete: removing a node with a value from the tree
9
+ 3. Find: Searching for a node with a value
10
+ 4. Pre-order Traversal: Going through the tree from the left side of the root first
11
+ 5. Post-order Traversal: Going through the tree printing the last nodes of the tree and upwards
12
+ 6. In-order Traversal: Going through the tree printing the left nodes first then the root and then the right nodes (Sorted order)
13
+ */
14
+
15
+ Tnode* BST::insertHelper(Tnode* node, int value){
16
+ if (node == nullptr){
17
+ Tnode* newNode = new Tnode();
18
+ newNode->data = value;
19
+ newNode->left = nullptr;
20
+ newNode->right = nullptr;
21
+ return newNode;
22
+ }
23
+
24
+ if (value < node->data)
25
+ node->left = insertHelper(node->left, value);
26
+ else if (value > node->data)
27
+ node->right = insertHelper(node->right, value);
28
+
29
+ return node;
30
+ }
31
+
32
+ Tnode* BST::deleteHelper(Tnode* node, int value){
33
+ if (node == nullptr)
34
+ return nullptr;
35
+
36
+ if (value < node->data)
37
+ node->left = deleteHelper(node->left, value);
38
+ else if (value > node->data)
39
+ node->right = deleteHelper(node->right, value);
40
+ else{
41
+ if (node->left == nullptr){
42
+ Tnode* temp = node->right;
43
+ delete node;
44
+ return temp;
45
+ }
46
+ else if (node->right == nullptr){
47
+ Tnode* temp = node->left;
48
+ delete node;
49
+ return temp;
50
+ }
51
+ Tnode* temp = findMin(node->right);
52
+ node->data = temp->data;
53
+ node->right = deleteHelper(node->right, temp->data);
54
+ }
55
+ return node;
56
+ }
57
+
58
+ Tnode* BST::findHelper(Tnode* node, int value) const{
59
+ if (node == nullptr)
60
+ return nullptr;
61
+
62
+ if (value < node->data)
63
+ return findHelper(node->left, value);
64
+ else if (value > node->data)
65
+ return findHelper(node->right, value);
66
+ else
67
+ return node;
68
+ }
69
+
70
+ Tnode* BST::findMin(Tnode* node) const {
71
+ while (node && node->left != nullptr) {
72
+ node = node->left;
73
+ }
74
+ return node;
75
+ }
76
+
77
+ void BST::preorderHelper(Tnode* node, string& result) const {
78
+ if (node != nullptr) {
79
+ result += to_string(node->data);
80
+ result += " ";
81
+ preorderHelper(node->left, result);
82
+ preorderHelper(node->right, result);
83
+ }
84
+ }
85
+
86
+ void BST::postorderHelper(Tnode* node, string& result) const{
87
+ if (node != nullptr) {
88
+ postorderHelper(node->left, result);
89
+ postorderHelper(node->right, result);
90
+ result += to_string(node->data);
91
+ result += " ";
92
+ }
93
+ }
94
+
95
+ void BST::inorderHelper(Tnode* node, string& result) const {
96
+ if (node != nullptr){
97
+ inorderHelper(node->left, result);
98
+ result += to_string(node->data);
99
+ result += " ";
100
+ inorderHelper(node->right, result);
101
+ }
102
+ }
103
+
104
+ void BST::freeTree(Tnode* node){
105
+ if (node != nullptr) {
106
+ freeTree(node->left);
107
+ freeTree(node->right);
108
+ delete node;
109
+ }
110
+ }
111
+
112
+
113
+ BST::BST() : root(nullptr) {}
114
+ BST::~BST(){
115
+ freeTree(root);
116
+ }
117
+
118
+ void BST::insert(int value){
119
+ root = insertHelper(root, value);
120
+ }
121
+
122
+ void BST::remove(int value){
123
+ if (!find(value)) {
124
+ throw std::runtime_error("Value not found in BST");
125
+ }
126
+ root = deleteHelper(root, value);
127
+ }
128
+
129
+ bool BST::find(int value) const{
130
+ Tnode* result = findHelper(root, value);
131
+ if (result != nullptr)
132
+ return true;
133
+ else
134
+ return false;
135
+ }
136
+
137
+ string BST::preorder() const {
138
+ if (isEmpty())
139
+ return "Pre-order: [empty]";
140
+ string result = "Pre-order: [";
141
+ preorderHelper(root, result);
142
+ result += "]";
143
+ return result;
144
+ }
145
+
146
+ string BST::postorder() const {
147
+ if (isEmpty())
148
+ return "Post-order: [empty]";
149
+ string result = "Post-order: [";
150
+ postorderHelper(root, result);
151
+ result += "]";
152
+ return result;
153
+ }
154
+
155
+ string BST::inorder() const{
156
+ if (isEmpty())
157
+ return "In-order: [empty]";
158
+ string result = "In-order: [";
159
+ inorderHelper(root, result);
160
+ result += "]";
161
+ return result;
162
+ }
163
+
164
+ bool BST::isEmpty() const{
165
+ return root == nullptr;
166
+ }
167
+
168
+ void BST::clear(){
169
+ freeTree(root);
170
+ root = nullptr;
171
+ }
@@ -0,0 +1,46 @@
1
+ #ifndef BST_H
2
+ #define BST_H
3
+
4
+ #include <stdexcept>
5
+ #include <string>
6
+
7
+ struct Tnode{
8
+ int data;
9
+ Tnode* left;
10
+ Tnode* right;
11
+ };
12
+
13
+ class BST{
14
+ private:
15
+ Tnode* root;
16
+
17
+ // Private helper methods
18
+ Tnode* insertHelper(Tnode* node, int value);
19
+ Tnode* deleteHelper(Tnode* node, int value);
20
+ Tnode* findHelper(Tnode* node, int value) const;
21
+ Tnode* findMin(Tnode* node) const;
22
+ void preorderHelper(Tnode* node, std::string& result) const;
23
+ void postorderHelper(Tnode* node, std::string& result) const;
24
+ void inorderHelper(Tnode* node, std::string& result) const;
25
+ void freeTree(Tnode* node);
26
+
27
+ public:
28
+ BST();
29
+ ~BST();
30
+
31
+ // Public methods
32
+ void insert(int value);
33
+ void remove(int value);
34
+ bool find(int value) const;
35
+
36
+ // Traversal methods returning strings for TUI
37
+ std::string preorder() const;
38
+ std::string postorder() const;
39
+ std::string inorder() const;
40
+
41
+ // Utility methods
42
+ bool isEmpty() const;
43
+ void clear();
44
+ };
45
+
46
+ #endif // BST_H
@@ -0,0 +1,88 @@
1
+ #include <iostream>
2
+ #include <string>
3
+ #include <sstream>
4
+ #include "BST.h"
5
+ using namespace std;
6
+
7
+ int main() {
8
+ BST bst;
9
+ cout << "READY" << endl;
10
+ cout.flush();
11
+
12
+ string line;
13
+ while (getline(cin, line)) {
14
+ istringstream iss(line);
15
+ string cmd;
16
+ iss >> cmd;
17
+
18
+ if (cmd == "INSERT") {
19
+ int val;
20
+ if (iss >> val) {
21
+ bst.insert(val);
22
+ cout << "OK " << bst.preorder() << endl; // Show preorder after insert
23
+ }
24
+ else
25
+ cout << "ERROR Invalid value" << endl;
26
+ cout.flush();
27
+ }
28
+ else if (cmd == "REMOVE") {
29
+ int val;
30
+ if (iss >> val) {
31
+ try {
32
+ bst.remove(val);
33
+ cout << "OK " << bst.preorder() << endl;
34
+ } catch (const exception& e) {
35
+ cout << "ERROR " << e.what() << endl;
36
+ }
37
+ }
38
+ else
39
+ cout << "ERROR Invalid value" << endl;
40
+ cout.flush();
41
+ }
42
+ else if (cmd == "FIND") {
43
+ int val;
44
+ if (iss >> val) {
45
+ bool found = bst.find(val);
46
+ cout << "OK " << (found ? "true" : "false") << endl;
47
+ } else {
48
+ cout << "ERROR Invalid value" << endl;
49
+ }
50
+ cout.flush();
51
+ }
52
+ else if (cmd == "PREORDER") {
53
+ cout << "OK " << bst.preorder() << endl;
54
+ cout.flush();
55
+ }
56
+ else if (cmd == "INORDER") {
57
+ cout << "OK " << bst.inorder() << endl;
58
+ cout.flush();
59
+ }
60
+ else if (cmd == "POSTORDER") {
61
+ cout << "OK " << bst.postorder() << endl;
62
+ cout.flush();
63
+ }
64
+ else if (cmd == "ISEMPTY") {
65
+ cout << "OK " << (bst.isEmpty() ? "true" : "false") << endl;
66
+ cout.flush();
67
+ }
68
+ else if (cmd == "CLEAR") {
69
+ bst.clear();
70
+ cout << "OK " << bst.preorder() << endl;
71
+ cout.flush();
72
+ }
73
+ else if (cmd == "PRINT") {
74
+ cout << "OK " << bst.preorder() << endl;
75
+ cout.flush();
76
+ }
77
+ else if (cmd == "EXIT") {
78
+ cout << "BYE" << endl;
79
+ cout.flush();
80
+ break;
81
+ }
82
+ else {
83
+ cout << "ERROR Unknown command: " << cmd << endl;
84
+ cout.flush();
85
+ }
86
+ }
87
+ return 0;
88
+ }
tracedsa-1.0.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Hassan Ahmed
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.