summaryrefslogtreecommitdiffstatshomepage
path: root/scripts/minimaws
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2019-12-16 01:46:47 +1100
committer Vas Crabb <vas@vastheman.com>2019-12-16 01:46:47 +1100
commitf43e9dbaa28ca8241b9b27d5dbbb5a6afd96553e (patch)
treee7e56370bdc98bf3cdf737ad7ed745361fa740e1 /scripts/minimaws
parentb99eb3774e657f4967f4676eba9e9593cbe81ff6 (diff)
minimaws: add software list support to web-based romident
(nw) also removed unused member that was breaking clang builds
Diffstat (limited to 'scripts/minimaws')
-rw-r--r--scripts/minimaws/lib/assets/romident.js213
-rw-r--r--scripts/minimaws/lib/dbaccess.py8
-rw-r--r--scripts/minimaws/lib/htmltmpl.py1
-rw-r--r--scripts/minimaws/lib/wsgiserve.py10
4 files changed, 214 insertions, 18 deletions
diff --git a/scripts/minimaws/lib/assets/romident.js b/scripts/minimaws/lib/assets/romident.js
index 20d5d2c2ba6..0dca192094e 100644
--- a/scripts/minimaws/lib/assets/romident.js
+++ b/scripts/minimaws/lib/assets/romident.js
@@ -5,6 +5,8 @@ var matched_names = new Array();
var unmatched_names = new Array();
var dump_info = Object.create(null);
var machine_info = Object.create(null);
+var softwarelist_info = Object.create(null);
+var software_info = Object.create(null);
var crc_table = new Uint32Array(256);
for (var i = 0; i < 256; i++)
@@ -97,6 +99,34 @@ function add_matches(table, names, matches)
}
+function add_software_matches(table, names, part, matches)
+{
+ for (var i = 0; i < names.length; i++)
+ {
+ var row = table.appendChild(document.createElement('tr'));
+ var name = row.appendChild(document.createElement('th'));
+ name.textContent = names[i];
+ if (matches !== null)
+ {
+ name.setAttribute('rowspan', matches.length);
+ row.appendChild(document.createElement('td')).textContent = part;
+ row.appendChild(document.createElement('td')).textContent = matches[0].name;
+ var bad = row.appendChild(document.createElement('td'));
+ if (matches[0].bad)
+ bad.textContent = 'BAD';
+ for (var j = 1; j < matches.length; j++)
+ {
+ row = table.appendChild(document.createElement('tr'));
+ row.appendChild(document.createElement('td')).textContent = matches[j].name;
+ bad = row.appendChild(document.createElement('td'));
+ if (matches[j].bad)
+ bad.textContent = 'BAD';
+ }
+ }
+ }
+}
+
+
function add_unmatched(names, crc, sha1)
{
var table;
@@ -159,6 +189,53 @@ function get_machine_table(shortname, description)
}
+function get_softwarelist_div(shortname, description)
+{
+ if (Object.hasOwnProperty.call(softwarelist_info, shortname))
+ {
+ return softwarelist_info[shortname];
+ }
+ else
+ {
+ software_info[shortname] = Object.create(null)
+ var div = document.getElementById('div-software');
+ if (!div.hasChildNodes())
+ {
+ var heading = div.appendChild(document.createElement('h2'));
+ heading.textContent = 'Software';
+ }
+ div = div.appendChild(document.createElement('div'));
+ var heading = div.appendChild(document.createElement('h3'));
+ var link = heading.appendChild(document.createElement('a'));
+ link.textContent = description;
+ link.setAttribute('href', appurl + 'softwarelist/' + encodeURIComponent(shortname));
+ softwarelist_info[shortname] = div;
+ return div;
+ }
+}
+
+
+function get_software_table(softwarelist, shortname, description)
+{
+ if (Object.hasOwnProperty.call(software_info, softwarelist) && Object.hasOwnProperty.call(software_info[softwarelist], shortname))
+ {
+ return software_info[softwarelist][shortname];
+ }
+ else
+ {
+ var div = softwarelist_info[softwarelist];
+ var heading = div.appendChild(document.createElement('h4'));
+ var link = heading.appendChild(document.createElement('a'));
+ link.textContent = description;
+ link.setAttribute('href', appurl + 'softwarelist/' + encodeURIComponent(softwarelist) + '/' + encodeURIComponent(shortname));
+ var table = div.appendChild(document.createElement('table'));
+ software_info[softwarelist][shortname] = table;
+ add_software_matches(table, matched_names, null, null);
+ return table;
+ }
+}
+
+
function request_dumps(name, group, crc, sha1, url, progress)
{
var req = new XMLHttpRequest();
@@ -169,34 +246,123 @@ function request_dumps(name, group, crc, sha1, url, progress)
if (req.status == 200)
{
var machines = Object.create(null);
+ var software = Object.create(null);
var matched = Object.keys(req.response.machines);
+ var softwarelists = Object.keys(req.response.software);
+
if (matched.length > 0)
{
Object.keys(machine_info).forEach(
function (shortname)
{
- var table = machine_info[shortname];
+ var machine_table = machine_info[shortname];
if (Object.hasOwnProperty.call(req.response.machines, shortname))
{
machines[shortname] = req.response.machines[shortname].matches;
- add_matches(table, group.names, req.response.machines[shortname].matches);
+ add_matches(machine_table, group.names, req.response.machines[shortname].matches);
}
else
{
- add_matches(table, group.names, null);
+ add_matches(machine_table, group.names, null);
}
});
+ if (softwarelists.length <= 0)
+ {
+ Object.keys(software_info).forEach(
+ function (listname)
+ {
+ Object.keys(software_info[listname]).forEach(
+ function (softwarename)
+ {
+ var software_table = software_info[listname][softwarename];
+ add_software_matches(software_table, group.names, null, null);
+ });
+ });
+ }
matched.forEach(
function (shortname)
{
if (!Object.hasOwnProperty.call(machine_info, shortname))
{
- var info = req.response.machines[shortname];
- var table = get_machine_table(shortname, info.description);
+ var machine_details = req.response.machines[shortname];
+ var machine_table = get_machine_table(shortname, machine_details.description);
machines[shortname] = req.response.machines[shortname].matches;
- add_matches(table, group.names, info.matches);
+ add_matches(machine_table, group.names, machine_details.matches);
}
});
+ }
+
+ if (softwarelists.length > 0)
+ {
+ if (matched.length <= 0)
+ {
+ Object.keys(machine_info).forEach(
+ function (shortname)
+ {
+ var machine_table = machine_info[shortname];
+ add_matches(machine_table, group.names, null);
+ });
+ }
+ Object.keys(software_info).forEach(
+ function (listname)
+ {
+ var haslist = Object.hasOwnProperty.call(req.response.software, listname);
+ Object.keys(software_info[listname]).forEach(
+ function (softwarename)
+ {
+ var software_table = software_info[listname][softwarename];
+ if (haslist && Object.hasOwnProperty.call(req.response.software[listname].software, softwarename))
+ {
+ if (!Object.hasOwnProperty.call(software, listname))
+ software[listname] = Object.create(null);
+ if (!Object.hasOwnProperty.call(software[listname], softwarename))
+ software[listname][softwarename] = Object.create(null);
+ var software_details = req.response.software[listname].software[softwarename];
+ Object.keys(software_details.parts).forEach(
+ function (partname)
+ {
+ var matches = software_details.parts[partname].matches;
+ software[listname][softwarename][partname] = matches;
+ add_software_matches(software_table, group.names, partname, matches);
+ });
+ }
+ else
+ {
+ add_software_matches(software_table, group.names, null, null);
+ }
+ });
+ });
+ softwarelists.forEach(
+ function (listname)
+ {
+ var haslist = Object.hasOwnProperty.call(software_info, listname);
+ var softwarelist_details = req.response.software[listname];
+ var softwarelist_div = get_softwarelist_div(listname, softwarelist_details.description);
+ Object.keys(softwarelist_details.software).forEach(
+ function (softwarename)
+ {
+ if (!haslist || !Object.hasOwnProperty.call(software_info[listname], softwarename))
+ {
+ if (!Object.hasOwnProperty.call(software, listname))
+ software[listname] = Object.create(null);
+ if (!Object.hasOwnProperty.call(software[listname], softwarename))
+ software[listname][softwarename] = Object.create(null);
+ var software_details = softwarelist_details.software[softwarename];
+ var software_table = get_software_table(listname, softwarename, software_details.description);
+ Object.keys(software_details.parts).forEach(
+ function (partname)
+ {
+ var matches = software_details.parts[partname].matches;
+ software[listname][softwarename][partname] = matches;
+ add_software_matches(software_table, group.names, partname, matches);
+ });
+ }
+ });
+ });
+ }
+
+ if ((matched.length > 0) | (softwarelists.length > 0))
+ {
for (var i = 0; i < group.names.length; i++)
matched_names.push(group.names[i]);
}
@@ -204,7 +370,9 @@ function request_dumps(name, group, crc, sha1, url, progress)
{
add_unmatched(group.names, crc, sha1);
}
+
group.machines = machines;
+ group.software = software;
progress.parentNode.removeChild(progress);
}
else
@@ -247,18 +415,43 @@ function add_name(group, name, crc, sha1)
if (group.hasOwnProperty('machines'))
{
var machines = group.machines;
+ var software = group.software;
var names = [ name ];
- if (Object.keys(machines).length > 0)
+ if ((Object.keys(machines).length > 0) || (Object.keys(software).length > 0))
{
Object.keys(machine_info).forEach(
function (shortname)
{
- var table = machine_info[shortname];
+ var machine_table = machine_info[shortname];
if (Object.hasOwnProperty.call(machines, shortname))
- add_matches(table, names, machines[shortname]);
+ add_matches(machine_table, names, machines[shortname]);
else
- add_matches(table, names, null);
+ add_matches(machine_table, names, null);
});
+
+ Object.keys(software_info).forEach(
+ function (listname)
+ {
+ var haslist = Object.hasOwnProperty.call(software, listname);
+ Object.keys(software_info[listname]).forEach(
+ function (softwarename)
+ {
+ var software_table = software_info[listname][softwarename];
+ if (haslist && Object.hasOwnProperty.call(software[listname], softwarename))
+ {
+ Object.keys(software[listname][softwarename]).forEach(
+ function (partname)
+ {
+ add_software_matches(software_table, names, partname, software[listname][softwarename][partname]);
+ });
+ }
+ else
+ {
+ add_software_matches(software_table, names, null, null);
+ }
+ });
+ });
+
matched_names.push(name);
}
else
diff --git a/scripts/minimaws/lib/dbaccess.py b/scripts/minimaws/lib/dbaccess.py
index 80bfabb92a5..68bdc98901b 100644
--- a/scripts/minimaws/lib/dbaccess.py
+++ b/scripts/minimaws/lib/dbaccess.py
@@ -716,15 +716,15 @@ class QueryCursor(object):
def get_softwarelist_software(self, id, pattern):
if pattern is not None:
return self.dbcurs.execute(
- 'SELECT software.shortname AS shortname, software.description AS description, software.year AS year, software.publisher AS publisher, software.supported AS supported, COUNT(*) AS parts ' \
- 'FROM software JOIN softwarepart ON software.id = softwarepart.software ' \
+ 'SELECT software.shortname AS shortname, software.description AS description, software.year AS year, software.publisher AS publisher, software.supported AS supported, COUNT(DISTINCT softwarepart.id) AS parts, COUNT(softwareromdump.rom) + COUNT(softwarediskdump.disk) AS baddumps ' \
+ 'FROM software JOIN softwarepart ON software.id = softwarepart.software LEFT JOIN softwareromdump ON softwarepart.id = softwareromdump.part AND softwareromdump.bad = 1 LEFT JOIN softwarediskdump ON softwarepart.id = softwarediskdump.part AND softwarediskdump.bad = 1 ' \
'WHERE software.softwarelist = ? AND software.shortname GLOB ? ' \
'GROUP BY software.id',
(id, pattern))
else:
return self.dbcurs.execute(
- 'SELECT software.shortname AS shortname, software.description AS description, software.year AS year, software.publisher AS publisher, software.supported AS supported, COUNT(*) AS parts ' \
- 'FROM software JOIN softwarepart ON software.id = softwarepart.software ' \
+ 'SELECT software.shortname AS shortname, software.description AS description, software.year AS year, software.publisher AS publisher, software.supported AS supported, COUNT(DISTINCT softwarepart.id) AS parts, COUNT(softwareromdump.rom) + COUNT(softwarediskdump.disk) AS baddumps ' \
+ 'FROM software JOIN softwarepart ON software.id = softwarepart.software LEFT JOIN softwareromdump ON softwarepart.id = softwareromdump.part AND softwareromdump.bad = 1 LEFT JOIN softwarediskdump ON softwarepart.id = softwarediskdump.part AND softwarediskdump.bad = 1 ' \
'WHERE software.softwarelist = ? ' \
'GROUP BY software.id',
(id, ))
diff --git a/scripts/minimaws/lib/htmltmpl.py b/scripts/minimaws/lib/htmltmpl.py
index 5ba004a03b2..b7354ae403a 100644
--- a/scripts/minimaws/lib/htmltmpl.py
+++ b/scripts/minimaws/lib/htmltmpl.py
@@ -241,6 +241,7 @@ SOFTWARELIST_ROW = string.Template(
' <td>${publisher}</td>\n' \
' <td>${supported}</td>\n' \
' <td style="text-align: right">${parts}</td>\n' \
+ ' <td style="text-align: right">${baddumps}</td>\n' \
' </tr>\n')
diff --git a/scripts/minimaws/lib/wsgiserve.py b/scripts/minimaws/lib/wsgiserve.py
index cbf4888e511..2a6a2e35325 100644
--- a/scripts/minimaws/lib/wsgiserve.py
+++ b/scripts/minimaws/lib/wsgiserve.py
@@ -47,7 +47,7 @@ class HandlerBase(object):
self.start_response = start_response
def error_page(self, code):
- yield htmltmpl.ERROR_PAGE.substitute(code=cgi.escape('%d' % code), message=cgi.escape(self.STATUS_MESSAGE[code])).encode('utf-8')
+ yield htmltmpl.ERROR_PAGE.substitute(code=cgi.escape('%d' % (code, )), message=cgi.escape(self.STATUS_MESSAGE[code])).encode('utf-8')
class ErrorPageHandler(HandlerBase):
@@ -371,7 +371,7 @@ class SourceFileHandler(QueryPageHandler):
for filename, machines in self.dbcurs.get_sourcefiles(pattern):
yield htmltmpl.SOURCEFILE_LIST_ROW.substitute(
sourcefile=self.linked_title(filename, True),
- machines=cgi.escape('%d' % machines)).encode('utf-8')
+ machines=cgi.escape('%d' % (machines, ))).encode('utf-8')
yield ' </tbody>\n</table>\n<script>make_table_sortable(document.getElementById("tbl-sourcefiles"));</script>\n</body>\n</html>\n'.encode('utf-8')
def sourcefile_page(self, id):
@@ -486,7 +486,7 @@ class SoftwareListHandler(QueryPageHandler):
href=self.softwarelist_href(shortname),
shortname=cgi.escape(shortname),
description=cgi.escape(description),
- total=cgi.escape('%d' % total),
+ total=cgi.escape('%d' % (total, )),
supported=cgi.escape('%.1f%%' % (supported * 100.0 / (total or 1), )),
partiallysupported=cgi.escape('%.1f%%' % (partiallysupported * 100.0 / (total or 1), )),
unsupported=cgi.escape('%.1f%%' % (unsupported * 100.0 / (total or 1), ))).encode('utf-8')
@@ -525,6 +525,7 @@ class SoftwareListHandler(QueryPageHandler):
' <th>Publisher</th>\n' \
' <th>Supported</th>\n' \
' <th class="numeric">Parts</th>\n' \
+ ' <th class="numeric">Bad dumps</th>\n' \
' </tr>\n' \
' </thead>\n' \
' <tbody>\n'.encode('utf-8')
@@ -573,7 +574,8 @@ class SoftwareListHandler(QueryPageHandler):
year=cgi.escape(software_info['year']),
publisher=cgi.escape(software_info['publisher']),
supported=cgi.escape('Yes' if software_info['supported'] == 0 else 'Partial' if software_info['supported'] == 1 else 'No'),
- parts=cgi.escape('%d' % software_info['parts'])).encode('utf-8')
+ parts=cgi.escape('%d' % (software_info['parts'], )),
+ baddumps=cgi.escape('%d' % (software_info['baddumps'], ))).encode('utf-8')
class RomIdentHandler(QueryPageHandler):