-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmodel.mjs
119 lines (105 loc) · 5.52 KB
/
model.mjs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import fs from "node:fs"
import csv from "csv-parser"
import { NeuralNetwork, utilities } from "brain.js"
const prepareData = (features, target) => {
const data = []
for (let i = 0; i < features.length; i++) data.push({input: features[i], output: target[i]})
return data
}
import mcVersions from "./mcVersions.json" with { type: "json" }
import bugs from "./bugs.json" with { type: "json" }
const results = []
fs.createReadStream("mcVersions.csv")
.pipe(csv())
.on("data", data => results.push(data))
.on("end", () => {
async function trainModel() {
results.sort(() => 0.5 - Math.random())
const trainSize = Math.floor(results.length * 0.7)
console.log("Splitting data into " + trainSize + " training and " + (results.length - trainSize) + " testing samples...")
const trainSet = results.slice(0, trainSize)
const testSet = results.slice(trainSize)
const net = new NeuralNetwork({
activation: "sigmoid"
})
const highestSnapshots = Math.max(...results.map(item => parseInt(item["Snapshots in the last three weeks"])))
const highestYear = Math.max(...results.map(item => parseInt(item["Day of year"])))
const highestSinceLast = Math.max(...results.map(item => parseInt(item["Hours since last snapshot"])))
const highestBugfixes = Math.max(...results.map(item => parseInt(item["Bugs fixed"])))
const highestDay = Math.max(...results.map(item => parseInt(item["Day of week"])))
const lowestSnapshots = Math.min(...results.map(item => parseInt(item["Snapshots in the last three weeks"])))
const lowestYear = Math.min(...results.map(item => parseInt(item["Day of year"])))
const lowestSinceLast = Math.min(...results.map(item => parseInt(item["Hours since last snapshot"])))
const lowestBugfixes = Math.min(...results.map(item => parseInt(item["Bugs fixed"])))
const lowestDay = Math.min(...results.map(item => parseInt(item["Day of week"])))
const normalize = item => ([
(parseInt(item["Snapshots in the last three weeks"]) - lowestSnapshots) / (highestSnapshots - lowestSnapshots),
(parseInt(item["Day of year"]) - lowestYear) / (highestYear - lowestYear),
(parseInt(item["Hours since last snapshot"]) - lowestSinceLast) / (highestSinceLast - lowestSinceLast),
(parseInt(item["Bugs fixed"]) - lowestBugfixes) / (highestBugfixes - lowestBugfixes),
(parseInt(item["Day of week"]) - lowestDay) / (highestDay - lowestDay)
])
net.train(prepareData(trainSet.map(normalize), trainSet.map(item => [item.Name == "" ? 0 : 1])), {
log: true,
logPeriod: 2500,
timeout: 1000 * 60,
iterations: 35000,
errorThresh: 0.008,
learningRate: 0.3
})
const stats = net.test(prepareData(testSet.map(normalize), testSet.map(item => [item.Name == "" ? 0 : 1])))
if (stats.accuracy < 0.885) {
console.log(stats.accuracy + " accuracy is not enough, retraining...")
return trainModel()
}
console.log(stats)
const lastThreeWeeks = results.filter(item => item.Name != "" && new Date(item.Date).getTime() > Date.now() - 1000 * 60 * 60 * 24 * 7 * 3).length
const date = new Date()
const defaultValues = {
"Snapshots in the last three weeks": lastThreeWeeks,
"Day of year": date.getMonth() * 30 + date.getDate(),
"Hours since last snapshot": Math.abs(Math.round((new Date(mcVersions[0].releaseTime).getTime() - Date.now()) / 1000 / 60 / 60)),
"Bugs fixed": bugs.filter(bug => date.toISOString().substring(0, 10) == bug).length,
"Day of week": date.getDay() == 0 ? 7 : date.getDay()
}
const prediction = net.run(normalize(defaultValues))
console.log("Current prediction for today: " + (prediction[0] * 100).toFixed(2) + "%")
const tomorrow = new Date(date)
tomorrow.setDate(tomorrow.getDate() + 1)
const tomorrowValues = {
"Snapshots in the last three weeks": results.filter(item => item.Name != "" && new Date(item.Date).getTime() > tomorrow.getTime() - 1000 * 60 * 60 * 24 * 7 * 3).length,
"Day of year": tomorrow.getMonth() * 30 + tomorrow.getDate(),
"Hours since last snapshot": Math.abs(Math.round((new Date(mcVersions[0].releaseTime).getTime() - tomorrow.getTime()) / 1000 / 60 / 60)),
"Bugs fixed": bugs.filter(bug => tomorrow.toISOString().substring(0, 10) == bug).length,
"Day of week": tomorrow.getDay() == 0 ? 7 : tomorrow.getDay()
}
const tomorrowPrediction = net.run(normalize(tomorrowValues))
console.log("Prediction for tomorrow: " + (tomorrowPrediction[0] * 100).toFixed(2) + "%")
fs.writeFileSync("./web/modelFunction.js",
net.toFunction().toString() +
"\n" +
"\nconst lastBuild = " + Date.now() +
"\n" +
"\nconst defaultSnapshots = " + defaultValues["Snapshots in the last three weeks"] +
"\nconst defaultYear = " + defaultValues["Day of year"] +
"\nconst defaultSinceLast = " + defaultValues["Hours since last snapshot"] +
"\nconst defaultBugfixes = " + defaultValues["Bugs fixed"] +
"\nconst defaultDay = " + defaultValues["Day of week"] +
"\n" +
"\nconst highestSnapshots = " + highestSnapshots +
"\nconst highestYear = " + highestYear +
"\nconst highestSinceLast = " + highestSinceLast +
"\nconst highestBugfixes = " + highestBugfixes +
"\nconst highestDay = " + highestDay +
"\nconst lowestSnapshots = " + lowestSnapshots +
"\nconst lowestYear = " + lowestYear +
"\nconst lowestSinceLast = " + lowestSinceLast +
"\nconst lowestBugfixes = " + lowestBugfixes +
"\nconst lowestDay = " + lowestDay +
"\n\nconst normalize = " + normalize.toString()
)
const svg = utilities.toSVG(net)
fs.writeFileSync("./web/model.svg", svg)
}
trainModel()
})