Skip to content

Commit 8529b8c

Browse files
authored
Merge pull request #31 from tuftsceeo/color_sensor
Color sensor
2 parents d34635e + 83a5181 commit 8529b8c

40 files changed

Lines changed: 3992 additions & 2795 deletions

firebase.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"hosting": {
3-
"public": "wildcatweb\\build",
3+
"public": "/wildcatweb/build",
44
"ignore": [
55
"firebase.json",
66
"**/.*",

wildcatweb/src/code-generation/InstructionDescriptionGenerator.js

Lines changed: 52 additions & 141 deletions
Original file line numberDiff line numberDiff line change
@@ -16,29 +16,14 @@ import { getTranslatedText, getUIText } from "../translations/loader";
1616
* @param {number} slotNumber - Current slot number for sequencing context (0-based)
1717
* @returns {string} Human-readable description
1818
*/
19-
export const generateDescription = (
20-
instruction,
21-
language = "en",
22-
complexityLevel = "intermediate",
23-
slotNumber = 0,
24-
) => {
19+
export const generateDescription = (instruction, language = "en", complexityLevel = "intermediate", slotNumber = 0) => {
2520
if (!instruction || !instruction.type) {
2621
return "Empty slot";
2722
}
2823

2924
// First, check if this is a multi-motor instruction
30-
if (
31-
instruction.type === "action" &&
32-
instruction.subtype === "motor" &&
33-
Array.isArray(instruction.configuration) &&
34-
instruction.configuration.length > 1
35-
) {
36-
return generateMultiMotorDescription(
37-
instruction,
38-
language,
39-
complexityLevel,
40-
slotNumber,
41-
);
25+
if (instruction.type === "action" && instruction.subtype === "motor" && Array.isArray(instruction.configuration) && instruction.configuration.length > 1) {
26+
return generateMultiMotorDescription(instruction, language, complexityLevel, slotNumber);
4227
}
4328

4429
// Normal single instruction description
@@ -47,20 +32,10 @@ export const generateDescription = (
4732

4833
if (Array.isArray(config) && config.length === 1) {
4934
// Single motor in array
50-
return generateSingleDescription(
51-
config[0],
52-
language,
53-
complexityLevel,
54-
slotNumber,
55-
);
35+
return generateSingleDescription(config[0], language, complexityLevel, slotNumber);
5636
} else if (config.port) {
5737
// Single motor configuration
58-
return generateSingleDescription(
59-
config,
60-
language,
61-
complexityLevel,
62-
slotNumber,
63-
);
38+
return generateSingleDescription(config, language, complexityLevel, slotNumber);
6439
}
6540

6641
return "Motor action (not set up)";
@@ -71,19 +46,10 @@ export const generateDescription = (
7146

7247
// Modify the template key based on whether it's the first slot
7348
const templateKey = "wait_action";
74-
let translatedText = getTranslatedText(
75-
templateKey,
76-
language,
77-
complexityLevel,
78-
{ seconds },
79-
);
49+
let translatedText = getTranslatedText(templateKey, language, complexityLevel, { seconds });
8050

8151
// For text_only and advanced levels, adjust for first slot if needed
82-
if (
83-
(complexityLevel === "text_only" ||
84-
complexityLevel === "advanced") &&
85-
slotNumber === 0
86-
) {
52+
if ((complexityLevel === "text_only" || complexityLevel === "advanced") && slotNumber === 0) {
8753
// Replace "Next" with "First" for the first slot
8854
translatedText = translatedText.replace(/^Next,|^Then,/i, "First,");
8955
}
@@ -94,25 +60,30 @@ export const generateDescription = (
9460
if (instruction.type === "input" && instruction.subtype === "button") {
9561
const config = instruction.configuration || {};
9662
const portText = getUIText(`button${config.port || "A"}`, language);
97-
const condition = getUIText(
98-
config.waitCondition || "pressed",
99-
language,
100-
);
63+
const condition = getUIText(config.waitCondition || "pressed", language);
10164

10265
// Get translated text from the appropriate template
103-
let translatedText = getTranslatedText(
104-
"button_action",
105-
language,
106-
complexityLevel,
107-
{ port: portText, condition },
108-
);
66+
let translatedText = getTranslatedText("button_action", language, complexityLevel, { port: portText, condition });
10967

11068
// For text_only and advanced levels, adjust for first slot if needed
111-
if (
112-
(complexityLevel === "text_only" ||
113-
complexityLevel === "advanced") &&
114-
slotNumber === 0
115-
) {
69+
if ((complexityLevel === "text_only" || complexityLevel === "advanced") && slotNumber === 0) {
70+
// Replace "Next" with "First" for the first slot
71+
translatedText = translatedText.replace(/^Next,|^Then,/i, "First,");
72+
}
73+
74+
return translatedText;
75+
}
76+
77+
if (instruction.type === "input" && instruction.subtype === "color") {
78+
const config = instruction.configuration || {};
79+
const portText = getUIText(`color${config.port || "A"}`, language);
80+
const color = config.color || "red";
81+
82+
// Get translated text from the appropriate template
83+
let translatedText = getTranslatedText("color_action", language, complexityLevel, { port: portText, color });
84+
85+
// For text_only and advanced levels, adjust for first slot if needed
86+
if ((complexityLevel === "text_only" || complexityLevel === "advanced") && slotNumber === 0) {
11687
// Replace "Next" with "First" for the first slot
11788
translatedText = translatedText.replace(/^Next,|^Then,/i, "First,");
11889
}
@@ -121,9 +92,7 @@ export const generateDescription = (
12192
}
12293

12394
// Default for unknown instruction types
124-
return `${instruction.type === "action" ? "Action" : "Input"}: ${
125-
instruction.subtype || "unknown"
126-
}`;
95+
return `${instruction.type === "action" ? "Action" : "Input"}: ${instruction.subtype || "unknown"}`;
12796
};
12897

12998
/**
@@ -135,12 +104,7 @@ export const generateDescription = (
135104
* @param {number} slotNumber - Current slot number (0-based)
136105
* @returns {string} Human-readable description
137106
*/
138-
function generateSingleDescription(
139-
config,
140-
language,
141-
complexityLevel,
142-
slotNumber,
143-
) {
107+
function generateSingleDescription(config, language, complexityLevel, slotNumber) {
144108
if (!config || !config.port) return "Motor action (not set up)";
145109

146110
const port = config.port;
@@ -149,19 +113,10 @@ function generateSingleDescription(
149113

150114
if (speed === 0) {
151115
// Get stop text from the appropriate template
152-
let translatedText = getTranslatedText(
153-
"motor_stop",
154-
language,
155-
complexityLevel,
156-
{ port: portText },
157-
);
116+
let translatedText = getTranslatedText("motor_stop", language, complexityLevel, { port: portText });
158117

159118
// For text_only and advanced levels, adjust for first slot if needed
160-
if (
161-
(complexityLevel === "text_only" ||
162-
complexityLevel === "advanced") &&
163-
slotNumber === 0
164-
) {
119+
if ((complexityLevel === "text_only" || complexityLevel === "advanced") && slotNumber === 0) {
165120
// Replace "Next" with "First" for the first slot
166121
translatedText = translatedText.replace(/^Next,|^Then,/i, "First,");
167122
}
@@ -172,22 +127,14 @@ function generateSingleDescription(
172127
const { level, direction } = getSpeedDescription(speed);
173128

174129
// Get motor action text from the appropriate template
175-
let translatedText = getTranslatedText(
176-
"motor_action",
177-
language,
178-
complexityLevel,
179-
{
180-
port: portText,
181-
direction,
182-
speed: level,
183-
},
184-
);
130+
let translatedText = getTranslatedText("motor_action", language, complexityLevel, {
131+
port: portText,
132+
direction,
133+
speed: level,
134+
});
185135

186136
// For text_only and advanced levels, adjust for first slot if needed
187-
if (
188-
(complexityLevel === "text_only" || complexityLevel === "advanced") &&
189-
slotNumber === 0
190-
) {
137+
if ((complexityLevel === "text_only" || complexityLevel === "advanced") && slotNumber === 0) {
191138
// Replace "Next" with "First" for the first slot
192139
translatedText = translatedText.replace(/^Next,|^Then,/i, "First,");
193140
}
@@ -204,16 +151,8 @@ function generateSingleDescription(
204151
* @param {number} slotNumber - Current slot number (0-based)
205152
* @returns {string} Combined human-readable description
206153
*/
207-
function generateMultiMotorDescription(
208-
instruction,
209-
language,
210-
complexityLevel,
211-
slotNumber,
212-
) {
213-
if (
214-
!Array.isArray(instruction.configuration) ||
215-
instruction.configuration.length === 0
216-
) {
154+
function generateMultiMotorDescription(instruction, language, complexityLevel, slotNumber) {
155+
if (!Array.isArray(instruction.configuration) || instruction.configuration.length === 0) {
217156
return "Motor action (not set up)";
218157
}
219158

@@ -228,48 +167,28 @@ function generateMultiMotorDescription(
228167

229168
if (speed === 0) {
230169
// Get base stop text without connector words
231-
description = getTranslatedText(
232-
"motor_stop",
233-
language,
234-
complexityLevel,
235-
{ port: portText },
236-
);
170+
description = getTranslatedText("motor_stop", language, complexityLevel, { port: portText });
237171
} else {
238172
// Get base action text without connector words
239173
const { level, direction } = getSpeedDescription(speed);
240-
description = getTranslatedText(
241-
"motor_action",
242-
language,
243-
complexityLevel,
244-
{
245-
port: portText,
246-
direction,
247-
speed: level,
248-
},
249-
);
174+
description = getTranslatedText("motor_action", language, complexityLevel, {
175+
port: portText,
176+
direction,
177+
speed: level,
178+
});
250179
}
251180

252181
// Remove leading connectors for all formats
253182
description = description.replace(/^Next,\s+|^Then,\s+/i, "");
254183

255184
// For first motor in first slot (index 0, slotNumber 0), add "First," prefix
256-
if (
257-
index === 0 &&
258-
slotNumber === 0 &&
259-
complexityLevel === "text_only"
260-
) {
185+
if (index === 0 && slotNumber === 0 && complexityLevel === "text_only") {
261186
// Convert first letter to lowercase after adding "First,"
262-
description =
263-
"First, " +
264-
description.charAt(0).toLowerCase() +
265-
description.slice(1);
187+
description = "First, " + description.charAt(0).toLowerCase() + description.slice(1);
266188
}
267189
if (index === 0 && slotNumber > 0 && complexityLevel === "text_only") {
268190
// Convert first letter to lowercase after adding "First,"
269-
description =
270-
"Next, " +
271-
description.charAt(0).toLowerCase() +
272-
description.slice(1);
191+
description = "Next, " + description.charAt(0).toLowerCase() + description.slice(1);
273192
}
274193

275194
return description;
@@ -283,27 +202,19 @@ function generateMultiMotorDescription(
283202
const firstDesc = descriptions[0];
284203

285204
// Convert first letter of second description to lowercase
286-
const secondDesc =
287-
descriptions[1].charAt(0).toLowerCase() +
288-
descriptions[1].slice(1);
205+
const secondDesc = descriptions[1].charAt(0).toLowerCase() + descriptions[1].slice(1);
289206

290207
// Remove period from first description if it exists
291-
const cleanFirstDesc = firstDesc.endsWith(".")
292-
? firstDesc.slice(0, -1)
293-
: firstDesc;
208+
const cleanFirstDesc = firstDesc.endsWith(".") ? firstDesc.slice(0, -1) : firstDesc;
294209

295210
return `${cleanFirstDesc} while ${secondDesc}`;
296211
} else {
297212
// For 3+ motors, use commas and "while" for the last one
298213
// "Motor A spins clockwise, Motor B spins countercw, while Motor C stops."
299-
const lastDesc =
300-
descriptions[descriptions.length - 1].charAt(0).toLowerCase() +
301-
descriptions[descriptions.length - 1].slice(1);
214+
const lastDesc = descriptions[descriptions.length - 1].charAt(0).toLowerCase() + descriptions[descriptions.length - 1].slice(1);
302215

303216
// Remove periods from all but the last description
304-
const firstDescriptions = descriptions
305-
.slice(0, -1)
306-
.map((desc) => (desc.endsWith(".") ? desc.slice(0, -1) : desc));
217+
const firstDescriptions = descriptions.slice(0, -1).map((desc) => (desc.endsWith(".") ? desc.slice(0, -1) : desc));
307218

308219
return `${firstDescriptions.join(", ")} while ${lastDesc}`;
309220
}

0 commit comments

Comments
 (0)