-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcommon.js
More file actions
171 lines (149 loc) · 6.16 KB
/
common.js
File metadata and controls
171 lines (149 loc) · 6.16 KB
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
/*
FSTAPLE
Free STatistics APpLEt
Public domain.
Free forever.
This JavaScript is common to many stapplets, and is therefore included with every stapplet.
*/
// chart element and chart variable
window.ctx = document.getElementById("chart");
window.chart = undefined;
// check if input is number
function input_validate(input) {
// +input will return NaN if not a number, but whitespace is considered 0 so we filter that out
return input !== null && !isNaN(+input) && input.split(" ").join("") !== "";
}
// line chart plotter
function plot_line_chart(data) {
// if there is a chart, we should destroy it
if (chart !== undefined) chart.destroy();
// generate a new color
let color = `rgb(${Math.round(Math.random() * 255)}, ${Math.round(Math.random() * 255)}, ${Math.round(Math.random() * 255)})`;
// set the chart to a new chart with what we want
chart = new Chart(ctx, {
type: "line",
data: {
datasets: [{
borderColor: color,
backgroundColor: color,
label: "Data",
data
}],
fill: false,
tension: 0.1
},
options: {
responsive: true,
scales: {
x: {
type: "linear",
position: "right",
min: data[0].x,
max: data[data.length - 1].x
}
},
maintainAspectRatio: false
}
});
}
// data generator
function generate_chart_data(distribution, ...dist_params) {
// make the width nice
const low = Math.floor(distribution.inv(0.001, ...dist_params));
const high = Math.ceil(distribution.inv(0.999, ...dist_params));
// calculate our step
const step = (high - low) / 200;
// this is where we store our data
let data_array = [];
// just get each datapoint
for (let i = low; i <= high; i += step) {
data_array.push({
x: i,
y: distribution.pdf(i, ...dist_params)
});
}
// return the array
return data_array;
}
// various normal distribution area functions
const normal_distribution_area_left = jStat.normal.cdf;
function normal_distribution_area_right(x, mean, std) {
// for the area on the right, we just return the area not on the left
return 1 - normal_distribution_area_left(x, mean, std);
}
function normal_distribution_area_region(a, b, mean, std) {
// for the area in a region, we subtract the area to the left of the leftmost point from the area to the left of the rightmost point
return normal_distribution_area_left(b, mean, std) - normal_distribution_area_left(a, mean, std);
}
function normal_distribution_area_outside_region(a, b, mean, std) {
// to find the area outside of a region, we add the area to the right of the rightmost point to the area to the left of the leftmost point
return normal_distribution_area_right(b, mean, std) + normal_distribution_area_left(a, mean, std);
}
const inv_normal_distribution_area_left = jStat.normal.inv;
function inv_normal_distribution_area_right(x, mean, std) {
// to find the boundary value for a right-tail area of x, we just find the boundary value for a left-tail area of 1 minus x
return inv_normal_distribution_area_left(1 - x, mean, std);
}
function inv_normal_distribution_area_central(x, mean, std) {
/*
a somewhat detailed explanation of how this works:
the boundary values of a central area x are just the
left boundary value of (1 - x) / 2 and the right
boundary value of (1 - x) / 2. this is because the area
outside of the center is 1 - x, since this is a
probability density function, and the integral of a
probability density function from -infinity to infinity
is 1. because a normal distribution is symmetric, the
area outside of our central area is split evenly on each
side, allowing for the method in the first sentence. to
increase efficiency, we find the distance of the left
boundary value of (1 - x) / 2 from the mean and then
subtract distance from the mean for the left boundary and
then add it to the mean for the right boundary.
*/
const distance = mean - inv_normal_distribution_area_left((1 - x) / 2, mean, std)
return [mean - distance, mean + distance];
}
/*
input via window.prompt()
conforms_to_specs should be a function
which returns true/false depending on
whether the input is in spec.
*/
function get_input(prompt, conforms_to_specs) {
let input = undefined;
while ((!conforms_to_specs(input) && input !== null) || input === undefined) {
input = window.prompt(prompt);
}
return input;
}
// various chi-square area functions
const chi_square_area_left = jStat.chisquare.cdf;
function chi_square_area_right(x, dof) {
// for the area on the right, we just return the area not on the left
return 1 - chi_square_area_left(x, dof);
}
function chi_square_area_region(a, b, dof) {
// for the area in a region, we subtract the area to the left of the leftmost point from the area to the left of the rightmost point
return chi_square_area_left(b, dof) - chi_square_area_left(a, dof);
}
function chi_square_area_outside_region(a, b, dof) {
// to find the area outside of a region, we add the area to the right of the rightmost point to the area to the left of the leftmost point
return chi_square_area_right(b, dof) + chi_square_area_left(a, dof);
}
const inv_chi_square_area_left = jStat.chisquare.inv;
function inv_chi_square_area_right(x, dof) {
// to find the boundary value for a right-tail area of x, we just find the boundary value for a left-tail area of 1 minus x
return inv_chi_square_area_left(1 - x, dof);
}
function inv_chi_square_area_central(x, dof) {
/*
haha finding boundaries go brr
right tail of 1/2 the area, left tail of half the area.
does that make sense? good.
(chi-square doesn't have to be symmetric)
*/
// area on both right and left tail
let area = (1 - x) / 2;
return [inv_chi_square_area_left(area, dof), inv_chi_square_area_right(area, dof)];
}