linny-r 1.1.5 → 1.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -35
- package/console.js +72 -11
- package/package.json +2 -2
- package/post-install.js +1 -1
- package/server.js +74 -170
- package/static/index.html +21 -17
package/README.md
CHANGED
@@ -44,23 +44,17 @@ so in all commands you should replace this with the actual directory path.
|
|
44
44
|
On a Windows machine you may choose something like `C:\Users\xyz\Documents\Linny-R`,
|
45
45
|
and on a macOS machine probably `/Users/xyz/Linny-R`.
|
46
46
|
|
47
|
-
To install Linny-R in this directory,
|
47
|
+
To install Linny-R in this directory, first create it:
|
48
48
|
|
49
|
-
``
|
49
|
+
``mkdir WORKING_DIRECTORY``
|
50
50
|
|
51
|
-
|
52
|
-
and two JSON files `package.json` and `package-lock.json` that should **not** be removed,
|
53
|
-
or you will have to re-install Linny-R.
|
51
|
+
then change to it:
|
54
52
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
where individual users each have their personal work space (e.g., a virtual drive U:),
|
61
|
-
you must edit the script file, adding the argument `workspace=path/to/workspace` to the
|
62
|
-
`node` command. This will instruct Linny-R to create the `user` directory in this workspace
|
63
|
-
directory instead of the Linny-R directory.
|
53
|
+
``cd WORKING_DIRECTORY``
|
54
|
+
|
55
|
+
and then type at the command line prompt:
|
56
|
+
|
57
|
+
``npm install --prefix . linny-r``
|
64
58
|
|
65
59
|
After installation has completed, `WORKING_DIRECTORY` should have this directory tree structure:
|
66
60
|
|
@@ -84,11 +78,22 @@ WORKING_DIRECTORY
|
|
84
78
|
+-sounds
|
85
79
|
</pre>
|
86
80
|
|
81
|
+
`WORKING_DIRECTORY` should contain two JSON files `package.json` and `package-lock.json`
|
82
|
+
that should **not** be removed, or you will have to re-install Linny-R. It should also contain
|
83
|
+
a script file to facilitate (single click) launch: on a macOS machine the shell script `linny-r.command`,
|
84
|
+
on a Windows machine the batch script `linny-r.bat`. By default, this script file contains
|
85
|
+
two commands: first change to the Linny-R directory and then tell Node.js to launch the
|
86
|
+
start the Linny-R server.
|
87
|
+
|
88
|
+
**NOTE:** When configuring Linny-R for a network environment where individual users
|
89
|
+
each have their personal work space (e.g., a virtual drive U:), you must edit this script file,
|
90
|
+
adding the argument `workspace=path/to/workspace` to the `node` command.
|
91
|
+
This will instruct Linny-R to create the `user` directory in this workspace directory
|
92
|
+
instead of the Linny-R directory.
|
93
|
+
|
87
94
|
The `linny-r` directory should contain this file `README.md`,
|
88
95
|
the files `server.js` and `console.js` that will be run by Node.js,
|
89
|
-
and the sub-directory `static`.
|
90
|
-
|
91
|
-
The `static` directory should contain three HTML files:
|
96
|
+
and the sub-directory `static`. This `static` directory should contain three HTML files:
|
92
97
|
|
93
98
|
* `index.html` (the browser-based GUI)
|
94
99
|
* `show-png.html` (to render SVG diagrams as PNG images)
|
@@ -155,31 +160,21 @@ If you reach this stage, Linny-R will be able to run LP_solve.
|
|
155
160
|
|
156
161
|
### Running Linny-R
|
157
162
|
|
158
|
-
Open the Command Line Interface (CLI) of your computer
|
159
|
-
On macOS, open `Terminal`, change to your `WORKING_DIRECTORY` and type:
|
163
|
+
Open the Command Line Interface (CLI) of your computer, change to your `WORKING_DIRECTORY` and type:
|
160
164
|
|
161
|
-
``
|
165
|
+
``linny-r``
|
162
166
|
|
163
|
-
|
164
|
-
|
165
|
-
``node node_modules\linny-r\server``
|
166
|
-
|
167
|
-
The response should be something similar to:
|
167
|
+
This response should be something similar to:
|
168
168
|
|
169
169
|
<pre>
|
170
170
|
Node.js server for Linny-R version 1.0
|
171
|
-
Node.js version: v18.
|
172
|
-
|
173
|
-
|
174
|
-
followed by some data on your Linny-R configuration.
|
175
|
-
The last line will be something like:
|
176
|
-
|
177
|
-
<pre>
|
178
|
-
Listening at: http://127.0.0.1:5050
|
171
|
+
Node.js version: v18.10.0
|
172
|
+
... etc.
|
179
173
|
</pre>
|
180
174
|
|
181
|
-
|
182
|
-
|
175
|
+
Meanwhile, your default web browser should have opened a tab for the local server URL,
|
176
|
+
which by default will be http://127.0.0.1:5050.
|
177
|
+
The Linny-R GUI should show in your browser window,
|
183
178
|
while in the CLI you should see a long series of server log messages like:
|
184
179
|
|
185
180
|
<pre>
|
package/console.js
CHANGED
@@ -42,22 +42,48 @@ SOFTWARE.
|
|
42
42
|
global.NODE = true;
|
43
43
|
|
44
44
|
const
|
45
|
-
VERSION_NUMBER = '1.1.2',
|
46
45
|
WORKING_DIRECTORY = process.cwd(),
|
47
46
|
path = require('path'),
|
48
|
-
|
47
|
+
MODULE_DIRECTORY = path.join(WORKING_DIRECTORY, 'node_modules', 'linny-r'),
|
49
48
|
// Load the required Node.js modules
|
49
|
+
child_process = require('child_process'),
|
50
50
|
fs = require('fs'),
|
51
51
|
os = require('os'),
|
52
52
|
readline = require('readline'),
|
53
53
|
// Get the platform name (win32, macOS, linux) of the user's computer
|
54
|
-
PLATFORM = os.platform()
|
54
|
+
PLATFORM = os.platform(),
|
55
|
+
// Get version of the installed Linny-R package
|
56
|
+
VERSION_INFO = getVersionInfo();
|
57
|
+
|
58
|
+
function getVersionInfo() {
|
59
|
+
// Reads version info from `package.json`
|
60
|
+
const info = {
|
61
|
+
current: 0,
|
62
|
+
current_time: 0,
|
63
|
+
latest: '0',
|
64
|
+
latest_time: 0,
|
65
|
+
up_to_date: false
|
66
|
+
};
|
67
|
+
try {
|
68
|
+
info.current = require('./package.json').version;
|
69
|
+
} catch(err) {
|
70
|
+
console.log('ERROR: Failed to read package.json');
|
71
|
+
console.log(err);
|
72
|
+
console.log('This indicates that Linny-R is not installed properly.');
|
73
|
+
process.exit();
|
74
|
+
}
|
75
|
+
// NOTE: unlike the Linny-R server, the console does not routinely
|
76
|
+
// check whether version is up-to-date is optional because this is
|
77
|
+
// a time-consuming action that would reduce multi-run performance.
|
78
|
+
// See command line options (much further down)
|
79
|
+
console.log('\nLinny-R Console version', info.current);
|
80
|
+
return info;
|
81
|
+
}
|
55
82
|
|
56
|
-
//
|
57
|
-
console.log('\nNode.js Linny-R console version', VERSION_NUMBER);
|
83
|
+
// Output some configuration information to the console
|
58
84
|
console.log('Node.js version:', process.version);
|
59
85
|
console.log('Platform:', PLATFORM, '(' + os.type() + ')');
|
60
|
-
console.log('
|
86
|
+
console.log('Module directory:', MODULE_DIRECTORY);
|
61
87
|
console.log('Working directory:', WORKING_DIRECTORY);
|
62
88
|
|
63
89
|
const
|
@@ -86,6 +112,7 @@ Usage: node console [options]
|
|
86
112
|
Possible options are:
|
87
113
|
channel=[identifier] will start listening at the specified channel
|
88
114
|
(FUTURE OPTION)
|
115
|
+
check will report whether current version is up-to-date
|
89
116
|
model=[path] will load model file in [path]
|
90
117
|
module=[name@repo] will load model [name] from repository [repo]
|
91
118
|
(if @repo is blank, repository "local host" is used)
|
@@ -125,9 +152,8 @@ function checkNodeModule(name) {
|
|
125
152
|
// XML-related functions defined in `linny-r-utils.js`
|
126
153
|
global.XML_PARSER = new DOMParser();
|
127
154
|
|
128
|
-
//
|
129
|
-
|
130
|
-
global.LINNY_R_VERSION = '1.1.0';
|
155
|
+
// Set the current version number
|
156
|
+
global.LINNY_R_VERSION = VERSION_INFO.current;
|
131
157
|
|
132
158
|
///////////////////////////////////////////////////////////////////////////////
|
133
159
|
// Class definitions must precede instatiation of Linny-R components //
|
@@ -675,17 +701,21 @@ function commandLineSettings() {
|
|
675
701
|
// Sets default settings, and then checks the command line arguments
|
676
702
|
const settings = {
|
677
703
|
cli_name: (PLATFORM.startsWith('win') ? 'Command Prompt' : 'Terminal'),
|
678
|
-
|
704
|
+
check: false,
|
679
705
|
preferred_solver: '',
|
706
|
+
run: false,
|
680
707
|
solver: '',
|
681
708
|
solver_path: '',
|
682
|
-
user_dir: path.join(WORKING_DIRECTORY, 'user')
|
709
|
+
user_dir: path.join(WORKING_DIRECTORY, 'user'),
|
710
|
+
verbose: false
|
683
711
|
};
|
684
712
|
let show_usage = process.argv.length < 3;
|
685
713
|
for(let i = 2; i < process.argv.length; i++) {
|
686
714
|
const lca = process.argv[i].toLowerCase();
|
687
715
|
if(lca === 'help' || lca === '?' || lca.startsWith('-')) {
|
688
716
|
show_usage = true;
|
717
|
+
} else if(lca === 'check') {
|
718
|
+
settings.check = true;
|
689
719
|
} else if(lca === 'run') {
|
690
720
|
settings.run = true;
|
691
721
|
} else if(lca === 'verbose') {
|
@@ -767,6 +797,8 @@ function commandLineSettings() {
|
|
767
797
|
console.log(usage);
|
768
798
|
process.exit();
|
769
799
|
}
|
800
|
+
// Perform version check only if asked for
|
801
|
+
if(settings.check) checkForUpdates();
|
770
802
|
// Check whether MILP solver(s) and Inkscape have been installed
|
771
803
|
const path_list = process.env.PATH.split(path.delimiter);
|
772
804
|
let gurobi_path = '',
|
@@ -876,6 +908,35 @@ function createWorkspace() {
|
|
876
908
|
return ws;
|
877
909
|
}
|
878
910
|
|
911
|
+
function checkForUpdates() {
|
912
|
+
// Check for newer version of the Node.js package `linny-r`
|
913
|
+
// NOTE: use `info` as shorthand for the global constant
|
914
|
+
const info = VERSION_INFO;
|
915
|
+
try {
|
916
|
+
const
|
917
|
+
json = child_process.execSync('npm show linny-r time version --json'),
|
918
|
+
obj = JSON.parse(json);
|
919
|
+
info.latest = obj.version;
|
920
|
+
info.latest_time = new Date(Date.parse(obj.time[info.latest]));
|
921
|
+
info.current_time = new Date(Date.parse(obj.time[info.current]));
|
922
|
+
info.up_to_date = info.current === info.latest;
|
923
|
+
} catch(err) {
|
924
|
+
// `latest` = 0 indicates that version check failed
|
925
|
+
info.latest = 0;
|
926
|
+
}
|
927
|
+
if(!info.latest) {
|
928
|
+
console.log('WARNING: Could not check for updates');
|
929
|
+
} else if(!info.up_to_date) {
|
930
|
+
console.log('UPDATE: Version ' + info.latest + ' was released on ' +
|
931
|
+
info.latest_time.toString());
|
932
|
+
} else {
|
933
|
+
console.log('Version ' + info.latest + ' is up-to-date (released on ' +
|
934
|
+
info.latest_time.toString() + ')');
|
935
|
+
}
|
936
|
+
// Return TRUE if current version is the latest one
|
937
|
+
return info.up_to_date;
|
938
|
+
}
|
939
|
+
|
879
940
|
// Initialize the solver
|
880
941
|
const SOLVER = new MILPSolver(SETTINGS, WORKSPACE);
|
881
942
|
/*
|
package/package.json
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
{
|
2
2
|
"name": "linny-r",
|
3
|
-
"version": "1.1.
|
3
|
+
"version": "1.1.7",
|
4
4
|
"description": "Executable graphical language with WYSIWYG editor for MILP models",
|
5
5
|
"main": "server.js",
|
6
6
|
"scripts": {
|
7
|
-
"
|
7
|
+
"postinstall": "node post-install.js",
|
8
8
|
"test": "echo \"Error: no test specified\" && exit 1"
|
9
9
|
},
|
10
10
|
"dependencies": {
|
package/post-install.js
CHANGED
@@ -76,7 +76,7 @@ try {
|
|
76
76
|
// Only write the script content if the file it does not yet exist
|
77
77
|
console.log('Creating launch script:', sp);
|
78
78
|
let code = lines.join(os.EOL);
|
79
|
-
if(PLATFORM.startsWith('win')) code = code.
|
79
|
+
if(PLATFORM.startsWith('win')) code = code.replaceAll('#', '::');
|
80
80
|
fs.writeFileSync(sp, code, 'utf8');
|
81
81
|
}
|
82
82
|
} catch(err) {
|
package/server.js
CHANGED
@@ -38,17 +38,11 @@ SOFTWARE.
|
|
38
38
|
///////////////////////////////////////////////////////////////////////////////
|
39
39
|
|
40
40
|
const
|
41
|
-
// The version number of this Linny-R server in Node.js
|
42
|
-
VERSION_NUMBER = '1.1.2',
|
43
|
-
|
44
|
-
// The URL of the official Linny-R website (with the most recent release)
|
45
|
-
PUBLIC_LINNY_R_URL = 'https://sysmod.tbm.tudelft.nl/linny-r',
|
46
|
-
|
47
41
|
// The current working directory (from where Node.js was started) is
|
48
42
|
// assumed to be the main directory
|
49
43
|
path = require('path'),
|
50
44
|
WORKING_DIRECTORY = process.cwd(),
|
51
|
-
|
45
|
+
MODULE_DIRECTORY = path.join(WORKING_DIRECTORY, 'node_modules', 'linny-r'),
|
52
46
|
|
53
47
|
// Get the required built-in Node.js modules
|
54
48
|
child_process = require('child_process'),
|
@@ -59,16 +53,57 @@ const
|
|
59
53
|
os = require('os'),
|
60
54
|
|
61
55
|
// Get the platform name (win32, macOS, linux) of the user's computer
|
62
|
-
PLATFORM = os.platform()
|
56
|
+
PLATFORM = os.platform(),
|
57
|
+
|
58
|
+
// Get version of the installed Linny-R package
|
59
|
+
VERSION_INFO = getVersionInfo();
|
60
|
+
|
61
|
+
function getVersionInfo() {
|
62
|
+
// Reads version info from `package.json`
|
63
|
+
const info = {
|
64
|
+
current: 0,
|
65
|
+
current_time: 0,
|
66
|
+
latest: '0',
|
67
|
+
latest_time: 0,
|
68
|
+
up_to_date: false
|
69
|
+
};
|
70
|
+
try {
|
71
|
+
info.current = require('./package.json').version;
|
72
|
+
} catch(err) {
|
73
|
+
console.log('ERROR: Failed to read package.json');
|
74
|
+
console.log(err);
|
75
|
+
console.log('This indicates that Linny-R is not installed properly.');
|
76
|
+
process.exit();
|
77
|
+
}
|
78
|
+
try {
|
79
|
+
const
|
80
|
+
json = child_process.execSync('npm show linny-r time version --json'),
|
81
|
+
obj = JSON.parse(json);
|
82
|
+
info.latest = obj.version;
|
83
|
+
info.latest_time = new Date(Date.parse(obj.time[info.latest]));
|
84
|
+
info.current_time = new Date(Date.parse(obj.time[info.current]));
|
85
|
+
info.up_to_date = info.current === info.latest;
|
86
|
+
} catch(err) {
|
87
|
+
// `latest` = 0 indicates that version check failed
|
88
|
+
info.latest = 0;
|
89
|
+
}
|
90
|
+
console.log('\nNode.js server for Linny-R version', info.current);
|
91
|
+
if(!info.latest) {
|
92
|
+
console.log('WARNING: Could not check for updates');
|
93
|
+
} else if(!info.up_to_date) {
|
94
|
+
console.log('UPDATE: Version ' + info.latest + ' was released on ' +
|
95
|
+
info.latest_time.toString());
|
96
|
+
}
|
97
|
+
return info;
|
98
|
+
}
|
63
99
|
|
64
|
-
//
|
65
|
-
console.log('\nNode.js server for Linny-R version', VERSION_NUMBER);
|
100
|
+
// Output some configuration information to the console
|
66
101
|
console.log('Node.js version:', process.version);
|
67
102
|
console.log('Platform:', PLATFORM, '(' + os.type() + ')');
|
68
|
-
console.log('
|
103
|
+
console.log('Module directory:', MODULE_DIRECTORY);
|
69
104
|
console.log('Working directory:', WORKING_DIRECTORY);
|
70
105
|
|
71
|
-
// Only
|
106
|
+
// Only now require the Node.js modules that are not "built-in"
|
72
107
|
|
73
108
|
const
|
74
109
|
{ DOMParser } = checkNodeModule('@xmldom/xmldom');
|
@@ -83,12 +118,10 @@ function checkNodeModule(name) {
|
|
83
118
|
}
|
84
119
|
}
|
85
120
|
|
121
|
+
|
86
122
|
// Load class MILPSolver
|
87
123
|
const MILPSolver = require('./static/scripts/linny-r-milp.js');
|
88
124
|
|
89
|
-
///////////////////////////////////////////////////////////////////////////////
|
90
|
-
// Code executed at start-up continues here //
|
91
|
-
///////////////////////////////////////////////////////////////////////////////
|
92
125
|
|
93
126
|
// Default settings are used unless these are overruled by arguments on the
|
94
127
|
// command line. Possible arguments are:
|
@@ -135,54 +168,25 @@ if(SETTINGS.launch) {
|
|
135
168
|
});
|
136
169
|
}
|
137
170
|
|
138
|
-
// Version check
|
139
|
-
//
|
140
|
-
// This section of code implements server responses to
|
141
|
-
// browser immediately after loading the GUI page (`index.html`)
|
142
|
-
// user clicks on the link "Version ..." below the Linny-R logo in the upper
|
143
|
-
// left corner of the GUI page.
|
144
|
-
|
145
|
-
const
|
146
|
-
|
147
|
-
VERSION_MESSAGE = `<!DOCTYPE html>
|
148
|
-
<html lang="en-US">
|
149
|
-
<head>
|
150
|
-
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
151
|
-
<title>Linny-R version information</title>
|
152
|
-
<link rel="shortcut icon" type="image/png" href="../images/icon.png">
|
153
|
-
<style>
|
154
|
-
body {
|
155
|
-
font-family: sans-serif;
|
156
|
-
font-size: 16px;
|
157
|
-
}
|
158
|
-
#linny-r-logo {
|
159
|
-
height: 40px;
|
160
|
-
margin-bottom: -10px;
|
161
|
-
}
|
162
|
-
</style>
|
163
|
-
</head>
|
164
|
-
<body>
|
165
|
-
<img id="linny-r-logo" src="../images/logo.png">
|
166
|
-
%1%
|
167
|
-
</body>
|
168
|
-
</html>`,
|
169
|
-
|
170
|
-
NO_INTERNET_MESSAGE = `
|
171
|
-
<h3>Version check failed</h3>
|
172
|
-
<p>
|
173
|
-
No contact with the on-line Linny-R server --
|
174
|
-
please check your internet connection.
|
175
|
-
</p>`,
|
176
|
-
|
177
|
-
UP_TO_DATE_MESSAGE = `
|
178
|
-
<h3>Version JS-%1% is up-to-date</h3>
|
179
|
-
<p>Released on %2%</p>`,
|
171
|
+
// Version check functionality
|
172
|
+
// ===========================
|
173
|
+
// This section of code implements server responses to the request made
|
174
|
+
// by the browser immediately after loading the GUI page (`index.html`)
|
180
175
|
|
181
|
-
|
182
|
-
|
183
|
-
|
176
|
+
function autoCheck(res) {
|
177
|
+
// Serves a string with the current version number plus info on a
|
178
|
+
// newer release if this is available
|
179
|
+
let check = VERSION_INFO.current + '|';
|
180
|
+
if(VERSION_INFO.up_to_date) {
|
181
|
+
check += 'up-to-date';
|
182
|
+
} else {
|
183
|
+
check += VERSION_INFO.latest + '|' + VERSION_INFO.latest_time;
|
184
|
+
}
|
185
|
+
servePlainText(res, check);
|
186
|
+
}
|
184
187
|
|
185
|
-
|
188
|
+
// HTML page to show then the server is shut down by the user
|
189
|
+
const SHUTDOWN_MESSAGE = `<!DOCTYPE html>
|
186
190
|
<html lang="en-US">
|
187
191
|
<head>
|
188
192
|
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
@@ -197,12 +201,14 @@ SHUTDOWN_MESSAGE = `<!DOCTYPE html>
|
|
197
201
|
</head>
|
198
202
|
<body>
|
199
203
|
<h3>Linny-R server (127.0.0.1) is shutting down</h3>
|
200
|
-
<p>To
|
201
|
-
|
202
|
-
|
204
|
+
<p>To restart Linny-R, switch to your ${SETTINGS.cli_name} window
|
205
|
+
and there at the prompt` +
|
206
|
+
(VERSION_INFO.up_to_date ? '' : `
|
207
|
+
first type:</p>
|
203
208
|
<p> <tt>npm update linny-r</tt><p>
|
204
|
-
|
205
|
-
|
209
|
+
to upgrade to Linny-R version ${VERSION_INFO.latest}, and then`) +
|
210
|
+
` type:</p>
|
211
|
+
<p> <tt>node node_modules\linny-r\server</tt></p>
|
206
212
|
<p>
|
207
213
|
Then switch back to this window, and click
|
208
214
|
<button type="button"
|
@@ -213,104 +219,6 @@ SHUTDOWN_MESSAGE = `<!DOCTYPE html>
|
|
213
219
|
</body>
|
214
220
|
</html>`;
|
215
221
|
|
216
|
-
|
217
|
-
function compareVersions(v1, v2) {
|
218
|
-
// Robust comparison of version numbers
|
219
|
-
nrs1 = (v1 + '.0.0.0').split('.');
|
220
|
-
nrs2 = (v2 + '.0.0.0').split('.');
|
221
|
-
for(i = 0; i < 4; i++) {
|
222
|
-
nrs1[i] = nrs1[i].padStart(6, '0');
|
223
|
-
nrs2[i] = nrs2[i].padStart(6, '0');
|
224
|
-
}
|
225
|
-
v1 = nrs1.slice(0, 4).join('.');
|
226
|
-
v2 = nrs2.slice(0, 4).join('.');
|
227
|
-
if(v1 > v2) return 1;
|
228
|
-
if(v1 < v2) return -1;
|
229
|
-
return 0;
|
230
|
-
}
|
231
|
-
|
232
|
-
function checkVersion(res, version) {
|
233
|
-
// Check whether current version is the most recent
|
234
|
-
console.log('Check version:', version);
|
235
|
-
if(!version) {
|
236
|
-
serveHTML(res, '<h3>No version number specified</h3>');
|
237
|
-
return;
|
238
|
-
}
|
239
|
-
version = version.split('-').pop();
|
240
|
-
getTextFromURL(PUBLIC_LINNY_R_URL + '/check-version/?info',
|
241
|
-
// The `on_ok` function
|
242
|
-
(data, res) => {
|
243
|
-
const
|
244
|
-
info = data.split('|');
|
245
|
-
// Should be [version, release date]
|
246
|
-
if(info.length === 2) {
|
247
|
-
if(compareVersions(version, info[0]) >= 0) {
|
248
|
-
message = UP_TO_DATE_MESSAGE.replace(
|
249
|
-
'%1%', info[0]).replace('%2%', info[1]);
|
250
|
-
} else {
|
251
|
-
message = DOWNLOAD_MESSAGE.replace(
|
252
|
-
'%1%', info[0]).replace('%2%', info[1]);
|
253
|
-
}
|
254
|
-
serveHTML(res, VERSION_MESSAGE.replace('%1%', message));
|
255
|
-
}
|
256
|
-
},
|
257
|
-
// The `on_error` function
|
258
|
-
(error, res) => {
|
259
|
-
console.log(error);
|
260
|
-
serveHTML(res, NO_INTERNET_MESSAGE);
|
261
|
-
},
|
262
|
-
// The response object
|
263
|
-
res);
|
264
|
-
}
|
265
|
-
|
266
|
-
function autoCheck(res) {
|
267
|
-
// Compares the version number in the static file `index.html`
|
268
|
-
// with the version number in the corresponding file on the official
|
269
|
-
// Linny-R website, and serves a status string that indicates whether
|
270
|
-
// a newer release is available
|
271
|
-
const gpath = path.join(MAIN_DIRECTORY, 'static', 'index.html');
|
272
|
-
// Read the globals script
|
273
|
-
fs.readFile(gpath, 'utf8', (err, data) => {
|
274
|
-
let v_match = null;
|
275
|
-
if(err) {
|
276
|
-
console.log('WARNING: Failed to read file', gpath);
|
277
|
-
} else {
|
278
|
-
// Extract the version number
|
279
|
-
v_match = data.match(/LINNY_R_VERSION = '(.+?)'/);
|
280
|
-
if(!v_match) console.log('WARNING: No version number found');
|
281
|
-
}
|
282
|
-
if(!v_match) {
|
283
|
-
servePlainText(res,'no version');
|
284
|
-
return;
|
285
|
-
}
|
286
|
-
let version = v_match[1];
|
287
|
-
// Get the current `index.html` file from the official Linny-R server
|
288
|
-
getTextFromURL(PUBLIC_LINNY_R_URL + '/check-version/?info',
|
289
|
-
// The `on_ok` function: compare versions and return status
|
290
|
-
(data, res) => {
|
291
|
-
let check = 'no match';
|
292
|
-
const
|
293
|
-
info = data.split('|');
|
294
|
-
// Should be [version, release date]
|
295
|
-
if(info.length === 2) {
|
296
|
-
if(compareVersions(version, info[0]) >= 0) {
|
297
|
-
check = 'up-to-date';
|
298
|
-
} else {
|
299
|
-
check = info[0] + '|' + info[1];
|
300
|
-
}
|
301
|
-
}
|
302
|
-
servePlainText(res, check);
|
303
|
-
},
|
304
|
-
// The `on_error` function
|
305
|
-
(error, res) => {
|
306
|
-
console.log(error);
|
307
|
-
servePlainText(res, 'no match');
|
308
|
-
},
|
309
|
-
// The response object
|
310
|
-
res);
|
311
|
-
});
|
312
|
-
}
|
313
|
-
|
314
222
|
// Repository functionality
|
315
223
|
// ========================
|
316
224
|
// For repository services, the Linny-R JavaScript application communicates with
|
@@ -1111,10 +1019,6 @@ function processRequest(req, res, cmd, data) {
|
|
1111
1019
|
SERVER.close();
|
1112
1020
|
} else if(cmd === '/auto-check') {
|
1113
1021
|
autoCheck(res);
|
1114
|
-
} else if(cmd === '/auto-update') {
|
1115
|
-
autoUpdate(res);
|
1116
|
-
} else if(cmd === '/check-version') {
|
1117
|
-
checkVersion(res, (new URLSearchParams(data)).get('v'));
|
1118
1022
|
} else if(cmd === '/repo/') {
|
1119
1023
|
repo(res, new URLSearchParams(data));
|
1120
1024
|
} else if(cmd === '/load-data/') {
|
@@ -1172,7 +1076,7 @@ function serveStaticFile(res, path) {
|
|
1172
1076
|
console.log('Static file:', path);
|
1173
1077
|
path = '/static' + path;
|
1174
1078
|
}
|
1175
|
-
fs.readFile(
|
1079
|
+
fs.readFile(MODULE_DIRECTORY + path, (err, data) => {
|
1176
1080
|
if(err) {
|
1177
1081
|
console.log(err);
|
1178
1082
|
res.writeHead(404);
|
@@ -1536,7 +1440,7 @@ function createLaunchScript() {
|
|
1536
1440
|
// Only write the script content if the file it does not yet exist
|
1537
1441
|
console.log('Creating launch script:', sp);
|
1538
1442
|
let code = lines.join(os.EOL);
|
1539
|
-
if(PLATFORM.startsWith('win')) code = code.
|
1443
|
+
if(PLATFORM.startsWith('win')) code = code.replaceAll('#', '::');
|
1540
1444
|
fs.writeFileSync(sp, code, 'utf8');
|
1541
1445
|
}
|
1542
1446
|
} catch(err) {
|
package/static/index.html
CHANGED
@@ -54,16 +54,17 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
54
54
|
<!-- NOTE: do not display the page until after software update check -->
|
55
55
|
<style>body { display: none; }</style>
|
56
56
|
<script>
|
57
|
+
// Create global variables
|
57
58
|
var
|
58
59
|
// NODE = false indicates that modules need not export their properties
|
59
60
|
NODE = false,
|
60
61
|
// Version number and release date
|
61
|
-
LINNY_R_VERSION = '
|
62
|
-
VERSION_RELEASE_DATE =
|
62
|
+
LINNY_R_VERSION = '0',
|
63
|
+
VERSION_RELEASE_DATE = 0,
|
63
64
|
// Linny-R server hosting public channels
|
64
65
|
PUBLIC_LINNY_R_URL = 'https://sysmod.tbm.tudelft.nl/linny-r',
|
65
66
|
// Create the XML parser
|
66
|
-
XML_PARSER = new DOMParser()
|
67
|
+
XML_PARSER = new DOMParser(),
|
67
68
|
// NOTE: global variables will be initialized when page has loaded
|
68
69
|
// The controller object (User Interface)
|
69
70
|
UI = null,
|
@@ -86,14 +87,14 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
86
87
|
// Stack for undo/redo operations
|
87
88
|
UNDO_STACK = null,
|
88
89
|
// The virtual machine
|
89
|
-
VM = null
|
90
|
+
VM = null,
|
90
91
|
|
91
92
|
// Load audio files
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
93
|
+
SOUNDS = {
|
94
|
+
notification: new Audio('sounds/notification.wav'),
|
95
|
+
warning: new Audio('sounds/warning.wav'),
|
96
|
+
error: new Audio('sounds/error.wav')
|
97
|
+
};
|
97
98
|
|
98
99
|
|
99
100
|
function loadLinnyR() {
|
@@ -149,14 +150,17 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
149
150
|
console.log('Version check:', data);
|
150
151
|
const info = data.split('|');
|
151
152
|
if(info.length > 1) {
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
153
|
+
LINNY_R_VERSION = info[0];
|
154
|
+
if(info[1] !== 'up-to-date') {
|
155
|
+
UI.check_update_modal.element('msg').innerHTML = [
|
156
|
+
'<a href="https://sysmod.tbm.tudelft.nl/linny-r/docs/?15" ',
|
157
|
+
'target="_blank">Version <strong>',
|
158
|
+
info[1], '</strong></a> released on ', info[2],
|
159
|
+
' can be installed.'].join('');
|
160
|
+
UI.check_update_modal.show();
|
161
|
+
UI.check_update_modal.element('buttons').style.display = 'block';
|
162
|
+
}
|
163
|
+
} else {
|
160
164
|
UI.warn('Version check failed: "' + data + '"');
|
161
165
|
}
|
162
166
|
})
|