I stick by what I said in my last post that I am skeptical of claims that AI is making hordes of people 5x developers. If that is the case, you probably sucked in the first place. Actually, that might be exactly it, because as I think of the areas that AI has helped me immensely, these are mostly in which I am not very good or knowledgable.
How does AI make me a 1.15x developer?
1. Using Gemini for Google apps scripts for simple tasks
This is an area where I have seen two promises of AI actually come true; it produces the correct output far faster than I could, and it has improved significantly over the last couple of years. For example, I wanted a simple function to go through my mail, find email bounces and highlight those names in a sheet. Doing this manually could take me 30 minutes or much more, depending on the number of bounces. The function below was produced in two prompts and took less than five minutes for Gemini to produce.
Since people who are doubters ask to see the code created, here it is:
function processAllBounces() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var data = sheet.getDataRange().getValues();
// 1. SEARCH BROADLY
// We only look for the sender. We DO NOT look at the subject.
// We include 'postmaster' as some servers use that instead of mailer-daemon.
var threads = GmailApp.search('{from:mailer-daemon from:postmaster}');
Logger.log("Found " + threads.length + " threads containing bounces.");
var bouncedEmails = [];
// 2. DIG THROUGH THREADS
for (var i = 0; i < threads.length; i++) {
var messages = threads[i].getMessages();
// Loop through every message in the thread (original + bounce)
for (var m = 0; m < messages.length; m++) {
var msg = messages[m];
var from = msg.getFrom().toLowerCase();
// Only check messages actually sent by the bounce bot
if (from.includes("mailer-daemon") || from.includes("postmaster")) {
var body = msg.getPlainBody();
// 3. EXTRACT EMAIL
// We try a few regex patterns to catch different bounce formats
var match = body.match(/To:.*?<([\w\.\-_]+@[\w\.\-_]+\.\w+)>/) ||
body.match(/Final-Recipient: rfc822; ([\w\.\-_]+@[\w\.\-_]+\.\w+)/) ||
body.match(/Failed recipient: ([\w\.\-_]+@[\w\.\-_]+\.\w+)/) ||
body.match(/([\w\.\-_]+@[\w\.\-_]+\.\w+)\s+Action: failed/);
if (match && match[1]) {
bouncedEmails.push(match[1]);
}
}
}
}
// Remove duplicates from the array
bouncedEmails = [...new Set(bouncedEmails)];
if (bouncedEmails.length === 0) {
Logger.log("No bounced email addresses extracted.");
return;
}
Logger.log("Extracted Addresses: " + bouncedEmails.join(", "));
// 4. MARK ROWS IN SHEET
for (var r = data.length - 1; r >= 0; r--) {
var rowEmail = data[r][0]; // Assumes Column A. Change to [1] for B.
// Check if the row's email is in our list of bounces
if (bouncedEmails.includes(rowEmail)) {
// Highlight RED
sheet.getRange(r + 1, 1, 1, sheet.getLastColumn()).setBackground("#FFCCCC");
sheet.getRange(r + 1, 1).setNote("Bounce detected by script");
Logger.log("Marked row for: " + rowEmail);
}
}
}
“But, AnnMaria, you know JavaScript, you could have written that code yourself.”
- Smart people who miss the point
Yes, I absolutely could have written it myself. Could I have written it in under 5 minutes? Probably not. I would have had to look up the specific functions for sheets because that is not normally something I use. My estimate is that this would have taken me from 10-30 minutes because I might not have thought of all the regular expressions and I would have had to look up things like getActiveSpreadsheet because very little of the coding I do relates to Google apps.
Does this make me a 6x developer? No, because I only have this type of use case every few weeks or so.
2. Adding comments and organizing files
I had CSS that looked like this:
:root {
--screen-width: 1024px;
--screen-height: 576px;
}
.bubble {
position: absolute;
height: fit-content;
padding: 2px 10px;
width: 80%;
font-size: 2em;
user-select: none;
}
.button_style {
border: 5px solid darkblue;
background-color: turquoise;
color:white ;
text-align: center;
user-select: none;
}
.button-row {
position: relative;
height: 50px;
/*left: 10px;*/
/*top: 0 ;*/
width: var(--screen-width) ;
z-index: 50 ;
}
.lang_style {
vertical-align: top;
}
/* Styles for dialog.js */
.choice-button-row {
display: flex;
flex-direction: row;
justify-content: space-between;
padding: 5px;
}
#dialog-box {
width: 50%;
height: auto;
font-size: 1.5em;
display: flex;
flex-direction: column;
padding: 10px;
}
… Just imagine a lot more of that.
I entered one prompt to copilot, to organize and comment the file, and uploaded it. The results are like this:
/* ============================================================
ROOT VARIABLES
------------------------------------------------------------
These define the fixed game screen dimensions used throughout.
============================================================ */
:root {
--screen-width: 1024px;
--screen-height: 576px;
}
/* ============================================================
GENERAL UI ELEMENTS
============================================================ */
/* Speech bubbles / text bubbles */
.bubble {
position: absolute;
height: fit-content;
padding: 2px 10px;
width: 80%;
font-size: 2em;
user-select: none;
}
/* Generic button styling */
.button_style {
border: 5px solid darkblue;
background-color: turquoise;
color: white;
text-align: center;
user-select: none;
}
/* Row that holds navigation or action buttons */
.button-row {
position: relative;
height: 50px;
width: var(--screen-width);
z-index: 50;
}
/* Language toggle button styling */
.lang_style {
vertical-align: top;
}
/* ============================================================
DIALOG SYSTEM (dialog.js)
============================================================ */
/* Row of choice buttons inside dialog */
.choice-button-row {
display: flex;
flex-direction: row;
justify-content: space-between;
padding: 5px;
}
Is that ideal? No. However, given the fact that I probably wasn’t going to get around to doing anything with this file for a while, it is better than the nothing that was going to be done in the way of comments. And you DO need to document your code, and if we disagree, this is a topic on which you can fight me. For new developers in our company, this will make the CSS a little easier to read. Personally, I found AI efforts at documenting JavaScript to generally be overly verbose, plus, I want to do it myself as I often think of ways to improve code as I step through it.
Artwork: The AI that infuriates some people
I’m terrible at art. Just ask my eighth-grade art teacher who gave me an F. She would argue that I deserved that F and she would be correct. Some people say you cannot fail art. Those people are wrong. You can, if you are really, really bad at it. Here are two images from a game I finished in two days, Axolotl Adventure. The purpose of this game is to give an example of how the demo version of 7 Gen Blocks, which you can download for free from this page, can be used to create an entire game.
Pretty much all of the artwork for this game was done with Adobe Firefly and then edited by me in Photoshop to the correct size and to occasionally add or delete something from a scene. For games that need to be historically accurate, like the Warrior Vets game we did, for example, AI wouldn’t work so well and I’d use primary sources, say, from the Library of Congress
Creating a game isn’t all coding. It is narrative, art, audio and design. Maybe if we were a huge studio, no developer would be ever expected to come up with artwork. We have one artist and he is currently working on something else for us. If I didn’t have Adobe, I would have used some of our existing artwork – we have thousands of images that I used a Google apps script to organize last year – but I’m not sure the game would have come out as well because I would have been limited to a story and characters that fit what we already had in our catalog.
Is this the greatest game in the history of the universe? No. The next Roblox? Also, no. However, kids who played it enjoyed it and learned some new vocabulary, and it gave the the opportunity to try out our blocks.
Now, I’m going to go make another game.



Pingback: Fixing the transcoding error in SAS – AnnMaria's Blog