aimyapi 1.0.8 → 1.0.9
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/LICENSE +21 -21
- package/README.md +195 -195
- package/dist/index.cjs +2 -0
- package/dist/index.js +2 -0
- package/dist/index.mjs +2 -0
- package/example/example1.ts +30 -30
- package/example/example2.ts +58 -58
- package/example/example3.ts +69 -69
- package/example/ordering_api.md +94 -94
- package/example/ordering_api.ts +191 -191
- package/example/ordering_api_impl.ts +207 -207
- package/example/sales_api.md +4 -4
- package/example/sales_api.ts +29 -29
- package/example/sales_api_impl.ts +60 -60
- package/package.json +1 -1
- package/prompts/create-task-prompt.md +37 -37
- package/src/index.ts +495 -495
- package/src/sandbox-wrappers.ts +251 -249
- package/src/sandbox.ts +277 -277
- package/src/utils.ts +2 -2
- package/tsconfig.json +12 -12
|
@@ -1,207 +1,207 @@
|
|
|
1
|
-
import { ChatCompletionMessageParam } from "openai/resources/index.mjs";
|
|
2
|
-
import { delay } from "../src/utils";
|
|
3
|
-
import {
|
|
4
|
-
Customization,
|
|
5
|
-
Menu,
|
|
6
|
-
MenuItemBase,
|
|
7
|
-
OrderingAPIInterface,
|
|
8
|
-
} from "./ordering_api";
|
|
9
|
-
|
|
10
|
-
// TODO: Typescript typing could be better on this API and it would probably benefit the agent.
|
|
11
|
-
|
|
12
|
-
export class OrderingAPI implements OrderingAPIInterface {
|
|
13
|
-
private _order: MenuItemBase[] = [];
|
|
14
|
-
private _lastOrderIdNumber: number = 0;
|
|
15
|
-
public _isCompleted:boolean = false;
|
|
16
|
-
|
|
17
|
-
private _history: ChatCompletionMessageParam[] = [];
|
|
18
|
-
|
|
19
|
-
// Mock implementation, doesn't actually send an email
|
|
20
|
-
sendEmail(to: string, subject: string, body: string): Promise<void> {
|
|
21
|
-
console.log(
|
|
22
|
-
`Sending email to "${to}" with subject "${subject}" and body\n"${body}"`
|
|
23
|
-
);
|
|
24
|
-
return delay(1000);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
respondToUser(text: string): void {
|
|
28
|
-
console.log(text);
|
|
29
|
-
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
delay(milliseconds: number): Promise<void> {
|
|
33
|
-
return delay(milliseconds);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
getCurrentOrder(): MenuItemBase[] {
|
|
37
|
-
return this._order;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// addItemToOrder(item: MenuItemBase) {
|
|
41
|
-
// item.orderId = "" + (this._lastOrderIdNumber++);
|
|
42
|
-
// this._order.push(item);
|
|
43
|
-
// }
|
|
44
|
-
|
|
45
|
-
getCustomizationByName(
|
|
46
|
-
itemName: string,
|
|
47
|
-
name: string
|
|
48
|
-
): Customization | undefined {
|
|
49
|
-
const item = Menu.find((item) => item.name === itemName);
|
|
50
|
-
if (!item) {
|
|
51
|
-
return undefined;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return item.allowedCustomizations.find(
|
|
55
|
-
(customization) => customization.name === name
|
|
56
|
-
);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
addItemToOrder(
|
|
60
|
-
itemName: string,
|
|
61
|
-
customizationNames: string[] | undefined,
|
|
62
|
-
toppings: string[] | undefined
|
|
63
|
-
) {
|
|
64
|
-
const item = Menu.find((item) => item.name === itemName);
|
|
65
|
-
if (!item) {
|
|
66
|
-
throw new Error(`Item with name "${itemName}" not found`);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// FIXME: we shouldn't allow adding an item with customizations that aren't in the allowedCustomizations list for that item
|
|
70
|
-
const customizations = customizationNames ? customizationNames
|
|
71
|
-
.map((customizationName) => {
|
|
72
|
-
return this.getCustomizationByName(itemName, customizationName);
|
|
73
|
-
})
|
|
74
|
-
.filter(
|
|
75
|
-
(customization) => customization !== undefined
|
|
76
|
-
) as Customization[] : [...item.customizations];
|
|
77
|
-
|
|
78
|
-
const newItem = {
|
|
79
|
-
...item,
|
|
80
|
-
customizations,
|
|
81
|
-
toppings: toppings ? toppings : [...item.toppings],
|
|
82
|
-
orderId: "" + this._lastOrderIdNumber++,
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
this._order.push(newItem);
|
|
86
|
-
|
|
87
|
-
//this.respondToUser(`Added ${itemName} with id ${newItem.orderId}`);
|
|
88
|
-
|
|
89
|
-
this._history.push({
|
|
90
|
-
role: "user",
|
|
91
|
-
name: "log",
|
|
92
|
-
content: `added added ${itemName} with id ${newItem.orderId}`,
|
|
93
|
-
});
|
|
94
|
-
this.displayItem(newItem, true);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
getItemInOrder(itemOrderId: string): MenuItemBase | undefined {
|
|
98
|
-
const item = this._order.find((item) => item.orderId === itemOrderId);
|
|
99
|
-
if (!item) {
|
|
100
|
-
return undefined;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
return item;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
removeItemFromOrder(itemOrderId: string) {
|
|
107
|
-
this._order = this._order.filter((item) => item.orderId !== itemOrderId);
|
|
108
|
-
|
|
109
|
-
this._history.push({
|
|
110
|
-
role: "user",
|
|
111
|
-
name: "log",
|
|
112
|
-
content: `removed item ${itemOrderId}`,
|
|
113
|
-
});
|
|
114
|
-
this.respondToUser(`Removed item ${itemOrderId}`);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
modifyItemInOrder(
|
|
118
|
-
itemOrderId: string,
|
|
119
|
-
customizationNames: string[],
|
|
120
|
-
toppings: string[]
|
|
121
|
-
) {
|
|
122
|
-
const existingIndex = this._order.findIndex(
|
|
123
|
-
(item) => item.orderId === itemOrderId
|
|
124
|
-
);
|
|
125
|
-
|
|
126
|
-
if (existingIndex !== -1) {
|
|
127
|
-
const customizations = customizationNames
|
|
128
|
-
.map((customizationName) => {
|
|
129
|
-
return this.getCustomizationByName(
|
|
130
|
-
this._order[existingIndex].name,
|
|
131
|
-
customizationName
|
|
132
|
-
);
|
|
133
|
-
})
|
|
134
|
-
.filter(
|
|
135
|
-
(customization) => customization !== undefined
|
|
136
|
-
) as Customization[];
|
|
137
|
-
|
|
138
|
-
this._order[existingIndex].customizations = customizations;
|
|
139
|
-
this._order[existingIndex].toppings = toppings;
|
|
140
|
-
} else {
|
|
141
|
-
throw new Error(`Item with id #"${itemOrderId}" not found in order`);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
this._history.push({
|
|
145
|
-
role: "user",
|
|
146
|
-
name: "log",
|
|
147
|
-
content: `modified item ${itemOrderId}`,
|
|
148
|
-
});
|
|
149
|
-
this.respondToUser(`Modified item ${itemOrderId}`);
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
getOrderTotal() {
|
|
153
|
-
const total = this._order.reduce((total, item) => {
|
|
154
|
-
const customizationTotal = item.customizations.reduce(
|
|
155
|
-
(total, customization) => {
|
|
156
|
-
return total + customization?.priceAdjustment || 0;
|
|
157
|
-
},
|
|
158
|
-
0
|
|
159
|
-
);
|
|
160
|
-
return total + item.price + customizationTotal;
|
|
161
|
-
}, 0);
|
|
162
|
-
|
|
163
|
-
return total;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
completeOrder(): void {
|
|
167
|
-
this.displayOrder();
|
|
168
|
-
this.respondToUser("Order completed!");
|
|
169
|
-
|
|
170
|
-
this._lastOrderIdNumber = 0;
|
|
171
|
-
// clear history
|
|
172
|
-
this._history = []
|
|
173
|
-
|
|
174
|
-
this._isCompleted = true;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
displayItem(item: MenuItemBase, justAdded: boolean = false) {
|
|
178
|
-
let output = "";
|
|
179
|
-
|
|
180
|
-
output += `\t${justAdded ? "added " : ""}#${item.orderId || ""} ${item.name}...\t\t$${item.price.toFixed(2)}\n`;
|
|
181
|
-
item.toppings.forEach((topping) => {
|
|
182
|
-
output += `\t\t${topping}\n`;
|
|
183
|
-
});
|
|
184
|
-
item.customizations.forEach((customization) => {
|
|
185
|
-
output += `\t\t${customization.name}...\t$${customization.priceAdjustment.toFixed(2)}\n`;
|
|
186
|
-
});
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
this.respondToUser(output)
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
displayOrder() {
|
|
193
|
-
this.respondToUser("----\n\nDisplaying order:\n\n");
|
|
194
|
-
this._order.forEach((item) => this.displayItem(item));
|
|
195
|
-
this.respondToUser(`--\tTotal:\t\t$${this.getOrderTotal().toFixed(2)}`);
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
_addMessageToHistory(message: ChatCompletionMessageParam) {
|
|
199
|
-
this._history.push(message);
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
_getHistory(): ChatCompletionMessageParam[] {
|
|
203
|
-
return this._history;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
}
|
|
1
|
+
import { ChatCompletionMessageParam } from "openai/resources/index.mjs";
|
|
2
|
+
import { delay } from "../src/utils";
|
|
3
|
+
import {
|
|
4
|
+
Customization,
|
|
5
|
+
Menu,
|
|
6
|
+
MenuItemBase,
|
|
7
|
+
OrderingAPIInterface,
|
|
8
|
+
} from "./ordering_api";
|
|
9
|
+
|
|
10
|
+
// TODO: Typescript typing could be better on this API and it would probably benefit the agent.
|
|
11
|
+
|
|
12
|
+
export class OrderingAPI implements OrderingAPIInterface {
|
|
13
|
+
private _order: MenuItemBase[] = [];
|
|
14
|
+
private _lastOrderIdNumber: number = 0;
|
|
15
|
+
public _isCompleted:boolean = false;
|
|
16
|
+
|
|
17
|
+
private _history: ChatCompletionMessageParam[] = [];
|
|
18
|
+
|
|
19
|
+
// Mock implementation, doesn't actually send an email
|
|
20
|
+
sendEmail(to: string, subject: string, body: string): Promise<void> {
|
|
21
|
+
console.log(
|
|
22
|
+
`Sending email to "${to}" with subject "${subject}" and body\n"${body}"`
|
|
23
|
+
);
|
|
24
|
+
return delay(1000);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
respondToUser(text: string): void {
|
|
28
|
+
console.log(text);
|
|
29
|
+
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
delay(milliseconds: number): Promise<void> {
|
|
33
|
+
return delay(milliseconds);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
getCurrentOrder(): MenuItemBase[] {
|
|
37
|
+
return this._order;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// addItemToOrder(item: MenuItemBase) {
|
|
41
|
+
// item.orderId = "" + (this._lastOrderIdNumber++);
|
|
42
|
+
// this._order.push(item);
|
|
43
|
+
// }
|
|
44
|
+
|
|
45
|
+
getCustomizationByName(
|
|
46
|
+
itemName: string,
|
|
47
|
+
name: string
|
|
48
|
+
): Customization | undefined {
|
|
49
|
+
const item = Menu.find((item) => item.name === itemName);
|
|
50
|
+
if (!item) {
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return item.allowedCustomizations.find(
|
|
55
|
+
(customization) => customization.name === name
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
addItemToOrder(
|
|
60
|
+
itemName: string,
|
|
61
|
+
customizationNames: string[] | undefined,
|
|
62
|
+
toppings: string[] | undefined
|
|
63
|
+
) {
|
|
64
|
+
const item = Menu.find((item) => item.name === itemName);
|
|
65
|
+
if (!item) {
|
|
66
|
+
throw new Error(`Item with name "${itemName}" not found`);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// FIXME: we shouldn't allow adding an item with customizations that aren't in the allowedCustomizations list for that item
|
|
70
|
+
const customizations = customizationNames ? customizationNames
|
|
71
|
+
.map((customizationName) => {
|
|
72
|
+
return this.getCustomizationByName(itemName, customizationName);
|
|
73
|
+
})
|
|
74
|
+
.filter(
|
|
75
|
+
(customization) => customization !== undefined
|
|
76
|
+
) as Customization[] : [...item.customizations];
|
|
77
|
+
|
|
78
|
+
const newItem = {
|
|
79
|
+
...item,
|
|
80
|
+
customizations,
|
|
81
|
+
toppings: toppings ? toppings : [...item.toppings],
|
|
82
|
+
orderId: "" + this._lastOrderIdNumber++,
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
this._order.push(newItem);
|
|
86
|
+
|
|
87
|
+
//this.respondToUser(`Added ${itemName} with id ${newItem.orderId}`);
|
|
88
|
+
|
|
89
|
+
this._history.push({
|
|
90
|
+
role: "user",
|
|
91
|
+
name: "log",
|
|
92
|
+
content: `added added ${itemName} with id ${newItem.orderId}`,
|
|
93
|
+
});
|
|
94
|
+
this.displayItem(newItem, true);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
getItemInOrder(itemOrderId: string): MenuItemBase | undefined {
|
|
98
|
+
const item = this._order.find((item) => item.orderId === itemOrderId);
|
|
99
|
+
if (!item) {
|
|
100
|
+
return undefined;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return item;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
removeItemFromOrder(itemOrderId: string) {
|
|
107
|
+
this._order = this._order.filter((item) => item.orderId !== itemOrderId);
|
|
108
|
+
|
|
109
|
+
this._history.push({
|
|
110
|
+
role: "user",
|
|
111
|
+
name: "log",
|
|
112
|
+
content: `removed item ${itemOrderId}`,
|
|
113
|
+
});
|
|
114
|
+
this.respondToUser(`Removed item ${itemOrderId}`);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
modifyItemInOrder(
|
|
118
|
+
itemOrderId: string,
|
|
119
|
+
customizationNames: string[],
|
|
120
|
+
toppings: string[]
|
|
121
|
+
) {
|
|
122
|
+
const existingIndex = this._order.findIndex(
|
|
123
|
+
(item) => item.orderId === itemOrderId
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
if (existingIndex !== -1) {
|
|
127
|
+
const customizations = customizationNames
|
|
128
|
+
.map((customizationName) => {
|
|
129
|
+
return this.getCustomizationByName(
|
|
130
|
+
this._order[existingIndex].name,
|
|
131
|
+
customizationName
|
|
132
|
+
);
|
|
133
|
+
})
|
|
134
|
+
.filter(
|
|
135
|
+
(customization) => customization !== undefined
|
|
136
|
+
) as Customization[];
|
|
137
|
+
|
|
138
|
+
this._order[existingIndex].customizations = customizations;
|
|
139
|
+
this._order[existingIndex].toppings = toppings;
|
|
140
|
+
} else {
|
|
141
|
+
throw new Error(`Item with id #"${itemOrderId}" not found in order`);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
this._history.push({
|
|
145
|
+
role: "user",
|
|
146
|
+
name: "log",
|
|
147
|
+
content: `modified item ${itemOrderId}`,
|
|
148
|
+
});
|
|
149
|
+
this.respondToUser(`Modified item ${itemOrderId}`);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
getOrderTotal() {
|
|
153
|
+
const total = this._order.reduce((total, item) => {
|
|
154
|
+
const customizationTotal = item.customizations.reduce(
|
|
155
|
+
(total, customization) => {
|
|
156
|
+
return total + customization?.priceAdjustment || 0;
|
|
157
|
+
},
|
|
158
|
+
0
|
|
159
|
+
);
|
|
160
|
+
return total + item.price + customizationTotal;
|
|
161
|
+
}, 0);
|
|
162
|
+
|
|
163
|
+
return total;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
completeOrder(): void {
|
|
167
|
+
this.displayOrder();
|
|
168
|
+
this.respondToUser("Order completed!");
|
|
169
|
+
|
|
170
|
+
this._lastOrderIdNumber = 0;
|
|
171
|
+
// clear history
|
|
172
|
+
this._history = []
|
|
173
|
+
|
|
174
|
+
this._isCompleted = true;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
displayItem(item: MenuItemBase, justAdded: boolean = false) {
|
|
178
|
+
let output = "";
|
|
179
|
+
|
|
180
|
+
output += `\t${justAdded ? "added " : ""}#${item.orderId || ""} ${item.name}...\t\t$${item.price.toFixed(2)}\n`;
|
|
181
|
+
item.toppings.forEach((topping) => {
|
|
182
|
+
output += `\t\t${topping}\n`;
|
|
183
|
+
});
|
|
184
|
+
item.customizations.forEach((customization) => {
|
|
185
|
+
output += `\t\t${customization.name}...\t$${customization.priceAdjustment.toFixed(2)}\n`;
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
this.respondToUser(output)
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
displayOrder() {
|
|
193
|
+
this.respondToUser("----\n\nDisplaying order:\n\n");
|
|
194
|
+
this._order.forEach((item) => this.displayItem(item));
|
|
195
|
+
this.respondToUser(`--\tTotal:\t\t$${this.getOrderTotal().toFixed(2)}`);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
_addMessageToHistory(message: ChatCompletionMessageParam) {
|
|
199
|
+
this._history.push(message);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
_getHistory(): ChatCompletionMessageParam[] {
|
|
203
|
+
return this._history;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
}
|
package/example/sales_api.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
## Examples:
|
|
2
|
-
|
|
3
|
-
to print hello:
|
|
4
|
-
|
|
1
|
+
## Examples:
|
|
2
|
+
|
|
3
|
+
to print hello:
|
|
4
|
+
|
|
5
5
|
submitCode("salesApi.print(\"Hello\")");
|
package/example/sales_api.ts
CHANGED
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
export const API_VERSION="1.0.1";
|
|
2
|
-
|
|
3
|
-
// Sales data for each month, per business unit
|
|
4
|
-
export interface SalesData {
|
|
5
|
-
sales: number;
|
|
6
|
-
month: number; // 1...12
|
|
7
|
-
year: number;
|
|
8
|
-
businessUnit: "Advertising" | "Hardware" | "Software";
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export interface APIInterface {
|
|
12
|
-
|
|
13
|
-
sendEmail(to: string, subject: string, body: string): Promise<void>;
|
|
14
|
-
|
|
15
|
-
getSalesData(): SalesData[];
|
|
16
|
-
// Returns an array of sales data.
|
|
17
|
-
|
|
18
|
-
print(text: string): void;
|
|
19
|
-
// Prints the specified text to the user.
|
|
20
|
-
|
|
21
|
-
delay(milliseconds: number): Promise<void>;
|
|
22
|
-
// waits for the specified number of milliseconds before resolving the promise.
|
|
23
|
-
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
// Global object for accessing the APIInterface
|
|
27
|
-
declare global {
|
|
28
|
-
const salesApi: APIInterface;
|
|
29
|
-
}
|
|
1
|
+
export const API_VERSION="1.0.1";
|
|
2
|
+
|
|
3
|
+
// Sales data for each month, per business unit
|
|
4
|
+
export interface SalesData {
|
|
5
|
+
sales: number;
|
|
6
|
+
month: number; // 1...12
|
|
7
|
+
year: number;
|
|
8
|
+
businessUnit: "Advertising" | "Hardware" | "Software";
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface APIInterface {
|
|
12
|
+
|
|
13
|
+
sendEmail(to: string, subject: string, body: string): Promise<void>;
|
|
14
|
+
|
|
15
|
+
getSalesData(): SalesData[];
|
|
16
|
+
// Returns an array of sales data.
|
|
17
|
+
|
|
18
|
+
print(text: string): void;
|
|
19
|
+
// Prints the specified text to the user.
|
|
20
|
+
|
|
21
|
+
delay(milliseconds: number): Promise<void>;
|
|
22
|
+
// waits for the specified number of milliseconds before resolving the promise.
|
|
23
|
+
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
// Global object for accessing the APIInterface
|
|
27
|
+
declare global {
|
|
28
|
+
const salesApi: APIInterface;
|
|
29
|
+
}
|
|
@@ -1,60 +1,60 @@
|
|
|
1
|
-
import { delay } from "../src/utils";
|
|
2
|
-
import { APIInterface, SalesData } from "./sales_api";
|
|
3
|
-
|
|
4
|
-
export class API implements APIInterface {
|
|
5
|
-
|
|
6
|
-
// Mock implementation, doesn't actually send an email
|
|
7
|
-
sendEmail(to: string, subject: string, body: string): Promise<void> {
|
|
8
|
-
console.log(`Sending email to "${to}" with subject "${subject}" and body\n"${body}"`);
|
|
9
|
-
return delay(1000);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
getSalesData(): SalesData[] {
|
|
13
|
-
return [
|
|
14
|
-
{ sales: 100, month: 1, year: 2020, businessUnit: "Advertising" },
|
|
15
|
-
{ sales: 200, month: 2, year: 2020, businessUnit: "Advertising" },
|
|
16
|
-
{ sales: 300, month: 3, year: 2020, businessUnit: "Advertising" },
|
|
17
|
-
{ sales: 400, month: 4, year: 2020, businessUnit: "Advertising" },
|
|
18
|
-
{ sales: 500, month: 5, year: 2020, businessUnit: "Advertising" },
|
|
19
|
-
{ sales: 600, month: 6, year: 2020, businessUnit: "Advertising" },
|
|
20
|
-
{ sales: 700, month: 7, year: 2020, businessUnit: "Advertising" },
|
|
21
|
-
{ sales: 800, month: 8, year: 2020, businessUnit: "Advertising" },
|
|
22
|
-
{ sales: 900, month: 9, year: 2020, businessUnit: "Advertising" },
|
|
23
|
-
{ sales: 1000, month: 10, year: 2020, businessUnit: "Advertising" },
|
|
24
|
-
{ sales: 1100, month: 11, year: 2020, businessUnit: "Advertising" },
|
|
25
|
-
{ sales: 1100, month: 12, year: 2020, businessUnit: "Advertising" },
|
|
26
|
-
{ sales: 1200, month: 1, year: 2020, businessUnit: "Software" },
|
|
27
|
-
{ sales: 1300, month: 2, year: 2020, businessUnit: "Software" },
|
|
28
|
-
{ sales: 1400, month: 3, year: 2020, businessUnit: "Software" },
|
|
29
|
-
{ sales: 1500, month: 4, year: 2020, businessUnit: "Software" },
|
|
30
|
-
{ sales: 1600, month: 5, year: 2020, businessUnit: "Software" },
|
|
31
|
-
{ sales: 1700, month: 6, year: 2020, businessUnit: "Software" },
|
|
32
|
-
{ sales: 1800, month: 7, year: 2020, businessUnit: "Software" },
|
|
33
|
-
{ sales: 1800, month: 8, year: 2020, businessUnit: "Software" },
|
|
34
|
-
{ sales: 1500, month: 9, year: 2020, businessUnit: "Software" },
|
|
35
|
-
{ sales: 1200, month: 10, year: 2020, businessUnit: "Software" },
|
|
36
|
-
{ sales: 1000, month: 11, year: 2020, businessUnit: "Software" },
|
|
37
|
-
{ sales: 100, month: 12, year: 2020, businessUnit: "Software" },
|
|
38
|
-
{ sales: 1200, month: 1, year: 2020, businessUnit: "Hardware" },
|
|
39
|
-
{ sales: 1300, month: 2, year: 2020, businessUnit: "Hardware" },
|
|
40
|
-
{ sales: 1400, month: 3, year: 2020, businessUnit: "Hardware" },
|
|
41
|
-
{ sales: 1500, month: 4, year: 2020, businessUnit: "Hardware" },
|
|
42
|
-
{ sales: 1600, month: 5, year: 2020, businessUnit: "Hardware" },
|
|
43
|
-
{ sales: 1700, month: 6, year: 2020, businessUnit: "Hardware" },
|
|
44
|
-
{ sales: 1800, month: 7, year: 2020, businessUnit: "Hardware" },
|
|
45
|
-
{ sales: 1800, month: 8, year: 2020, businessUnit: "Hardware" },
|
|
46
|
-
{ sales: 1500, month: 9, year: 2020, businessUnit: "Hardware" },
|
|
47
|
-
{ sales: 1200, month: 10, year: 2020, businessUnit: "Hardware" },
|
|
48
|
-
{ sales: 1000, month: 11, year: 2020, businessUnit: "Hardware" },
|
|
49
|
-
{ sales: 100, month: 12, year: 2020, businessUnit: "Hardware" },
|
|
50
|
-
]
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
print(text: string): void {
|
|
54
|
-
console.log(`[API]: ${text}`);
|
|
55
|
-
}
|
|
56
|
-
delay(milliseconds: number): Promise<void> {
|
|
57
|
-
return delay(milliseconds);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
1
|
+
import { delay } from "../src/utils";
|
|
2
|
+
import { APIInterface, SalesData } from "./sales_api";
|
|
3
|
+
|
|
4
|
+
export class API implements APIInterface {
|
|
5
|
+
|
|
6
|
+
// Mock implementation, doesn't actually send an email
|
|
7
|
+
sendEmail(to: string, subject: string, body: string): Promise<void> {
|
|
8
|
+
console.log(`Sending email to "${to}" with subject "${subject}" and body\n"${body}"`);
|
|
9
|
+
return delay(1000);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
getSalesData(): SalesData[] {
|
|
13
|
+
return [
|
|
14
|
+
{ sales: 100, month: 1, year: 2020, businessUnit: "Advertising" },
|
|
15
|
+
{ sales: 200, month: 2, year: 2020, businessUnit: "Advertising" },
|
|
16
|
+
{ sales: 300, month: 3, year: 2020, businessUnit: "Advertising" },
|
|
17
|
+
{ sales: 400, month: 4, year: 2020, businessUnit: "Advertising" },
|
|
18
|
+
{ sales: 500, month: 5, year: 2020, businessUnit: "Advertising" },
|
|
19
|
+
{ sales: 600, month: 6, year: 2020, businessUnit: "Advertising" },
|
|
20
|
+
{ sales: 700, month: 7, year: 2020, businessUnit: "Advertising" },
|
|
21
|
+
{ sales: 800, month: 8, year: 2020, businessUnit: "Advertising" },
|
|
22
|
+
{ sales: 900, month: 9, year: 2020, businessUnit: "Advertising" },
|
|
23
|
+
{ sales: 1000, month: 10, year: 2020, businessUnit: "Advertising" },
|
|
24
|
+
{ sales: 1100, month: 11, year: 2020, businessUnit: "Advertising" },
|
|
25
|
+
{ sales: 1100, month: 12, year: 2020, businessUnit: "Advertising" },
|
|
26
|
+
{ sales: 1200, month: 1, year: 2020, businessUnit: "Software" },
|
|
27
|
+
{ sales: 1300, month: 2, year: 2020, businessUnit: "Software" },
|
|
28
|
+
{ sales: 1400, month: 3, year: 2020, businessUnit: "Software" },
|
|
29
|
+
{ sales: 1500, month: 4, year: 2020, businessUnit: "Software" },
|
|
30
|
+
{ sales: 1600, month: 5, year: 2020, businessUnit: "Software" },
|
|
31
|
+
{ sales: 1700, month: 6, year: 2020, businessUnit: "Software" },
|
|
32
|
+
{ sales: 1800, month: 7, year: 2020, businessUnit: "Software" },
|
|
33
|
+
{ sales: 1800, month: 8, year: 2020, businessUnit: "Software" },
|
|
34
|
+
{ sales: 1500, month: 9, year: 2020, businessUnit: "Software" },
|
|
35
|
+
{ sales: 1200, month: 10, year: 2020, businessUnit: "Software" },
|
|
36
|
+
{ sales: 1000, month: 11, year: 2020, businessUnit: "Software" },
|
|
37
|
+
{ sales: 100, month: 12, year: 2020, businessUnit: "Software" },
|
|
38
|
+
{ sales: 1200, month: 1, year: 2020, businessUnit: "Hardware" },
|
|
39
|
+
{ sales: 1300, month: 2, year: 2020, businessUnit: "Hardware" },
|
|
40
|
+
{ sales: 1400, month: 3, year: 2020, businessUnit: "Hardware" },
|
|
41
|
+
{ sales: 1500, month: 4, year: 2020, businessUnit: "Hardware" },
|
|
42
|
+
{ sales: 1600, month: 5, year: 2020, businessUnit: "Hardware" },
|
|
43
|
+
{ sales: 1700, month: 6, year: 2020, businessUnit: "Hardware" },
|
|
44
|
+
{ sales: 1800, month: 7, year: 2020, businessUnit: "Hardware" },
|
|
45
|
+
{ sales: 1800, month: 8, year: 2020, businessUnit: "Hardware" },
|
|
46
|
+
{ sales: 1500, month: 9, year: 2020, businessUnit: "Hardware" },
|
|
47
|
+
{ sales: 1200, month: 10, year: 2020, businessUnit: "Hardware" },
|
|
48
|
+
{ sales: 1000, month: 11, year: 2020, businessUnit: "Hardware" },
|
|
49
|
+
{ sales: 100, month: 12, year: 2020, businessUnit: "Hardware" },
|
|
50
|
+
]
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
print(text: string): void {
|
|
54
|
+
console.log(`[API]: ${text}`);
|
|
55
|
+
}
|
|
56
|
+
delay(milliseconds: number): Promise<void> {
|
|
57
|
+
return delay(milliseconds);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|