Show progress for selected Hugvey
This commit is contained in:
parent
2a712fb7e1
commit
d00b676ad8
6 changed files with 115 additions and 25 deletions
|
@ -91,9 +91,9 @@ class CentralCommand(object):
|
||||||
status['status'] = hv.getStatus()
|
status['status'] = hv.getStatus()
|
||||||
status['language'] = hv.language_code
|
status['language'] = hv.language_code
|
||||||
status['msg'] = hv.story.currentMessage.id if hv.story.currentMessage else None
|
status['msg'] = hv.story.currentMessage.id if hv.story.currentMessage else None
|
||||||
status['counts'] = hv.story.getStoryCounts()
|
|
||||||
status['finished'] = hv.story.isFinished()
|
status['finished'] = hv.story.isFinished()
|
||||||
|
status['history'] = hv.story.getLogSummary()
|
||||||
|
status['counts'] = {t: len(a) for t, a in status['history'].items() }
|
||||||
|
|
||||||
return status
|
return status
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ class Message(object):
|
||||||
self.text = text
|
self.text = text
|
||||||
self.isStart = False
|
self.isStart = False
|
||||||
self.reply = None
|
self.reply = None
|
||||||
|
self.replyTime = None
|
||||||
self.audioFile= None
|
self.audioFile= None
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -23,8 +24,9 @@ class Message(object):
|
||||||
msg.audioFile = data['audio']['file']
|
msg.audioFile = data['audio']['file']
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
def setReply(self, text):
|
def setReply(self, text, replyTime):
|
||||||
self.reply = text
|
self.reply = text
|
||||||
|
self.replyTime = replyTime
|
||||||
|
|
||||||
def hasReply(self):
|
def hasReply(self):
|
||||||
return self.reply is not None
|
return self.reply is not None
|
||||||
|
@ -36,6 +38,13 @@ class Message(object):
|
||||||
|
|
||||||
return self.reply
|
return self.reply
|
||||||
|
|
||||||
|
def getLogSummary(self):
|
||||||
|
return {
|
||||||
|
'id': self.id,
|
||||||
|
'time': self.replyTime,
|
||||||
|
'replyText': self.reply
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class Condition(object):
|
class Condition(object):
|
||||||
"""
|
"""
|
||||||
|
@ -98,6 +107,10 @@ class Condition(object):
|
||||||
return True
|
return True
|
||||||
return self.vars['contains'] in story.currentMessage.getReply()
|
return self.vars['contains'] in story.currentMessage.getReply()
|
||||||
|
|
||||||
|
def getLogSummary(self):
|
||||||
|
return {
|
||||||
|
'id': self.id
|
||||||
|
}
|
||||||
|
|
||||||
class Direction(object):
|
class Direction(object):
|
||||||
"""
|
"""
|
||||||
|
@ -109,10 +122,14 @@ class Direction(object):
|
||||||
self.msgFrom = msgFrom
|
self.msgFrom = msgFrom
|
||||||
self.msgTo = msgTo
|
self.msgTo = msgTo
|
||||||
self.conditions = []
|
self.conditions = []
|
||||||
|
self.conditionMet = None
|
||||||
|
|
||||||
def addCondition(self, condition: Condition):
|
def addCondition(self, condition: Condition):
|
||||||
self.conditions.append(condition)
|
self.conditions.append(condition)
|
||||||
|
|
||||||
|
def setMetCondition(self, condition: Condition):
|
||||||
|
self.conditionMet = condition
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def initFromJson(direction, data, story):
|
def initFromJson(direction, data, story):
|
||||||
msgFrom = story.get(data['source'])
|
msgFrom = story.get(data['source'])
|
||||||
|
@ -124,6 +141,12 @@ class Direction(object):
|
||||||
direction.addCondition(c)
|
direction.addCondition(c)
|
||||||
return direction
|
return direction
|
||||||
|
|
||||||
|
def getLogSummary(self):
|
||||||
|
return {
|
||||||
|
'id': self.id,
|
||||||
|
'condition': self.conditionMet.id if self.conditionMet else None
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class Diversion(object):
|
class Diversion(object):
|
||||||
"""
|
"""
|
||||||
|
@ -147,6 +170,13 @@ class Diversion(object):
|
||||||
return diversion
|
return diversion
|
||||||
|
|
||||||
|
|
||||||
|
def getLogSummary(self):
|
||||||
|
return {
|
||||||
|
'id': self.id,
|
||||||
|
# 'time': self.replyTime
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
storyClasses = {
|
storyClasses = {
|
||||||
'Msg': Message,
|
'Msg': Message,
|
||||||
'Direction': Direction,
|
'Direction': Direction,
|
||||||
|
@ -224,18 +254,15 @@ class Story(object):
|
||||||
logger.debug('resume hugvey')
|
logger.debug('resume hugvey')
|
||||||
self.timer.resume()
|
self.timer.resume()
|
||||||
|
|
||||||
def getStoryCounts(self):
|
def getLogSummary(self):
|
||||||
# counts = {}
|
summary = {
|
||||||
# for item in self.log:
|
# e[0]: the entity, e[1]: the logged time
|
||||||
# n =item.__class__.__name__
|
'messages': [(e[0].getLogSummary(), e[1]) for e in self.log if isinstance(e[0], Message)],
|
||||||
# if n not in counts:
|
'directions': [(e[0].getLogSummary(), e[1]) for e in self.log if isinstance(e[0], Direction)],
|
||||||
# counts[n] = 0
|
'diversions': [(e[0].getLogSummary(), e[1]) for e in self.log if isinstance(e[0], Diversion)],
|
||||||
# counts[n] += 1
|
|
||||||
# return counts
|
|
||||||
return {
|
|
||||||
'messages': len([e for e in self.log if isinstance(e, Message)]),
|
|
||||||
'diversions': len([e for e in self.log if isinstance(e, Diversion)])
|
|
||||||
}
|
}
|
||||||
|
# print(self.log)
|
||||||
|
return summary
|
||||||
|
|
||||||
def setStoryData(self, story_data):
|
def setStoryData(self, story_data):
|
||||||
"""
|
"""
|
||||||
|
@ -347,7 +374,7 @@ class Story(object):
|
||||||
if e['is_final']:
|
if e['is_final']:
|
||||||
# final result
|
# final result
|
||||||
self.lastSpeechEndTime = e['time']
|
self.lastSpeechEndTime = e['time']
|
||||||
self.currentMessage.setReply(e['transcript'])
|
self.currentMessage.setReply(e['transcript'], self.timer.getElapsed())
|
||||||
|
|
||||||
def _processDirections(self, directions):
|
def _processDirections(self, directions):
|
||||||
for direction in directions:
|
for direction in directions:
|
||||||
|
@ -355,11 +382,15 @@ class Story(object):
|
||||||
if condition.isMet(self):
|
if condition.isMet(self):
|
||||||
logger.info("Condition is met: {0}, going to {1}".format(
|
logger.info("Condition is met: {0}, going to {1}".format(
|
||||||
condition.id, direction.msgTo.id))
|
condition.id, direction.msgTo.id))
|
||||||
self.log.append(condition)
|
direction.setMetCondition(condition)
|
||||||
self.log.append(direction)
|
self.addToLog(condition)
|
||||||
|
self.addToLog(direction)
|
||||||
self.setCurrentMessage(direction.msgTo)
|
self.setCurrentMessage(direction.msgTo)
|
||||||
return direction
|
return direction
|
||||||
|
|
||||||
|
def addToLog(self, node):
|
||||||
|
self.log.append((node, self.timer.getElapsed()))
|
||||||
|
|
||||||
async def _renderer(self):
|
async def _renderer(self):
|
||||||
"""
|
"""
|
||||||
every 1/10 sec. determine what needs to be done based on the current story state
|
every 1/10 sec. determine what needs to be done based on the current story state
|
||||||
|
@ -400,7 +431,7 @@ class Story(object):
|
||||||
|
|
||||||
logger.info("Current message: ({0}) \"{1}\"".format(
|
logger.info("Current message: ({0}) \"{1}\"".format(
|
||||||
message.id, message.text))
|
message.id, message.text))
|
||||||
self.log.append(message)
|
self.addToLog(message)
|
||||||
# TODO: prep events & timer etc.
|
# TODO: prep events & timer etc.
|
||||||
if message.audioFile:
|
if message.audioFile:
|
||||||
self.hugvey.sendCommand({
|
self.hugvey.sendCommand({
|
||||||
|
|
|
@ -101,6 +101,11 @@ img.icon {
|
||||||
cursor: grab; }
|
cursor: grab; }
|
||||||
#story svg#graph:active {
|
#story svg#graph:active {
|
||||||
cursor: grabbing; }
|
cursor: grabbing; }
|
||||||
|
#story svg#graph .beenHit circle {
|
||||||
|
stroke: #0f0;
|
||||||
|
stroke-width: 2px; }
|
||||||
|
#story svg#graph line.beenHit {
|
||||||
|
stroke: #0f0; }
|
||||||
#story circle {
|
#story circle {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
fill: #77618e; }
|
fill: #77618e; }
|
||||||
|
|
|
@ -28,7 +28,9 @@
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class='hugvey' v-for="hv in hugveys"
|
<div class='hugvey' v-for="hv in hugveys"
|
||||||
:class="[{'hugvey--on': hv.status != 'off'},'hugvey--' + hv.status]">
|
:class="[{'hugvey--on': hv.status != 'off'},'hugvey--' + hv.status]"
|
||||||
|
@click="showHugvey(hv)"
|
||||||
|
>
|
||||||
<h1>
|
<h1>
|
||||||
{{ hv.id }}
|
{{ hv.id }}
|
||||||
</h1>
|
</h1>
|
||||||
|
@ -54,9 +56,9 @@
|
||||||
{{ hv.msg }}
|
{{ hv.msg }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class='btn' v-if="hv.status == 'running'" @click="pause(hv)">Pause</div>
|
<div class='btn' v-if="hv.status == 'running'" @click.stop="pause(hv)">Pause</div>
|
||||||
<div class='btn' v-if="hv.status == 'paused'" @click="resume(hv)">Resume</div>
|
<div class='btn' v-if="hv.status == 'paused'" @click.stop="resume(hv)">Resume</div>
|
||||||
<div class='btn' v-if="hv.status == 'finished'" @click="restart(hv)">Restart</div>
|
<div class='btn' v-if="hv.status == 'finished'" @click.stop="restart(hv)">Restart</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -4,6 +4,7 @@ class Panopticon {
|
||||||
constructor() {
|
constructor() {
|
||||||
console.log( "Init panopticon" );
|
console.log( "Init panopticon" );
|
||||||
this.languages = []
|
this.languages = []
|
||||||
|
this.selectedHugvey = null;
|
||||||
this.hugveys = new Vue( {
|
this.hugveys = new Vue( {
|
||||||
el: "#status",
|
el: "#status",
|
||||||
data: {
|
data: {
|
||||||
|
@ -37,6 +38,10 @@ class Panopticon {
|
||||||
change_lang: function(hv, lang_code) {
|
change_lang: function(hv, lang_code) {
|
||||||
hv.status = "loading";
|
hv.status = "loading";
|
||||||
return panopticon.change_language(hv.id, lang_code);
|
return panopticon.change_language(hv.id, lang_code);
|
||||||
|
},
|
||||||
|
showHugvey: function(hv) {
|
||||||
|
panopticon.selectedHugvey = hv.id;
|
||||||
|
panopticon.updateSelectedHugvey();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
|
@ -73,11 +78,35 @@ class Panopticon {
|
||||||
this.hugveys.languages = msg['languages'];
|
this.hugveys.languages = msg['languages'];
|
||||||
this.languages = msg['languages'];
|
this.languages = msg['languages'];
|
||||||
this.hugveys.hugveys = msg['hugveys'];
|
this.hugveys.hugveys = msg['hugveys'];
|
||||||
|
if(this.selectedHugvey) {
|
||||||
|
this.updateSelectedHugvey();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateSelectedHugvey() {
|
||||||
|
if(! this.selectedHugvey) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log('showNOW', this.selectedHugvey);
|
||||||
|
let hv = this.getHugvey(this.selectedHugvey);
|
||||||
|
if(this.graph.language_code != hv.language) {
|
||||||
|
this.loadNarrative(hv.language);
|
||||||
|
}
|
||||||
|
this.graph.updateHugveyStatus(hv);
|
||||||
|
}
|
||||||
|
|
||||||
|
getHugvey(id) {
|
||||||
|
for(let hv of this.hugveys.hugveys) {
|
||||||
|
if(hv.id == id) {
|
||||||
|
return hv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
send( msg ) {
|
send( msg ) {
|
||||||
if ( this.socket.readyState == WebSocket.OPEN ) {
|
if ( this.socket.readyState == WebSocket.OPEN ) {
|
||||||
this.socket.send( JSON.stringify( msg ) );
|
this.socket.send( JSON.stringify( msg ) );
|
||||||
|
@ -129,10 +158,10 @@ class Panopticon {
|
||||||
this.send( { action: 'resume', hugvey: hv_id } )
|
this.send( { action: 'resume', hugvey: hv_id } )
|
||||||
}
|
}
|
||||||
pause( hv_id ) {
|
pause( hv_id ) {
|
||||||
this.send( { action: 'play', hugvey: hv_id } )
|
this.send( { action: 'pause', hugvey: hv_id } )
|
||||||
}
|
}
|
||||||
restart( hv_id ) {
|
restart( hv_id ) {
|
||||||
this.send( { action: 'restart', hugvey: hv_id } )
|
this.send( { action: 'restart', hugvey: hv_id } );
|
||||||
}
|
}
|
||||||
change_language( hv_id, lang_code ) {
|
change_language( hv_id, lang_code ) {
|
||||||
this.send( { action: 'change_language', hugvey: hv_id, lang_code: lang_code } );
|
this.send( { action: 'change_language', hugvey: hv_id, lang_code: lang_code } );
|
||||||
|
@ -718,6 +747,19 @@ class Graph {
|
||||||
this.saveState();
|
this.saveState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateHugveyStatus(hv) {
|
||||||
|
let els = document.getElementsByClassName('beenHit');
|
||||||
|
while(els.length > 0) {
|
||||||
|
els[0].classList.remove('beenHit');
|
||||||
|
}
|
||||||
|
for(let msg of hv['history']['messages']) {
|
||||||
|
document.getElementById(msg[0]['id']).classList.add('beenHit');
|
||||||
|
}
|
||||||
|
for(let msg of hv['history']['directions']) {
|
||||||
|
document.getElementById(msg[0]['id']).classList.add('beenHit');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
saveState() {
|
saveState() {
|
||||||
window.localStorage.setItem( "lastState", this.getJsonString() );
|
window.localStorage.setItem( "lastState", this.getJsonString() );
|
||||||
}
|
}
|
||||||
|
|
|
@ -177,6 +177,16 @@ img.icon{
|
||||||
&:active{
|
&:active{
|
||||||
cursor: grabbing;
|
cursor: grabbing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.beenHit{
|
||||||
|
circle {
|
||||||
|
stroke: #0f0;
|
||||||
|
stroke-width: 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
line.beenHit {
|
||||||
|
stroke: #0f0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
circle{
|
circle{
|
||||||
|
|
Loading…
Reference in a new issue