DEV Community

Cover image for Using Node.js to steal £10,000: Putting it into code
gleroux
gleroux

Posted on

Using Node.js to steal £10,000: Putting it into code

Formulas to functions

To generate a list of daily transfer amounts, we need a few things:

  • A savings goal and a savings period (to calculate F)
  • Our totalSaved formula from earlier
    • totalSaved = (dayNumber * (dayNumber + 1)) * F
  • Our transferAmount formula from earlier
    • transferAmount(today) = totalSaved(today) -totalSaved(yesterday)
const generateDailyTransferAmounts = (savingsGoal, savingsPeriod) => {

    //multiplication factor
    const factor = savingsGoal / savingsPeriod / (savingsPeriod + 1)

    //totalSaved formula
    const calculateTotalSavedByDay = (dayNum) => {
        return dayNum * (dayNum+1) * factor
    }

    //transferAmount formula
    const calculateTransferAmount = (dayNum) => {
        return calculateTotalSavedByDay(dayNum) - calculateTotalSavedByDay(dayNum-1)     
    }

    ...

}
Enter fullscreen mode Exit fullscreen mode

We also need an array containing the numbers 1 to savingsPeriod to iterate over.

To populate an array with the numbers 1 to savingsPeriod, we first pass the Array constructor savingsPeriod + 1, as we know the array will be zero indexed, and we don't want "Day 0". We can make use of the keys() method, which returns a new array containing the keys for each index of the array, and the spread operator, which allows us to use slice() on the returned array, removing the leading 0 and giving us an array of length savingsPeriod containing the numbers 1 to savingsPeriod.

const days = [...Array(savingsPeriod+1).keys()].slice(1)
Enter fullscreen mode Exit fullscreen mode

We can now use map() on the days array, calling our calculateTransferAmount() function on each day number to calculate the amount to be transferred on each day. We assign the resulting array to transferAmounts.

const transferAmounts = days.map(dayNum => parseFloat(calculateTransferAmount(dayNum).toFixed(2)))
Enter fullscreen mode Exit fullscreen mode

So far our code looks likes this:

const generateDailyTransferAmounts = (savingsGoal, savingsPeriod) => {

    const factor = savingsGoal/savingsPeriod/(savingsPeriod+1)

    const calculateTotalSaved = (dayNum) => {
        return dayNum * factor * (dayNum+1)
    }

    const calculateTransferAmount = (dayNum) => {
        return calculateTotalSaved(dayNum) - calculateTotalSaved(dayNum-1)     
    }

    //Array of numbers from 1 to savingsPeriod
    const days = [...Array(savingsPeriod+1).keys()].slice(1)

    //Array of transfer amounts for each day of the savingsPeriod
    const transferAmounts = days.map(dayNum => parseFloat(calculateTransferAmount(dayNum).toFixed(2)))

    ...

}
Enter fullscreen mode Exit fullscreen mode

Making things 'random' (not quite)

As it stands we have an array, transferAmounts, that is sorted in ascending order — our first transfer will be the smallest, and our last the biggest.

To get the feeling of 'random' amounts leaving our account in the middle of night, we need to shuffle our transferAmounts. Shuffling – or truly shuffling — appears to be a contentious topic 😅

I have an array like this:

var arr1 = ["a", "b", "c", "d"];

How can I randomize / shuffle it?

As we don't really need the ultimate shuffle here – just enough for it to feel random – we can use a nice clean implementation of the Durstenfeld shuffle (credit to Laurens Holst on Stackoverflow).

const shuffleArray = (array) => {
    for (let i = array.length - 1; i > 0; i--) {
        const j = Math.floor(Math.random() * (i + 1));
        [array[i], array[j]] = [array[j], array[i]];
    }
}
Enter fullscreen mode Exit fullscreen mode

Our final code, then, for generating a shuffled list of daily transfer amounts, for our chosen savings goal and savings period is as follows:

const generateDailyTransferAmounts = (goal, period) => {

    const savingsGoal = goal
    const savingsPeriod = period

    const factor = savingsGoal/savingsPeriod/(savingsPeriod+1)

    const calculateTotalSaved = (dayNum) => {
        return dayNum * factor * (dayNum+1)
    }

    const calculateTransferAmount = (dayNum) => {
        return calculateTotalSaved(dayNum) - calculateTotalSaved(dayNum-1)     
    }

    const days = [...Array(savingsPeriod+1).keys()].slice(1)

    const transferAmounts = days.map(dayNum => parseFloat(calculateTransferAmount(dayNum).toFixed(2)))

    const shuffleArray = (array) => {
        for (let i = array.length - 1; i > 0; i--) {
            const j = Math.floor(Math.random() * (i + 1));
            [array[i], array[j]] = [array[j], array[i]];
        }
    }

    return shuffleArray(transferAmounts)    

}

module.exports = generateDailyTransferAmounts
Enter fullscreen mode Exit fullscreen mode

We have included an export statement so this function can be used elsewhere.

Writing our transfer amounts to a file

As we will be using Serverless and AWS Lambda to run our program every day, we need to make our shuffled transfer amounts array accessible in the file system to any Starling API-based function we will write.

This is achieved through a new function, writeDailyTransferAmounts:

// this allows us to interact with the file system
const fs = require("fs");

//we import our function from earlier
const generateDailyAmounts = require('./generateDailyAmounts')


const writeDailyAmounts = (goal, period) => {

    const dailyTransferAmounts = JSON.stringify(generateDailyTransferAmounts(goal,period))

    ...

}
Enter fullscreen mode Exit fullscreen mode

You'll notice that as well as calling generateDailyTransferAmounts with our savings goal and savings period, we are using JSON.stringify on the result. This is because when you try and write an array to a file, it is converted to a string in the process, and you end up with something like this.

var array = [1, 2, 3, 4];
console.log(array.toString());
// 1,2,3,4
Enter fullscreen mode Exit fullscreen mode

And it loses its array functionality in the destination file.

Using JSON.stringify allows us to turn an array into a string in a way that means it stays functionally intact.

We can now use fs.writeFile() to write our array to a new file. As we want a Javascript file that can be accessed by our Starling transfer function, we use template literals to write our file content, substituting in our dailyTransferAmounts array:

const fileContent = 
    `const dailyAmounts = ${dailyTransferAmounts}
    module.exports = dailyAmounts`
Enter fullscreen mode Exit fullscreen mode

Next we write that content to the file system, to a file called dailyAmounts.js:

fs.writeFile('../dailyTransferAmounts.js', content, function(err) {
    if(err) {
          console.log(err);
    } 
    else {
      console.log("Output saved to dailyAmounts.js");
    }
});
Enter fullscreen mode Exit fullscreen mode

The full code for this step is as follows:

const fs = require("fs");

const generateDailyAmounts = require('./generateDailyAmounts')

const writeDailyAmounts = (goal, period) => {

    const dailyTransferAmounts = JSON.stringify(generateDailyTransferAmounts(goal,period))

    const fileContent = 
    `const dailyAmounts = ${dailyTransferAmounts}
    module.exports = dailyAmounts`

    fs.writeFile('./dailyTransferAmounts.js', fileContent, function(err) {
        if(err) {
            console.log(err);
        } 
        else {
            console.log("Output saved to dailyAmounts.js");
        }
    })
}

module.exports = writeDailyAmounts
Enter fullscreen mode Exit fullscreen mode

Again we include an export statement so this function can be used elsewhere.

Latest comments (2)

Collapse
 
byt3h3ad profile image
Adhiraj Dutta

really great post and idea!

Collapse
 
gleroux profile image
gleroux

thanks! More to come 😄