This commit is contained in:
Philip Schell 2019-08-23 14:09:52 +02:00
parent 28bf1c585b
commit 26bbf9c6c5
4 changed files with 80 additions and 114 deletions

View File

@ -15,8 +15,8 @@ namespace Fraunhofer.Fit.IoT.LoraMap {
class Server : Webserver { class Server : Webserver {
private readonly SortedDictionary<String, PositionItem> positions = new SortedDictionary<String, PositionItem>(); private readonly SortedDictionary<String, PositionItem> positions = new SortedDictionary<String, PositionItem>();
private readonly SortedDictionary<String, AlarmItem> alarms = new SortedDictionary<String, AlarmItem>(); private readonly SortedDictionary<String, AlarmItem> alarms = new SortedDictionary<String, AlarmItem>();
private readonly SortedDictionary<String, Camera> cameras = new SortedDictionary<String, Camera>(); private readonly SortedDictionary<String, Camera> counter = new SortedDictionary<String, Camera>();
private readonly SortedDictionary<String, Crowd> crowds = new SortedDictionary<String, Crowd>(); private readonly SortedDictionary<String, Crowd> density = new SortedDictionary<String, Crowd>();
private readonly SortedDictionary<String, Fight> fights = new SortedDictionary<String, Fight>(); private readonly SortedDictionary<String, Fight> fights = new SortedDictionary<String, Fight>();
private JsonData marker; private JsonData marker;
private readonly Settings settings; private readonly Settings settings;
@ -26,6 +26,8 @@ namespace Fraunhofer.Fit.IoT.LoraMap {
private readonly Object lockData = new Object(); private readonly Object lockData = new Object();
private readonly Object lockPanic = new Object(); private readonly Object lockPanic = new Object();
private readonly Object lockFight = new Object(); private readonly Object lockFight = new Object();
private readonly Object lockCount = new Object();
private readonly Object lockDensy = new Object();
public Server(ADataBackend backend, Dictionary<String, String> settings, InIReader requests) : base(backend, settings, requests) { public Server(ADataBackend backend, Dictionary<String, String> settings, InIReader requests) : base(backend, settings, requests) {
this.logger.SetPath(settings["loggingpath"]); this.logger.SetPath(settings["loggingpath"]);
@ -96,20 +98,24 @@ namespace Fraunhofer.Fit.IoT.LoraMap {
Console.WriteLine("PANIC erhalten!"); Console.WriteLine("PANIC erhalten!");
} else if(Camera.CheckJson(d) && ((String)mqtt.From).Contains("camera/count")) { } else if(Camera.CheckJson(d) && ((String)mqtt.From).Contains("camera/count")) {
String cameraid = Camera.GetId(d); String cameraid = Camera.GetId(d);
if(this.cameras.ContainsKey(cameraid)) { lock (this.lockCount) {
this.cameras[cameraid].Update(d); if (this.counter.ContainsKey(cameraid)) {
} else { this.counter[cameraid].Update(d);
this.cameras.Add(cameraid, new Camera(d)); } else {
this.counter.Add(cameraid, new Camera(d));
}
} }
} else if((((String)mqtt.From).Contains("sfn/crowd_density_local") && Crowd.CheckJsonCrowdDensityLocal(d)) || } else if(((((String)mqtt.From).Contains("sfn/crowd_density_local") || ((String)mqtt.From).Contains("camera/crowd")) && Crowd.CheckJsonCrowdDensityLocal(d)) ||
(((String)mqtt.From).Contains("sfn/flow") && Crowd.CheckJsonFlow(d))) { (((String)mqtt.From).Contains("sfn/flow") && Crowd.CheckJsonFlow(d))) {
String cameraid = Crowd.GetId(d); String cameraid = Crowd.GetId(d);
if(this.crowds.ContainsKey(cameraid)) { lock (this.lockDensy) {
this.crowds[cameraid].Update(d); if (this.density.ContainsKey(cameraid)) {
} else { this.density[cameraid].Update(d);
this.crowds.Add(cameraid, new Crowd(d)); } else {
this.density.Add(cameraid, new Crowd(d));
}
} }
} else if(((String)mqtt.From).Contains("camera/fighting_detection") && Fight.CheckJsonFightingDetection(d)) { } else if((((String)mqtt.From).Contains("camera/fighting_detection") || ((String)mqtt.From).Contains("sfn/fighting_detection")) && Fight.CheckJsonFightingDetection(d)) {
String cameraid = Fight.GetId(d); String cameraid = Fight.GetId(d);
lock (this.lockFight) { lock (this.lockFight) {
if (this.fights.ContainsKey(cameraid)) { if (this.fights.ContainsKey(cameraid)) {
@ -130,8 +136,8 @@ namespace Fraunhofer.Fit.IoT.LoraMap {
return SendJsonResponse(new Dictionary<String, Object>() { return SendJsonResponse(new Dictionary<String, Object>() {
{ "loc", this.positions }, { "loc", this.positions },
{ "panic", this.alarms }, { "panic", this.alarms },
{ "cameracount", this.cameras }, { "cameracount", this.counter },
{ "crowdcount", this.crowds }, { "crowdcount", this.density },
{ "fightdedect", this.fights }, { "fightdedect", this.fights },
{ "weatherwarnings", this.weather.Warnungen } { "weatherwarnings", this.weather.Warnungen }
}, cont); }, cont);

View File

@ -30,54 +30,42 @@
margin-left: 210px; margin-left: 210px;
border-left: 1px solid black; border-left: 1px solid black;
} }
#content #nameeditor .title {
margin-bottom: 20px; #content .settingstable {
font-weight: bold;
}
#content #nameeditor #nametable {
margin-left: 15px; margin-left: 15px;
border-collapse: collapse; border-collapse: separate;
} }
#content #nameeditor #nametable thead { #content .settingstable thead {
background-color: #CCCCCC; background-color: #CCCCCC;
background-color: rgba(0,0,0,0.2); background-color: rgba(0,0,0,0.2);
} }
#content #nameeditor #nametable thead th { #content .settingstable thead th {
text-align: left; text-align: left;
} }
#content #nameeditor #nametable thead .rowid { #content .settingstable tbody tr:nth-child(odd) {
width: 60px;
}
#content #nameeditor #nametable thead .rowicon {
width: 65px;
}
#content #nameeditor #nametable thead .rowedit {
width: 50px;
}
#content #nameeditor #nametable thead .rowname {
width: 250px;
}
#content #nameeditor #nametable tbody tr:nth-child(odd) {
background-color: #f39d9d; background-color: #f39d9d;
background-color: rgba(20,0,250,0.1); background-color: rgba(20,0,250,0.1);
} }
#content #nameeditor #nametable tbody tr:nth-child(even) { #content .settingstable tbody tr:nth-child(even) {
background-color: #9c9eee; background-color: #9c9eee;
background-color: rgba(250,59,0,0.1); background-color: rgba(250,59,0,0.1);
} }
#content #nameeditor #nametable tbody tr:hover { #content .settingstable tbody tr:hover {
background-color: #e4e1e1; background-color: #e4e1e1;
background-color: rgba(0,0,0,0.1); background-color: rgba(0,0,0,0.1);
} }
#content #nameeditor #nametable tfoot { #content .settingstable tfoot {
background-color: #e4e1e1; background-color: #e4e1e1;
background-color: rgba(0,0,0,0.1); background-color: rgba(0,0,0,0.1);
} }
#content #nameeditor .pointer {
#content .pointer {
cursor: pointer; cursor: pointer;
} }
#content #nameeditor #nametable tbody .name {
width: 55px; #content #nameeditor .title {
margin-bottom: 20px;
font-weight: bold;
} }
#iconeditor { #iconeditor {
@ -132,54 +120,3 @@
margin-left: 15px; margin-left: 15px;
margin-top: 20px; margin-top: 20px;
} }
#content #settingseditor #fighttable,
#content #settingseditor #crowdtable {
border-collapse: collapse;
}
#content #settingseditor #fighttable thead,
#content #settingseditor #crowdtable thead {
background-color: #CCCCCC;
background-color: rgba(0,0,0,0.2);
}
#content #settingseditor #fighttable thead th,
#content #settingseditor #crowdtable thead th {
text-align: left;
}
#content #settingseditor #fighttable thead .rowid,
#content #settingseditor #crowdtable thead .rowid {
width: 60px;
}
#content #settingseditor #crowdtable thead .rownum {
width: 200px;
}
#content #settingseditor #fighttable thead .rowcoord,
#content #settingseditor #crowdtable thead .rowcoord {
width: 250px;
}
#content #settingseditor #fighttable thead .rowedit,
#content #settingseditor #crowdtable thead .rowedit {
width: 50px;
}
#content #settingseditor #fighttable tbody tr:nth-child(odd),
#content #settingseditor #crowdtable tbody tr:nth-child(odd) {
background-color: #f39d9d;
background-color: rgba(20,0,250,0.1);
}
#content #settingseditor #fighttable tbody tr:nth-child(even),
#content #settingseditor #crowdtable tbody tr:nth-child(even) {
background-color: #9c9eee;
background-color: rgba(250,59,0,0.1);
}
#content #settingseditor #fighttable tbody tr:hover,
#content #settingseditor #crowdtable tbody tr:hover {
background-color: #e4e1e1;
background-color: rgba(0,0,0,0.1);
}
#content #settingseditor #fighttable tfoot,
#content #settingseditor #crowdtable tfoot {
background-color: #e4e1e1;
background-color: rgba(0,0,0,0.1);
}
#content #settingseditor .pointer {
cursor: pointer;
}

View File

@ -57,8 +57,8 @@ var NamesEditor = {
document.getElementById("content").innerHTML = ""; document.getElementById("content").innerHTML = "";
var namesconfig = JSON.parse(jsontext); var namesconfig = JSON.parse(jsontext);
var html = "<div id='nameeditor'><div class='title'>Namenseinträge in den Einstellungen</div>"; var html = "<div id='nameeditor'><div class='title'>Namenseinträge in den Einstellungen</div>";
html += "<table id='nametable'>"; html += "<table id='nametable' class='settingstable'>";
html += "<thead><tr><th class='rowid'>ID</th><th class='rowname'>Name</th><th class='rowicon'>Icon</th><th class='rowedit'></th></tr></thead>"; html += "<thead><tr><th width='60'>ID</th><th width='250'>Name</th><th width='65'>Icon</th><th width='150'>Filter Gruppe</th><th width='50'></th></tr></thead>";
html += "<tbody>"; html += "<tbody>";
for (var id in namesconfig) { for (var id in namesconfig) {
if (namesconfig.hasOwnProperty(id)) { if (namesconfig.hasOwnProperty(id)) {
@ -73,12 +73,13 @@ var NamesEditor = {
} else { } else {
html += "<td><img src='../js/leaflet/images/marker-icon.png'></td>"; html += "<td><img src='../js/leaflet/images/marker-icon.png'></td>";
} }
html += "<td>"+nameentry.Group+"</td>";
html += "<td><img src='../icons/general/edit.png' onclick='NamesEditor.Edit(this.parentNode.parentNode)' class='pointer'> <img src='../icons/general/remove.png' onclick='NamesEditor.Delete(this.parentNode.parentNode)' class='pointer'></td>" + html += "<td><img src='../icons/general/edit.png' onclick='NamesEditor.Edit(this.parentNode.parentNode)' class='pointer'> <img src='../icons/general/remove.png' onclick='NamesEditor.Delete(this.parentNode.parentNode)' class='pointer'></td>" +
"</tr>"; "</tr>";
} }
} }
html += "</tbody>"; html += "</tbody>";
html += "<tfoot><tr><td></td><td></td><td></td><td><img src='../icons/general/add.png' onclick='NamesEditor.Add()' class='pointer'> <img src='../icons/general/save.png' onclick='NamesEditor.Save()' class='pointer'></td></tr></tfoot>"; html += "<tfoot><tr><td></td><td></td><td></td><td></td><td><img src='../icons/general/add.png' onclick='NamesEditor.Add()' class='pointer'> <img src='../icons/general/save.png' onclick='NamesEditor.Save()' class='pointer'></td></tr></tfoot>";
html += "</table>"; html += "</table>";
document.getElementById("content").innerHTML = html + "</div>"; document.getElementById("content").innerHTML = html + "</div>";
}, },
@ -139,9 +140,19 @@ var NamesEditor = {
}, },
Add: function () { Add: function () {
var newrow = document.createElement("tr"); var newrow = document.createElement("tr");
newrow.innerHTML = "<td><input class='name'/></td>"; newrow.innerHTML = "<td><input style='width: 55px;'/></td>";
newrow.innerHTML += "<td><input /></td>"; newrow.innerHTML += "<td><input style='width: 245px;'/></td>";
newrow.innerHTML += "<td><img src='../icons/general/icon_edit.png' onclick='NamesEditor.IconEditor(this.parentNode)' class='pointer'> wähle Icon</td>"; newrow.innerHTML += "<td><img src='../icons/general/icon_edit.png' onclick='NamesEditor.IconEditor(this.parentNode)' class='pointer'> wähle Icon</td>";
newrow.innerHTML += "<td><select style='width: 145px;'>" +
"<option value='no'>immer Sichtbar</option>" +
"<option value='fw'>Feuerwehr</option>" +
"<option value='sani'>Sanitäter</option>" +
"<option value='pol'>Polizei</option>" +
"<option value='oa'>Ordnungsamt</option>" +
"<option value='sicherheitsdienst'>Sicherheitsdienst</option>" +
"<option value='thw'>THW</option>" +
"<option value='crew'>Veranstalter</option>" +
"</select></td>";
newrow.innerHTML += "<td><img src='../icons/general/save.png' onclick='NamesEditor.SaveRow(this.parentNode.parentNode)' class='pointer'> <img src='../icons/general/remove.png' onclick='NamesEditor.Abort(this.parentNode.parentNode)' class='pointer'></td>"; newrow.innerHTML += "<td><img src='../icons/general/save.png' onclick='NamesEditor.SaveRow(this.parentNode.parentNode)' class='pointer'> <img src='../icons/general/remove.png' onclick='NamesEditor.Abort(this.parentNode.parentNode)' class='pointer'></td>";
document.getElementById("nametable").children[1].appendChild(newrow); document.getElementById("nametable").children[1].appendChild(newrow);
}, },
@ -187,13 +198,23 @@ var NamesEditor = {
if (el.children[2].children[0].hasAttribute("data")) { if (el.children[2].children[0].hasAttribute("data")) {
url = el.children[2].children[0].data; url = el.children[2].children[0].data;
} }
el.innerHTML = "<td><input class='name' value='" + id + "'/></td>"; el.innerHTML = "<td><input style='width: 55px;' value='" + id + "'/></td>";
el.innerHTML += "<td><input value='" + name + "'/></td>"; el.innerHTML += "<td><input style='width: 245px;' value='" + name + "'/></td>";
if (url === null) { if (url === null) {
el.innerHTML += "<td><img src='../icons/general/icon_edit.png' onclick='NamesEditor.IconEditor(this.parentNode)' class='pointer'> wähle Icon</td>"; el.innerHTML += "<td><img src='../icons/general/icon_edit.png' onclick='NamesEditor.IconEditor(this.parentNode)' class='pointer'> wähle Icon</td>";
} else { } else {
el.innerHTML += "<td><img src='../icons/general/icon_edit.png' onclick='NamesEditor.IconEditor(this.parentNode)' class='pointer'> <object data='" + url + "' type='image/svg+xml' style='height:50px; width:50px;'></object></td>"; el.innerHTML += "<td><img src='../icons/general/icon_edit.png' onclick='NamesEditor.IconEditor(this.parentNode)' class='pointer'> <object data='" + url + "' type='image/svg+xml' style='height:50px; width:50px;'></object></td>";
} }
el.innerHTML += "<td><select style='width: 145px;'>" +
"<option value='no'>immer Sichtbar</option>" +
"<option value='fw'>Feuerwehr</option>" +
"<option value='sani'>Sanitäter</option>" +
"<option value='pol'>Polizei</option>" +
"<option value='oa'>Ordnungsamt</option>" +
"<option value='sicherheitsdienst'>Sicherheitsdienst</option>" +
"<option value='thw'>THW</option>" +
"<option value='crew'>Veranstalter</option>" +
"</select></td>";
el.innerHTML += "<td><img src='../icons/general/save.png' onclick='NamesEditor.SaveRow(this.parentNode.parentNode)' class='pointer'> <img src='../icons/general/remove.png' onclick='NamesEditor.Abort(this.parentNode.parentNode)' class='pointer'></td>"; el.innerHTML += "<td><img src='../icons/general/save.png' onclick='NamesEditor.SaveRow(this.parentNode.parentNode)' class='pointer'> <img src='../icons/general/remove.png' onclick='NamesEditor.Abort(this.parentNode.parentNode)' class='pointer'></td>";
}, },
Abort: function (el) { Abort: function (el) {
@ -206,6 +227,7 @@ var NamesEditor = {
if (el.children[2].children.length === 2) { if (el.children[2].children.length === 2) {
url = el.children[2].children[1].data; url = el.children[2].children[1].data;
} }
var group = "";
el.innerHTML = "<td>" + id + "</td>" + el.innerHTML = "<td>" + id + "</td>" +
"<td>" + name + "</td>"; "<td>" + name + "</td>";
if (url === null) { if (url === null) {
@ -213,6 +235,7 @@ var NamesEditor = {
} else { } else {
el.innerHTML += "<td><object data='" + url +"' type='image/svg+xml' style='height:50px; width:50px;'></object></td>"; el.innerHTML += "<td><object data='" + url +"' type='image/svg+xml' style='height:50px; width:50px;'></object></td>";
} }
el.innerHTML += "<td>" + group + "</td>";
el.innerHTML += "<td><img src='../icons/general/edit.png' onclick='NamesEditor.Edit(this.parentNode.parentNode)' class='pointer'> <img src='../icons/general/remove.png' onclick='NamesEditor.Delete(this.parentNode.parentNode)' class='pointer'></td>"; el.innerHTML += "<td><img src='../icons/general/edit.png' onclick='NamesEditor.Edit(this.parentNode.parentNode)' class='pointer'> <img src='../icons/general/remove.png' onclick='NamesEditor.Delete(this.parentNode.parentNode)' class='pointer'></td>";
}, },
IconEditor: function (el) { IconEditor: function (el) {
@ -430,8 +453,8 @@ var Settings = {
}, },
_renderFightDedection: function (json) { _renderFightDedection: function (json) {
var ret = ""; var ret = "";
ret += "<table id='fighttable'>"; ret += "<table id='fighttable' class='settingstable'>";
ret += "<thead><tr><th class='rowid'>ID</th><th class='rowcoord'>Koordinaten</th><th class='rowedit'></th></tr></thead>"; ret += "<thead><tr><th width='150'>ID</th><th width='250'>Koordinaten</th><th width='50'></th></tr></thead>";
ret += "<tbody>"; ret += "<tbody>";
for (var id in json) { for (var id in json) {
var coords = []; var coords = [];
@ -451,8 +474,8 @@ var Settings = {
}, },
_renderCrowdDensity: function (json) { _renderCrowdDensity: function (json) {
var ret = ""; var ret = "";
ret += "<table id='crowdtable'>"; ret += "<table id='crowdtable' class='settingstable'>";
ret += "<thead><tr><th class='rowid'>ID</th><th class='rownum'>Personenanzahl</th><th class='rowcoord'>Koordinaten</th><th class='rowedit'></th></tr></thead>"; ret += "<thead><tr><th width='150'>ID</th><th width='200'>Personenanzahl</th><th width='250'>Koordinaten</th><th width='50'></th></tr></thead>";
ret += "<tbody>"; ret += "<tbody>";
for (var id in json) { for (var id in json) {
var coords = []; var coords = [];
@ -473,16 +496,16 @@ var Settings = {
}, },
AddFight: function () { AddFight: function () {
var newrow = document.createElement("tr"); var newrow = document.createElement("tr");
newrow.innerHTML = "<td><input class='id'/></td>"; newrow.innerHTML = "<td><input style='width: 145px;'/></td>";
newrow.innerHTML += "<td><textarea></textarea></td>"; newrow.innerHTML += "<td><textarea style='width: 240px;height: 60px;'></textarea></td>";
newrow.innerHTML += "<td><img src='../icons/general/save.png' onclick='Settings.SaveRowfight(this.parentNode.parentNode)' class='pointer'> <img src='../icons/general/remove.png' onclick='Settings.Abort(this.parentNode.parentNode)' class='pointer'></td>"; newrow.innerHTML += "<td><img src='../icons/general/save.png' onclick='Settings.SaveRowfight(this.parentNode.parentNode)' class='pointer'> <img src='../icons/general/remove.png' onclick='Settings.Abort(this.parentNode.parentNode)' class='pointer'></td>";
document.getElementById("fighttable").children[1].appendChild(newrow); document.getElementById("fighttable").children[1].appendChild(newrow);
}, },
AddDensity: function () { AddDensity: function () {
var newrow = document.createElement("tr"); var newrow = document.createElement("tr");
newrow.innerHTML = "<td><input class='id'/></td>"; newrow.innerHTML = "<td><input style='width: 145px;'/></td>";
newrow.innerHTML += "<td><input class='count'/></td>"; newrow.innerHTML += "<td><input style='width: 195px;'/></td>";
newrow.innerHTML += "<td><textarea></textarea></td>"; newrow.innerHTML += "<td><textarea style='width: 240px;height: 60px;'></textarea></td>";
newrow.innerHTML += "<td><img src='../icons/general/save.png' onclick='Settings.SaveRowdensity(this.parentNode.parentNode)' class='pointer'> <img src='../icons/general/remove.png' onclick='Settings.Abort(this.parentNode.parentNode)' class='pointer'></td>"; newrow.innerHTML += "<td><img src='../icons/general/save.png' onclick='Settings.SaveRowdensity(this.parentNode.parentNode)' class='pointer'> <img src='../icons/general/remove.png' onclick='Settings.Abort(this.parentNode.parentNode)' class='pointer'></td>";
document.getElementById("crowdtable").children[1].appendChild(newrow); document.getElementById("crowdtable").children[1].appendChild(newrow);
}, },
@ -547,14 +570,14 @@ var Settings = {
} }
}, },
EditFight: function (el) { EditFight: function (el) {
el.innerHTML = "<td><input class='id' value='" + el.children[0].innerText + "'/></td>" + el.innerHTML = "<td><input style='width: 145px;' value='" + el.children[0].innerText + "'/></td>" +
"<td><textarea>" + el.children[1].innerText + "</textarea></td>" + "<td><textarea style='width: 240px;height: 60px;'>" + el.children[1].innerText + "</textarea></td>" +
"<td><img src='../icons/general/save.png' onclick='Settings.SaveRowfight(this.parentNode.parentNode)' class='pointer'> <img src='../icons/general/remove.png' onclick='Settings.Abort(this.parentNode.parentNode)' class='pointer'></td>"; "<td><img src='../icons/general/save.png' onclick='Settings.SaveRowfight(this.parentNode.parentNode)' class='pointer'> <img src='../icons/general/remove.png' onclick='Settings.Abort(this.parentNode.parentNode)' class='pointer'></td>";
}, },
EditDensity: function (el) { EditDensity: function (el) {
el.innerHTML = "<td><input class='id' value='" + el.children[0].innerText + "'/></td>" + el.innerHTML = "<td><input style='width: 145px;' value='" + el.children[0].innerText + "'/></td>" +
"<td><input class='count' value='" + el.children[1].innerText + "'/></td>" + "<td><input style='width: 195px;' value='" + el.children[1].innerText + "'/></td>" +
"<td><textarea>" + el.children[2].innerText + "</textarea></td>" + "<td><textarea style='width: 240px;height: 60px;'>" + el.children[2].innerText + "</textarea></td>" +
"<td><img src='../icons/general/save.png' onclick='Settings.SaveRowdensity(this.parentNode.parentNode)' class='pointer'> <img src='../icons/general/remove.png' onclick='Settings.Abort(this.parentNode.parentNode)' class='pointer'></td>"; "<td><img src='../icons/general/save.png' onclick='Settings.SaveRowdensity(this.parentNode.parentNode)' class='pointer'> <img src='../icons/general/remove.png' onclick='Settings.Abort(this.parentNode.parentNode)' class='pointer'></td>";
}, },
_filterFloat: function (value) { _filterFloat: function (value) {

View File

@ -110,7 +110,7 @@
} }
box.setStyle({ color: this._createRGB(cur, max) }); box.setStyle({ color: this._createRGB(cur, max) });
var p = box.getPopup().setContent("<strong>Besuchermenge:</strong><br>" + var p = box.getPopup().setContent("<strong>Besuchermenge:</strong><br>" +
"Besucher <strong>(" + cur + "/" + max + ")</strong> Personen<br>" + "Besucher <strong>(" + crowd.DensityCount + "/" + max + ")</strong> Personen<br>" +
"<progress value='" + cur + "' max='" + max + "'></progress>").update(); "<progress value='" + cur + "' max='" + max + "'></progress>").update();
} }
} }